@paro.io/expert-shared-components 1.14.65 → 1.14.67
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/DocumentCenter/MultiFileUploadSection.js +220 -121
- package/lib/components/TaxAxis/TaxAxisApi.d.ts +0 -1
- package/lib/components/TaxAxis/TaxAxisShell.js +5 -80
- package/lib/components/shared/UploadClient.d.ts +2 -1
- package/lib/components/shared/UploadClient.js +6 -2
- package/lib/index.d.ts +1 -13
- package/lib/index.js +1 -27
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +4 -1
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +10 -6
- package/lib/tax-axis/components/clientReport/Methodology.js +2 -2
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.d.ts +6 -1
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.js +26 -24
- package/lib/tax-axis/components/clientReport/StrategyCard.d.ts +1 -1
- package/lib/tax-axis/components/clientReport/StrategyCard.js +39 -23
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +5 -2
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +9 -7
- package/lib/tax-axis/components/dashboard/DashboardActions.js +6 -5
- package/lib/tax-axis/components/dashboard/DashboardSummary.d.ts +6 -1
- package/lib/tax-axis/components/dashboard/DashboardSummary.js +19 -10
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.d.ts +1 -1
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +122 -95
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +58 -4
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +375 -56
- package/lib/tax-axis/components/documents/DocumentCard.d.ts +6 -3
- package/lib/tax-axis/components/documents/DocumentCard.js +72 -15
- package/lib/tax-axis/components/documents/DocumentReviewModal.d.ts +3 -1
- package/lib/tax-axis/components/documents/DocumentReviewModal.js +113 -263
- package/lib/tax-axis/components/documents/DocumentTier.d.ts +5 -4
- package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +28 -8
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +340 -156
- 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/intake/ClientParametersSection.js +14 -30
- package/lib/tax-axis/components/intake/CpaIntakeQuestionsSection.js +3 -3
- package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +1 -2
- package/lib/tax-axis/components/intake/IntakeCtaCards.js +6 -13
- package/lib/tax-axis/components/intake/RefineAnalysisSection.js +7 -7
- package/lib/tax-axis/components/intake/TaxAxisIntake.js +7 -95
- package/lib/tax-axis/components/intake/intakeSchema.d.ts +0 -3
- package/lib/tax-axis/components/intake/intakeSchema.js +2 -4
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +23 -4
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +15 -4
- package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +2 -1
- package/lib/tax-axis/components/processing/TaxAxisProcessing.js +102 -31
- package/lib/tax-axis/components/prospectReport/ProspectPrintView.js +0 -2
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +1 -8
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +5 -5
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +1 -27
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +25 -43
- package/lib/tax-axis/index.d.ts +3 -1
- package/lib/tax-axis/index.js +4 -3
- package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +138 -13
- package/lib/tax-axis/lib/adapters/useEngineOutput.js +156 -7
- package/lib/tax-axis/lib/data/documents.d.ts +3 -2
- package/lib/tax-axis/lib/data/documents.js +225 -25
- package/lib/tax-axis/lib/data/strategies.js +9 -9
- package/lib/tax-axis/lib/documentFieldCatalog.d.ts +7 -12
- package/lib/tax-axis/lib/documentFieldCatalog.js +805 -8
- package/lib/tax-axis/lib/types/index.d.ts +13 -1
- package/package.json +1 -1
- package/lib/README.md +0 -2
- package/lib/package.json +0 -68
|
@@ -20,10 +20,14 @@ class UploadClient {
|
|
|
20
20
|
bucketName: props.bucketName,
|
|
21
21
|
escalationId: props.escalationId,
|
|
22
22
|
taskId: props.taskId,
|
|
23
|
+
keyPrefix: props.keyPrefix,
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
generateS3Key(projectId, escalationId, fileName, taskId) {
|
|
26
|
+
generateS3Key(projectId, escalationId, fileName, taskId, keyPrefix) {
|
|
26
27
|
const sanitizedFileName = fileName.replace(/[^a-zA-Z0-9.-]/g, '_');
|
|
28
|
+
if (!!keyPrefix) {
|
|
29
|
+
return `${keyPrefix.replace(/\/+$/, '')}/${sanitizedFileName}`;
|
|
30
|
+
}
|
|
27
31
|
if (!!taskId) {
|
|
28
32
|
return `project-task-${taskId}/${sanitizedFileName}`;
|
|
29
33
|
}
|
|
@@ -37,7 +41,7 @@ class UploadClient {
|
|
|
37
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
42
|
var _a, _b;
|
|
39
43
|
try {
|
|
40
|
-
const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '');
|
|
44
|
+
const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '', this.state.keyPrefix);
|
|
41
45
|
this.state = Object.assign(Object.assign({}, this.state), { fileName: fileName });
|
|
42
46
|
const params = {
|
|
43
47
|
fileName: this.state.fileName,
|
package/lib/index.d.ts
CHANGED
|
@@ -16,17 +16,5 @@ export { DiscussionSection } from './components/Invoices/DiscussionSection';
|
|
|
16
16
|
export { fileDownloader } from './components/FileDownloader';
|
|
17
17
|
export { Escalations } from './components/Escalations';
|
|
18
18
|
export { ProjectIntelligence } from "./components/ProjectIntelligence";
|
|
19
|
-
export { SectionHeader } from './tax-axis';
|
|
20
|
-
export { TaxAxisBadge } from './tax-axis';
|
|
21
|
-
export { TaxAxisButton } from './tax-axis';
|
|
22
|
-
export { TaxAxisCard } from './tax-axis';
|
|
23
|
-
export { TaxAxisIntake } from './tax-axis';
|
|
24
|
-
export { TaxAxisDocuments } from './tax-axis';
|
|
25
|
-
export { TaxAxisProcessing } from './tax-axis';
|
|
26
|
-
export { TaxAxisDashboard } from './tax-axis';
|
|
27
|
-
export { TaxAxisClientReport } from './tax-axis';
|
|
28
|
-
export { TaxAxisPreparerWorkpaper } from './tax-axis';
|
|
29
|
-
export { TaxAxisExtractionReview } from './tax-axis';
|
|
30
|
-
export { TaxAxisProspectReport } from './tax-axis';
|
|
31
|
-
export { TaxAxisPresentationMode } from './tax-axis';
|
|
32
19
|
export { TaxAxisShell } from './components/TaxAxis';
|
|
20
|
+
export type { TaxAxisApi, TaxAxisSessionInput, TaxAxisUploadInput } from './components/TaxAxis';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TaxAxisShell = exports.
|
|
3
|
+
exports.TaxAxisShell = exports.ProjectIntelligence = exports.Escalations = exports.fileDownloader = exports.DiscussionSection = exports.fileUploader = exports.InvoiceCard = exports.ActiveProjectCard = exports.sharedUtils = exports.ServiceLinesTemplate = exports.HeaderNavBar = exports.DocumentCenter = exports.ProfileCompletedPercentage = exports.ExpertProfileHeader = exports.OrganizationChart = exports.FirmEmployeeSection = exports.ClientReferenceSection = exports.Reviews = exports.ReviewsTab = void 0;
|
|
4
4
|
var ReviewsTab_1 = require("./components/ReviewsTab");
|
|
5
5
|
Object.defineProperty(exports, "ReviewsTab", { enumerable: true, get: function () { return ReviewsTab_1.ReviewsTab; } });
|
|
6
6
|
var Reviews_1 = require("./components/Reviews");
|
|
@@ -37,31 +37,5 @@ var Escalations_1 = require("./components/Escalations");
|
|
|
37
37
|
Object.defineProperty(exports, "Escalations", { enumerable: true, get: function () { return Escalations_1.Escalations; } });
|
|
38
38
|
var ProjectIntelligence_1 = require("./components/ProjectIntelligence");
|
|
39
39
|
Object.defineProperty(exports, "ProjectIntelligence", { enumerable: true, get: function () { return ProjectIntelligence_1.ProjectIntelligence; } });
|
|
40
|
-
var tax_axis_1 = require("./tax-axis");
|
|
41
|
-
Object.defineProperty(exports, "SectionHeader", { enumerable: true, get: function () { return tax_axis_1.SectionHeader; } });
|
|
42
|
-
var tax_axis_2 = require("./tax-axis");
|
|
43
|
-
Object.defineProperty(exports, "TaxAxisBadge", { enumerable: true, get: function () { return tax_axis_2.TaxAxisBadge; } });
|
|
44
|
-
var tax_axis_3 = require("./tax-axis");
|
|
45
|
-
Object.defineProperty(exports, "TaxAxisButton", { enumerable: true, get: function () { return tax_axis_3.TaxAxisButton; } });
|
|
46
|
-
var tax_axis_4 = require("./tax-axis");
|
|
47
|
-
Object.defineProperty(exports, "TaxAxisCard", { enumerable: true, get: function () { return tax_axis_4.TaxAxisCard; } });
|
|
48
|
-
var tax_axis_5 = require("./tax-axis");
|
|
49
|
-
Object.defineProperty(exports, "TaxAxisIntake", { enumerable: true, get: function () { return tax_axis_5.TaxAxisIntake; } });
|
|
50
|
-
var tax_axis_6 = require("./tax-axis");
|
|
51
|
-
Object.defineProperty(exports, "TaxAxisDocuments", { enumerable: true, get: function () { return tax_axis_6.TaxAxisDocuments; } });
|
|
52
|
-
var tax_axis_7 = require("./tax-axis");
|
|
53
|
-
Object.defineProperty(exports, "TaxAxisProcessing", { enumerable: true, get: function () { return tax_axis_7.TaxAxisProcessing; } });
|
|
54
|
-
var tax_axis_8 = require("./tax-axis");
|
|
55
|
-
Object.defineProperty(exports, "TaxAxisDashboard", { enumerable: true, get: function () { return tax_axis_8.TaxAxisDashboard; } });
|
|
56
|
-
var tax_axis_9 = require("./tax-axis");
|
|
57
|
-
Object.defineProperty(exports, "TaxAxisClientReport", { enumerable: true, get: function () { return tax_axis_9.TaxAxisClientReport; } });
|
|
58
|
-
var tax_axis_10 = require("./tax-axis");
|
|
59
|
-
Object.defineProperty(exports, "TaxAxisPreparerWorkpaper", { enumerable: true, get: function () { return tax_axis_10.TaxAxisPreparerWorkpaper; } });
|
|
60
|
-
var tax_axis_11 = require("./tax-axis");
|
|
61
|
-
Object.defineProperty(exports, "TaxAxisExtractionReview", { enumerable: true, get: function () { return tax_axis_11.TaxAxisExtractionReview; } });
|
|
62
|
-
var tax_axis_12 = require("./tax-axis");
|
|
63
|
-
Object.defineProperty(exports, "TaxAxisProspectReport", { enumerable: true, get: function () { return tax_axis_12.TaxAxisProspectReport; } });
|
|
64
|
-
var tax_axis_13 = require("./tax-axis");
|
|
65
|
-
Object.defineProperty(exports, "TaxAxisPresentationMode", { enumerable: true, get: function () { return tax_axis_13.TaxAxisPresentationMode; } });
|
|
66
40
|
var TaxAxis_1 = require("./components/TaxAxis");
|
|
67
41
|
Object.defineProperty(exports, "TaxAxisShell", { enumerable: true, get: function () { return TaxAxis_1.TaxAxisShell; } });
|
|
@@ -10,6 +10,9 @@ interface ExecutiveSummaryProps {
|
|
|
10
10
|
nowCount: number;
|
|
11
11
|
top3: Strategy[];
|
|
12
12
|
palette: Palette;
|
|
13
|
+
effectiveTaxRate?: number;
|
|
14
|
+
confidenceTier?: string;
|
|
15
|
+
dataYears?: number;
|
|
13
16
|
}
|
|
14
|
-
export declare function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCount, top3, palette }: ExecutiveSummaryProps): React.JSX.Element;
|
|
17
|
+
export declare function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCount, top3, palette, effectiveTaxRate, confidenceTier, dataYears }: ExecutiveSummaryProps): React.JSX.Element;
|
|
15
18
|
export {};
|
|
@@ -8,16 +8,17 @@ 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
|
-
function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCount, top3, palette }) {
|
|
11
|
+
function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCount, top3, palette, effectiveTaxRate, confidenceTier, dataYears }) {
|
|
12
12
|
const bizName = profile.bizName || "Client";
|
|
13
13
|
const rev = parseInt((profile.revenue || "0").replace(/,/g, "")) || 500000;
|
|
14
|
+
const dataYearsLabel = dataYears ? `${dataYears} year${dataYears > 1 ? "s" : ""}` : (profile.taxDataYears || "1 year");
|
|
14
15
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
15
16
|
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: [
|
|
16
17
|
eligible.length + " strategies apply to your current profile, with combined estimated savings of $" + totalLo + "K\u2013$" + totalHi + "K annually.",
|
|
17
18
|
nowCount > 0
|
|
18
19
|
? nowCount + " can be initiated this week without any structural changes to your business."
|
|
19
20
|
: "Implementation timeline spans the current tax year with no structural changes required.",
|
|
20
|
-
"Analysis is based on " +
|
|
21
|
+
"Analysis is based on " + dataYearsLabel + " of financial data and current law as of April 2026, including OBBBA provisions.",
|
|
21
22
|
], palette: palette }),
|
|
22
23
|
react_1.default.createElement("div", { style: { marginBottom: 28 } },
|
|
23
24
|
react_1.default.createElement("div", { style: { background: palette.gray50, border: "1px solid " + palette.gray200, borderRadius: 10, padding: "24px 28px", marginBottom: 20 } },
|
|
@@ -46,15 +47,18 @@ function ExecutiveSummary({ profile, eligible, computed, totalLo, totalHi, nowCo
|
|
|
46
47
|
nowCount > 0 ? "Of these and the broader eligible set, " + nowCount + " can be initiated this week with no structural changes to your business." : "",
|
|
47
48
|
" Savings estimates reflect your current revenue of ",
|
|
48
49
|
"$" + Math.round(rev / 1000) + "K",
|
|
49
|
-
",
|
|
50
|
-
parseFloat(profile.federalRate || "24") + parseFloat(profile.stateRate || "4.95"),
|
|
50
|
+
", 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")),
|
|
51
52
|
"%, and ",
|
|
52
|
-
|
|
53
|
+
dataYearsLabel,
|
|
53
54
|
" of financial data."),
|
|
54
55
|
(() => {
|
|
55
56
|
const fedRate = parseFloat(profile.federalRate || "24");
|
|
56
57
|
const stateRate = parseFloat(profile.stateRate || "4.95");
|
|
57
|
-
|
|
58
|
+
// If engine provided effective_tax_rate (as a decimal 0-1), convert to percentage
|
|
59
|
+
const currentRate = effectiveTaxRate != null
|
|
60
|
+
? (effectiveTaxRate <= 1 ? effectiveTaxRate * 100 : effectiveTaxRate)
|
|
61
|
+
: (fedRate + stateRate);
|
|
58
62
|
const net = (0, compute_1.parseNum)(profile.netIncome) || (rev * 0.20);
|
|
59
63
|
const aggregateMidSavings = eligible.reduce((a, s) => {
|
|
60
64
|
var _a, _b;
|
|
@@ -10,13 +10,13 @@ const SectionOpener_1 = require("./SectionOpener");
|
|
|
10
10
|
function Methodology({ profile, eligible, palette }) {
|
|
11
11
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
12
12
|
react_1.default.createElement(SectionOpener_1.SectionOpener, { number: "04", eyebrow: "METHODOLOGY", headline: "How TaxAxis arrives at these numbers.", bullets: [
|
|
13
|
-
"25 federal strategies evaluated against your profile
|
|
13
|
+
"25 federal strategies evaluated against your profile through a two-stage AI and deterministic pipeline \u2014 every recommendation traces to a specific IRC section, revenue ruling, or OBBBA provision.",
|
|
14
14
|
"Confidence bands reflect data quality: \u00B130% on single-year data, narrowing to \u00B115% with multi-year history.",
|
|
15
15
|
"Aggregate savings on the cover chart are adjusted by an interaction-discount factor reflecting strategy stacking, marginal-rate exhaustion, and \u00A76694 reasonableness.",
|
|
16
16
|
], palette: palette }),
|
|
17
17
|
react_1.default.createElement("div", { style: { marginBottom: 28 } },
|
|
18
18
|
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.12em", color: palette.gray400, fontFamily: palette.mono, marginBottom: 8 } }, "EVAL PIPELINE"),
|
|
19
|
-
react_1.default.createElement("div", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.8, fontFamily: palette.body } }, "TaxAxis evaluates 25 federal tax strategies against each client profile.
|
|
19
|
+
react_1.default.createElement("div", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.8, fontFamily: palette.body } }, "TaxAxis evaluates 25 federal tax strategies against each client profile through a two-stage pipeline. An AI model (Claude Sonnet 4.5 via AWS Bedrock) reads your financial documents, identifies applicable strategies, and drafts narrative content. A deterministic post-processing engine then recomputes savings ranges against IRC-cited rules, corrects confidence bands based on data quality, and validates every output through an 8-gate compliance check \u2014 covering schema integrity, strategy coverage, profile consistency, mathematical accuracy, business rules, \u00A76694 compliance, narrative quality, and entity eligibility. Every recommendation is reviewed by a qualified tax professional before the report is issued.")),
|
|
20
20
|
react_1.default.createElement("div", { style: { marginBottom: 28 } },
|
|
21
21
|
react_1.default.createElement("div", { style: { fontSize: 10, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.12em", color: palette.gray400, fontFamily: palette.mono, marginBottom: 8 } }, "CONFIDENCE BANDS"),
|
|
22
22
|
react_1.default.createElement("div", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.8, fontFamily: palette.body, marginBottom: 12 } }, "Savings ranges reflect data quality. Clients who provide multiple years of financial history receive tighter bands of \u00B115%, because multi-year data reveals trends and reduces estimation variance. Single-year data widens the bands to \u00B130%. Within each band, the low estimate uses conservative inputs at the minimum applicable rate, while the high estimate uses full applicable inputs at the client's marginal rate."),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { ClientProfile, Strategy, ComputedMap } from "../../lib/types";
|
|
3
3
|
import type { Palette } from "./palette";
|
|
4
|
+
interface InteractionWarning {
|
|
5
|
+
strategy_pair: [string, string];
|
|
6
|
+
warning_text: string;
|
|
7
|
+
}
|
|
4
8
|
interface RecommendedStrategiesProps {
|
|
5
9
|
profile: ClientProfile;
|
|
6
10
|
eligible: Strategy[];
|
|
@@ -8,6 +12,7 @@ interface RecommendedStrategiesProps {
|
|
|
8
12
|
top3: Strategy[];
|
|
9
13
|
hasOBBBA: boolean;
|
|
10
14
|
palette: Palette;
|
|
15
|
+
interactionWarnings?: InteractionWarning[];
|
|
11
16
|
}
|
|
12
|
-
export declare function RecommendedStrategies({ profile, eligible, computed, top3, hasOBBBA, palette }: RecommendedStrategiesProps): React.JSX.Element;
|
|
17
|
+
export declare function RecommendedStrategies({ profile, eligible, computed, top3, hasOBBBA, palette, interactionWarnings }: RecommendedStrategiesProps): React.JSX.Element;
|
|
13
18
|
export {};
|
|
@@ -5,47 +5,49 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RecommendedStrategies = RecommendedStrategies;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const data_1 = require("../../lib/data");
|
|
9
8
|
const SectionOpener_1 = require("./SectionOpener");
|
|
10
9
|
const SavingsStackChart_1 = require("./SavingsStackChart");
|
|
11
10
|
const StrategyCard_1 = require("./StrategyCard");
|
|
12
|
-
function RecommendedStrategies({ profile, eligible, computed, top3, hasOBBBA, palette }) {
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
11
|
+
function RecommendedStrategies({ profile, eligible, computed, top3, hasOBBBA, palette, interactionWarnings = [] }) {
|
|
12
|
+
// Build a map from strategy code → strategy index in top3 (for interaction display)
|
|
13
|
+
const top3Codes = new Set(top3.map(s => s.code));
|
|
14
|
+
// Interaction warnings that involve at least one top-3 strategy
|
|
15
|
+
const activeWarnings = interactionWarnings.filter((w) => w.strategy_pair.some((id) => top3Codes.has(id)));
|
|
16
|
+
// For each top-3 strategy, find if it participates in any active interaction
|
|
17
|
+
const interactionMap = new Map(); // code → index of the other strategy in top3
|
|
18
|
+
for (const w of activeWarnings) {
|
|
19
|
+
const [a, b] = w.strategy_pair;
|
|
20
|
+
const idxA = top3.findIndex(s => s.code === a);
|
|
21
|
+
const idxB = top3.findIndex(s => s.code === b);
|
|
22
|
+
if (idxA >= 0 && idxB >= 0) {
|
|
23
|
+
interactionMap.set(a, idxB + 1);
|
|
24
|
+
interactionMap.set(b, idxA + 1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
18
27
|
const stSavings = (s) => {
|
|
19
28
|
var _a, _b;
|
|
20
29
|
const c = computed.get(s.rank);
|
|
21
30
|
const lo = Math.round(((_a = c === null || c === void 0 ? void 0 : c.lo) !== null && _a !== void 0 ? _a : s.lo) / 100) * 100;
|
|
22
31
|
const hi = Math.round(((_b = c === null || c === void 0 ? void 0 : c.hi) !== null && _b !== void 0 ? _b : s.hi) / 100) * 100;
|
|
23
|
-
return "$" + (lo / 1000).toFixed(1) + "K
|
|
32
|
+
return "$" + (lo / 1000).toFixed(1) + "K–$" + (hi / 1000).toFixed(1) + "K";
|
|
24
33
|
};
|
|
25
34
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
26
35
|
react_1.default.createElement(SectionOpener_1.SectionOpener, { number: "02", eyebrow: "RECOMMENDED STRATEGIES", headline: "Three priorities to discuss first.", bullets: [
|
|
27
|
-
|
|
28
|
-
"Each strategy
|
|
36
|
+
top3.length + " strategies highlighted below are ranked by combined impact score — weighting dollar value, audit posture, and implementation effort.",
|
|
37
|
+
"Each strategy is anchored to a specific IRC section and explains the math, the audit posture, and the implementation path.",
|
|
29
38
|
hasOBBBA
|
|
30
|
-
? "One or more recommendations rely on OBBBA provisions enacted July 2025 with limited IRS guidance
|
|
39
|
+
? "One or more recommendations rely on OBBBA provisions enacted July 2025 with limited IRS guidance — flagged where applicable."
|
|
31
40
|
: "All recommendations rely on settled IRS guidance, published rulings, or controlling case law.",
|
|
32
41
|
], palette: palette }),
|
|
33
42
|
react_1.default.createElement(SavingsStackChart_1.SavingsStackChart, { eligible: eligible, computed: computed, palette: palette }),
|
|
34
43
|
react_1.default.createElement("div", { style: { marginBottom: 28 } }, top3.map((s, i) => {
|
|
44
|
+
var _a, _b;
|
|
35
45
|
const rank = i + 1;
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
return (react_1.default.createElement(StrategyCard_1.StrategyCard, { key: s.rank, strategy: s, rank: rank, profile: profile, computed: computed, palette: palette, nextStepText:
|
|
46
|
+
const interactsIdx = (_a = interactionMap.get(s.code)) !== null && _a !== void 0 ? _a : 0;
|
|
47
|
+
const interactsWith = interactsIdx > 0 ? (_b = top3[interactsIdx - 1]) === null || _b === void 0 ? void 0 : _b.rank : undefined;
|
|
48
|
+
return (react_1.default.createElement(StrategyCard_1.StrategyCard, { key: s.rank, strategy: s, rank: rank, profile: profile, computed: computed, palette: palette, nextStepText: s.action || "Discuss with your CPA to implement this strategy.", interactsWith: interactsWith, interactsIdx: interactsIdx, stSavings: stSavings(s) }));
|
|
39
49
|
})),
|
|
40
|
-
|
|
50
|
+
activeWarnings.length > 0 && (react_1.default.createElement("div", { style: { background: palette.orangePale, borderLeft: "3px solid " + palette.orange, borderRadius: "0 8px 8px 0", padding: "16px 20px", marginBottom: 24 } },
|
|
41
51
|
react_1.default.createElement("div", { style: { fontSize: 13, fontWeight: 700, color: palette.gray800, fontFamily: palette.head, marginBottom: 6 } }, "Strategy Interactions"),
|
|
42
|
-
|
|
43
|
-
const idxA = top3.findIndex(t => t.rank === a) + 1;
|
|
44
|
-
const idxB = top3.findIndex(t => t.rank === b) + 1;
|
|
45
|
-
return (react_1.default.createElement("p", { key: pi, style: { fontSize: 12, color: palette.gray700, lineHeight: 1.7, fontFamily: palette.body, marginBottom: 4 } }, "Strategies #" + idxA + " and #" + idxB + " affect each other. Your preparer has accounted for this \u2014 the combined savings may be less than the sum of individual estimates."));
|
|
46
|
-
})))));
|
|
47
|
-
}
|
|
48
|
-
// Inline fallback for next-steps text when NARRATIVE_FALLBACK is needed
|
|
49
|
-
function NARRATIVE_FALLBACK_NEXT(s) {
|
|
50
|
-
return "Discuss with your preparer to implement " + s.name + ".";
|
|
52
|
+
activeWarnings.map((w, i) => (react_1.default.createElement("p", { key: i, style: { fontSize: 12, color: palette.gray700, lineHeight: 1.7, fontFamily: palette.body, marginBottom: 4 } }, w.warning_text)))))));
|
|
51
53
|
}
|
|
@@ -12,5 +12,5 @@ interface StrategyCardProps {
|
|
|
12
12
|
interactsIdx: number;
|
|
13
13
|
stSavings: string;
|
|
14
14
|
}
|
|
15
|
-
export declare function StrategyCard({ strategy: s, rank, profile, computed, palette, nextStepText, interactsWith, interactsIdx, stSavings, }: StrategyCardProps): React.JSX.Element;
|
|
15
|
+
export declare function StrategyCard({ strategy: s, rank, profile: _profile, computed, palette, nextStepText, interactsWith, interactsIdx, stSavings, }: StrategyCardProps): React.JSX.Element;
|
|
16
16
|
export {};
|
|
@@ -5,11 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.StrategyCard = StrategyCard;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const data_1 = require("../../lib/data");
|
|
9
8
|
const Sidebar_1 = require("./Sidebar");
|
|
10
|
-
|
|
11
|
-
const FootnoteBlock_1 = require("./FootnoteBlock");
|
|
12
|
-
function StrategyCard({ strategy: s, rank, profile, computed, palette, nextStepText, interactsWith, interactsIdx, stSavings, }) {
|
|
9
|
+
function StrategyCard({ strategy: s, rank, profile: _profile, computed, palette, nextStepText, interactsWith, interactsIdx, stSavings, }) {
|
|
13
10
|
const card = {
|
|
14
11
|
background: palette.white,
|
|
15
12
|
border: "1px solid " + palette.gray200,
|
|
@@ -19,14 +16,13 @@ function StrategyCard({ strategy: s, rank, profile, computed, palette, nextStepT
|
|
|
19
16
|
boxShadow: "0 1px 3px rgba(0,0,0,0.04)",
|
|
20
17
|
};
|
|
21
18
|
const pct = s.score;
|
|
22
|
-
const narr = data_1.STRATEGY_NARRATIVE[s.rank];
|
|
23
19
|
const c = computed.get(s.rank);
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const
|
|
20
|
+
// Live text — client brief is the plain-language "why it applies to you" sentence
|
|
21
|
+
const clientFacingWhy = s.clientBrief || "";
|
|
22
|
+
// Full CPA engagement recommendation covers both why + breakdown
|
|
23
|
+
const cpaEngagement = s.abstract || "";
|
|
24
|
+
// Next step: prefer live engine value, fall back to passed-in prop, then generic
|
|
25
|
+
const nextText = s.action || nextStepText || "Work with your CPA to implement this strategy.";
|
|
30
26
|
return (react_1.default.createElement("div", { className: "strategy-card", style: Object.assign(Object.assign({}, card), { padding: 0, overflow: "hidden", marginBottom: 20 }) },
|
|
31
27
|
react_1.default.createElement("div", { style: { padding: "24px 28px 20px" } },
|
|
32
28
|
react_1.default.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 16 } },
|
|
@@ -34,7 +30,9 @@ function StrategyCard({ strategy: s, rank, profile, computed, palette, nextStepT
|
|
|
34
30
|
react_1.default.createElement("div", { style: { width: 36, height: 36, borderRadius: "50%", background: "linear-gradient(135deg," + palette.teal + ",#1A6B6C)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 15, fontWeight: 700, color: palette.white, fontFamily: palette.body, flexShrink: 0 } }, rank),
|
|
35
31
|
react_1.default.createElement("div", null,
|
|
36
32
|
react_1.default.createElement("div", { style: { fontSize: 18, fontWeight: 700, color: palette.gray900, fontFamily: palette.head } }, s.name),
|
|
37
|
-
react_1.default.createElement("div", { style: { fontSize: 12, color: palette.gray500, fontFamily: palette.mono, marginTop: 3 } },
|
|
33
|
+
react_1.default.createElement("div", { style: { fontSize: 12, color: palette.gray500, fontFamily: palette.mono, marginTop: 3 } },
|
|
34
|
+
s.code + " · " + s.timeline,
|
|
35
|
+
s.quickWin && (react_1.default.createElement("span", { style: { marginLeft: 8, background: palette.tealPale, color: palette.teal, padding: "1px 6px", borderRadius: 4, fontSize: 10, fontWeight: 700 } }, "\u26A1 Quick Win"))))),
|
|
38
36
|
react_1.default.createElement("div", { style: { textAlign: "right", flexShrink: 0 } },
|
|
39
37
|
react_1.default.createElement("div", { style: { fontSize: 20, fontWeight: 800, color: palette.teal, fontFamily: palette.head } }, stSavings),
|
|
40
38
|
react_1.default.createElement("div", { style: { fontSize: 10, color: palette.gray400, fontFamily: palette.body } }, "est. annual savings"))),
|
|
@@ -45,19 +43,37 @@ function StrategyCard({ strategy: s, rank, profile, computed, palette, nextStepT
|
|
|
45
43
|
pct,
|
|
46
44
|
"/100")),
|
|
47
45
|
react_1.default.createElement(Sidebar_1.Sidebar, { ircCode: s.code, palette: palette }),
|
|
48
|
-
react_1.default.createElement("div", { style: { marginBottom: 12 } },
|
|
49
|
-
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.gray400, marginBottom: 8, fontFamily: palette.mono } }, "WHY THIS
|
|
50
|
-
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.75, fontFamily: palette.body } },
|
|
51
|
-
react_1.default.createElement("div", { style: { marginBottom: 12 } },
|
|
52
|
-
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.gray400, marginBottom: 8, fontFamily: palette.mono } }, "
|
|
53
|
-
react_1.default.createElement("
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
clientFacingWhy && (react_1.default.createElement("div", { style: { marginBottom: 12 } },
|
|
47
|
+
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.gray400, marginBottom: 8, fontFamily: palette.mono } }, "WHY THIS APPLIES TO YOU"),
|
|
48
|
+
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.75, fontFamily: palette.body } }, clientFacingWhy))),
|
|
49
|
+
s.sourceDocuments && s.sourceDocuments.length > 0 && (react_1.default.createElement("div", { style: { marginBottom: 12 } },
|
|
50
|
+
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.gray400, marginBottom: 8, fontFamily: palette.mono } }, "DATA USED IN THIS ANALYSIS"),
|
|
51
|
+
react_1.default.createElement("div", { style: { border: "1px solid " + palette.gray200, borderRadius: 8, overflow: "hidden" } }, s.sourceDocuments.map((ref, i) => (react_1.default.createElement("div", { key: i, style: {
|
|
52
|
+
display: "flex",
|
|
53
|
+
justifyContent: "space-between",
|
|
54
|
+
alignItems: "center",
|
|
55
|
+
padding: "8px 14px",
|
|
56
|
+
background: i % 2 === 0 ? palette.gray50 : palette.white,
|
|
57
|
+
borderTop: i > 0 ? "1px solid " + palette.gray100 : "none",
|
|
58
|
+
gap: 12,
|
|
59
|
+
} },
|
|
60
|
+
react_1.default.createElement("div", { style: { flex: 1 } },
|
|
61
|
+
react_1.default.createElement("div", { style: { fontSize: 12, fontWeight: 600, color: palette.gray800, fontFamily: palette.body } }, ref.field_label),
|
|
62
|
+
react_1.default.createElement("div", { style: { fontSize: 10, color: palette.gray400, fontFamily: palette.mono, marginTop: 1 } }, ref.source_hint)),
|
|
63
|
+
react_1.default.createElement("div", { style: { fontSize: 13, fontWeight: 700, color: palette.teal, fontFamily: palette.mono, flexShrink: 0 } }, ref.value_display))))))),
|
|
64
|
+
cpaEngagement && (react_1.default.createElement("div", { style: { marginBottom: 12 } },
|
|
65
|
+
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.gray400, marginBottom: 8, fontFamily: palette.mono } }, "CPA ANALYSIS"),
|
|
66
|
+
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.75, fontFamily: palette.body, whiteSpace: "pre-line" } }, cpaEngagement))),
|
|
67
|
+
s.specialistNote && (react_1.default.createElement("div", { style: { marginBottom: 14, borderLeft: "3px solid " + palette.orange, paddingLeft: 16 } },
|
|
68
|
+
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.orange, marginBottom: 6, fontFamily: palette.mono } }, "WHY YOU NEED A SPECIALIST"),
|
|
69
|
+
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.75, fontFamily: palette.body } }, s.specialistNote))),
|
|
70
|
+
s.authority && (react_1.default.createElement("div", { style: { marginBottom: 14, padding: "6px 10px", background: palette.gray50, borderRadius: 6, fontSize: 11, fontFamily: palette.mono, color: palette.gray500 } },
|
|
71
|
+
"Authority: ",
|
|
72
|
+
s.authority,
|
|
73
|
+
s.forms ? " · Forms: " + s.forms : "")),
|
|
57
74
|
react_1.default.createElement("div", { className: "card-footer" },
|
|
58
75
|
react_1.default.createElement("div", { style: { background: palette.tealPale, borderRadius: 8, padding: "12px 16px" } },
|
|
59
76
|
react_1.default.createElement("div", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em", color: palette.green, marginBottom: 6, fontFamily: palette.mono } }, "WHAT WE'D DO NEXT"),
|
|
60
|
-
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.7, fontFamily: palette.body } },
|
|
61
|
-
react_1.default.createElement(FootnoteBlock_1.FootnoteBlock, { assigned: fnCounter.assigned, palette: palette }))),
|
|
77
|
+
react_1.default.createElement("p", { style: { fontSize: 13, color: palette.gray700, lineHeight: 1.7, fontFamily: palette.body } }, nextText)))),
|
|
62
78
|
interactsWith !== undefined && interactsIdx > 0 && (react_1.default.createElement("div", { style: { padding: "10px 28px", background: palette.orangePale, borderTop: "1px solid rgba(251,154,29,0.2)", fontSize: 12, color: palette.gray700, fontFamily: palette.body } }, "Note: This strategy interacts with Strategy #" + interactsIdx + ". Combined savings may differ from the sum of individual estimates."))));
|
|
63
79
|
}
|
|
@@ -5,8 +5,11 @@ export interface TaxAxisClientReportProps extends TaxAxisScreenProps {
|
|
|
5
5
|
profile: ClientProfile;
|
|
6
6
|
onBack: () => void;
|
|
7
7
|
onNavigatePreparer?: () => void;
|
|
8
|
+
/** When provided, bypasses local filterEligibleStrategies + computeAllStrategies. */
|
|
8
9
|
liveStrategies?: Strategy[];
|
|
10
|
+
/** When provided, bypasses local computeAllStrategies. Must accompany liveStrategies. */
|
|
9
11
|
liveComputedMap?: ComputedMap;
|
|
10
|
-
|
|
12
|
+
/** Live engine output fields — passed through to sub-components */
|
|
13
|
+
engineRawOutput?: Record<string, any>;
|
|
11
14
|
}
|
|
12
|
-
export declare function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }: TaxAxisClientReportProps): React.JSX.Element;
|
|
15
|
+
export declare function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategies, liveComputedMap, engineRawOutput }: TaxAxisClientReportProps): React.JSX.Element;
|
|
@@ -34,11 +34,13 @@ const ExecutiveSummary_1 = require("./ExecutiveSummary");
|
|
|
34
34
|
const RecommendedStrategies_1 = require("./RecommendedStrategies");
|
|
35
35
|
const ImplementationRoadmap_1 = require("./ImplementationRoadmap");
|
|
36
36
|
const Methodology_1 = require("./Methodology");
|
|
37
|
-
function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }) {
|
|
38
|
-
var _a, _b, _c;
|
|
37
|
+
function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategies, liveComputedMap, engineRawOutput }) {
|
|
38
|
+
var _a, _b, _c, _d, _e, _f;
|
|
39
39
|
const [view, setView] = (0, react_1.useState)("client");
|
|
40
|
-
const
|
|
41
|
-
const
|
|
40
|
+
const staticEligible = (0, react_1.useMemo)(() => (0, compute_1.filterEligibleStrategies)(profile), [profile]);
|
|
41
|
+
const staticComputed = (0, react_1.useMemo)(() => (0, compute_1.computeAllStrategies)(profile), [profile]);
|
|
42
|
+
const eligible = liveStrategies !== null && liveStrategies !== void 0 ? liveStrategies : staticEligible;
|
|
43
|
+
const computed = liveComputedMap !== null && liveComputedMap !== void 0 ? liveComputedMap : staticComputed;
|
|
42
44
|
const totalLo = Math.round(eligible.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) / 1000);
|
|
43
45
|
const totalHi = Math.round(eligible.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) / 1000);
|
|
44
46
|
const top3 = [...eligible].sort((a, b) => b.score - a.score).slice(0, 3);
|
|
@@ -100,7 +102,7 @@ function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }) {
|
|
|
100
102
|
.report-meta { break-inside: avoid; page-break-inside: avoid; }
|
|
101
103
|
.toc-page { break-after: page; page-break-after: always; }
|
|
102
104
|
* { color-adjust: exact; -webkit-print-color-adjust: exact; }
|
|
103
|
-
|
|
105
|
+
p, span, div, td, th, li { color: #212529 !important; }
|
|
104
106
|
h1, h2, h3, h4, h5, h6, strong, b { color: #060821 !important; }
|
|
105
107
|
}
|
|
106
108
|
`),
|
|
@@ -108,11 +110,11 @@ function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }) {
|
|
|
108
110
|
react_1.default.createElement("div", { style: { maxWidth: 680, margin: "0 auto", padding: "32px 20px 60px" } },
|
|
109
111
|
react_1.default.createElement(ClientReportCover_1.ClientReportCover, { profile: profile, palette: palette_1.P }),
|
|
110
112
|
react_1.default.createElement(ClientReportTOC_1.ClientReportTOC, { bizName: bizName, palette: palette_1.P }),
|
|
111
|
-
react_1.default.createElement(ExecutiveSummary_1.ExecutiveSummary, { profile: profile, eligible: eligible, computed: computed, totalLo: totalLo, totalHi: totalHi, nowCount: nowCount, top3: top3, palette: palette_1.P }),
|
|
113
|
+
react_1.default.createElement(ExecutiveSummary_1.ExecutiveSummary, { profile: profile, eligible: eligible, computed: computed, totalLo: totalLo, totalHi: totalHi, nowCount: nowCount, top3: top3, palette: palette_1.P, effectiveTaxRate: (_d = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _d === void 0 ? void 0 : _d.effective_tax_rate, confidenceTier: (_e = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _e === void 0 ? void 0 : _e.confidence_tier, dataYears: (_f = engineRawOutput === null || engineRawOutput === void 0 ? void 0 : engineRawOutput.business_profile) === null || _f === void 0 ? void 0 : _f.data_years }),
|
|
112
114
|
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 } },
|
|
113
115
|
"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.",
|
|
114
116
|
hasOBBBA && " Some strategies reference provisions from the One Big Beautiful Bill Act (OBBBA), signed July 4, 2025, with limited IRS guidance."),
|
|
115
|
-
react_1.default.createElement(RecommendedStrategies_1.RecommendedStrategies, { profile: profile, eligible: eligible, computed: computed, top3: top3, hasOBBBA: hasOBBBA, palette: palette_1.P }),
|
|
117
|
+
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 }),
|
|
116
118
|
react_1.default.createElement(ImplementationRoadmap_1.ImplementationRoadmap, { eligible: eligible, computed: computed, top3: top3, nowCount: nowCount, nowMidK: nowMidK, bucketDefs: bucketDefs, bucketTotals: bucketTotals, activeBuckets: activeBuckets, palette: palette_1.P }),
|
|
117
119
|
react_1.default.createElement(Methodology_1.Methodology, { profile: profile, eligible: eligible, palette: palette_1.P }),
|
|
118
120
|
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."),
|
|
@@ -25,7 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.DashboardActions = DashboardActions;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
|
-
const data_1 = require("../../lib/data");
|
|
29
28
|
const compute_1 = require("../../lib/compute");
|
|
30
29
|
const TaxAxisButton_1 = require("../shared/TaxAxisButton");
|
|
31
30
|
function DashboardActions({ profile, dashEligible, computed, onDownloadPreparer, onPresent, onSend, onReset, }) {
|
|
@@ -69,13 +68,15 @@ function DashboardActions({ profile, dashEligible, computed, onDownloadPreparer,
|
|
|
69
68
|
"\u2013",
|
|
70
69
|
(0, compute_1.fmtK)(totalHi),
|
|
71
70
|
"across ",
|
|
72
|
-
|
|
71
|
+
dashEligible.length,
|
|
73
72
|
" strategies \u2014 use this to close the engagement or expand scope."),
|
|
74
|
-
react_1.default.createElement("div", { className: "flex gap-2.5 flex-wrap" },
|
|
75
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick:
|
|
73
|
+
react_1.default.createElement("div", { className: "flex flex-col sm:flex-row gap-2.5 flex-wrap" },
|
|
74
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "orange", onClick: onSend, className: "w-full sm:w-auto" }, "Send Report to Client"),
|
|
75
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onPresent, className: "w-full sm:w-auto" }, "Present to Client"),
|
|
76
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", className: "w-full sm:w-auto" }, "Generate Engagement Letter")))),
|
|
76
77
|
react_1.default.createElement("div", { className: "flex gap-4 mt-4 pt-3.5", style: { borderTop: "1px solid rgba(36,131,132,0.15)" } }, [
|
|
77
78
|
{ v: "3x", l: "Faster than Manual" },
|
|
78
|
-
{ v:
|
|
79
|
+
{ v: String(dashEligible.length), l: "Strategies Found" },
|
|
79
80
|
{ v: "100%", l: "IRS-Cited" },
|
|
80
81
|
{ v: String(stateCount), l: `State${stateCount > 1 ? "s" : ""}` },
|
|
81
82
|
].map(({ v, l }) => (react_1.default.createElement("div", { key: l },
|
|
@@ -6,6 +6,11 @@ interface DashboardSummaryProps {
|
|
|
6
6
|
computed: ComputedMap;
|
|
7
7
|
dataConfirmed: boolean;
|
|
8
8
|
reviewUnreviewed: number;
|
|
9
|
+
liveSavingsMin?: number;
|
|
10
|
+
liveSavingsMax?: number;
|
|
11
|
+
liveStrategyCount?: number;
|
|
12
|
+
confidenceTier?: string;
|
|
13
|
+
dataYears?: number;
|
|
9
14
|
}
|
|
10
|
-
export declare function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, reviewUnreviewed, }: DashboardSummaryProps): React.JSX.Element;
|
|
15
|
+
export declare function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, reviewUnreviewed, liveSavingsMin, liveSavingsMax, liveStrategyCount, confidenceTier, dataYears, }: DashboardSummaryProps): React.JSX.Element;
|
|
11
16
|
export {};
|
|
@@ -6,10 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.DashboardSummary = DashboardSummary;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const useCountUp_1 = require("./useCountUp");
|
|
9
|
-
function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, reviewUnreviewed, }) {
|
|
9
|
+
function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, reviewUnreviewed, liveSavingsMin, liveSavingsMax, liveStrategyCount, confidenceTier, dataYears, }) {
|
|
10
10
|
var _a;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const computedLo = dashEligible.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);
|
|
12
|
+
const computedHi = dashEligible.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);
|
|
13
|
+
const totalLo = liveSavingsMin !== null && liveSavingsMin !== void 0 ? liveSavingsMin : computedLo;
|
|
14
|
+
const totalHi = liveSavingsMax !== null && liveSavingsMax !== void 0 ? liveSavingsMax : computedHi;
|
|
15
|
+
const strategyCount = liveStrategyCount !== null && liveStrategyCount !== void 0 ? liveStrategyCount : dashEligible.length;
|
|
13
16
|
const bizName = profile.bizName || "Client";
|
|
14
17
|
const stateCount = ((_a = profile.states) === null || _a === void 0 ? void 0 : _a.length) || 1;
|
|
15
18
|
const scoreAvg = Math.round(dashEligible.reduce((a, s) => a + s.score, 0) / (dashEligible.length || 1));
|
|
@@ -20,10 +23,9 @@ function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, revi
|
|
|
20
23
|
const fmtHero = (k) => k >= 1000 ? "$" + (k / 1000).toFixed(1) + "M" : "$" + k + "K";
|
|
21
24
|
const riskVal = parseInt(profile.riskTolerance) || 3;
|
|
22
25
|
const riskLabels = ["", "Very Conservative", "Conservative", "Moderate", "Aggressive", "Very Aggressive"];
|
|
23
|
-
return (react_1.default.createElement("div", { className: "relative overflow-hidden rounded-2xl mb-5", style: {
|
|
26
|
+
return (react_1.default.createElement("div", { className: "relative overflow-hidden rounded-2xl mb-5 p-4 sm:p-8", style: {
|
|
24
27
|
background: "radial-gradient(ellipse at 30% 0%, rgba(36,131,132,0.08) 0%, transparent 60%), #0E1132",
|
|
25
28
|
border: "1px solid rgba(36,131,132,0.12)",
|
|
26
|
-
padding: "32px 32px 28px",
|
|
27
29
|
boxShadow: "0 4px 20px rgba(6,8,33,0.3)",
|
|
28
30
|
} },
|
|
29
31
|
react_1.default.createElement("div", { className: "absolute inset-0 opacity-[0.02]", style: {
|
|
@@ -76,16 +78,23 @@ function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, revi
|
|
|
76
78
|
profile.cpaName && (react_1.default.createElement("div", { className: "text-xs text-tax-axis-text-3 mt-1" },
|
|
77
79
|
"Preparer: ",
|
|
78
80
|
profile.cpaName)),
|
|
79
|
-
react_1.default.createElement("div", { className: "flex gap-6 mt-[22px] pt-[18px]", style: { borderTop: "1px solid rgba(36,131,132,0.12)" } }, [
|
|
80
|
-
{ v:
|
|
81
|
-
{ v:
|
|
81
|
+
react_1.default.createElement("div", { className: "grid grid-cols-2 gap-4 sm:flex sm:gap-6 mt-[22px] pt-[18px]", style: { borderTop: "1px solid rgba(36,131,132,0.12)" } }, [
|
|
82
|
+
{ v: confidenceTier ? confidenceTier.replace(/-DATA$/, "").replace(/-/g, " ") : "—", u: "", l: "Confidence Tier", warn: false, ok: !!confidenceTier },
|
|
83
|
+
{ v: String(strategyCount), u: "", l: "Strategies Identified", warn: false, ok: false },
|
|
82
84
|
{
|
|
83
|
-
v: dataConfirmed ? "
|
|
85
|
+
v: dataConfirmed ? "Verified" : String(reviewUnreviewed),
|
|
84
86
|
u: "",
|
|
85
|
-
l:
|
|
87
|
+
l: "Data Quality",
|
|
86
88
|
warn: !dataConfirmed && reviewUnreviewed > 0,
|
|
87
89
|
ok: dataConfirmed,
|
|
88
90
|
},
|
|
91
|
+
...(confidenceTier ? [{
|
|
92
|
+
v: dataYears ? String(dataYears) : "1",
|
|
93
|
+
u: "yr",
|
|
94
|
+
l: confidenceTier.replace(/-DATA$/, "").replace(/-/g, " ").replace(/YR/, "yr"),
|
|
95
|
+
warn: (dataYears !== null && dataYears !== void 0 ? dataYears : 1) < 2,
|
|
96
|
+
ok: (dataYears !== null && dataYears !== void 0 ? dataYears : 1) >= 3,
|
|
97
|
+
}] : []),
|
|
89
98
|
].map(({ v, u, l, warn, ok }) => (react_1.default.createElement("div", { key: l },
|
|
90
99
|
react_1.default.createElement("div", { className: "font-tax-axis-mono font-bold leading-none", style: {
|
|
91
100
|
fontSize: 24,
|
|
@@ -6,5 +6,5 @@ interface StrategyDetailPanelProps {
|
|
|
6
6
|
computed: ComputedMap;
|
|
7
7
|
onClose: () => void;
|
|
8
8
|
}
|
|
9
|
-
export declare function StrategyDetailPanel({ s, profile, computed, onClose }: StrategyDetailPanelProps): React.JSX.Element;
|
|
9
|
+
export declare function StrategyDetailPanel({ s, profile: _profile, computed, onClose }: StrategyDetailPanelProps): React.JSX.Element;
|
|
10
10
|
export {};
|