@paro.io/expert-shared-components 1.14.59 → 1.14.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/lib/README.md +2 -0
  2. package/lib/components/DocumentCenter/MultiFileUploadSection.js +121 -220
  3. package/lib/components/TaxAxis/TaxAxisApi.d.ts +1 -0
  4. package/lib/components/TaxAxis/TaxAxisShell.js +52 -3
  5. package/lib/components/shared/UploadClient.d.ts +1 -2
  6. package/lib/components/shared/UploadClient.js +2 -6
  7. package/lib/index.d.ts +13 -2
  8. package/lib/index.js +27 -3
  9. package/lib/package.json +68 -0
  10. package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +1 -4
  11. package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +6 -10
  12. package/lib/tax-axis/components/clientReport/Methodology.js +2 -2
  13. package/lib/tax-axis/components/clientReport/RecommendedStrategies.d.ts +1 -6
  14. package/lib/tax-axis/components/clientReport/RecommendedStrategies.js +24 -26
  15. package/lib/tax-axis/components/clientReport/StrategyCard.d.ts +1 -1
  16. package/lib/tax-axis/components/clientReport/StrategyCard.js +23 -39
  17. package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +2 -8
  18. package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +7 -9
  19. package/lib/tax-axis/components/dashboard/DashboardActions.js +5 -6
  20. package/lib/tax-axis/components/dashboard/DashboardSummary.d.ts +1 -6
  21. package/lib/tax-axis/components/dashboard/DashboardSummary.js +10 -19
  22. package/lib/tax-axis/components/dashboard/StrategyDetailPanel.d.ts +1 -1
  23. package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +95 -122
  24. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +2 -59
  25. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +49 -433
  26. package/lib/tax-axis/components/documents/DocumentCard.d.ts +3 -8
  27. package/lib/tax-axis/components/documents/DocumentCard.js +14 -83
  28. package/lib/tax-axis/components/documents/DocumentTier.d.ts +2 -5
  29. package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
  30. package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +1 -36
  31. package/lib/tax-axis/components/documents/TaxAxisDocuments.js +86 -363
  32. package/lib/tax-axis/components/extractionReview/TaxAxisExtractionReview.js +17 -17
  33. package/lib/tax-axis/components/intake/ClientParametersSection.js +30 -14
  34. package/lib/tax-axis/components/intake/CpaIntakeQuestionsSection.js +3 -3
  35. package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +2 -1
  36. package/lib/tax-axis/components/intake/IntakeCtaCards.js +13 -6
  37. package/lib/tax-axis/components/intake/RefineAnalysisSection.js +7 -7
  38. package/lib/tax-axis/components/intake/TaxAxisIntake.js +45 -6
  39. package/lib/tax-axis/components/intake/intakeSchema.d.ts +3 -0
  40. package/lib/tax-axis/components/intake/intakeSchema.js +4 -2
  41. package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +2 -26
  42. package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +4 -15
  43. package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +1 -3
  44. package/lib/tax-axis/components/processing/TaxAxisProcessing.js +31 -102
  45. package/lib/tax-axis/components/prospectReport/ProspectPrintView.js +2 -0
  46. package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +8 -1
  47. package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +5 -5
  48. package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +27 -1
  49. package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +43 -25
  50. package/lib/tax-axis/index.d.ts +0 -4
  51. package/lib/tax-axis/index.js +1 -6
  52. package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +13 -138
  53. package/lib/tax-axis/lib/adapters/useEngineOutput.js +7 -156
  54. package/lib/tax-axis/lib/data/documents.d.ts +2 -3
  55. package/lib/tax-axis/lib/data/documents.js +25 -225
  56. package/lib/tax-axis/lib/data/strategies.js +9 -9
  57. package/lib/tax-axis/lib/documentFieldCatalog.d.ts +12 -7
  58. package/lib/tax-axis/lib/documentFieldCatalog.js +8 -805
  59. package/lib/tax-axis/lib/types/index.d.ts +1 -13
  60. package/package.json +1 -1
package/lib/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # expert-shared-components
2
+ Repository to store Components shared between the Expert Apps and Internal Apps
@@ -38,7 +38,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.MultiFileUploadSection = void 0;
39
39
  const react_1 = __importStar(require("react"));
40
40
  const core_1 = require("@material-ui/core");
41
- const CheckCircle_1 = __importDefault(require("@material-ui/icons/CheckCircle"));
42
41
  const ExpandMore_1 = __importDefault(require("@material-ui/icons/ExpandMore"));
43
42
  const ExpandLess_1 = __importDefault(require("@material-ui/icons/ExpandLess"));
44
43
  const date_fns_1 = require("date-fns");
