@paro.io/expert-shared-components 1.14.70 → 1.14.72
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/components/TaxAxis/TaxAxisApi.d.ts +0 -8
- package/lib/components/TaxAxis/TaxAxisShell.js +13 -29
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +4 -2
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +18 -12
- package/lib/tax-axis/components/clientReport/ImplementationRoadmap.d.ts +5 -3
- package/lib/tax-axis/components/clientReport/ImplementationRoadmap.js +12 -9
- package/lib/tax-axis/components/clientReport/ImplementationTimelineChart.d.ts +2 -1
- package/lib/tax-axis/components/clientReport/ImplementationTimelineChart.js +9 -3
- package/lib/tax-axis/components/clientReport/QuarterlyCashChart.d.ts +2 -1
- package/lib/tax-axis/components/clientReport/QuarterlyCashChart.js +9 -3
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +22 -6
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +3 -1
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +5 -2
- package/lib/tax-axis/components/intake/ClientParametersSection.js +14 -4
- package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +2 -8
- package/lib/tax-axis/components/intake/IntakeCtaCards.js +7 -70
- package/lib/tax-axis/components/intake/TaxAxisIntake.js +1 -1
- package/lib/tax-axis/components/intake/intakeSchema.js +1 -1
- package/lib/tax-axis/components/preparerWorkpaper/EngagementHeader.js +6 -2
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +3 -3
- package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +1 -5
- package/lib/tax-axis/components/processing/TaxAxisProcessing.js +11 -27
- package/lib/tax-axis/components/prospectReport/ProspectNextSteps.js +1 -3
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +1 -7
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +6 -8
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +1 -33
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +56 -57
- package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +42 -58
- package/lib/tax-axis/lib/adapters/useEngineOutput.js +136 -36
- package/lib/tax-axis/lib/data/nextSteps.js +13 -13
- package/lib/tax-axis/lib/data/sourceDescriptions.js +6 -0
- package/lib/tax-axis/lib/documentFieldCatalog.d.ts +10 -5
- package/lib/tax-axis/lib/documentFieldCatalog.js +329 -115
- package/lib/tax-axis/lib/types/index.d.ts +2 -0
- package/package.json +1 -1
- package/lib/tax-axis/components/prospectReport/ProspectReportSkeleton.d.ts +0 -2
- package/lib/tax-axis/components/prospectReport/ProspectReportSkeleton.js +0 -78
|
@@ -55,12 +55,4 @@ 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: {
|
|
59
|
-
freelancerId?: number | null;
|
|
60
|
-
clientProfile: Record<string, unknown>;
|
|
61
|
-
}) => Promise<{
|
|
62
|
-
reportId: string;
|
|
63
|
-
computePayload: Record<string, unknown>;
|
|
64
|
-
outputPayload: Record<string, unknown>;
|
|
65
|
-
}>;
|
|
66
58
|
};
|
|
@@ -147,8 +147,6 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
147
147
|
const [busyMessage, setBusyMessage] = (0, react_1.useState)('Syncing Tax Axis session...');
|
|
148
148
|
const [reportReady, setReportReady] = (0, react_1.useState)(false);
|
|
149
149
|
const isPollingRef = react_1.default.useRef(false);
|
|
150
|
-
const [prospectLoading, setProspectLoading] = (0, react_1.useState)(false);
|
|
151
|
-
const [prospectData, setProspectData] = (0, react_1.useState)(null);
|
|
152
150
|
// QBO state driven by EPS props — not localStorage
|
|
153
151
|
const [qboConnectedState, setQboConnectedState] = (0, react_1.useState)(!!qboConnected);
|
|
154
152
|
const [qboCompanyNameState, setQboCompanyNameState] = (0, react_1.useState)(qboCompanyName !== null && qboCompanyName !== void 0 ? qboCompanyName : null);
|
|
@@ -157,8 +155,12 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
157
155
|
react_1.default.useEffect(() => { setQboCompanyNameState(qboCompanyName !== null && qboCompanyName !== void 0 ? qboCompanyName : null); }, [qboCompanyName]);
|
|
158
156
|
// Derive live strategies from engineOutput so CLIENT_REPORT and PREPARER_WORKPAPER
|
|
159
157
|
// render real engine data instead of the static STRATEGIES catalog.
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
// preComputed comes from the formula engine — only strategies with status=COMPLETE
|
|
159
|
+
// should appear in reports. Without preComputed, the hook falls back to
|
|
160
|
+
// _reconciledPreComputed flags on strategy_analysis entries.
|
|
161
|
+
const engineOutput = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.engineOutput) !== null && _a !== void 0 ? _a : llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) !== null && _b !== void 0 ? _b : null; }, [llmResult]);
|
|
162
|
+
const preComputed = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.meta) === null || _a === void 0 ? void 0 : _a.preComputed) !== null && _b !== void 0 ? _b : null; }, [llmResult]);
|
|
163
|
+
const adapted = (0, useEngineOutput_1.useEngineOutput)(engineOutput, preComputed);
|
|
162
164
|
const fetchAndSetParsedDocuments = (0, react_1.useCallback)((sid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
163
165
|
try {
|
|
164
166
|
const docs = yield taxAxisApi.getDocuments(sid);
|
|
@@ -240,30 +242,11 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
240
242
|
setReportReady(false);
|
|
241
243
|
updateSessionId(null);
|
|
242
244
|
}, [updateSessionId]);
|
|
243
|
-
const handleProspect = (
|
|
245
|
+
const handleProspect = (0, react_1.useCallback)((nextProfile) => {
|
|
244
246
|
setProfile(nextProfile);
|
|
245
247
|
setIsProspectFlow(true);
|
|
246
|
-
setProspectData(null);
|
|
247
|
-
setProspectLoading(true);
|
|
248
248
|
setStep('PROSPECT_REPORT');
|
|
249
|
-
|
|
250
|
-
if (taxAxisApi.generateProspectReport) {
|
|
251
|
-
const result = yield taxAxisApi.generateProspectReport({
|
|
252
|
-
clientProfile: nextProfile,
|
|
253
|
-
});
|
|
254
|
-
setProspectData({
|
|
255
|
-
computePayload: result.computePayload,
|
|
256
|
-
outputPayload: result.outputPayload,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
catch (err) {
|
|
261
|
-
console.error('[TaxAxisShell] generateProspectReport failed', err);
|
|
262
|
-
}
|
|
263
|
-
finally {
|
|
264
|
-
setProspectLoading(false);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
249
|
+
}, []);
|
|
267
250
|
const handleFullAnalysis = (0, react_1.useCallback)((nextProfile) => __awaiter(void 0, void 0, void 0, function* () {
|
|
268
251
|
setProfile(nextProfile);
|
|
269
252
|
setIsProspectFlow(false);
|
|
@@ -432,7 +415,7 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
432
415
|
}
|
|
433
416
|
}), [sessionId, taxAxisApi]);
|
|
434
417
|
const currentView = (0, react_1.useMemo)(() => {
|
|
435
|
-
var _a, _b, _c, _d
|
|
418
|
+
var _a, _b, _c, _d;
|
|
436
419
|
if (step === 'SESSION_SETUP') {
|
|
437
420
|
return (react_1.default.createElement(ShellContainer, null,
|
|
438
421
|
react_1.default.createElement(TaxAxisIntake_1.TaxAxisIntake, { userContext: userContext, initialProfile: initialProfile, onProspect: handleProspect, onFullAnalysis: handleFullAnalysis })));
|
|
@@ -443,7 +426,8 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
443
426
|
}
|
|
444
427
|
switch (step) {
|
|
445
428
|
case 'PROSPECT_REPORT':
|
|
446
|
-
return (react_1.default.createElement(ShellContainer, null,
|
|
429
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
430
|
+
react_1.default.createElement(TaxAxisProspectReport_1.TaxAxisProspectReport, { profile: profile, userContext: userContext, onUpgrade: () => setStep('DOCUMENT_UPLOAD'), onPresent: () => setStep('PRESENTATION'), onReset: handleReset })));
|
|
447
431
|
case 'DOCUMENT_UPLOAD':
|
|
448
432
|
return (react_1.default.createElement(ShellContainer, null,
|
|
449
433
|
react_1.default.createElement("div", { className: "flex items-center justify-between rounded-lg px-4 py-3 mb-5", style: {
|
|
@@ -507,10 +491,10 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
507
491
|
react_1.default.createElement(TaxAxisDashboard_1.TaxAxisDashboard, { profile: profile, userContext: userContext, llmResult: llmResult, parsedDocuments: parsedDocuments, onDownloadClient: () => setStep('CLIENT_REPORT'), onDownloadPreparer: () => setStep('PREPARER_WORKPAPER'), onPresent: () => setStep('PRESENTATION'), onSend: handleSendReport, onReviewData: () => setStep('PARSED_REVIEW'), onReset: handleReset })));
|
|
508
492
|
case 'CLIENT_REPORT':
|
|
509
493
|
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
510
|
-
react_1.default.createElement(TaxAxisClientReport_1.TaxAxisClientReport, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onNavigatePreparer: () => setStep('PREPARER_WORKPAPER'), liveStrategies: adapted === null || adapted === void 0 ? void 0 : adapted.strategies, liveComputedMap: adapted === null || adapted === void 0 ? void 0 : adapted.computedMap, engineRawOutput: (
|
|
494
|
+
react_1.default.createElement(TaxAxisClientReport_1.TaxAxisClientReport, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onNavigatePreparer: () => setStep('PREPARER_WORKPAPER'), liveStrategies: adapted === null || adapted === void 0 ? void 0 : adapted.strategies, liveComputedMap: adapted === null || adapted === void 0 ? void 0 : adapted.computedMap, engineRawOutput: (_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) !== null && _a !== void 0 ? _a : llmResult === null || llmResult === void 0 ? void 0 : llmResult.engineOutput })));
|
|
511
495
|
case 'PREPARER_WORKPAPER':
|
|
512
496
|
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
513
|
-
react_1.default.createElement(TaxAxisPreparerWorkpaper_1.TaxAxisPreparerWorkpaper, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onToggleToClient: () => setStep('CLIENT_REPORT'), liveStrategies: adapted === null || adapted === void 0 ? void 0 : adapted.strategies, liveComputedMap: adapted === null || adapted === void 0 ? void 0 : adapted.computedMap, cpaWorkflow: (
|
|
497
|
+
react_1.default.createElement(TaxAxisPreparerWorkpaper_1.TaxAxisPreparerWorkpaper, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onToggleToClient: () => setStep('CLIENT_REPORT'), liveStrategies: adapted === null || adapted === void 0 ? void 0 : adapted.strategies, liveComputedMap: adapted === null || adapted === void 0 ? void 0 : adapted.computedMap, cpaWorkflow: (_b = llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) === null || _b === void 0 ? void 0 : _b.cpa_workflow, riskDisclosures: (_c = llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) === null || _c === void 0 ? void 0 : _c.risk_disclosures, businessProfile: (_d = llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) === null || _d === void 0 ? void 0 : _d.business_profile })));
|
|
514
498
|
case 'PRESENTATION':
|
|
515
499
|
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
516
500
|
react_1.default.createElement(TaxAxisPresentationMode_1.TaxAxisPresentationMode, { profile: profile, userContext: userContext, onBack: () => setStep(isProspectFlow ? 'PROSPECT_REPORT' : 'DASHBOARD') })));
|
|
@@ -7,12 +7,14 @@ interface ExecutiveSummaryProps {
|
|
|
7
7
|
computed: ComputedMap;
|
|
8
8
|
totalLo: number;
|
|
9
9
|
totalHi: number;
|
|
10
|
-
|
|
10
|
+
leadCount: number;
|
|
11
|
+
leadMidK: number;
|
|
12
|
+
leadLabel: string;
|
|
11
13
|
top3: Strategy[];
|
|
12
14
|
palette: Palette;
|
|
13
15
|
effectiveTaxRate?: number;
|
|
14
16
|
confidenceTier?: string;
|
|
15
17
|
dataYears?: number;
|
|
16
18
|
}
|
|
17
|
-
export declare function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi,
|
|
19
|
+
export declare function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, leadCount, leadMidK, leadLabel, top3, palette, effectiveTaxRate, confidenceTier, dataYears }: ExecutiveSummaryProps): React.JSX.Element;
|
|
18
20
|
export {};
|
|
@@ -8,25 +8,29 @@ const react_1 = __importDefault(require("react"));
|
|
|
8
8
|
const compute_1 = require("../../lib/compute");
|
|
9
9
|
const SectionOpener_1 = require("./SectionOpener");
|
|
10
10
|
const ETRChart_1 = require("./ETRChart");
|
|
11
|
-
|
|
11
|
+
// Format K values: >= 1000K -> "$X.XM", otherwise "$XK"
|
|
12
|
+
const fmtKRange = (k) => k >= 1000 ? "$" + (k / 1000).toFixed(1) + "M" : "$" + k + "K";
|
|
13
|
+
function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, leadCount, leadMidK, leadLabel, top3, palette, effectiveTaxRate, confidenceTier, dataYears }) {
|
|
14
|
+
const actionLabel = leadLabel === "this week" ? "Immediate Actions"
|
|
15
|
+
: leadLabel === "within 30 days" ? "30-Day Actions"
|
|
16
|
+
: leadLabel === "within 90 days" ? "90-Day Actions"
|
|
17
|
+
: "Planned Actions";
|
|
12
18
|
const bizName = profile.bizName || "Client";
|
|
13
19
|
const rev = parseInt((profile.revenue || "0").replace(/,/g, "")) || 500000;
|
|
14
20
|
const dataYearsLabel = dataYears ? `${dataYears} year${dataYears > 1 ? "s" : ""}` : (profile.taxDataYears || "1 year");
|
|
15
21
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
16
22
|
react_1.default.createElement(SectionOpener_1.SectionOpener, { number: "01", eyebrow: "EXECUTIVE SUMMARY", headline: "Where " + bizName + "'s tax dollars are going \u2014 and where they don't have to.", bullets: [
|
|
17
|
-
eligible.length + " strategies apply to your current profile, with combined estimated savings of
|
|
18
|
-
|
|
19
|
-
? nowCount + " can be initiated this week without any structural changes to your business."
|
|
20
|
-
: "Implementation timeline spans the current tax year with no structural changes required.",
|
|
23
|
+
eligible.length + " strategies apply to your current profile, with combined estimated savings of " + fmtKRange(totalLo) + "\u2013" + fmtKRange(totalHi) + " annually.",
|
|
24
|
+
leadCount + " " + (leadCount === 1 ? "strategy" : "strategies") + " can be initiated " + leadLabel + ", representing roughly $" + leadMidK + "K of the midpoint savings estimate.",
|
|
21
25
|
"Analysis is based on " + dataYearsLabel + " of financial data and current law as of April 2026, including OBBBA provisions.",
|
|
22
26
|
], palette: palette }),
|
|
23
27
|
react_1.default.createElement("div", { style: { marginBottom: 28 } },
|
|
24
28
|
react_1.default.createElement("div", { style: { background: palette.gray50, border: "1px solid " + palette.gray200, borderRadius: 10, padding: "24px 28px", marginBottom: 20 } },
|
|
25
29
|
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.15em", color: palette.gray400, marginBottom: 16, fontFamily: palette.mono } }, "KEY METRICS"),
|
|
26
30
|
react_1.default.createElement("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr", gap: 16 } }, [
|
|
27
|
-
{ v:
|
|
31
|
+
{ v: fmtKRange(totalLo) + "\u2013" + fmtKRange(totalHi), l: "Est. Annual Savings" },
|
|
28
32
|
{ v: String(eligible.length), l: "Strategies Identified" },
|
|
29
|
-
{ v: String(
|
|
33
|
+
{ v: String(leadCount), l: actionLabel },
|
|
30
34
|
{ v: String(top3.length), l: "Priority Recommendations" },
|
|
31
35
|
].map(({ v, l }) => (react_1.default.createElement("div", { key: l },
|
|
32
36
|
react_1.default.createElement("div", { style: { fontSize: 22, fontWeight: 800, color: palette.teal, fontFamily: palette.head, lineHeight: 1.2, marginBottom: 4 } }, v),
|
|
@@ -39,21 +43,23 @@ function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCo
|
|
|
39
43
|
eligible.length,
|
|
40
44
|
" applicable strategies"),
|
|
41
45
|
" with combined estimated savings of ",
|
|
42
|
-
react_1.default.createElement("strong", { style: { color: palette.teal } },
|
|
46
|
+
react_1.default.createElement("strong", { style: { color: palette.teal } }, fmtKRange(totalLo) + "\u2013" + fmtKRange(totalHi) + " annually"),
|
|
43
47
|
"."),
|
|
44
48
|
react_1.default.createElement("div", { style: { fontSize: 14, color: palette.gray700, lineHeight: 1.8, fontFamily: palette.body, marginBottom: 16 } },
|
|
45
49
|
top3.length,
|
|
46
50
|
" strategies represent the highest-impact opportunities and are detailed below. ",
|
|
47
|
-
|
|
51
|
+
"Of these and the broader eligible set, " + leadCount + " can be initiated " + leadLabel + ".",
|
|
48
52
|
" Savings estimates reflect your current revenue of ",
|
|
49
|
-
"$" + Math.round(rev / 1000) + "K",
|
|
53
|
+
rev >= 1000000 ? "$" + (rev / 1000000).toFixed(1) + "M" : "$" + Math.round(rev / 1000) + "K",
|
|
50
54
|
", an effective tax rate of ",
|
|
51
|
-
effectiveTaxRate != null ? Math.round((effectiveTaxRate <= 1 ? effectiveTaxRate * 100 : effectiveTaxRate) * 10) / 10 : (parseFloat(profile.federalRate || "24") + parseFloat(profile.stateRate || "4.95")),
|
|
55
|
+
effectiveTaxRate != null ? Math.round((effectiveTaxRate <= 1 ? effectiveTaxRate * 100 : effectiveTaxRate) * 10) / 10 : ((profile.entity === "C-Corporation" ? 21 : parseFloat(profile.federalRate || "24")) + parseFloat(profile.stateRate || "4.95")),
|
|
52
56
|
"%, and ",
|
|
53
57
|
dataYearsLabel,
|
|
54
58
|
" of financial data."),
|
|
55
59
|
(() => {
|
|
56
|
-
|
|
60
|
+
// C-Corps have a flat 21% federal rate
|
|
61
|
+
const isCCorp = profile.entity === "C-Corporation";
|
|
62
|
+
const fedRate = isCCorp ? 21 : parseFloat(profile.federalRate || "24");
|
|
57
63
|
const stateRate = parseFloat(profile.stateRate || "4.95");
|
|
58
64
|
// If engine provided effective_tax_rate (as a decimal 0-1), convert to percentage
|
|
59
65
|
const currentRate = effectiveTaxRate != null
|
|
@@ -15,12 +15,14 @@ interface ImplementationRoadmapProps {
|
|
|
15
15
|
eligible: Strategy[];
|
|
16
16
|
computed: ComputedMap;
|
|
17
17
|
top3: Strategy[];
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
leadCount: number;
|
|
19
|
+
leadMidK: number;
|
|
20
|
+
leadLabel: string;
|
|
20
21
|
bucketDefs: BucketDef[];
|
|
21
22
|
bucketTotals: Record<string, BucketTotal>;
|
|
22
23
|
activeBuckets: BucketDef[];
|
|
23
24
|
palette: Palette;
|
|
25
|
+
taxYear?: string;
|
|
24
26
|
}
|
|
25
|
-
export declare function ImplementationRoadmap({ eligible, computed, top3,
|
|
27
|
+
export declare function ImplementationRoadmap({ eligible, computed, top3, leadCount, leadMidK, leadLabel, bucketDefs, bucketTotals, activeBuckets, palette, taxYear, }: ImplementationRoadmapProps): React.JSX.Element;
|
|
26
28
|
export {};
|
|
@@ -9,7 +9,7 @@ const data_1 = require("../../lib/data");
|
|
|
9
9
|
const SectionOpener_1 = require("./SectionOpener");
|
|
10
10
|
const QuarterlyCashChart_1 = require("./QuarterlyCashChart");
|
|
11
11
|
const ImplementationTimelineChart_1 = require("./ImplementationTimelineChart");
|
|
12
|
-
function ImplementationRoadmap({ eligible, computed, top3,
|
|
12
|
+
function ImplementationRoadmap({ eligible, computed, top3, leadCount, leadMidK, leadLabel, bucketDefs, bucketTotals, activeBuckets, palette, taxYear, }) {
|
|
13
13
|
const card = {
|
|
14
14
|
background: palette.white,
|
|
15
15
|
border: "1px solid " + palette.gray200,
|
|
@@ -27,12 +27,12 @@ function ImplementationRoadmap({ eligible, computed, top3, nowCount, nowMidK, bu
|
|
|
27
27
|
};
|
|
28
28
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
29
29
|
react_1.default.createElement(SectionOpener_1.SectionOpener, { number: "03", eyebrow: "IMPLEMENTATION ROADMAP", headline: "Most savings can be locked in within the current quarter.", bullets: [
|
|
30
|
-
|
|
30
|
+
leadCount + " eligible " + (leadCount === 1 ? "strategy" : "strategies") + " can be initiated " + leadLabel + ", representing roughly $" + leadMidK + "K of the midpoint savings estimate.",
|
|
31
31
|
"Time-sensitive elections and filings have firm deadlines noted in each strategy detail above.",
|
|
32
32
|
"Year-end planning items will be reviewed in a coordinated session before December 31.",
|
|
33
33
|
], palette: palette }),
|
|
34
|
-
react_1.default.createElement(QuarterlyCashChart_1.QuarterlyCashChart, { eligible: eligible, computed: computed, palette: palette }),
|
|
35
|
-
react_1.default.createElement(ImplementationTimelineChart_1.ImplementationTimelineChart, { top3: top3, computed: computed, palette: palette }),
|
|
34
|
+
react_1.default.createElement(QuarterlyCashChart_1.QuarterlyCashChart, { eligible: eligible, computed: computed, palette: palette, taxYear: taxYear }),
|
|
35
|
+
react_1.default.createElement(ImplementationTimelineChart_1.ImplementationTimelineChart, { top3: top3, computed: computed, palette: palette, taxYear: taxYear }),
|
|
36
36
|
react_1.default.createElement("div", { style: { marginBottom: 28 } }, activeBuckets.map(b => {
|
|
37
37
|
const bt = bucketTotals[b.key];
|
|
38
38
|
const midK = Math.round((bt.lo + bt.hi) / 2 / 1000);
|
|
@@ -42,10 +42,13 @@ function ImplementationRoadmap({ eligible, computed, top3, nowCount, nowMidK, bu
|
|
|
42
42
|
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: b.color, fontFamily: palette.mono } }, b.label),
|
|
43
43
|
react_1.default.createElement("div", { style: { fontSize: 11, color: palette.gray400, fontFamily: palette.mono } }, bt.strategies.length + " " + (bt.strategies.length === 1 ? "strategy" : "strategies"))),
|
|
44
44
|
react_1.default.createElement("div", { style: { fontSize: 13, fontWeight: 700, color: palette.teal, fontFamily: palette.mono } }, "~$" + midK + "K midpoint")),
|
|
45
|
-
bt.strategies.map(s =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
react_1.default.createElement("div", { style: {
|
|
49
|
-
|
|
45
|
+
bt.strategies.map(s => {
|
|
46
|
+
var _a;
|
|
47
|
+
return (react_1.default.createElement("div", { key: s.rank, style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "10px 0", borderBottom: "1px solid " + palette.gray100 } },
|
|
48
|
+
react_1.default.createElement("div", { style: { flex: 1 } },
|
|
49
|
+
react_1.default.createElement("div", { style: { fontSize: 14, fontWeight: 600, color: palette.gray800, fontFamily: palette.head } }, s.name),
|
|
50
|
+
react_1.default.createElement("div", { style: { fontSize: 12, color: palette.gray500, marginTop: 2, fontFamily: palette.body } }, data_1.NEXT_STEPS[(_a = s.strategyNumber) !== null && _a !== void 0 ? _a : s.rank] || "Discuss with your preparer.")),
|
|
51
|
+
react_1.default.createElement("div", { style: { fontSize: 13, fontWeight: 700, color: palette.teal, fontFamily: palette.mono, flexShrink: 0, marginLeft: 12 } }, stSavings(s))));
|
|
52
|
+
})));
|
|
50
53
|
}))));
|
|
51
54
|
}
|
|
@@ -5,6 +5,7 @@ interface ImplementationTimelineChartProps {
|
|
|
5
5
|
top3: Strategy[];
|
|
6
6
|
computed: ComputedMap;
|
|
7
7
|
palette: Palette;
|
|
8
|
+
taxYear?: string;
|
|
8
9
|
}
|
|
9
|
-
export declare function ImplementationTimelineChart({ top3, computed, palette }: ImplementationTimelineChartProps): React.JSX.Element;
|
|
10
|
+
export declare function ImplementationTimelineChart({ top3, computed, palette, taxYear }: ImplementationTimelineChartProps): React.JSX.Element;
|
|
10
11
|
export {};
|
|
@@ -5,17 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ImplementationTimelineChart = ImplementationTimelineChart;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
function ImplementationTimelineChart({ top3, computed, palette }) {
|
|
8
|
+
function ImplementationTimelineChart({ top3, computed, palette, taxYear }) {
|
|
9
9
|
const W = 640, H = Math.max(180, 60 + top3.length * 44);
|
|
10
10
|
const padL = 180, padR = 80, padT = 44, padB = 24;
|
|
11
11
|
const plotW = W - padL - padR, plotH = H - padT - padB;
|
|
12
12
|
const BUCKET_RANGE = { now: [0, 2], "30d": [0, 4], "90d": [2, 12], filing: [36, 52] };
|
|
13
13
|
const weekScale = (w) => padL + (w / 52) * plotW;
|
|
14
14
|
const qDividers = [13, 26, 39];
|
|
15
|
+
const currentYear = new Date().getFullYear();
|
|
16
|
+
const year = taxYear || String(currentYear);
|
|
17
|
+
const yearNum = parseInt(year, 10);
|
|
18
|
+
const isHistorical = yearNum < currentYear;
|
|
19
|
+
const chartTitle = isHistorical ? "IMPLEMENTATION SEQUENCE" : "IMPLEMENTATION TIMELINE";
|
|
15
20
|
const qLabels = ["Q1", "Q2", "Q3", "Q4"];
|
|
16
21
|
return (react_1.default.createElement("div", { className: "chart-block", style: { background: palette.white, border: "1px solid " + palette.gray200, borderRadius: 10, padding: "24px 28px", marginBottom: 24 } },
|
|
17
22
|
react_1.default.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 18 } },
|
|
18
|
-
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.15em", color: palette.gray400, fontFamily: palette.mono } },
|
|
23
|
+
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.15em", color: palette.gray400, fontFamily: palette.mono } }, chartTitle),
|
|
19
24
|
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, color: palette.teal, fontFamily: palette.mono } }, "top " + top3.length + " priorities")),
|
|
20
25
|
react_1.default.createElement("svg", { viewBox: "0 0 " + W + " " + H, style: { width: "100%", height: "auto", display: "block" } },
|
|
21
26
|
[0, 1, 2, 3].map(qi => {
|
|
@@ -27,7 +32,8 @@ function ImplementationTimelineChart({ top3, computed, palette }) {
|
|
|
27
32
|
const cx = weekScale(qi * 13 + 6.5);
|
|
28
33
|
return react_1.default.createElement("text", { key: q, x: cx, y: padT - 18, fontSize: "10", fontWeight: "700", fill: palette.gray400, fontFamily: palette.mono, textAnchor: "middle" },
|
|
29
34
|
q,
|
|
30
|
-
"
|
|
35
|
+
" ",
|
|
36
|
+
year);
|
|
31
37
|
}),
|
|
32
38
|
qDividers.map(w => (react_1.default.createElement("line", { key: w, x1: weekScale(w), y1: padT - 12, x2: weekScale(w), y2: padT + plotH + 4, stroke: palette.gray200, strokeWidth: "1", strokeDasharray: "2,3" }))),
|
|
33
39
|
top3.map((s, i) => {
|
|
@@ -5,6 +5,7 @@ interface QuarterlyCashChartProps {
|
|
|
5
5
|
eligible: Strategy[];
|
|
6
6
|
computed: ComputedMap;
|
|
7
7
|
palette: Palette;
|
|
8
|
+
taxYear?: string;
|
|
8
9
|
}
|
|
9
|
-
export declare function QuarterlyCashChart({ eligible, computed, palette }: QuarterlyCashChartProps): React.JSX.Element;
|
|
10
|
+
export declare function QuarterlyCashChart({ eligible, computed, palette, taxYear }: QuarterlyCashChartProps): React.JSX.Element;
|
|
10
11
|
export {};
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.QuarterlyCashChart = QuarterlyCashChart;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
function QuarterlyCashChart({ eligible, computed, palette }) {
|
|
8
|
+
function QuarterlyCashChart({ eligible, computed, palette, taxYear }) {
|
|
9
9
|
const W = 600, H = 240;
|
|
10
10
|
const padL = 56, padR = 24, padT = 32, padB = 52;
|
|
11
11
|
const plotW = W - padL - padR, plotH = H - padT - padB;
|
|
@@ -25,8 +25,14 @@ function QuarterlyCashChart({ eligible, computed, palette }) {
|
|
|
25
25
|
const yScale = (v) => padT + plotH - (v / maxVal) * plotH;
|
|
26
26
|
const barW = Math.min(72, (plotW - 60) / 4);
|
|
27
27
|
const slot = plotW / 4;
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const currentYear = new Date().getFullYear();
|
|
29
|
+
const year = taxYear || String(currentYear);
|
|
30
|
+
const yearNum = parseInt(year, 10);
|
|
31
|
+
const isHistorical = yearNum < currentYear;
|
|
32
|
+
const labels = [`Q1 ${year}`, `Q2 ${year}`, `Q3 ${year}`, `Q4 ${year}`];
|
|
33
|
+
const sublabels = isHistorical
|
|
34
|
+
? ["Q1 actions", "Q2 actions", "Q3 actions", "Q4 actions"]
|
|
35
|
+
: ["Now / 30 days", "Within 90 days", "Mid-year", "At filing"];
|
|
30
36
|
const tickStep = maxVal > 200000 ? 100000 : maxVal > 100000 ? 50000 : 25000;
|
|
31
37
|
const yTicks = [];
|
|
32
38
|
for (let v = 0; v <= maxVal * 1.05; v += tickStep)
|
|
@@ -35,7 +35,7 @@ const RecommendedStrategies_1 = require("./RecommendedStrategies");
|
|
|
35
35
|
const ImplementationRoadmap_1 = require("./ImplementationRoadmap");
|
|
36
36
|
const Methodology_1 = require("./Methodology");
|
|
37
37
|
function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategies, liveComputedMap, engineRawOutput }) {
|
|
38
|
-
var _a, _b, _c
|
|
38
|
+
var _a, _b, _c;
|
|
39
39
|
const [view, setView] = (0, react_1.useState)("client");
|
|
40
40
|
const staticEligible = (0, react_1.useMemo)(() => (0, compute_1.filterEligibleStrategies)(profile), [profile]);
|
|
41
41
|
const staticComputed = (0, react_1.useMemo)(() => (0, compute_1.computeAllStrategies)(profile), [profile]);
|
|
@@ -55,14 +55,30 @@ function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategi
|
|
|
55
55
|
];
|
|
56
56
|
const bucketTotals = {};
|
|
57
57
|
bucketDefs.forEach(b => {
|
|
58
|
-
const strategies = eligible.filter(s =>
|
|
58
|
+
const strategies = eligible.filter(s => {
|
|
59
|
+
var _a, _b, _c, _d;
|
|
60
|
+
if (s.timelineBucket !== b.key)
|
|
61
|
+
return false;
|
|
62
|
+
const clo = (_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.lo) !== null && _b !== void 0 ? _b : s.lo;
|
|
63
|
+
const chi = (_d = (_c = computed.get(s.rank)) === null || _c === void 0 ? void 0 : _c.hi) !== null && _d !== void 0 ? _d : s.hi;
|
|
64
|
+
return clo > 0 || chi > 0;
|
|
65
|
+
}).sort((a, c) => c.score - a.score);
|
|
59
66
|
const lo = strategies.reduce((a, s) => { var _a, _b; return a + ((_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.lo) !== null && _b !== void 0 ? _b : s.lo); }, 0);
|
|
60
67
|
const hi = strategies.reduce((a, s) => { var _a, _b; return a + ((_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : s.hi); }, 0);
|
|
61
68
|
bucketTotals[b.key] = { strategies, lo, hi };
|
|
62
69
|
});
|
|
63
70
|
const activeBuckets = bucketDefs.filter(b => bucketTotals[b.key].strategies.length > 0);
|
|
64
|
-
|
|
65
|
-
const
|
|
71
|
+
// Lead bucket: first non-empty bucket for AT A GLANCE summaries
|
|
72
|
+
const leadBucket = activeBuckets[0];
|
|
73
|
+
const leadBt = leadBucket ? bucketTotals[leadBucket.key] : undefined;
|
|
74
|
+
const leadCount = (leadBt === null || leadBt === void 0 ? void 0 : leadBt.strategies.length) || 0;
|
|
75
|
+
const leadMidK = Math.round((((leadBt === null || leadBt === void 0 ? void 0 : leadBt.lo) || 0) + ((leadBt === null || leadBt === void 0 ? void 0 : leadBt.hi) || 0)) / 2 / 1000);
|
|
76
|
+
const leadLabel = leadBucket
|
|
77
|
+
? leadBucket.key === "now" ? "this week"
|
|
78
|
+
: leadBucket.key === "30d" ? "within 30 days"
|
|
79
|
+
: leadBucket.key === "90d" ? "within 90 days"
|
|
80
|
+
: "before year-end"
|
|
81
|
+
: "this quarter";
|
|
66
82
|
const handleToggle = (v) => {
|
|
67
83
|
if (v === "preparer" && onNavigatePreparer) {
|
|
68
84
|
onNavigatePreparer();
|
|
@@ -110,12 +126,12 @@ function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategi
|
|
|
110
126
|
react_1.default.createElement("div", { style: { maxWidth: 680, margin: "0 auto", padding: "32px 20px 60px" } },
|
|
111
127
|
react_1.default.createElement(ClientReportCover_1.ClientReportCover, { profile: profile, palette: palette_1.P }),
|
|
112
128
|
react_1.default.createElement(ClientReportTOC_1.ClientReportTOC, { bizName: bizName, palette: palette_1.P }),
|
|
113
|
-
react_1.default.createElement(ExecutiveSummary_1.ExecutiveSummary, { profile: profile, eligible: eligible, computed: computed, totalLo: totalLo, totalHi: totalHi,
|
|
129
|
+
react_1.default.createElement(ExecutiveSummary_1.ExecutiveSummary, { profile: profile, eligible: eligible, computed: computed, totalLo: totalLo, totalHi: totalHi, leadCount: leadCount, leadMidK: leadMidK, leadLabel: leadLabel, top3: top3, palette: palette_1.P, effectiveTaxRate: (_a = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _a === void 0 ? void 0 : _a.effective_tax_rate, confidenceTier: (_b = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _b === void 0 ? void 0 : _b.confidence_tier, dataYears: (_c = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _c === void 0 ? void 0 : _c.data_years }),
|
|
114
130
|
react_1.default.createElement("div", { style: { background: palette_1.P.gray50, borderLeft: "3px solid " + palette_1.P.gray300, borderRadius: "0 8px 8px 0", padding: "14px 20px", marginBottom: 20, fontSize: 11, color: palette_1.P.gray500, lineHeight: 1.7, fontFamily: palette_1.P.body } },
|
|
115
131
|
"This summary was prepared using TaxAxis, Paro's AI-powered tax analysis engine. Savings estimates are based on financial data provided for tax year " + profile.year + " (" + (profile.taxDataYears || "1 year") + " of data). All figures are estimates. Your tax preparer has reviewed these recommendations.",
|
|
116
132
|
hasOBBBA && " Some strategies reference provisions from the One Big Beautiful Bill Act (OBBBA), signed July 4, 2025, with limited IRS guidance."),
|
|
117
133
|
react_1.default.createElement(RecommendedStrategies_1.RecommendedStrategies, { profile: profile, eligible: eligible, computed: computed, top3: top3, hasOBBBA: hasOBBBA, palette: palette_1.P, interactionWarnings: engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.strategy_interaction_warnings }),
|
|
118
|
-
react_1.default.createElement(ImplementationRoadmap_1.ImplementationRoadmap, { eligible: eligible, computed: computed, top3: top3,
|
|
134
|
+
react_1.default.createElement(ImplementationRoadmap_1.ImplementationRoadmap, { eligible: eligible, computed: computed, top3: top3, leadCount: leadCount, leadMidK: leadMidK, leadLabel: leadLabel, bucketDefs: bucketDefs, bucketTotals: bucketTotals, activeBuckets: activeBuckets, palette: palette_1.P, taxYear: profile.year }),
|
|
119
135
|
react_1.default.createElement(Methodology_1.Methodology, { profile: profile, eligible: eligible, palette: palette_1.P }),
|
|
120
136
|
react_1.default.createElement("div", { style: { padding: "16px 20px", marginBottom: 16, fontSize: 10, color: palette_1.P.gray400, lineHeight: 1.7, fontFamily: palette_1.P.body } }, "This summary was generated by TaxAxis, an AI-powered analysis tool by Paro. Recommendations are based on financial data provided and current tax law as of April 2026, including OBBBA provisions. These are estimates, not guarantees. Consult your tax preparer before implementing any strategy. This is not legal or financial advice."),
|
|
121
137
|
react_1.default.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 0", borderTop: "1px solid " + palette_1.P.gray200, fontSize: 10, color: palette_1.P.gray400, fontFamily: palette_1.P.mono } },
|
|
@@ -11,7 +11,9 @@ function Sec({ title, children, titleColor }) {
|
|
|
11
11
|
react_1.default.createElement("div", { className: "text-[11px] font-bold uppercase tracking-widest mb-2.5 font-tax-axis-mono", style: { color: titleColor || "#A1E5E6" } }, title),
|
|
12
12
|
children));
|
|
13
13
|
}
|
|
14
|
-
const fmtK = (n) =>
|
|
14
|
+
const fmtK = (n) => n >= 1000000
|
|
15
|
+
? `$${(n / 1000000).toFixed(1)}M`
|
|
16
|
+
: `$${(n / 1000).toFixed(n % 1000 ? 1 : 0)}K`;
|
|
15
17
|
function positionStrengthLabel(positionStrength) {
|
|
16
18
|
if (!positionStrength)
|
|
17
19
|
return { label: "Position Under Review", color: "#9498B8", dots: 2 };
|
|
@@ -235,7 +235,9 @@ function buildLlmComputed(strategies) {
|
|
|
235
235
|
return map;
|
|
236
236
|
}
|
|
237
237
|
// ─── Formatting helper ──────────────────────────────────────────
|
|
238
|
-
const fmtK = (n) =>
|
|
238
|
+
const fmtK = (n) => n >= 1000000
|
|
239
|
+
? `$${(n / 1000000).toFixed(1)}M`
|
|
240
|
+
: `$${(n / 1000).toFixed(n % 1000 ? 1 : 0)}K`;
|
|
239
241
|
// ─── Timeline buckets for Client Summary ────────────────────────
|
|
240
242
|
const BUCKETS = [
|
|
241
243
|
{ key: "now", label: "Act Now", desc: "Claim on your return or adjust this pay period" },
|
|
@@ -264,7 +266,8 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
264
266
|
// clientBrief from why_it_applies, etc.) over the thin mapLlmToStrategies fallback.
|
|
265
267
|
// engineOutput is at llmResult.engineOutput or llmResult.rawOutput (both present).
|
|
266
268
|
const engineOutputForAdapter = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.engineOutput) !== null && _a !== void 0 ? _a : llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) !== null && _b !== void 0 ? _b : null; }, [llmResult]);
|
|
267
|
-
const
|
|
269
|
+
const preComputedForAdapter = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.meta) === null || _a === void 0 ? void 0 : _a.preComputed) !== null && _b !== void 0 ? _b : null; }, [llmResult]);
|
|
270
|
+
const adapted = (0, useEngineOutput_1.useEngineOutput)(engineOutputForAdapter, preComputedForAdapter);
|
|
268
271
|
const llmStrategies = (0, react_1.useMemo)(() => {
|
|
269
272
|
var _a;
|
|
270
273
|
if (!hasLlm)
|
|
@@ -66,10 +66,20 @@ const INDUSTRY_OPTIONS = [
|
|
|
66
66
|
"Real Estate",
|
|
67
67
|
"Other",
|
|
68
68
|
];
|
|
69
|
-
const
|
|
70
|
-
const YEAR_OPTIONS = ["2024", "2025", "2026"];
|
|
69
|
+
const CURRENT_YEAR = new Date().getFullYear();
|
|
70
|
+
const YEAR_OPTIONS = ["2023", "2024", "2025", "2026"];
|
|
71
71
|
function ClientParametersSection({ userContext = "expert", }) {
|
|
72
|
-
const { control, formState: { errors }, } = (0, react_hook_form_1.useFormContext)();
|
|
72
|
+
const { control, formState: { errors }, watch, setValue, } = (0, react_hook_form_1.useFormContext)();
|
|
73
|
+
const selectedYear = watch("year");
|
|
74
|
+
const yearNum = parseInt(selectedYear || "2026", 10);
|
|
75
|
+
const isCurrentOrFuture = yearNum >= CURRENT_YEAR;
|
|
76
|
+
const periodOptions = isCurrentOrFuture ? ["YTD"] : ["Full Year", "YTD"];
|
|
77
|
+
// Auto-switch period to "YTD" when user selects a current/future tax year
|
|
78
|
+
react_1.default.useEffect(() => {
|
|
79
|
+
if (isCurrentOrFuture) {
|
|
80
|
+
setValue("period", "YTD");
|
|
81
|
+
}
|
|
82
|
+
}, [isCurrentOrFuture, setValue]);
|
|
73
83
|
const [expanded, setExpanded] = (0, react_1.useState)(true);
|
|
74
84
|
return (react_1.default.createElement(TaxAxisCard_1.TaxAxisCard, null,
|
|
75
85
|
react_1.default.createElement("div", { onClick: () => setExpanded((prev) => !prev), className: "flex items-center justify-between cursor-pointer", style: { marginBottom: expanded ? 14 : 0 } },
|
|
@@ -103,7 +113,7 @@ function ClientParametersSection({ userContext = "expert", }) {
|
|
|
103
113
|
react_1.default.createElement(react_hook_form_1.Controller, { name: "period", control: control, render: ({ field }) => {
|
|
104
114
|
var _a;
|
|
105
115
|
return (react_1.default.createElement("div", { className: "relative" },
|
|
106
|
-
react_1.default.createElement("select", Object.assign({}, field, { value: (_a = field.value) !== null && _a !== void 0 ? _a : "Full Year", className: selectCls }),
|
|
116
|
+
react_1.default.createElement("select", Object.assign({}, field, { value: (_a = field.value) !== null && _a !== void 0 ? _a : (isCurrentOrFuture ? "YTD" : "Full Year"), className: selectCls }), periodOptions.map(o => (react_1.default.createElement("option", { key: o, value: o, className: "bg-tax-axis-surface-2" }, o)))),
|
|
107
117
|
react_1.default.createElement(Chevron, null)));
|
|
108
118
|
} })),
|
|
109
119
|
react_1.default.createElement("div", null,
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
interface ProspectReadiness {
|
|
4
|
-
ready: boolean;
|
|
5
|
-
missingFields: string[];
|
|
6
|
-
}
|
|
7
|
-
export declare function isProspectReady(profile: Partial<ClientProfile>): ProspectReadiness;
|
|
2
|
+
import { UserContext } from "../../lib/types";
|
|
8
3
|
interface IntakeCtaCardsProps {
|
|
9
|
-
profile: Partial<ClientProfile>;
|
|
10
4
|
onProspect: () => void;
|
|
11
5
|
onFullAnalysis: () => void;
|
|
12
6
|
userContext?: UserContext;
|
|
13
7
|
}
|
|
14
|
-
export declare function IntakeCtaCards({
|
|
8
|
+
export declare function IntakeCtaCards({ onProspect, onFullAnalysis, userContext, }: IntakeCtaCardsProps): React.JSX.Element;
|
|
15
9
|
export {};
|
|
@@ -1,84 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
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;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
4
|
};
|
|
25
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.isProspectReady = isProspectReady;
|
|
27
6
|
exports.IntakeCtaCards = IntakeCtaCards;
|
|
28
|
-
const react_1 =
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
29
8
|
const TaxAxisButton_1 = require("../shared/TaxAxisButton");
|
|
30
9
|
const TaxAxisBadge_1 = require("../shared/TaxAxisBadge");
|
|
31
|
-
function
|
|
32
|
-
const missing = [];
|
|
33
|
-
if (!profile.entity)
|
|
34
|
-
missing.push("Entity Type");
|
|
35
|
-
if (!profile.states || profile.states.length === 0)
|
|
36
|
-
missing.push("States of Operation");
|
|
37
|
-
if (!profile.federalRate)
|
|
38
|
-
missing.push("Federal Marginal Rate");
|
|
39
|
-
if (!profile.stateRate)
|
|
40
|
-
missing.push("State Marginal Rate");
|
|
41
|
-
if (!profile.taxDataYears)
|
|
42
|
-
missing.push("Tax Data Years Available");
|
|
43
|
-
if (!profile.riskTolerance)
|
|
44
|
-
missing.push("Client Risk Tolerance");
|
|
45
|
-
const hasFinancial = parseFloat(profile.netIncome || "0") > 0 ||
|
|
46
|
-
parseFloat(profile.equipmentPurchased || "0") > 0 ||
|
|
47
|
-
parseFloat(profile.capitalGains || "0") > 0 ||
|
|
48
|
-
parseFloat(profile.revenue || "0") > 0;
|
|
49
|
-
if (!hasFinancial)
|
|
50
|
-
missing.push("Annual Revenue or Net Income (at least one > 0)");
|
|
51
|
-
return { ready: missing.length === 0, missingFields: missing };
|
|
52
|
-
}
|
|
53
|
-
function IntakeCtaCards({ profile, onProspect, onFullAnalysis, userContext = "expert", }) {
|
|
54
|
-
const [showTooltip, setShowTooltip] = (0, react_1.useState)(false);
|
|
55
|
-
const { ready, missingFields } = isProspectReady(profile);
|
|
10
|
+
function IntakeCtaCards({ onProspect, onFullAnalysis, userContext = "expert", }) {
|
|
56
11
|
return (react_1.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3" },
|
|
57
12
|
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" },
|
|
58
13
|
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"),
|
|
59
14
|
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"),
|
|
60
15
|
react_1.default.createElement("div", { className: "flex-1" }),
|
|
61
|
-
react_1.default.createElement(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
: "Generate Prospect Report"),
|
|
65
|
-
!ready && showTooltip && (react_1.default.createElement("div", { style: {
|
|
66
|
-
position: "absolute",
|
|
67
|
-
bottom: "calc(100% + 8px)",
|
|
68
|
-
left: 0,
|
|
69
|
-
right: 0,
|
|
70
|
-
background: "#1a1f3d",
|
|
71
|
-
border: "1px solid #2a2f5d",
|
|
72
|
-
borderRadius: 8,
|
|
73
|
-
padding: "10px 12px",
|
|
74
|
-
zIndex: 50,
|
|
75
|
-
boxShadow: "0 4px 24px rgba(0,0,0,0.5)",
|
|
76
|
-
} },
|
|
77
|
-
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, color: "#f97316", marginBottom: 6, textTransform: "uppercase", letterSpacing: "0.1em" } }, "Required to generate:"),
|
|
78
|
-
missingFields.map((f) => (react_1.default.createElement("div", { key: f, style: { fontSize: 11, color: "#94a3b8", marginBottom: 2, display: "flex", alignItems: "center", gap: 6 } },
|
|
79
|
-
react_1.default.createElement("span", { style: { color: "#f97316", fontSize: 9 } }, "\u25CF"),
|
|
80
|
-
" ",
|
|
81
|
-
f))))))),
|
|
16
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "orange", onClick: onProspect, className: "w-full text-xs" }, userContext === "cpa-firm-client"
|
|
17
|
+
? "Generate My Savings Report"
|
|
18
|
+
: "Generate Prospect Report")),
|
|
82
19
|
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: {
|
|
83
20
|
background: "radial-gradient(ellipse at 50% 0%,rgba(36,131,132,0.06) 0%,transparent 70%) #0F1330",
|
|
84
21
|
boxShadow: "0 0 30px rgba(36,131,132,0.15)",
|
|
@@ -32,7 +32,7 @@ function TaxAxisIntake({ userContext = "expert", onProspect, onFullAnalysis, ini
|
|
|
32
32
|
react_1.default.createElement(ClientParametersSection_1.ClientParametersSection, { userContext: userContext }),
|
|
33
33
|
react_1.default.createElement(RefineAnalysisSection_1.RefineAnalysisSection, { userContext: userContext }),
|
|
34
34
|
react_1.default.createElement(CpaIntakeQuestionsSection_1.CpaIntakeQuestionsSection, { userContext: userContext }),
|
|
35
|
-
react_1.default.createElement(IntakeCtaCards_1.IntakeCtaCards, {
|
|
35
|
+
react_1.default.createElement(IntakeCtaCards_1.IntakeCtaCards, { onProspect: handleProspect, onFullAnalysis: handleFull, userContext: userContext })),
|
|
36
36
|
react_1.default.createElement("div", { className: "hidden sm:block sm:sticky sm:top-5 sm:self-start" },
|
|
37
37
|
react_1.default.createElement(StrategyRadar_1.StrategyRadar, { profile: profile })))));
|
|
38
38
|
}
|