@paro.io/expert-shared-components 1.14.57 → 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.
- package/lib/README.md +2 -0
- package/lib/components/DocumentCenter/MultiFileUploadSection.js +121 -220
- package/lib/components/TaxAxis/TaxAxisApi.d.ts +2 -0
- package/lib/components/TaxAxis/TaxAxisShell.d.ts +1 -1
- package/lib/components/TaxAxis/TaxAxisShell.js +104 -5
- package/lib/components/TaxAxis/types.d.ts +5 -0
- package/lib/components/shared/UploadClient.d.ts +1 -2
- package/lib/components/shared/UploadClient.js +2 -6
- package/lib/index.d.ts +13 -2
- package/lib/index.js +27 -3
- package/lib/package.json +68 -0
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +1 -4
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +6 -10
- package/lib/tax-axis/components/clientReport/Methodology.js +2 -2
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.d.ts +1 -6
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.js +24 -26
- package/lib/tax-axis/components/clientReport/StrategyCard.d.ts +1 -1
- package/lib/tax-axis/components/clientReport/StrategyCard.js +23 -39
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +2 -8
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +7 -9
- package/lib/tax-axis/components/dashboard/DashboardActions.js +4 -5
- package/lib/tax-axis/components/dashboard/DashboardSummary.d.ts +1 -6
- package/lib/tax-axis/components/dashboard/DashboardSummary.js +4 -14
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.d.ts +1 -1
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +91 -120
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +2 -59
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +36 -412
- package/lib/tax-axis/components/documents/DocumentCard.d.ts +3 -7
- package/lib/tax-axis/components/documents/DocumentCard.js +12 -65
- package/lib/tax-axis/components/documents/DocumentTier.d.ts +2 -5
- package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +1 -25
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +52 -267
- package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.d.ts +13 -0
- package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.js +180 -0
- package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.d.ts +10 -0
- package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.js +155 -0
- package/lib/tax-axis/components/documents/qbo/QboConnectBanner.d.ts +9 -0
- package/lib/tax-axis/components/documents/qbo/QboConnectBanner.js +55 -0
- package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.d.ts +10 -0
- package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.js +202 -0
- package/lib/tax-axis/components/documents/qbo/QboImportingModal.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/QboImportingModal.js +75 -0
- package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.js +126 -0
- package/lib/tax-axis/components/documents/qbo/index.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/index.js +17 -0
- package/lib/tax-axis/components/documents/qbo/qboConstants.d.ts +24 -0
- package/lib/tax-axis/components/documents/qbo/qboConstants.js +71 -0
- package/lib/tax-axis/components/documents/qbo/types.d.ts +43 -0
- package/lib/tax-axis/components/documents/qbo/types.js +3 -0
- package/lib/tax-axis/components/documents/qbo/useQboFlow.d.ts +19 -0
- package/lib/tax-axis/components/documents/qbo/useQboFlow.js +207 -0
- package/lib/tax-axis/components/extractionReview/TaxAxisExtractionReview.js +17 -17
- package/lib/tax-axis/components/intake/ClientParametersSection.js +29 -13
- package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +2 -1
- package/lib/tax-axis/components/intake/IntakeCtaCards.js +13 -6
- package/lib/tax-axis/components/intake/TaxAxisIntake.js +44 -5
- package/lib/tax-axis/components/intake/intakeSchema.d.ts +3 -0
- package/lib/tax-axis/components/intake/intakeSchema.js +4 -2
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +2 -26
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +4 -15
- package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +1 -3
- package/lib/tax-axis/components/processing/TaxAxisProcessing.js +31 -102
- package/lib/tax-axis/components/prospectReport/ProspectPrintView.js +2 -0
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +8 -1
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +5 -5
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +27 -1
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +43 -25
- package/lib/tax-axis/index.d.ts +0 -4
- package/lib/tax-axis/index.js +1 -6
- package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +13 -138
- package/lib/tax-axis/lib/adapters/useEngineOutput.js +7 -156
- package/lib/tax-axis/lib/data/documents.d.ts +2 -3
- package/lib/tax-axis/lib/data/documents.js +25 -225
- package/lib/tax-axis/lib/data/strategies.js +9 -9
- package/lib/tax-axis/lib/documentFieldCatalog.d.ts +12 -7
- package/lib/tax-axis/lib/documentFieldCatalog.js +8 -805
- package/lib/tax-axis/lib/types/index.d.ts +1 -13
- package/package.json +1 -1
|
@@ -89,22 +89,6 @@ function TaxAxisExtractionReview({ onStatusChange, onConfirmAndUnlock, onBack, }
|
|
|
89
89
|
return (react_1.default.createElement("div", null,
|
|
90
90
|
react_1.default.createElement("style", null, `@keyframes spin{to{transform:rotate(360deg)}}`),
|
|
91
91
|
react_1.default.createElement(PurposeBlock_1.PurposeBlock, { totalFields: totalFields, totalDocs: data_1.EXTRACTED_DATA.length }),
|
|
92
|
-
onConfirmAndUnlock && (react_1.default.createElement("div", { style: {
|
|
93
|
-
marginBottom: 16,
|
|
94
|
-
background: "linear-gradient(135deg, rgba(36,131,132,0.12), rgba(36,131,132,0.06))",
|
|
95
|
-
border: "1px solid rgba(36,131,132,0.3)",
|
|
96
|
-
borderRadius: 12,
|
|
97
|
-
padding: "18px 20px",
|
|
98
|
-
} },
|
|
99
|
-
react_1.default.createElement("div", { className: "flex items-center gap-4" },
|
|
100
|
-
react_1.default.createElement("div", { className: "flex-1" },
|
|
101
|
-
react_1.default.createElement("div", { className: "text-[15px] font-bold text-white font-tax-axis-head mb-1" }, "Ready to view your report?"),
|
|
102
|
-
react_1.default.createElement("div", { className: "text-[13px] text-tax-axis-text leading-relaxed font-tax-axis-body" }, totalFlags - totalEdits > 0
|
|
103
|
-
? (totalFlags - totalEdits) + " value" + (totalFlags - totalEdits > 1 ? "s" : "") + " still flagged. You can confirm now or correct values first."
|
|
104
|
-
: "All extracted values look good. Confirm to unlock the Intelligence Report.")),
|
|
105
|
-
react_1.default.createElement("div", { className: "flex gap-2.5" },
|
|
106
|
-
onBack && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back to Dashboard")),
|
|
107
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onConfirmAndUnlock }, totalFlags - totalEdits > 0 ? "Confirm & Unlock Report" : "Confirm & View Report"))))),
|
|
108
92
|
react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 12 } },
|
|
109
93
|
react_1.default.createElement("div", { style: {
|
|
110
94
|
width: 8,
|
|
@@ -182,5 +166,21 @@ function TaxAxisExtractionReview({ onStatusChange, onConfirmAndUnlock, onBack, }
|
|
|
182
166
|
borderRadius: 4,
|
|
183
167
|
border: "1px solid #2E3160",
|
|
184
168
|
} }, d.code))))))),
|
|
185
|
-
react_1.default.createElement(RerunFooter_1.RerunFooter, { totalEdits: totalEdits, rerunning: rerunning, onRerun: handleRerun })
|
|
169
|
+
react_1.default.createElement(RerunFooter_1.RerunFooter, { totalEdits: totalEdits, rerunning: rerunning, onRerun: handleRerun }),
|
|
170
|
+
onConfirmAndUnlock && (react_1.default.createElement("div", { style: {
|
|
171
|
+
marginTop: 16,
|
|
172
|
+
background: "linear-gradient(135deg, rgba(36,131,132,0.12), rgba(36,131,132,0.06))",
|
|
173
|
+
border: "1px solid rgba(36,131,132,0.3)",
|
|
174
|
+
borderRadius: 12,
|
|
175
|
+
padding: "18px 20px",
|
|
176
|
+
} },
|
|
177
|
+
react_1.default.createElement("div", { className: "flex items-center gap-4" },
|
|
178
|
+
react_1.default.createElement("div", { className: "flex-1" },
|
|
179
|
+
react_1.default.createElement("div", { className: "text-[15px] font-bold text-white font-tax-axis-head mb-1" }, "Ready to view your report?"),
|
|
180
|
+
react_1.default.createElement("div", { className: "text-[13px] text-tax-axis-text leading-relaxed font-tax-axis-body" }, totalFlags - totalEdits > 0
|
|
181
|
+
? (totalFlags - totalEdits) + " value" + (totalFlags - totalEdits > 1 ? "s" : "") + " still flagged. You can confirm now or correct values first."
|
|
182
|
+
: "All extracted values look good. Confirm to unlock the Intelligence Report.")),
|
|
183
|
+
react_1.default.createElement("div", { className: "flex gap-2.5" },
|
|
184
|
+
onBack && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back to Dashboard")),
|
|
185
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onConfirmAndUnlock }, totalFlags - totalEdits > 0 ? "Confirm & Unlock Report" : "Confirm & View Report")))))));
|
|
186
186
|
}
|
|
@@ -49,8 +49,8 @@ const Chevron = () => (react_1.default.createElement("svg", { className: "absolu
|
|
|
49
49
|
react_1.default.createElement("path", { d: "M3 4.5l3 3 3-3", stroke: "#E6E8F5", strokeWidth: "1.5", strokeLinecap: "round" })));
|
|
50
50
|
/* ═══ Option lists (spec-canonical) ═══ */
|
|
51
51
|
const ENTITY_OPTIONS = [
|
|
52
|
-
"C-Corporation",
|
|
53
52
|
"S-Corporation",
|
|
53
|
+
"C-Corporation",
|
|
54
54
|
"LLC",
|
|
55
55
|
"Partnership",
|
|
56
56
|
"Sole Proprietor",
|
|
@@ -67,15 +67,23 @@ const INDUSTRY_OPTIONS = [
|
|
|
67
67
|
"Other",
|
|
68
68
|
];
|
|
69
69
|
const PERIOD_OPTIONS = ["Full Year", "YTD"];
|
|
70
|
-
|
|
70
|
+
// Dynamic year options based on analysis period
|
|
71
|
+
const CURRENT_YEAR = new Date().getFullYear();
|
|
72
|
+
function getYearOptions(period) {
|
|
73
|
+
if (period === "YTD") {
|
|
74
|
+
return [String(CURRENT_YEAR)];
|
|
75
|
+
}
|
|
76
|
+
// Full Year — only completed years
|
|
77
|
+
return [
|
|
78
|
+
String(CURRENT_YEAR - 1),
|
|
79
|
+
String(CURRENT_YEAR - 2),
|
|
80
|
+
String(CURRENT_YEAR - 3),
|
|
81
|
+
];
|
|
82
|
+
}
|
|
71
83
|
function ClientParametersSection({ userContext = "expert", }) {
|
|
72
|
-
const { control, formState: { errors }, } = (0, react_hook_form_1.useFormContext)();
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// field. computeAllStrategies does not read this value. Spec defect.
|
|
76
|
-
// Resolve post-BDO by either adding `period` to ClientProfile or removing
|
|
77
|
-
// the field entirely.
|
|
78
|
-
const [analysisPeriod, setAnalysisPeriod] = (0, react_1.useState)("Full Year");
|
|
84
|
+
const { control, watch, setValue, formState: { errors }, } = (0, react_hook_form_1.useFormContext)();
|
|
85
|
+
const period = watch("period") || "Full Year";
|
|
86
|
+
const yearOptions = getYearOptions(period);
|
|
79
87
|
const [expanded, setExpanded] = (0, react_1.useState)(true);
|
|
80
88
|
return (react_1.default.createElement(TaxAxisCard_1.TaxAxisCard, null,
|
|
81
89
|
react_1.default.createElement("div", { onClick: () => setExpanded((prev) => !prev), className: "flex items-center justify-between cursor-pointer", style: { marginBottom: expanded ? 14 : 0 } },
|
|
@@ -106,9 +114,17 @@ function ClientParametersSection({ userContext = "expert", }) {
|
|
|
106
114
|
errors.industry && react_1.default.createElement("div", { className: errCls }, errors.industry.message)),
|
|
107
115
|
react_1.default.createElement("div", null,
|
|
108
116
|
react_1.default.createElement("label", { className: labelCls }, "Analysis Period"),
|
|
109
|
-
react_1.default.createElement("div", { className: "relative" },
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
react_1.default.createElement(react_hook_form_1.Controller, { name: "period", control: control, render: ({ field }) => (react_1.default.createElement("div", { className: "relative" },
|
|
118
|
+
react_1.default.createElement("select", Object.assign({}, field, { value: field.value || "Full Year", onChange: e => {
|
|
119
|
+
field.onChange(e.target.value);
|
|
120
|
+
// When switching period, auto-fix year to valid option
|
|
121
|
+
const nextOptions = getYearOptions(e.target.value);
|
|
122
|
+
const currentYear = watch("year");
|
|
123
|
+
if (!nextOptions.includes(currentYear || "")) {
|
|
124
|
+
setValue("year", nextOptions[0]);
|
|
125
|
+
}
|
|
126
|
+
}, className: selectCls }), PERIOD_OPTIONS.map(o => (react_1.default.createElement("option", { key: o, value: o, className: "bg-tax-axis-surface-2" }, o)))),
|
|
127
|
+
react_1.default.createElement(Chevron, null))) })),
|
|
112
128
|
react_1.default.createElement("div", null,
|
|
113
129
|
react_1.default.createElement("label", { className: labelCls }, "Annual Revenue"),
|
|
114
130
|
react_1.default.createElement(react_hook_form_1.Controller, { name: "revenue", control: control, render: ({ field }) => (react_1.default.createElement("div", { className: "relative" },
|
|
@@ -126,7 +142,7 @@ function ClientParametersSection({ userContext = "expert", }) {
|
|
|
126
142
|
react_1.default.createElement("div", null,
|
|
127
143
|
react_1.default.createElement("label", { className: labelCls }, "Tax Year"),
|
|
128
144
|
react_1.default.createElement(react_hook_form_1.Controller, { name: "year", control: control, render: ({ field }) => (react_1.default.createElement("div", { className: "relative" },
|
|
129
|
-
react_1.default.createElement("select", Object.assign({}, field, { className: selectCls }),
|
|
145
|
+
react_1.default.createElement("select", Object.assign({}, field, { className: selectCls, disabled: period === "YTD", style: period === "YTD" ? { opacity: 0.6, cursor: "not-allowed" } : undefined }), yearOptions.map(o => (react_1.default.createElement("option", { key: o, value: o, className: "bg-tax-axis-surface-2" }, o)))),
|
|
130
146
|
react_1.default.createElement(Chevron, null))) }),
|
|
131
147
|
errors.year && react_1.default.createElement("div", { className: errCls }, errors.year.message))),
|
|
132
148
|
react_1.default.createElement("div", { className: "border-t border-tax-axis-border pt-3 mt-3.5" },
|
|
@@ -4,6 +4,7 @@ interface IntakeCtaCardsProps {
|
|
|
4
4
|
onProspect: () => void;
|
|
5
5
|
onFullAnalysis: () => void;
|
|
6
6
|
userContext?: UserContext;
|
|
7
|
+
missingFields?: string[];
|
|
7
8
|
}
|
|
8
|
-
export declare function IntakeCtaCards({ onProspect, onFullAnalysis, userContext, }: IntakeCtaCardsProps): React.JSX.Element;
|
|
9
|
+
export declare function IntakeCtaCards({ onProspect, onFullAnalysis, userContext, missingFields, }: IntakeCtaCardsProps): React.JSX.Element;
|
|
9
10
|
export {};
|
|
@@ -7,15 +7,19 @@ exports.IntakeCtaCards = IntakeCtaCards;
|
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const TaxAxisButton_1 = require("../shared/TaxAxisButton");
|
|
9
9
|
const TaxAxisBadge_1 = require("../shared/TaxAxisBadge");
|
|
10
|
-
function IntakeCtaCards({ onProspect, onFullAnalysis, userContext = "expert", }) {
|
|
11
|
-
|
|
10
|
+
function IntakeCtaCards({ onProspect, onFullAnalysis, userContext = "expert", missingFields = [], }) {
|
|
11
|
+
const disabled = missingFields.length > 0;
|
|
12
|
+
return (react_1.default.createElement("div", { className: "grid grid-cols-2 gap-3", style: { position: "sticky", bottom: 0, zIndex: 10, paddingTop: 12, paddingBottom: 4, background: "linear-gradient(to bottom, transparent 0%, #060821 16%)" } },
|
|
12
13
|
react_1.default.createElement("div", { className: "bg-tax-axis-surface border border-tax-axis-border rounded-xl p-4 min-h-[140px] flex flex-col transition-all" },
|
|
13
14
|
react_1.default.createElement("div", { className: "text-[11px] font-bold text-tax-axis-orange uppercase tracking-widest mb-2.5 font-tax-axis-body" }, "Prospect Report"),
|
|
14
15
|
react_1.default.createElement("div", { className: "text-xs text-tax-axis-text-3 font-tax-axis-body mb-3" }, "Top 3 strategies \u00B7 Savings ranges \u00B7 ~2 min \u00B7 No docs"),
|
|
15
16
|
react_1.default.createElement("div", { className: "flex-1" }),
|
|
16
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "orange", onClick: onProspect, className: "w-full text-xs" }, userContext === "cpa-firm-client"
|
|
17
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "orange", onClick: onProspect, className: "w-full text-xs", disabled: disabled }, userContext === "cpa-firm-client"
|
|
17
18
|
? "Generate My Savings Report"
|
|
18
|
-
: "Generate Prospect Report")
|
|
19
|
+
: "Generate Prospect Report"),
|
|
20
|
+
disabled && (react_1.default.createElement("div", { className: "text-[10px] text-tax-axis-text-4 mt-1.5 font-tax-axis-body leading-tight" },
|
|
21
|
+
"Missing: ",
|
|
22
|
+
missingFields.join(", ")))),
|
|
19
23
|
react_1.default.createElement("div", { className: "bg-tax-axis-surface border border-tax-axis-teal rounded-xl p-4 min-h-[140px] flex flex-col transition-all", style: {
|
|
20
24
|
background: "radial-gradient(ellipse at 50% 0%,rgba(36,131,132,0.06) 0%,transparent 70%) #0F1330",
|
|
21
25
|
boxShadow: "0 0 30px rgba(36,131,132,0.15)",
|
|
@@ -24,7 +28,10 @@ function IntakeCtaCards({ onProspect, onFullAnalysis, userContext = "expert", })
|
|
|
24
28
|
react_1.default.createElement("div", { className: "text-[11px] font-bold text-tax-axis-teal uppercase tracking-widest mt-2 mb-2.5 font-tax-axis-body" }, "Full Analysis"),
|
|
25
29
|
react_1.default.createElement("div", { className: "text-xs text-tax-axis-text-3 font-tax-axis-body mb-3" }, "All 25 strategies \u00B7 Real dollar savings \u00B7 ~15 min"),
|
|
26
30
|
react_1.default.createElement("div", { className: "flex-1" }),
|
|
27
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "primary", onClick: onFullAnalysis, className: "w-full text-xs" }, userContext === "cpa-firm-client"
|
|
31
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "primary", onClick: onFullAnalysis, className: "w-full text-xs", disabled: disabled }, userContext === "cpa-firm-client"
|
|
28
32
|
? "Run Full Analysis on My Business"
|
|
29
|
-
: "Start Full Analysis")
|
|
33
|
+
: "Start Full Analysis"),
|
|
34
|
+
disabled && (react_1.default.createElement("div", { className: "text-[10px] text-tax-axis-text-4 mt-1.5 font-tax-axis-body leading-tight" },
|
|
35
|
+
"Missing: ",
|
|
36
|
+
missingFields.join(", "))))));
|
|
30
37
|
}
|
|
@@ -1,18 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
exports.TaxAxisIntake = TaxAxisIntake;
|
|
7
|
-
const react_1 =
|
|
27
|
+
const react_1 = __importStar(require("react"));
|
|
8
28
|
const react_hook_form_1 = require("react-hook-form");
|
|
9
29
|
const yup_1 = require("@hookform/resolvers/yup");
|
|
30
|
+
const compute_1 = require("../../lib/compute");
|
|
10
31
|
const intakeSchema_1 = require("./intakeSchema");
|
|
11
32
|
const ClientParametersSection_1 = require("./ClientParametersSection");
|
|
12
33
|
const RefineAnalysisSection_1 = require("./RefineAnalysisSection");
|
|
13
34
|
const CpaIntakeQuestionsSection_1 = require("./CpaIntakeQuestionsSection");
|
|
14
35
|
const StrategyRadar_1 = require("./StrategyRadar");
|
|
15
36
|
const IntakeCtaCards_1 = require("./IntakeCtaCards");
|
|
37
|
+
/** Returns a list of human-readable labels for missing required fields. */
|
|
38
|
+
function getMissingFields(p) {
|
|
39
|
+
const missing = [];
|
|
40
|
+
if (!p.entity)
|
|
41
|
+
missing.push("Entity Type");
|
|
42
|
+
if (!p.states || p.states.length === 0)
|
|
43
|
+
missing.push("State");
|
|
44
|
+
if (!p.revenue || (0, compute_1.parseNum)(p.revenue) <= 0)
|
|
45
|
+
missing.push("Revenue");
|
|
46
|
+
const fedPct = parseFloat((p.federalRate || "0").replace("%", ""));
|
|
47
|
+
if (!fedPct || fedPct <= 0)
|
|
48
|
+
missing.push("Federal Rate");
|
|
49
|
+
const statePct = parseFloat((p.stateRate || "0").replace("%", ""));
|
|
50
|
+
if (!statePct || statePct <= 0)
|
|
51
|
+
missing.push("State Rate");
|
|
52
|
+
return missing;
|
|
53
|
+
}
|
|
16
54
|
function TaxAxisIntake({ userContext = "expert", onProspect, onFullAnalysis, initialProfile, }) {
|
|
17
55
|
const methods = (0, react_hook_form_1.useForm)({
|
|
18
56
|
resolver: (0, yup_1.yupResolver)(intakeSchema_1.intakeSchema), // yupResolver generic incompatibility with RHF v7 — cast is intentional
|
|
@@ -20,6 +58,7 @@ function TaxAxisIntake({ userContext = "expert", onProspect, onFullAnalysis, ini
|
|
|
20
58
|
mode: "onChange",
|
|
21
59
|
});
|
|
22
60
|
const profile = methods.watch();
|
|
61
|
+
const missingFields = (0, react_1.useMemo)(() => getMissingFields(profile), [profile]);
|
|
23
62
|
const handleProspect = () => {
|
|
24
63
|
methods.handleSubmit((valid) => onProspect(valid), () => { })();
|
|
25
64
|
};
|
|
@@ -32,7 +71,7 @@ function TaxAxisIntake({ userContext = "expert", onProspect, onFullAnalysis, ini
|
|
|
32
71
|
react_1.default.createElement(ClientParametersSection_1.ClientParametersSection, { userContext: userContext }),
|
|
33
72
|
react_1.default.createElement(RefineAnalysisSection_1.RefineAnalysisSection, { userContext: userContext }),
|
|
34
73
|
react_1.default.createElement(CpaIntakeQuestionsSection_1.CpaIntakeQuestionsSection, { userContext: userContext }),
|
|
35
|
-
react_1.default.createElement(IntakeCtaCards_1.IntakeCtaCards, { onProspect: handleProspect, onFullAnalysis: handleFull, userContext: userContext })),
|
|
36
|
-
react_1.default.createElement("div", { className: "sticky top-5 self-start" },
|
|
74
|
+
react_1.default.createElement(IntakeCtaCards_1.IntakeCtaCards, { onProspect: handleProspect, onFullAnalysis: handleFull, userContext: userContext, missingFields: missingFields })),
|
|
75
|
+
react_1.default.createElement("div", { className: "sticky top-5 self-start", style: { minWidth: 0, overflow: 'hidden' } },
|
|
37
76
|
react_1.default.createElement(StrategyRadar_1.StrategyRadar, { profile: profile })))));
|
|
38
77
|
}
|
|
@@ -20,6 +20,7 @@ export declare const intakeSchema: Yup.ObjectSchema<import("yup/lib/object").Ass
|
|
|
20
20
|
equipmentPurchased: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
21
21
|
realEstateValue: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
22
22
|
capitalGains: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
23
|
+
period: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
23
24
|
federalRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
24
25
|
stateRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
25
26
|
taxDataYears: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
@@ -51,6 +52,7 @@ export declare const intakeSchema: Yup.ObjectSchema<import("yup/lib/object").Ass
|
|
|
51
52
|
equipmentPurchased: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
52
53
|
realEstateValue: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
53
54
|
capitalGains: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
55
|
+
period: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
54
56
|
federalRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
55
57
|
stateRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
56
58
|
taxDataYears: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
@@ -82,6 +84,7 @@ export declare const intakeSchema: Yup.ObjectSchema<import("yup/lib/object").Ass
|
|
|
82
84
|
equipmentPurchased: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
83
85
|
realEstateValue: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
84
86
|
capitalGains: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
87
|
+
period: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
85
88
|
federalRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
86
89
|
stateRate: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
87
90
|
taxDataYears: Yup.StringSchema<string, import("yup/lib/types").AnyObject, string>;
|
|
@@ -45,6 +45,7 @@ exports.intakeSchema = Yup.object().shape({
|
|
|
45
45
|
equipmentPurchased: Yup.string().ensure(),
|
|
46
46
|
realEstateValue: Yup.string().ensure(),
|
|
47
47
|
capitalGains: Yup.string().ensure(),
|
|
48
|
+
period: Yup.string().ensure(),
|
|
48
49
|
federalRate: Yup.string().ensure(),
|
|
49
50
|
stateRate: Yup.string().ensure(),
|
|
50
51
|
taxDataYears: Yup.string().ensure(),
|
|
@@ -60,13 +61,13 @@ exports.intakeSchema = Yup.object().shape({
|
|
|
60
61
|
exports.intakeDefaultValues = {
|
|
61
62
|
bizName: "",
|
|
62
63
|
cpaName: "",
|
|
63
|
-
entity: "
|
|
64
|
+
entity: "S-Corporation",
|
|
64
65
|
industry: "Professional Services",
|
|
65
66
|
revenue: "",
|
|
66
67
|
netIncome: "",
|
|
67
68
|
ownerComp: "",
|
|
68
69
|
employees: "",
|
|
69
|
-
year:
|
|
70
|
+
year: String(new Date().getFullYear() - 1),
|
|
70
71
|
states: [],
|
|
71
72
|
filingStatus: "MFJ",
|
|
72
73
|
age: "",
|
|
@@ -77,6 +78,7 @@ exports.intakeDefaultValues = {
|
|
|
77
78
|
equipmentPurchased: "0",
|
|
78
79
|
realEstateValue: "0",
|
|
79
80
|
capitalGains: "0",
|
|
81
|
+
period: "Full Year",
|
|
80
82
|
federalRate: "24%",
|
|
81
83
|
stateRate: "",
|
|
82
84
|
taxDataYears: "1 year",
|
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { ClientProfile
|
|
2
|
+
import type { ClientProfile } from "../../lib/types";
|
|
3
3
|
import type { TaxAxisScreenProps } from "../../lib/types";
|
|
4
4
|
export interface TaxAxisPreparerWorkpaperProps extends TaxAxisScreenProps {
|
|
5
5
|
profile: ClientProfile;
|
|
6
6
|
onBack: () => void;
|
|
7
7
|
onToggleToClient?: () => void;
|
|
8
|
-
/** When provided, bypasses local filterEligibleStrategies + computeAllStrategies. */
|
|
9
|
-
liveStrategies?: Strategy[];
|
|
10
|
-
/** When provided, bypasses local computeAllStrategies. Must accompany liveStrategies. */
|
|
11
|
-
liveComputedMap?: ComputedMap;
|
|
12
|
-
/** Live cpa_workflow from engine output */
|
|
13
|
-
cpaWorkflow?: {
|
|
14
|
-
workpaper_codes?: string[] | null;
|
|
15
|
-
section_6694_notices?: Array<{
|
|
16
|
-
strategy_id: string;
|
|
17
|
-
position_strength: string;
|
|
18
|
-
notice: string;
|
|
19
|
-
}>;
|
|
20
|
-
prior_year_flags?: string[];
|
|
21
|
-
engagement_recommendations?: string[];
|
|
22
|
-
};
|
|
23
|
-
/** Live risk disclosures from engine output */
|
|
24
|
-
riskDisclosures?: string[];
|
|
25
|
-
/** Live business profile from engine output */
|
|
26
|
-
businessProfile?: {
|
|
27
|
-
confidence_tier?: string;
|
|
28
|
-
data_years?: number;
|
|
29
|
-
data_quality_flags?: string[];
|
|
30
|
-
effective_tax_rate?: number;
|
|
31
|
-
};
|
|
32
8
|
}
|
|
33
|
-
export declare function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient
|
|
9
|
+
export declare function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient }: TaxAxisPreparerWorkpaperProps): React.JSX.Element;
|
|
@@ -32,14 +32,12 @@ const ReportToolbar_1 = require("../shared/ReportToolbar");
|
|
|
32
32
|
const EngagementHeader_1 = require("./EngagementHeader");
|
|
33
33
|
const Section6694Summary_1 = require("./Section6694Summary");
|
|
34
34
|
const PriorityGroup_1 = require("./PriorityGroup");
|
|
35
|
-
function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient
|
|
35
|
+
function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient }) {
|
|
36
36
|
const [expanded, setExpanded] = (0, react_1.useState)({});
|
|
37
37
|
const [printMode, setPrintMode] = (0, react_1.useState)(false);
|
|
38
38
|
const toggle = (rank, section) => setExpanded(prev => (Object.assign(Object.assign({}, prev), { [rank + "-" + section]: !prev[rank + "-" + section] })));
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const eligible = liveStrategies !== null && liveStrategies !== void 0 ? liveStrategies : staticEligible;
|
|
42
|
-
const computed = liveComputedMap !== null && liveComputedMap !== void 0 ? liveComputedMap : staticComputed;
|
|
39
|
+
const eligible = (0, react_1.useMemo)(() => (0, compute_1.filterEligibleStrategies)(profile), [profile]);
|
|
40
|
+
const computed = (0, react_1.useMemo)(() => (0, compute_1.computeAllStrategies)(profile), [profile]);
|
|
43
41
|
const states = profile.states || [];
|
|
44
42
|
const bizName = profile.bizName || "Client";
|
|
45
43
|
const rev = parseInt((profile.revenue || "0").replace(/,/g, "")) || 0;
|
|
@@ -113,7 +111,7 @@ function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrat
|
|
|
113
111
|
.flex.flex-col.w-full { margin-top: 0 !important; }
|
|
114
112
|
main.w-full { width: 100% !important; margin-left: 0 !important; padding: 0 !important; }
|
|
115
113
|
* { color-adjust: exact; -webkit-print-color-adjust: exact; }
|
|
116
|
-
p, span, div, td, th, li { color: #212529 !important; }
|
|
114
|
+
body, p, span, div, td, th, li { color: #212529 !important; }
|
|
117
115
|
h1, h2, h3, h4, h5, h6, strong, b { color: #060821 !important; }
|
|
118
116
|
}
|
|
119
117
|
`),
|
|
@@ -168,15 +166,6 @@ function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrat
|
|
|
168
166
|
"$" + interactionAdj.toLocaleString() + " ",
|
|
169
167
|
react_1.default.createElement("span", { style: { fontWeight: 400, fontSize: 10 } }, "(\u221215%)")),
|
|
170
168
|
react_1.default.createElement("td", { colSpan: 2 })))))),
|
|
171
|
-
(cpaWorkflow === null || cpaWorkflow === void 0 ? void 0 : cpaWorkflow.engagement_recommendations) && cpaWorkflow.engagement_recommendations.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24 }) },
|
|
172
|
-
react_1.default.createElement("div", { style: sectionTitle }, "CPA ENGAGEMENT NOTES"),
|
|
173
|
-
cpaWorkflow.engagement_recommendations.map((rec, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 12, color: palette_1.P.gray700, lineHeight: 1.7, fontFamily: palette_1.P.body, padding: '8px 0', borderTop: i > 0 ? '1px solid ' + palette_1.P.gray100 : 'none' } }, rec))))),
|
|
174
|
-
riskDisclosures && riskDisclosures.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24, borderColor: '#FDBA74' }) },
|
|
175
|
-
react_1.default.createElement("div", { style: Object.assign(Object.assign({}, sectionTitle), { color: palette_1.P.orange }) }, "RISK DISCLOSURES"),
|
|
176
|
-
riskDisclosures.map((r, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 11, color: palette_1.P.gray600, lineHeight: 1.65, fontFamily: palette_1.P.body, padding: '6px 0', borderTop: i > 0 ? '1px solid ' + palette_1.P.gray100 : 'none' } }, r))))),
|
|
177
|
-
(businessProfile === null || businessProfile === void 0 ? void 0 : businessProfile.data_quality_flags) && businessProfile.data_quality_flags.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24, borderColor: '#FDBA74' }) },
|
|
178
|
-
react_1.default.createElement("div", { style: Object.assign(Object.assign({}, sectionTitle), { color: palette_1.P.orange }) }, "DATA QUALITY FLAGS"),
|
|
179
|
-
businessProfile.data_quality_flags.map((f, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 11, color: palette_1.P.gray600, padding: '4px 0', fontFamily: palette_1.P.body } }, f))))),
|
|
180
169
|
react_1.default.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 0", borderTop: "1px solid " + palette_1.P.gray200, fontSize: 11, color: palette_1.P.gray500, fontFamily: palette_1.P.body } },
|
|
181
170
|
react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 6 } },
|
|
182
171
|
react_1.default.createElement("div", { style: { width: 16, height: 16, borderRadius: 4, background: palette_1.P.navy, display: "flex", alignItems: "center", justifyContent: "center" } },
|
|
@@ -3,7 +3,5 @@ import { ClientProfile, TaxAxisScreenProps } from "../../lib/types";
|
|
|
3
3
|
export interface TaxAxisProcessingProps extends TaxAxisScreenProps {
|
|
4
4
|
onComplete: () => void;
|
|
5
5
|
profile?: ClientProfile;
|
|
6
|
-
/** Set to true by the shell poller when stage===REPORT_READY is detected. */
|
|
7
|
-
reportReady?: boolean;
|
|
8
6
|
}
|
|
9
|
-
export declare function TaxAxisProcessing({ onComplete, profile,
|
|
7
|
+
export declare function TaxAxisProcessing({ onComplete, profile, userContext: _userContext, }: TaxAxisProcessingProps): React.JSX.Element;
|
|
@@ -26,25 +26,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.TaxAxisProcessing = TaxAxisProcessing;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
28
|
const ProcessingStages_1 = require("./ProcessingStages");
|
|
29
|
-
const CRAWL_CEILING = 99; // pause here until reportReady
|
|
30
|
-
const CRAWL_TICK_MS = 300; // interval between crawl ticks
|
|
31
|
-
const CRAWL_STEP = 0.27; // % added each tick → 0.27 / 0.3s = 0.9%/s
|
|
32
|
-
const FINISH_MS = 400; // ms to animate from 99% → 100% once ready
|
|
33
|
-
const STAGE_ADVANCE_MS = 3200; // how often the displayed stage advances
|
|
34
29
|
function buildStages(profile) {
|
|
35
30
|
var _a;
|
|
36
31
|
if (!profile) {
|
|
37
32
|
return [
|
|
38
33
|
"Parsing source documents",
|
|
39
34
|
"Injecting IRS 2026 parameters",
|
|
40
|
-
"Screening eligible strategies",
|
|
35
|
+
"Screening 25 eligible strategies",
|
|
41
36
|
"Computing deterministic tax math",
|
|
42
37
|
"Generating IRS citations",
|
|
43
38
|
];
|
|
44
39
|
}
|
|
45
|
-
const entity = profile.entity || "your
|
|
40
|
+
const entity = profile.entity || "your";
|
|
46
41
|
const stateCount = ((_a = profile.states) === null || _a === void 0 ? void 0 : _a.length) || 1;
|
|
47
42
|
const bizName = profile.bizName || "your business";
|
|
43
|
+
// Verbatim from mock (App.jsx:1473-1477)
|
|
48
44
|
const base = [
|
|
49
45
|
"Parsing source documents",
|
|
50
46
|
"Injecting IRS 2026 parameters",
|
|
@@ -57,120 +53,53 @@ function buildStages(profile) {
|
|
|
57
53
|
if (entity === "S-Corporation") {
|
|
58
54
|
base.push("Benchmarking officer salary against BLS data");
|
|
59
55
|
}
|
|
60
|
-
base.push("Screening
|
|
56
|
+
base.push("Screening 25 eligible strategies", "Computing deterministic tax math", "Cross-validating source documents", "Generating IRS citations", `Assembling TaxAxis report for ${bizName}`);
|
|
61
57
|
return base;
|
|
62
58
|
}
|
|
63
|
-
function TaxAxisProcessing({ onComplete, profile,
|
|
59
|
+
function TaxAxisProcessing({ onComplete, profile, userContext: _userContext = "expert", }) {
|
|
64
60
|
const stages = (0, react_1.useMemo)(() => buildStages(profile), [profile]);
|
|
65
61
|
const [progress, setProgress] = (0, react_1.useState)(0);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
const progressRef = (0, react_1.useRef)(0);
|
|
72
|
-
// ── Stall detection: show patience message after 35s of no progress change ──
|
|
73
|
-
const [showPatience, setShowPatience] = (0, react_1.useState)(false);
|
|
74
|
-
const lastProgressRef = (0, react_1.useRef)(0);
|
|
75
|
-
const stallTimerRef = (0, react_1.useRef)(null);
|
|
62
|
+
// Staged timer from mock (App.jsx:1481). setInterval advances one stage
|
|
63
|
+
// per tick; after the final stage, a 1000ms delay fires onComplete.
|
|
64
|
+
// Target: ~8s total. Dynamic path: 10 stages × 700ms = 7s + 1s nav = 8s.
|
|
65
|
+
// Fallback path (no profile): 5 stages × 1400ms = 7s + 1s nav = 8s.
|
|
66
|
+
const stageInterval = stages.length <= 5 ? 1400 : 700;
|
|
76
67
|
(0, react_1.useEffect)(() => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (progress !== lastProgressRef.current) {
|
|
82
|
-
lastProgressRef.current = progress;
|
|
83
|
-
setShowPatience(false);
|
|
84
|
-
if (stallTimerRef.current)
|
|
85
|
-
clearTimeout(stallTimerRef.current);
|
|
86
|
-
stallTimerRef.current = setTimeout(() => {
|
|
87
|
-
if (!finishingRef.current)
|
|
88
|
-
setShowPatience(true);
|
|
89
|
-
}, 8000);
|
|
90
|
-
}
|
|
91
|
-
return () => {
|
|
92
|
-
if (stallTimerRef.current)
|
|
93
|
-
clearTimeout(stallTimerRef.current);
|
|
94
|
-
};
|
|
95
|
-
}, [progress]);
|
|
96
|
-
const setProgressSync = (v) => {
|
|
97
|
-
progressRef.current = v;
|
|
98
|
-
setProgress(v);
|
|
99
|
-
};
|
|
100
|
-
// ── Crawl: 0 → 80% — skipped entirely if reportReady already true on mount ──
|
|
101
|
-
(0, react_1.useEffect)(() => {
|
|
102
|
-
if (reportReady || finishingRef.current)
|
|
103
|
-
return;
|
|
68
|
+
let i = 0;
|
|
69
|
+
let navTimer = null;
|
|
104
70
|
const iv = setInterval(() => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
const next = Math.min(progressRef.current + CRAWL_STEP, CRAWL_CEILING);
|
|
110
|
-
setProgressSync(next);
|
|
111
|
-
if (next >= CRAWL_CEILING)
|
|
71
|
+
i++;
|
|
72
|
+
setProgress(i);
|
|
73
|
+
if (i >= stages.length) {
|
|
112
74
|
clearInterval(iv);
|
|
113
|
-
|
|
114
|
-
return () => clearInterval(iv);
|
|
115
|
-
// reportReady intentionally in deps: if it arrives before mount effect runs, skip crawl
|
|
116
|
-
}, [reportReady]);
|
|
117
|
-
// ── Stage labels: advance every STAGE_ADVANCE_MS ─────────────────
|
|
118
|
-
(0, react_1.useEffect)(() => {
|
|
119
|
-
const iv = setInterval(() => {
|
|
120
|
-
setStageIdx((i) => (i + 1 < stages.length ? i + 1 : i));
|
|
121
|
-
}, STAGE_ADVANCE_MS);
|
|
122
|
-
return () => clearInterval(iv);
|
|
123
|
-
}, [stages.length]);
|
|
124
|
-
// ── Finish: reportReady → fast fill to 100%, then onComplete ─────
|
|
125
|
-
(0, react_1.useEffect)(() => {
|
|
126
|
-
if (!reportReady || finishingRef.current || completedRef.current)
|
|
127
|
-
return;
|
|
128
|
-
finishingRef.current = true;
|
|
129
|
-
setStageIdx(stages.length - 1);
|
|
130
|
-
// Read current progress synchronously from ref — not from stale state closure
|
|
131
|
-
const startPct = progressRef.current;
|
|
132
|
-
const startTime = Date.now();
|
|
133
|
-
const frame = () => {
|
|
134
|
-
const elapsed = Date.now() - startTime;
|
|
135
|
-
const t = Math.min(elapsed / FINISH_MS, 1);
|
|
136
|
-
const eased = t < 1 ? t * (2 - t) : 1;
|
|
137
|
-
setProgressSync(startPct + (100 - startPct) * eased);
|
|
138
|
-
if (t < 1) {
|
|
139
|
-
requestAnimationFrame(frame);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
setProgressSync(100);
|
|
143
|
-
if (!completedRef.current) {
|
|
144
|
-
completedRef.current = true;
|
|
145
|
-
setTimeout(onComplete, 150);
|
|
146
|
-
}
|
|
75
|
+
navTimer = setTimeout(onComplete, 1000);
|
|
147
76
|
}
|
|
77
|
+
}, stageInterval);
|
|
78
|
+
return () => {
|
|
79
|
+
clearInterval(iv);
|
|
80
|
+
if (navTimer !== null)
|
|
81
|
+
clearTimeout(navTimer);
|
|
148
82
|
};
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const isFinishing = finishingRef.current;
|
|
83
|
+
}, [stages.length, stageInterval, onComplete]);
|
|
84
|
+
const pct = Math.round((progress / stages.length) * 100);
|
|
85
|
+
const title = (profile === null || profile === void 0 ? void 0 : profile.bizName)
|
|
86
|
+
? `Analyzing ${profile.bizName}`
|
|
87
|
+
: "Running Analysis";
|
|
155
88
|
return (react_1.default.createElement("div", { className: "pt-[60px] text-center" },
|
|
156
89
|
react_1.default.createElement("div", { className: "relative w-[72px] h-[72px] mx-auto mb-7" },
|
|
157
90
|
react_1.default.createElement("div", { className: "absolute inset-0 rounded-full animate-ping", style: {
|
|
158
91
|
background: "radial-gradient(circle, #248384, transparent 70%)",
|
|
159
92
|
opacity: 0.15,
|
|
160
|
-
animationDuration: isFinishing ? "0.4s" : "1.4s",
|
|
161
93
|
} }),
|
|
162
94
|
react_1.default.createElement("div", { className: "absolute inset-0 w-[72px] h-[72px] rounded-full bg-tax-axis-surface flex items-center justify-center", style: { border: "2px solid rgba(36,131,132,0.4)" } },
|
|
163
|
-
react_1.default.createElement("span", { className: "font-bold text-tax-axis-teal-light font-tax-axis-mono"
|
|
95
|
+
react_1.default.createElement("span", { className: "text-[28px] font-bold text-tax-axis-teal-light font-tax-axis-mono" }, pct))),
|
|
164
96
|
react_1.default.createElement("h2", { className: "text-[22px] font-bold text-white font-tax-axis-head mb-1" }, title),
|
|
165
|
-
react_1.default.createElement("p", { className: "text-[13px] text-tax-axis-text-3 font-tax-axis-body mb-7" },
|
|
97
|
+
react_1.default.createElement("p", { className: "text-[13px] text-tax-axis-text-3 font-tax-axis-body mb-7" }, "Deterministic \u00B7 Temperature 0 \u00B7 IRS-cited"),
|
|
166
98
|
react_1.default.createElement("div", { className: "max-w-[360px] mx-auto mb-6 h-0.5 bg-tax-axis-surface-2 rounded-sm overflow-hidden" },
|
|
167
|
-
react_1.default.createElement("div", { className: "h-full rounded-sm", style: {
|
|
168
|
-
width: `${
|
|
99
|
+
react_1.default.createElement("div", { className: "h-full rounded-sm transition-[width] duration-[400ms]", style: {
|
|
100
|
+
width: `${pct}%`,
|
|
169
101
|
background: "linear-gradient(90deg, #248384, #A1E5E6)",
|
|
170
102
|
boxShadow: "0 0 8px #248384",
|
|
171
|
-
transition: isFinishing ? "none" : "width 0.18s linear",
|
|
172
103
|
} })),
|
|
173
|
-
react_1.default.createElement(ProcessingStages_1.ProcessingStages, { stages: stages, progress:
|
|
174
|
-
pct >= CRAWL_CEILING && !isFinishing && (react_1.default.createElement("p", { className: "text-[11px] text-tax-axis-text-4 font-tax-axis-mono mt-4 animate-pulse" }, "Finalizing analysis\u2026")),
|
|
175
|
-
showPatience && !isFinishing && (react_1.default.createElement("p", { className: "text-[13px] text-tax-axis-text-3 font-tax-axis-body mt-4 text-center" }, "Still running \u2014 document analysis typically takes 2\u20133 minutes. Do not navigate away."))));
|
|
104
|
+
react_1.default.createElement(ProcessingStages_1.ProcessingStages, { stages: stages, progress: progress })));
|
|
176
105
|
}
|
|
@@ -16,6 +16,8 @@ function ProspectPrintView({ profile, bizName, displayLo, displayHi, currentTax,
|
|
|
16
16
|
body * { visibility: hidden !important; }
|
|
17
17
|
.prospect-print-root, .prospect-print-root * { visibility: visible !important; }
|
|
18
18
|
.prospect-print-root { position: absolute !important; left: 0 !important; top: 0 !important; width: 100% !important; }
|
|
19
|
+
body, p, span, div, td, th, li { color: #212529 !important; }
|
|
20
|
+
h1, h2, h3, h4, h5, h6, strong, b { color: #060821 !important; }
|
|
19
21
|
.no-print { display: none !important; }
|
|
20
22
|
}
|
|
21
23
|
`),
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Strategy, ClientProfile, ComputedMap } from "../../lib/types";
|
|
3
|
+
interface BackendNarrative {
|
|
4
|
+
whyThisMatters: string;
|
|
5
|
+
howSavingsBreakDown: string;
|
|
6
|
+
whyYouNeedSpecialist: string;
|
|
7
|
+
whatWeDoNext: string;
|
|
8
|
+
}
|
|
3
9
|
interface ProspectStrategyCardProps {
|
|
4
10
|
strategy: Strategy;
|
|
5
11
|
index: number;
|
|
6
12
|
profile: ClientProfile;
|
|
7
13
|
computed: ComputedMap;
|
|
14
|
+
backendNarrative?: BackendNarrative | null;
|
|
8
15
|
}
|
|
9
|
-
export declare function ProspectStrategyCard({ strategy: s, index: i, profile, computed }: ProspectStrategyCardProps): React.JSX.Element;
|
|
16
|
+
export declare function ProspectStrategyCard({ strategy: s, index: i, profile, computed, backendNarrative }: ProspectStrategyCardProps): React.JSX.Element;
|
|
10
17
|
export {};
|