@@ -71,13 +70,15 @@ const generateOptions = (array, clientOptions, isClientPortal) => {
71
70
  ? `${item === null || item === void 0 ? void 0 : item.id}_${index}`
72
71
  : item === null || item === void 0 ? void 0 : item.split(" ").join("_").concat(index);
73
72
  if (clientOptions) {
74
- // Show only project name for project dropdown
75
- if (projectName) {
76
- newText = projectName;
73
+ if (name && projectName) {
74
+ newText = `${name} - ${projectName}`;
77
75
  }
78
76
  else if (name) {
79
77
  newText = name;
80
78
  }
79
+ else if (projectName) {
80
+ newText = projectName;
81
+ }
81
82
  else {
82
83
  newText = "N/A";
83
84
  }
@@ -93,6 +94,7 @@ const generateOptions = (array, clientOptions, isClientPortal) => {
93
94
  });
94
95
  };
95
96
  const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadExpertClientFiles, uploadInternalFile, foldername, refetchFiles, legacyFreelancerId, freelancerName, freelancerEmail, isClientPortal = false, documentUploadUrl, showAsPage, }) => {
97
+ var _a;
96
98
  const [uploadItems, setUploadItems] = (0, react_1.useState)([]);
97
99
  const [isUploading, setIsUploading] = (0, react_1.useState)(false);
98
100
  const [showUploadSection, setShowUploadSection] = (0, react_1.useState)(true);
@@ -120,9 +122,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
120
122
  const excludedStatuses = ["complete", "completed", "doa", "churned"];
121
123
  const isValidProject = projectStatus &&
122
124
  !excludedStatuses.includes(projectStatus.toLowerCase());
123
- // Filter out "System Fee" expert on client side
124
- const isSystemFee = isClientPortal && (name === null || name === void 0 ? void 0 : name.toLowerCase()) === "system fee";
125
- if (id && name && !isSystemFee) {
125
+ if (id && name) {
126
126
  if (!groups.has(id)) {
127
127
  groups.set(id, {
128
128
  expert: { id, name },
@@ -193,7 +193,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
193
193
  if (!selectedExpert)
194
194
  return [];
195
195
  return clientOptions.filter((opt) => {
196
- var _a, _b, _c, _d;
196
+ var _a, _b;
197
197
  const isMatch = isClientPortal
198
198
  ? ((_a = opt.freelancer) === null || _a === void 0 ? void 0 : _a.id) === selectedExpert.id
199
199
  : ((_b = opt.client) === null || _b === void 0 ? void 0 : _b.id) === selectedExpert.id;
@@ -201,12 +201,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
201
201
  const excludedStatuses = ["complete", "completed", "doa", "churned"];
202
202
  const isValidProject = projectStatus &&
203
203
  !excludedStatuses.includes(projectStatus.toLowerCase());
204
- // Filter out System Fee projects on client side
205
- const expertName = isClientPortal
206
- ? (_c = opt.freelancer) === null || _c === void 0 ? void 0 : _c.name
207
- : (_d = opt.client) === null || _d === void 0 ? void 0 : _d.name;
208
- const isSystemFee = isClientPortal && (expertName === null || expertName === void 0 ? void 0 : expertName.toLowerCase()) === "system fee";
209
- return isMatch && isValidProject && !isSystemFee;
204
+ return isMatch && isValidProject;
210
205
  });
211
206
  }, [selectedExpert, clientOptions, isClientPortal]);
212
207
  // Check if all files have projects assigned (for multi-project experts/clients)
@@ -215,15 +210,6 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
215
210
  return true;
216
211
  return uploadItems.every((item) => { var _a; return (_a = item.clientAndProject) === null || _a === void 0 ? void 0 : _a.value; });
217
212
  }, [uploadItems, hasMultipleProjects]);
218
- // Count files that need projects
219
- const filesNeedingProjects = react_1.default.useMemo(() => {
220
- if (!selectedExpert)
221
- return 0;
222
- return uploadItems.filter((item) => { var _a; return !((_a = item.clientAndProject) === null || _a === void 0 ? void 0 : _a.value) && item.status !== "success"; }).length;
223
- }, [uploadItems, selectedExpert]);
224
- // Determine step states
225
- const step1Complete = selectedExpert !== null;
226
- const step2Complete = step1Complete && uploadItems.length > 0 && allFilesHaveProjects;
227
213
  const handleFilesSelected = (files) => {
228
214
  const newItems = files.map((file) => ({
229
215
  id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
@@ -425,198 +411,78 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
425
411
  ".jpg",
426
412
  ".png",
427
413
  ], disabled: isUploading })),
428
- uploadItems.length > 0 && (react_1.default.createElement(core_1.Box, { mb: 3 },
429
- react_1.default.createElement(core_1.Typography, { variant: "h5", style: {
430
- fontWeight: 700,
431
- color: "#1a1a2e",
432
- marginBottom: "4px",
433
- } }, !paroDocuments
434
- ? isClientPortal
435
- ? "Send Files to Expert"
436
- : "Send Files to Client"
437
- : "Upload Documents"),
438
- react_1.default.createElement(core_1.Typography, { variant: "body2", style: { color: "#8b8fa3" } }, "Choose a recipient, assign each file to a project, then upload."))),
439
- !paroDocuments &&
440
- expertGroups.length > 0 &&
441
- uploadItems.length > 0 && (react_1.default.createElement(core_1.Paper, { elevation: 0, style: {
442
- marginBottom: "24px",
443
- borderRadius: "12px",
444
- border: step1Complete
445
- ? "2px solid #248384"
446
- : "2px solid #a8a8a8",
447
- backgroundColor: step1Complete ? "#FDFEFD" : "#fafafa",
448
- overflow: "hidden",
449
- } },
450
- react_1.default.createElement(core_1.Box, { p: 2, style: {
451
- backgroundColor: step1Complete ? "#F0FAF0" : "#f7f7f9",
452
- borderBottom: "1px solid #f0f0f5",
453
- display: "flex",
454
- alignItems: "center",
455
- gap: "12px",
456
- } },
457
- react_1.default.createElement(core_1.Box, { style: {
458
- width: "24px",
459
- height: "24px",
460
- borderRadius: "50%",
461
- backgroundColor: step1Complete ? "white" : "gray",
462
- color: step1Complete ? "#248384" : "white",
463
- display: "flex",
464
- alignItems: "center",
465
- justifyContent: "center",
466
- fontSize: "13px",
467
- fontWeight: 700,
468
- flexShrink: 0,
469
- } }, step1Complete ? (react_1.default.createElement(CheckCircle_1.default, { style: { fontSize: "28px" } })) : ("1")),
470
- react_1.default.createElement(core_1.Box, null,
471
- react_1.default.createElement(core_1.Typography, { variant: "subtitle1", style: {
472
- fontSize: "14px",
473
- fontWeight: 600,
474
- color: "#1a1a2e",
475
- } }, "Select recipient"),
476
- react_1.default.createElement(core_1.Typography, { variant: "caption", style: { fontSize: "12px", color: "#8b8fa3" } }, "Who should receive these files?"))),
477
- react_1.default.createElement(core_1.Box, { p: 2 },
478
- react_1.default.createElement(core_1.Box, { display: "flex", flexWrap: "wrap", style: { gap: "10px" } }, expertGroups.map((group) => (react_1.default.createElement(core_1.Chip, { key: group.expert.id, label: react_1.default.createElement(core_1.Box, { display: "flex", alignItems: "center", style: { gap: "6px" } },
479
- (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id && (react_1.default.createElement(CheckCircle_1.default, { style: { fontSize: "20px" } })),
480
- react_1.default.createElement("span", { style: { fontWeight: 600 } }, group.expert.name),
481
- react_1.default.createElement("span", { style: {
482
- fontSize: "11px",
483
- fontWeight: 500,
484
- padding: "2px 7px",
485
- borderRadius: "10px",
486
- backgroundColor: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
487
- ? "#e2e8f0"
488
- : "#f0f1f4",
489
- color: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
490
- ? "#248384"
491
- : "#8b8fa3",
492
- } },
493
- group.projects.length,
494
- " ",
495
- group.projects.length === 1
496
- ? "project"
497
- : "projects")), onClick: () => handleExpertSelection(group.expert), clickable: true, disabled: group.projects.length === 0, style: {
498
- padding: "10px 18px",
499
- height: "auto",
500
- borderRadius: "8px",
501
- border: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
502
- ? "2px solid #248384"
503
- : "2px solid #e2e4ea",
504
- backgroundColor: "#fff",
505
- color: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
506
- ? "#248384"
507
- : "#3d3f4a",
508
- opacity: group.projects.length === 0 ? 0.5 : 1,
509
- cursor: group.projects.length === 0
510
- ? "not-allowed"
511
- : "pointer",
512
- } }))))))),
513
- uploadItems.length > 0 && (react_1.default.createElement(core_1.Paper, { elevation: 0, style: {
514
- marginBottom: "24px",
515
- borderRadius: "12px",
516
- border: step2Complete
517
- ? "2px solid #248384"
518
- : !paroDocuments && !step1Complete
519
- ? "2px solid #e2e4ea"
520
- : "2px solid #006cff",
521
- backgroundColor: step2Complete
522
- ? "#FDFEFD"
523
- : !paroDocuments && !step1Complete
524
- ? "#fafafa"
525
- : "#ffffff",
526
- overflow: "hidden",
527
- opacity: !paroDocuments && !step1Complete ? 0.5 : 1,
528
- pointerEvents: !paroDocuments && !step1Complete ? "none" : "auto",
529
- } },
530
- react_1.default.createElement(core_1.Box, { p: 2, style: {
531
- backgroundColor: step2Complete
532
- ? "#F0FAF0"
533
- : !paroDocuments && !step1Complete
534
- ? "#f7f7f9"
535
- : "#f2f2f25e",
536
- borderBottom: "1px solid #f0f0f5",
537
- display: "flex",
538
- alignItems: "center",
539
- gap: "12px",
540
- } },
414
+ uploadItems.length > 0 &&
415
+ !paroDocuments &&
416
+ expertGroups.length > 0 && (react_1.default.createElement(core_1.Box, { mb: 3, p: 2, style: { backgroundColor: "#F7FAFC", borderRadius: "8px" } },
417
+ react_1.default.createElement(core_1.Box, { display: "flex", alignItems: "center", mb: 2 },
541
418
  react_1.default.createElement(core_1.Box, { style: {
542
- width: "24px",
543
- height: "24px",
419
+ width: "32px",
420
+ height: "32px",
544
421
  borderRadius: "50%",
545
- backgroundColor: step2Complete
546
- ? "white"
547
- : !paroDocuments && !step1Complete
548
- ? "#ccc"
549
- : "#006cff",
550
- color: step2Complete ? "#248384" : "white",
422
+ backgroundColor: "#48BB78",
423
+ color: "white",
551
424
  display: "flex",
552
425
  alignItems: "center",
553
426
  justifyContent: "center",
554
- fontSize: "13px",
555
- fontWeight: 700,
556
- flexShrink: 0,
557
- } }, step2Complete ? (react_1.default.createElement(CheckCircle_1.default, { style: { fontSize: "28px" } })) : paroDocuments ? ("1") : ("2")),
558
- react_1.default.createElement(core_1.Box, { flex: 1 },
559
- react_1.default.createElement(core_1.Typography, { variant: "subtitle1", style: {
560
- fontSize: "14px",
561
- fontWeight: 600,
562
- color: "#1a1a2e",
563
- } }, "Assign files to projects"),
564
- react_1.default.createElement(core_1.Typography, { variant: "caption", style: { fontSize: "12px", color: "#8b8fa3" } }, "Categorize each file and select its project")),
565
- !paroDocuments && filesNeedingProjects > 0 && (react_1.default.createElement(core_1.Chip, { label: `${filesNeedingProjects} need${filesNeedingProjects === 1 ? "s" : ""} a project`, size: "small", style: {
566
- fontSize: "11px",
427
+ fontWeight: "bold",
428
+ marginRight: "12px",
429
+ } }, "1"),
430
+ react_1.default.createElement(core_1.Typography, { variant: "subtitle1", style: { fontWeight: 600 } }, isClientPortal
431
+ ? "SEND TO EXPERT — select who these files are for"
432
+ : "SEND TO CLIENT — select which client these files are for")),
433
+ react_1.default.createElement(core_1.Box, { display: "flex", flexWrap: "wrap", style: { gap: "8px" } }, expertGroups.map((group) => (react_1.default.createElement(core_1.Chip, { key: group.expert.id, label: react_1.default.createElement(core_1.Box, null,
434
+ react_1.default.createElement("strong", null, group.expert.name),
435
+ react_1.default.createElement(core_1.Box, { component: "span", ml: 1, style: { color: "#718096" } },
436
+ group.projects.length,
437
+ " ",
438
+ group.projects.length === 1
439
+ ? "project"
440
+ : "projects")), onClick: () => handleExpertSelection(group.expert), clickable: true, disabled: group.projects.length === 0, color: "default", style: {
441
+ padding: "8px 12px",
442
+ height: "auto",
443
+ borderRadius: "20px",
444
+ border: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
445
+ ? "2px solid #3182CE"
446
+ : "1px solid #CBD5E0",
447
+ backgroundColor: (selectedExpert === null || selectedExpert === void 0 ? void 0 : selectedExpert.id) === group.expert.id
448
+ ? "#EBF8FF"
449
+ : "white",
450
+ opacity: group.projects.length === 0 ? 0.5 : 1,
451
+ cursor: group.projects.length === 0
452
+ ? "not-allowed"
453
+ : "pointer",
454
+ } })))),
455
+ selectedExpert && hasSingleProject && (react_1.default.createElement(core_1.Box, { mt: 2 },
456
+ react_1.default.createElement(core_1.Chip, { label: "AUTO-ASSIGNED", size: "small", style: {
457
+ backgroundColor: "#C6F6D5",
458
+ color: "#22543D",
567
459
  fontWeight: 600,
568
- padding: "4px 10px",
569
- backgroundColor: "#FFF3E0",
570
- color: "#E65100",
571
- } }))),
572
- react_1.default.createElement(core_1.Box, { p: 2 },
460
+ } }),
461
+ react_1.default.createElement(core_1.Typography, { variant: "caption", style: { marginLeft: "8px", color: "#718096" } },
462
+ ((_a = selectedExpertProjects[0]) === null || _a === void 0 ? void 0 : _a.name) || "Project",
463
+ " \u2014 only project with ",
464
+ selectedExpert.name))),
465
+ selectedExpert && hasMultipleProjects && (react_1.default.createElement(core_1.Box, { mt: 2 },
466
+ react_1.default.createElement(core_1.Chip, { label: `${selectedExpertProjects.length} PROJECTS`, size: "small", style: {
467
+ backgroundColor: "#FEF5E7",
468
+ color: "#D97706",
469
+ fontWeight: 600,
470
+ }, icon: react_1.default.createElement(base_icons_1.IconExclamation, { stroke: "#D97706" }) }),
471
+ react_1.default.createElement(core_1.Typography, { variant: "caption", style: { marginLeft: "8px", color: "#718096" } }, "Select which project each file is for below"))))),
472
+ uploadItems.length > 0 && (react_1.default.createElement(core_1.Box, null,
473
+ react_1.default.createElement(core_1.Box, null,
573
474
  react_1.default.createElement(core_1.Grid, { container: true, spacing: 2 }, uploadItems.map((item, index) => {
574
- var _a, _b, _c;
575
- const needsProject = !paroDocuments && !((_a = item.clientAndProject) === null || _a === void 0 ? void 0 : _a.value);
475
+ var _a;
576
476
  return (react_1.default.createElement(core_1.Grid, { item: true, xs: 12, key: item.id },
577
477
  react_1.default.createElement(core_1.Paper, { elevation: 1, style: {
578
478
  padding: "12px 16px",
579
- backgroundColor: needsProject ? "#FFFBF5" : "white",
580
- border: needsProject
581
- ? "2px solid #FFE0B2"
582
- : "1.5px solid #f0f1f4",
583
- borderRadius: "10px",
479
+ backgroundColor: "white",
480
+ border: "1px solid #E2E8F0",
481
+ borderRadius: "4px",
584
482
  } },
585
483
  react_1.default.createElement(core_1.Grid, { container: true, spacing: 2 },
586
- react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: "auto", style: {
587
- display: "flex",
588
- alignItems: "center",
589
- } },
590
- react_1.default.createElement(core_1.Box, { style: {
591
- width: "36px",
592
- height: "42px",
593
- borderRadius: "4px",
594
- display: "flex",
595
- alignItems: "flex-end",
596
- justifyContent: "center",
597
- paddingBottom: "4px",
598
- fontSize: "10px",
599
- fontWeight: 700,
600
- letterSpacing: "0.5px",
601
- textTransform: "uppercase",
602
- backgroundColor: item.file.name.endsWith(".csv")
603
- ? "#E8F5E9"
604
- : item.file.name.endsWith(".pdf")
605
- ? "#FFF3E0"
606
- : "#E3F2FD",
607
- border: item.file.name.endsWith(".csv")
608
- ? "1.5px solid #A5D6A7"
609
- : item.file.name.endsWith(".pdf")
610
- ? "1.5px solid #FFCC80"
611
- : "1.5px solid #90CAF9",
612
- color: item.file.name.endsWith(".csv")
613
- ? "#248384"
614
- : item.file.name.endsWith(".pdf")
615
- ? "#E65100"
616
- : "#1976D2",
617
- } }, ((_b = item.file.name
618
- .split(".")
619
- .pop()) === null || _b === void 0 ? void 0 : _b.toUpperCase()) || "FILE")),
484
+ react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: "auto", style: { display: "flex", alignItems: "center" } },
485
+ react_1.default.createElement(base_icons_1.IconDocument, { size: "lg" })),
620
486
  react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: true },
621
487
  react_1.default.createElement(base_ui_1.Input, { type: "text", value: item.documentName, onChange: (e) => updateItem(item.id, {
622
488
  documentName: e.target.value,
@@ -645,8 +511,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
645
511
  }
646
512
  }, options: documentTypeOptions, disabled: item.status === "uploading" ||
647
513
  item.status === "success", required: false })),
648
- paroDocuments &&
649
- item.docType === "EO Insurance" && (react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: 3, style: { marginTop: "5px" } },
514
+ paroDocuments && item.docType === "EO Insurance" && (react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: 3, style: { marginTop: "5px" } },
650
515
  react_1.default.createElement(core_1.TextField, { type: "date", label: "Expiration Date", value: item.expiryDate
651
516
  ? new Date(item.expiryDate)
652
517
  .toISOString()
@@ -681,7 +546,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
681
546
  }, disabled: item.status === "uploading" ||
682
547
  item.status === "success", fullWidth: true, variant: "outlined", size: "small", required: true, error: !!item.dateError, helperText: item.dateError }))),
683
548
  !paroDocuments && !hasSingleProject && (react_1.default.createElement(core_1.Grid, { item: true, xs: 12, sm: 3 },
684
- react_1.default.createElement(base_ui_1.Select, { value: ((_c = item.clientAndProject) === null || _c === void 0 ? void 0 : _c.value) || "", onChange: (e) => {
549
+ react_1.default.createElement(base_ui_1.Select, { value: ((_a = item.clientAndProject) === null || _a === void 0 ? void 0 : _a.value) || "", onChange: (e) => {
685
550
  // Handle empty selection
686
551
  if (e.target.value === "") {
687
552
  updateItem(item.id, {
@@ -697,7 +562,7 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
697
562
  {
698
563
  id: "placeholder",
699
564
  value: "",
700
- label: "Select project",
565
+ label: "Which project?",
701
566
  },
702
567
  ...filteredProjectOptions,
703
568
  ], disabled: item.status === "uploading" ||
@@ -720,19 +585,55 @@ const MultiFileUploadSection = ({ paroDocuments, clientAndProjectsList, uploadEx
720
585
  react_1.default.createElement(core_1.Typography, { variant: "caption", style: { color: "#38A169" } }, "\u2713 Upload successful"))),
721
586
  item.status === "error" && (react_1.default.createElement(core_1.Box, { mt: 1, ml: { xs: 0, sm: 6 } },
722
587
  react_1.default.createElement(core_1.Typography, { variant: "caption", style: { color: "#E53E3E" } }, "\u2717 Upload failed"))))));
723
- }))))),
724
- uploadItems.length > 0 && (react_1.default.createElement(core_1.Box, { display: "flex", justifyContent: "flex-end" },
725
- react_1.default.createElement(base_ui_1.Button, { label: isUploading
726
- ? "Uploading..."
727
- : `Upload ${uploadItems.filter((i) => i.status !== "success").length} File${uploadItems.filter((i) => i.status !== "success").length !== 1 ? "s" : ""}`, onClick: handleUploadAll, disabled: uploadItems.length === 0 ||
728
- isUploading ||
729
- uploadItems.every((i) => i.status === "success") ||
730
- (!paroDocuments && !selectedExpert) ||
731
- (hasMultipleProjects && !allFilesHaveProjects) ||
732
- uploadItems.some((i) => paroDocuments &&
733
- i.docType === "EO Insurance" &&
734
- (!i.expiryDate || !!i.dateError) &&
735
- i.status !== "success"), color: "primary", isLoading: isUploading })))))));
588
+ }))),
589
+ react_1.default.createElement(core_1.Divider, { style: { marginTop: "24px" } }),
590
+ react_1.default.createElement(core_1.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, mt: 2 },
591
+ react_1.default.createElement(core_1.Box, null,
592
+ react_1.default.createElement(core_1.Typography, { variant: "body2", style: { color: "#718096" } }, paroDocuments ? (react_1.default.createElement(react_1.default.Fragment, null,
593
+ react_1.default.createElement("span", { style: { fontWeight: "bold" } }, uploadItems.filter((i) => i.status !== "success")
594
+ .length),
595
+ " ",
596
+ uploadItems.filter((i) => i.status !== "success")
597
+ .length === 1
598
+ ? "file"
599
+ : "files")) : (react_1.default.createElement(react_1.default.Fragment, null,
600
+ react_1.default.createElement("span", { style: { fontWeight: "bold" } }, uploadItems.filter((i) => i.status !== "success")
601
+ .length),
602
+ " ",
603
+ "files \u2022",
604
+ " ",
605
+ react_1.default.createElement("span", { style: { color: "#718096" } },
606
+ react_1.default.createElement("span", { style: { fontWeight: "bold" } }, uploadItems.filter((i) => {
607
+ var _a;
608
+ return ((_a = i.clientAndProject) === null || _a === void 0 ? void 0 : _a.value) &&
609
+ i.status !== "success";
610
+ }).length),
611
+ " ",
612
+ "project-assigned"),
613
+ " ",
614
+ "\u2022",
615
+ " ",
616
+ react_1.default.createElement("span", { style: { color: "#D97706" } },
617
+ react_1.default.createElement("span", { style: { fontWeight: "bold" } }, uploadItems.filter((i) => {
618
+ var _a;
619
+ return !((_a = i.clientAndProject) === null || _a === void 0 ? void 0 : _a.value) &&
620
+ i.status !== "success";
621
+ }).length),
622
+ " ",
623
+ "need project"))))),
624
+ react_1.default.createElement(core_1.Box, null,
625
+ react_1.default.createElement(core_1.Box, { component: "span", ml: 1 },
626
+ react_1.default.createElement(base_ui_1.Button, { label: isUploading
627
+ ? "Uploading..."
628
+ : `Upload ${uploadItems.filter((i) => i.status !== "success").length} Files`, onClick: handleUploadAll, disabled: uploadItems.length === 0 ||
629
+ isUploading ||
630
+ uploadItems.every((i) => i.status === "success") ||
631
+ (!paroDocuments && !selectedExpert) ||
632
+ (hasMultipleProjects && !allFilesHaveProjects) ||
633
+ uploadItems.some((i) => paroDocuments &&
634
+ i.docType === "EO Insurance" &&
635
+ (!i.expiryDate || !!i.dateError) &&
636
+ i.status !== "success"), color: "primary", isLoading: isUploading }))))))))));
736
637
  };
737
638
  exports.MultiFileUploadSection = MultiFileUploadSection;
738
639
  exports.default = exports.MultiFileUploadSection;
@@ -55,4 +55,5 @@ export type TaxAxisApi = {
55
55
  generatePdf: (sessionId: string) => Promise<any>;
56
56
  getArtifacts: (sessionId: string) => Promise<any[]>;
57
57
  importQboReport?: (sessionId: string, expertId: string, year: number, reportType: string) => Promise<any>;
58
+ generateProspectReport?: (input: Record<string, unknown>) => Promise<any>;
58
59
  };
@@ -128,6 +128,30 @@ function buildSessionInput(profile) {
128
128
  states: profile.states || [],
129
129
  };
130
130
  }
131
+ function buildProspectInput(profile) {
132
+ var _a;
133
+ const fedRateStr = (profile.federalRate || '24%').replace('%', '');
134
+ const stateRateStr = (profile.stateRate || '0').replace('%', '');
135
+ return {
136
+ businessName: profile.bizName || 'Client',
137
+ entityType: profile.entity || 'S-Corporation',
138
+ primaryState: ((_a = profile.states) === null || _a === void 0 ? void 0 : _a[0]) || 'IL',
139
+ states: profile.states || [],
140
+ industry: profile.industry || 'Professional Services',
141
+ annualRevenue: toInt(profile.revenue),
142
+ netIncome: toInt(profile.netIncome) || null,
143
+ ownerCompensation: toInt(profile.ownerComp) || null,
144
+ employees: toInt(profile.employees) || null,
145
+ federalRate: parseFloat(fedRateStr) / 100 || 0.24,
146
+ stateRate: parseFloat(stateRateStr) / 100 || 0,
147
+ taxYear: Number(profile.year) || new Date().getFullYear(),
148
+ analysisPeriod: profile.period || 'Full Year',
149
+ riskTolerance: profile.riskTolerance || null,
150
+ equipmentPurchased: toInt(profile.equipmentPurchased) || null,
151
+ realEstateValue: toInt(profile.realEstateValue) || null,
152
+ capitalGains: toInt(profile.capitalGains) || null,
153
+ };
154
+ }
131
155
  function ShellContainer({ children, fullWidth = false, }) {
132
156
  if (fullWidth) {
133
157
  return react_1.default.createElement(react_1.default.Fragment, null, children);
@@ -146,6 +170,8 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
146
170
  const [error, setError] = (0, react_1.useState)(null);
147
171
  const [busyMessage, setBusyMessage] = (0, react_1.useState)('Syncing Tax Axis session...');
148
172
  const [reportReady, setReportReady] = (0, react_1.useState)(false);
173
+ const [backendResults, setBackendResults] = (0, react_1.useState)(null);
174
+ const [generating, setGenerating] = (0, react_1.useState)(false);
149
175
  const isPollingRef = react_1.default.useRef(false);
150
176
  // QBO state driven by EPS props — not localStorage
151
177
  const [qboConnectedState, setQboConnectedState] = (0, react_1.useState)(!!qboConnected);
@@ -236,13 +262,29 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
236
262
  setIsProspectFlow(false);
237
263
  setError(null);
238
264
  setReportReady(false);
265
+ setBackendResults(null);
239
266
  updateSessionId(null);
240
267
  }, [updateSessionId]);
241
- const handleProspect = (0, react_1.useCallback)((nextProfile) => {
268
+ const handleProspect = (0, react_1.useCallback)((nextProfile) => __awaiter(void 0, void 0, void 0, function* () {
242
269
  setProfile(nextProfile);
243
270
  setIsProspectFlow(true);
271
+ setBackendResults(null);
272
+ if (taxAxisApi.generateProspectReport) {
273
+ setGenerating(true);
274
+ try {
275
+ const input = buildProspectInput(nextProfile);
276
+ const result = yield taxAxisApi.generateProspectReport(input);
277
+ if (result) {
278
+ setBackendResults(result);
279
+ }
280
+ }
281
+ catch (_err) {
282
+ // LLM call failed — fall through to template mode
283
+ }
284
+ setGenerating(false);
285
+ }
244
286
  setStep('PROSPECT_REPORT');
245
- }, []);
287
+ }), [taxAxisApi]);
246
288
  const handleFullAnalysis = (0, react_1.useCallback)((nextProfile) => __awaiter(void 0, void 0, void 0, function* () {
247
289
  setProfile(nextProfile);
248
290
  setIsProspectFlow(false);
@@ -423,7 +465,7 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
423
465
  switch (step) {
424
466
  case 'PROSPECT_REPORT':
425
467
  return (react_1.default.createElement(ShellContainer, null,
426
- react_1.default.createElement(TaxAxisProspectReport_1.TaxAxisProspectReport, { profile: profile, userContext: userContext, onUpgrade: () => setStep('DOCUMENT_UPLOAD'), onPresent: () => setStep('PRESENTATION'), onReset: handleReset })));
468
+ react_1.default.createElement(TaxAxisProspectReport_1.TaxAxisProspectReport, { profile: profile, userContext: userContext, backendResults: backendResults, onUpgrade: () => setStep('DOCUMENT_UPLOAD'), onPresent: () => setStep('PRESENTATION'), onReset: handleReset })));
427
469
  case 'DOCUMENT_UPLOAD':
428
470
  return (react_1.default.createElement(ShellContainer, null,
429
471
  react_1.default.createElement("div", { className: "flex items-center justify-between rounded-lg px-4 py-3 mb-5", style: {
@@ -513,6 +555,8 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
513
555
  llmResult,
514
556
  adapted,
515
557
  reportReady,
558
+ backendResults,
559
+ generating,
516
560
  parsedDocuments,
517
561
  qboConnectedState,
518
562
  qboCompanyNameState,
@@ -530,6 +574,11 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
530
574
  react_1.default.createElement("div", { className: 'flex items-center gap-2' },
531
575
  react_1.default.createElement("div", { className: 'w-3 h-3 rounded-full animate-spin flex-shrink-0', style: { border: '2px solid transparent', borderTopColor: '#248384' } }),
532
576
  busyMessage)))),
577
+ generating && (react_1.default.createElement("div", { className: 'fixed inset-0 z-[180] bg-black/25' },
578
+ react_1.default.createElement("div", { className: 'absolute left-1/2 top-1/3 -translate-x-1/2 rounded-xl bg-tax-axis-surface px-8 py-6 text-center shadow-lg border border-tax-axis-border', style: { maxWidth: 360 } },
579
+ react_1.default.createElement("div", { className: 'w-6 h-6 rounded-full animate-spin mx-auto mb-3', style: { border: '2.5px solid transparent', borderTopColor: '#248384' } }),
580
+ react_1.default.createElement("div", { className: 'text-sm font-semibold text-white mb-1 font-tax-axis-body' }, "Generating Prospect Report"),
581
+ react_1.default.createElement("div", { className: 'text-xs text-tax-axis-text-3 font-tax-axis-body' }, "Analyzing strategies and generating insights...")))),
533
582
  currentView));
534
583
  };
535
584
  exports.TaxAxisShell = TaxAxisShell;
@@ -8,10 +8,9 @@ export default class UploadClient {
8
8
  bucketName: string;
9
9
  escalationId?: string;
10
10
  taskId?: string;
11
- keyPrefix?: string;
12
11
  };
13
12
  constructor(props: any);
14
- generateS3Key(projectId: number, escalationId: string, fileName: string, taskId: string, keyPrefix?: string): string;
13
+ generateS3Key(projectId: number, escalationId: string, fileName: string, taskId: string): string;
15
14
  triggerMultipartUpload(): Promise<string | undefined>;
16
15
  uploadMultiPartFile(): Promise<string | undefined>;
17
16
  completeUpload(partsArray: any): Promise<string | undefined>;
@@ -20,14 +20,10 @@ class UploadClient {
20
20
  bucketName: props.bucketName,
21
21
  escalationId: props.escalationId,
22
22
  taskId: props.taskId,
23
- keyPrefix: props.keyPrefix,
24
23
  };
25
24
  }
26
- generateS3Key(projectId, escalationId, fileName, taskId, keyPrefix) {
25
+ generateS3Key(projectId, escalationId, fileName, taskId) {
27
26
  const sanitizedFileName = fileName.replace(/[^a-zA-Z0-9.-]/g, '_');
28
- if (!!keyPrefix) {
29
- return `${keyPrefix.replace(/\/+$/, '')}/${sanitizedFileName}`;
30
- }
31
27
  if (!!taskId) {
32
28
  return `project-task-${taskId}/${sanitizedFileName}`;
33
29
  }
@@ -41,7 +37,7 @@ class UploadClient {
41
37
  return __awaiter(this, void 0, void 0, function* () {
42
38
  var _a, _b;
43
39
  try {
44
- const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '', this.state.keyPrefix);
40
+ const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '');
45
41
  this.state = Object.assign(Object.assign({}, this.state), { fileName: fileName });
46
42
  const params = {
47
43
  fileName: this.state.fileName,
package/lib/index.d.ts CHANGED
@@ -16,5 +16,16 @@ export { DiscussionSection } from './components/Invoices/DiscussionSection';
16
16
  export { fileDownloader } from './components/FileDownloader';
17
17
  export { Escalations } from './components/Escalations';
18
18
  export { ProjectIntelligence } from "./components/ProjectIntelligence";
19
- export { TaxAxisShell } from './components/TaxAxis';
20
- export type { TaxAxisApi, TaxAxisSessionInput, TaxAxisUploadInput } from './components/TaxAxis';
19
+ export { SectionHeader } from './tax-axis';
20
+ export { TaxAxisBadge } from './tax-axis';
21
+ export { TaxAxisButton } from './tax-axis';
22
+ export { TaxAxisCard } from './tax-axis';
23
+ export { TaxAxisIntake } from './tax-axis';
24
+ export { TaxAxisDocuments } from './tax-axis';
25
+ export { TaxAxisProcessing } from './tax-axis';
26
+ export { TaxAxisDashboard } from './tax-axis';
27
+ export { TaxAxisClientReport } from './tax-axis';
28
+ export { TaxAxisPreparerWorkpaper } from './tax-axis';
29
+ export { TaxAxisExtractionReview } from './tax-axis';
30
+ export { TaxAxisProspectReport } from './tax-axis';
31
+ export { TaxAxisPresentationMode } from './tax-axis';