@paro.io/expert-shared-components 1.14.57 → 1.14.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/README.md +2 -0
- package/lib/components/DocumentCenter/MultiFileUploadSection.js +121 -220
- package/lib/components/TaxAxis/TaxAxisApi.d.ts +2 -0
- package/lib/components/TaxAxis/TaxAxisShell.d.ts +1 -1
- package/lib/components/TaxAxis/TaxAxisShell.js +104 -5
- package/lib/components/TaxAxis/types.d.ts +5 -0
- package/lib/components/shared/UploadClient.d.ts +1 -2
- package/lib/components/shared/UploadClient.js +2 -6
- package/lib/index.d.ts +13 -2
- package/lib/index.js +27 -3
- package/lib/package.json +68 -0
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +1 -4
- package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +6 -10
- package/lib/tax-axis/components/clientReport/Methodology.js +2 -2
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.d.ts +1 -6
- package/lib/tax-axis/components/clientReport/RecommendedStrategies.js +24 -26
- package/lib/tax-axis/components/clientReport/StrategyCard.d.ts +1 -1
- package/lib/tax-axis/components/clientReport/StrategyCard.js +23 -39
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +2 -8
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +7 -9
- package/lib/tax-axis/components/dashboard/DashboardActions.js +4 -5
- package/lib/tax-axis/components/dashboard/DashboardSummary.d.ts +1 -6
- package/lib/tax-axis/components/dashboard/DashboardSummary.js +4 -14
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.d.ts +1 -1
- package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +91 -120
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +2 -59
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +36 -412
- package/lib/tax-axis/components/documents/DocumentCard.d.ts +3 -7
- package/lib/tax-axis/components/documents/DocumentCard.js +12 -65
- package/lib/tax-axis/components/documents/DocumentTier.d.ts +2 -5
- package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +1 -25
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +52 -267
- package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.d.ts +13 -0
- package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.js +180 -0
- package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.d.ts +10 -0
- package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.js +155 -0
- package/lib/tax-axis/components/documents/qbo/QboConnectBanner.d.ts +9 -0
- package/lib/tax-axis/components/documents/qbo/QboConnectBanner.js +55 -0
- package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.d.ts +10 -0
- package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.js +202 -0
- package/lib/tax-axis/components/documents/qbo/QboImportingModal.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/QboImportingModal.js +75 -0
- package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.js +126 -0
- package/lib/tax-axis/components/documents/qbo/index.d.ts +8 -0
- package/lib/tax-axis/components/documents/qbo/index.js +17 -0
- package/lib/tax-axis/components/documents/qbo/qboConstants.d.ts +24 -0
- package/lib/tax-axis/components/documents/qbo/qboConstants.js +71 -0
- package/lib/tax-axis/components/documents/qbo/types.d.ts +43 -0
- package/lib/tax-axis/components/documents/qbo/types.js +3 -0
- package/lib/tax-axis/components/documents/qbo/useQboFlow.d.ts +19 -0
- package/lib/tax-axis/components/documents/qbo/useQboFlow.js +207 -0
- package/lib/tax-axis/components/extractionReview/TaxAxisExtractionReview.js +17 -17
- package/lib/tax-axis/components/intake/ClientParametersSection.js +29 -13
- package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +2 -1
- package/lib/tax-axis/components/intake/IntakeCtaCards.js +13 -6
- package/lib/tax-axis/components/intake/TaxAxisIntake.js +44 -5
- package/lib/tax-axis/components/intake/intakeSchema.d.ts +3 -0
- package/lib/tax-axis/components/intake/intakeSchema.js +4 -2
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +2 -26
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +4 -15
- package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +1 -3
- package/lib/tax-axis/components/processing/TaxAxisProcessing.js +31 -102
- package/lib/tax-axis/components/prospectReport/ProspectPrintView.js +2 -0
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +8 -1
- package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +5 -5
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +27 -1
- package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +43 -25
- package/lib/tax-axis/index.d.ts +0 -4
- package/lib/tax-axis/index.js +1 -6
- package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +13 -138
- package/lib/tax-axis/lib/adapters/useEngineOutput.js +7 -156
- package/lib/tax-axis/lib/data/documents.d.ts +2 -3
- package/lib/tax-axis/lib/data/documents.js +25 -225
- package/lib/tax-axis/lib/data/strategies.js +9 -9
- package/lib/tax-axis/lib/documentFieldCatalog.d.ts +12 -7
- package/lib/tax-axis/lib/documentFieldCatalog.js +8 -805
- package/lib/tax-axis/lib/types/index.d.ts +1 -13
- package/package.json +1 -1
|
@@ -26,9 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.TaxAxisDashboard = TaxAxisDashboard;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
28
|
const data_1 = require("../../lib/data");
|
|
29
|
-
const strategyNarrative_1 = require("../../lib/data/strategyNarrative");
|
|
30
29
|
const compute_1 = require("../../lib/compute");
|
|
31
|
-
const useEngineOutput_1 = require("../../lib/adapters/useEngineOutput");
|
|
32
30
|
const TaxAxisButton_1 = require("../shared/TaxAxisButton");
|
|
33
31
|
const TaxAxisBadge_1 = require("../shared/TaxAxisBadge");
|
|
34
32
|
const DashboardSummary_1 = require("./DashboardSummary");
|
|
@@ -36,205 +34,6 @@ const DashboardTopBar_1 = require("./DashboardTopBar");
|
|
|
36
34
|
const DashboardActions_1 = require("./DashboardActions");
|
|
37
35
|
const StrategyTile_1 = require("./StrategyTile");
|
|
38
36
|
const StrategyDetailPanel_1 = require("./StrategyDetailPanel");
|
|
39
|
-
const STRATEGY_TYPE_LABELS = {
|
|
40
|
-
ENTITY_RESTRUCTURING: "Entity Restructuring",
|
|
41
|
-
QBI_199A_OPTIMIZATION: "QBI §199A Optimization",
|
|
42
|
-
DOCUMENTATION_GAP_REMEDIATION: "Documentation Gap Remediation",
|
|
43
|
-
RETIREMENT_PLAN: "Retirement Plan Optimization",
|
|
44
|
-
DEPRECIATION_ACCELERATION: "Depreciation Acceleration",
|
|
45
|
-
COST_SEGREGATION: "Cost Segregation",
|
|
46
|
-
RD_CREDIT: "R&D Tax Credit",
|
|
47
|
-
HSA_MAXIMIZATION: "HSA Maximization",
|
|
48
|
-
SALT_PTE: "SALT / PTE Optimization",
|
|
49
|
-
WOTC: "Work Opportunity Tax Credit",
|
|
50
|
-
INCOME_DEFERRAL: "Income Deferral",
|
|
51
|
-
CHARITABLE_GIVING: "Charitable Giving Strategy",
|
|
52
|
-
FAMILY_EMPLOYMENT: "Family Employment",
|
|
53
|
-
MEALS_DEDUCTIONS: "Business Meals Deduction",
|
|
54
|
-
OPPORTUNITY_ZONE: "Opportunity Zone Investment",
|
|
55
|
-
ACCOUNTING_METHOD: "Accounting Method Change",
|
|
56
|
-
BONUS_DEPRECIATION: "Bonus Depreciation §168(k)",
|
|
57
|
-
SECTION_179: "Section 179 Expensing",
|
|
58
|
-
};
|
|
59
|
-
function humanizeStrategyType(raw) {
|
|
60
|
-
if (STRATEGY_TYPE_LABELS[raw])
|
|
61
|
-
return STRATEGY_TYPE_LABELS[raw];
|
|
62
|
-
return raw
|
|
63
|
-
.replace(/_/g, " ")
|
|
64
|
-
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
65
|
-
}
|
|
66
|
-
// Build a lookup from strategy_id → strategy_name using engineOutput.strategy_analysis
|
|
67
|
-
function buildEngineNameLookup(llm) {
|
|
68
|
-
var _a;
|
|
69
|
-
const map = new Map();
|
|
70
|
-
const analysis = (_a = llm.engineOutput) === null || _a === void 0 ? void 0 : _a.strategy_analysis;
|
|
71
|
-
if (Array.isArray(analysis)) {
|
|
72
|
-
for (const a of analysis) {
|
|
73
|
-
if (a.strategy_id && a.strategy_name)
|
|
74
|
-
map.set(a.strategy_id, a.strategy_name);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return map;
|
|
78
|
-
}
|
|
79
|
-
// Build a lookup from strategy_id → roadmap bucket using engineOutput.implementation_roadmap
|
|
80
|
-
function buildRoadmapBucketLookup(llm) {
|
|
81
|
-
var _a, _b;
|
|
82
|
-
const map = new Map();
|
|
83
|
-
const roadmap = (_a = llm.engineOutput) === null || _a === void 0 ? void 0 : _a.implementation_roadmap;
|
|
84
|
-
if (!roadmap)
|
|
85
|
-
return map;
|
|
86
|
-
const bucketKeys = [
|
|
87
|
-
{ key: "quick_wins", bucket: "now" },
|
|
88
|
-
{ key: "immediate", bucket: "now" },
|
|
89
|
-
{ key: "thirty_day", bucket: "30d" },
|
|
90
|
-
{ key: "ninety_day", bucket: "90d" },
|
|
91
|
-
{ key: "annual", bucket: "filing" },
|
|
92
|
-
];
|
|
93
|
-
for (const { key, bucket } of bucketKeys) {
|
|
94
|
-
for (const item of (_b = roadmap[key]) !== null && _b !== void 0 ? _b : []) {
|
|
95
|
-
if (item.strategy_id)
|
|
96
|
-
map.set(item.strategy_id, bucket);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return map;
|
|
100
|
-
}
|
|
101
|
-
// LLM sometimes emits these literal placeholder strings as why_it_applies / next_step
|
|
102
|
-
// content. When detected, we fall back to STRATEGY_NARRATIVE static content.
|
|
103
|
-
const PLACEHOLDER_WHY = "This strategy may apply based on your financial profile.";
|
|
104
|
-
const PLACEHOLDER_NEXT = "Discuss with your CPA to evaluate and implement this strategy.";
|
|
105
|
-
function isMissingOrPlaceholder(value, knownPlaceholder) {
|
|
106
|
-
if (!value)
|
|
107
|
-
return true;
|
|
108
|
-
const trimmed = value.trim();
|
|
109
|
-
if (trimmed === "")
|
|
110
|
-
return true;
|
|
111
|
-
if (trimmed === knownPlaceholder)
|
|
112
|
-
return true;
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
// Parse "S10" -> 10. Returns null if strategyId doesn't match the SN pattern.
|
|
116
|
-
function parseStrategyNumber(strategyId) {
|
|
117
|
-
if (!strategyId)
|
|
118
|
-
return null;
|
|
119
|
-
const match = strategyId.match(/^S(\d+)$/);
|
|
120
|
-
if (!match)
|
|
121
|
-
return null;
|
|
122
|
-
return parseInt(match[1], 10);
|
|
123
|
-
}
|
|
124
|
-
// Build a strategy_id -> client_summary entry lookup using strategy_analysis as the join table.
|
|
125
|
-
function buildClientSummaryLookup(llm) {
|
|
126
|
-
var _a, _b, _c, _d;
|
|
127
|
-
const lookup = new Map();
|
|
128
|
-
const engineOutput = (_a = llm.engineOutput) !== null && _a !== void 0 ? _a : llm.rawOutput;
|
|
129
|
-
if (!engineOutput)
|
|
130
|
-
return lookup;
|
|
131
|
-
const strategyAnalysis = (_b = engineOutput.strategy_analysis) !== null && _b !== void 0 ? _b : [];
|
|
132
|
-
const clientSummaryStrategies = (_d = (_c = engineOutput.client_summary) === null || _c === void 0 ? void 0 : _c.strategies) !== null && _d !== void 0 ? _d : [];
|
|
133
|
-
// strategy_name -> client_summary entry
|
|
134
|
-
const byName = new Map();
|
|
135
|
-
for (const cs of clientSummaryStrategies) {
|
|
136
|
-
if (cs.strategy_name) {
|
|
137
|
-
byName.set(cs.strategy_name, cs);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// strategy_id -> client_summary entry (via strategy_analysis name lookup)
|
|
141
|
-
for (const sa of strategyAnalysis) {
|
|
142
|
-
if (sa.strategy_id && sa.strategy_name) {
|
|
143
|
-
const cs = byName.get(sa.strategy_name);
|
|
144
|
-
if (cs) {
|
|
145
|
-
lookup.set(sa.strategy_id, cs);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return lookup;
|
|
150
|
-
}
|
|
151
|
-
function mapLlmToStrategies(llm, profile) {
|
|
152
|
-
const nameLookup = buildEngineNameLookup(llm);
|
|
153
|
-
const bucketLookup = buildRoadmapBucketLookup(llm);
|
|
154
|
-
const clientSummaryLookup = buildClientSummaryLookup(llm);
|
|
155
|
-
return llm.strategies
|
|
156
|
-
.filter((s) => s.applicable)
|
|
157
|
-
.map((s, idx) => {
|
|
158
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
159
|
-
const id = (_a = s.strategyId) !== null && _a !== void 0 ? _a : s.strategyType;
|
|
160
|
-
const name = (_b = nameLookup.get(id)) !== null && _b !== void 0 ? _b : humanizeStrategyType(s.strategyType);
|
|
161
|
-
const timelineBucket = (_c = bucketLookup.get(id)) !== null && _c !== void 0 ? _c : (s.priority === "HIGH" ? "now" : "90d");
|
|
162
|
-
const weightedScore = (_d = s.weightedScore) !== null && _d !== void 0 ? _d : (s.priority === "HIGH" ? 85 : s.priority === "MEDIUM" ? 70 : 55);
|
|
163
|
-
// Lookup the client_summary entry for this strategy (top-3 strategies only)
|
|
164
|
-
const csEntry = clientSummaryLookup.get(id);
|
|
165
|
-
const llmWhy = csEntry === null || csEntry === void 0 ? void 0 : csEntry.why_it_applies;
|
|
166
|
-
const llmNext = csEntry === null || csEntry === void 0 ? void 0 : csEntry.next_step;
|
|
167
|
-
// Strategy number for STRATEGY_NARRATIVE static lookup (e.g. "S10" -> 10)
|
|
168
|
-
const strategyNumber = parseStrategyNumber(id);
|
|
169
|
-
const staticNarrative = strategyNumber !== null ? strategyNarrative_1.STRATEGY_NARRATIVE[strategyNumber] : undefined;
|
|
170
|
-
// clientBrief: prefer LLM why_it_applies, fall back to static, then neutral default
|
|
171
|
-
let clientBrief;
|
|
172
|
-
if (!isMissingOrPlaceholder(llmWhy, PLACEHOLDER_WHY)) {
|
|
173
|
-
clientBrief = llmWhy;
|
|
174
|
-
}
|
|
175
|
-
else if (staticNarrative === null || staticNarrative === void 0 ? void 0 : staticNarrative.whyMatters) {
|
|
176
|
-
clientBrief = staticNarrative.whyMatters(profile);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
clientBrief = "Your preparer will review this strategy and include the analysis in your engagement report.";
|
|
180
|
-
}
|
|
181
|
-
// action: prefer LLM next_step, fall back to static nextSteps, then implementationSteps[0]
|
|
182
|
-
let action;
|
|
183
|
-
if (!isMissingOrPlaceholder(llmNext, PLACEHOLDER_NEXT)) {
|
|
184
|
-
action = llmNext;
|
|
185
|
-
}
|
|
186
|
-
else if (staticNarrative === null || staticNarrative === void 0 ? void 0 : staticNarrative.nextSteps) {
|
|
187
|
-
action = staticNarrative.nextSteps;
|
|
188
|
-
}
|
|
189
|
-
else if ((_e = s.implementationSteps) === null || _e === void 0 ? void 0 : _e[0]) {
|
|
190
|
-
action = s.implementationSteps[0];
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
action = "Work with your CPA to implement this strategy.";
|
|
194
|
-
}
|
|
195
|
-
// Pull calculation_trace fields. Defensive about shape.
|
|
196
|
-
const ct = ((_f = s.calculationTrace) !== null && _f !== void 0 ? _f : {});
|
|
197
|
-
const sourceDocuments = Array.isArray(ct.source_documents) ? ct.source_documents : undefined;
|
|
198
|
-
const specialistNote = typeof ct.specialist_note === "string" && ct.specialist_note.trim() !== ""
|
|
199
|
-
? ct.specialist_note
|
|
200
|
-
: ((_g = staticNarrative === null || staticNarrative === void 0 ? void 0 : staticNarrative.whySpecialist) !== null && _g !== void 0 ? _g : undefined);
|
|
201
|
-
const positionStrength = typeof ct.position_strength === "string" ? ct.position_strength : undefined;
|
|
202
|
-
const authority = typeof ct.irs_cite === "string" ? ct.irs_cite : undefined;
|
|
203
|
-
const formsFromTrace = Array.isArray(ct.forms_required) ? ct.forms_required.join(", ") : undefined;
|
|
204
|
-
return {
|
|
205
|
-
rank: idx + 1,
|
|
206
|
-
code: id,
|
|
207
|
-
name,
|
|
208
|
-
cat: "income",
|
|
209
|
-
priority: (s.priority || "MEDIUM").toUpperCase(),
|
|
210
|
-
score: Math.round(weightedScore),
|
|
211
|
-
entities: [],
|
|
212
|
-
lo: s.estimatedSavings.min,
|
|
213
|
-
hi: s.estimatedSavings.max,
|
|
214
|
-
timeline: timelineBucket === "now" ? "Act now" : timelineBucket === "30d" ? "Within 30 days" : "Within 90 days",
|
|
215
|
-
timelineBucket,
|
|
216
|
-
clientBrief,
|
|
217
|
-
action,
|
|
218
|
-
forms: formsFromTrace !== null && formsFromTrace !== void 0 ? formsFromTrace : s.requiredForms.join(", "),
|
|
219
|
-
abstract: s.summary,
|
|
220
|
-
sources: [],
|
|
221
|
-
trace: [],
|
|
222
|
-
cost: undefined,
|
|
223
|
-
sourceDocuments,
|
|
224
|
-
specialistNote,
|
|
225
|
-
positionStrength,
|
|
226
|
-
authority,
|
|
227
|
-
quickWin: s.quickWin,
|
|
228
|
-
};
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
function buildLlmComputed(strategies) {
|
|
232
|
-
const map = new Map();
|
|
233
|
-
for (const s of strategies) {
|
|
234
|
-
map.set(s.rank, { lo: s.lo, hi: s.hi, sources: s.sources, trace: s.trace });
|
|
235
|
-
}
|
|
236
|
-
return map;
|
|
237
|
-
}
|
|
238
37
|
// ─── Formatting helper ──────────────────────────────────────────
|
|
239
38
|
const fmtK = (n) => `$${(n / 1000).toFixed(n % 1000 ? 1 : 0)}K`;
|
|
240
39
|
// ─── Timeline buckets for Client Summary ────────────────────────
|
|
@@ -243,66 +42,21 @@ const BUCKETS = [
|
|
|
243
42
|
{ key: "30d", label: "Within 30 Days", desc: "Documentation or payroll changes" },
|
|
244
43
|
{ key: "90d", label: "Within 90 Days", desc: "Structural changes — new accounts or plan setup" },
|
|
245
44
|
];
|
|
246
|
-
function TaxAxisDashboard({ profile,
|
|
247
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
248
|
-
const hasLlm = !!((_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.strategies) === null || _a === void 0 ? void 0 : _a.length);
|
|
249
|
-
// All live fields from rawOutput — nothing hardcoded
|
|
250
|
-
const rawOutput = (_c = (_b = llmResult === null || llmResult === void 0 ? void 0 : llmResult.rawOutput) !== null && _b !== void 0 ? _b : llmResult === null || llmResult === void 0 ? void 0 : llmResult.engineOutput) !== null && _c !== void 0 ? _c : null;
|
|
251
|
-
const businessProfile = (_d = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.business_profile) !== null && _d !== void 0 ? _d : null;
|
|
252
|
-
const dataQualityFlags = (_e = businessProfile === null || businessProfile === void 0 ? void 0 : businessProfile.data_quality_flags) !== null && _e !== void 0 ? _e : [];
|
|
253
|
-
const riskDisclosures = (_f = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.risk_disclosures) !== null && _f !== void 0 ? _f : [];
|
|
254
|
-
const nexusFlags = (_g = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.nexus_flags) !== null && _g !== void 0 ? _g : [];
|
|
255
|
-
const engagementRecs = (_j = (_h = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.cpa_workflow) === null || _h === void 0 ? void 0 : _h.engagement_recommendations) !== null && _j !== void 0 ? _j : [];
|
|
256
|
-
const excludedStrategies = (_l = (_k = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.eligibility_screening) === null || _k === void 0 ? void 0 : _k.excluded_strategies) !== null && _l !== void 0 ? _l : [];
|
|
257
|
-
const clientSummaryOpening = (_o = (_m = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.client_summary) === null || _m === void 0 ? void 0 : _m.opening) !== null && _o !== void 0 ? _o : "";
|
|
258
|
-
const clientSummaryClosing = (_q = (_p = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.client_summary) === null || _p === void 0 ? void 0 : _p.closing) !== null && _q !== void 0 ? _q : "";
|
|
259
|
-
const dataQualityNote = (_s = (_r = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.client_summary) === null || _r === void 0 ? void 0 : _r.data_quality_note) !== null && _s !== void 0 ? _s : "";
|
|
260
|
-
const interactionWarning = (_u = (_t = rawOutput === null || rawOutput === void 0 ? void 0 : rawOutput.client_summary) === null || _t === void 0 ? void 0 : _t.interaction_warning) !== null && _u !== void 0 ? _u : null;
|
|
261
|
-
// Extracted documents: live from session if provided, otherwise empty (no mock fallback)
|
|
262
|
-
const extractionDocs = parsedDocuments !== null && parsedDocuments !== void 0 ? parsedDocuments : [];
|
|
45
|
+
function TaxAxisDashboard({ profile, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, userContext: _userContext = "expert", }) {
|
|
263
46
|
// ─── Derived data ──────────────────────────────────────────────
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// engineOutput is at llmResult.engineOutput or llmResult.rawOutput (both present).
|
|
267
|
-
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]);
|
|
268
|
-
const adapted = (0, useEngineOutput_1.useEngineOutput)(engineOutputForAdapter);
|
|
269
|
-
const llmStrategies = (0, react_1.useMemo)(() => {
|
|
270
|
-
var _a;
|
|
271
|
-
if (!hasLlm)
|
|
272
|
-
return [];
|
|
273
|
-
// Use adapted strategies when available — they carry the full engine data.
|
|
274
|
-
if ((_a = adapted === null || adapted === void 0 ? void 0 : adapted.strategies) === null || _a === void 0 ? void 0 : _a.length)
|
|
275
|
-
return adapted.strategies;
|
|
276
|
-
// Fallback to thin mapping for old payload shapes without engineOutput.
|
|
277
|
-
return mapLlmToStrategies(llmResult, profile);
|
|
278
|
-
}, [hasLlm, adapted, llmResult, profile]);
|
|
279
|
-
const llmComputed = (0, react_1.useMemo)(() => {
|
|
280
|
-
var _a;
|
|
281
|
-
if (!hasLlm)
|
|
282
|
-
return new Map();
|
|
283
|
-
if ((_a = adapted === null || adapted === void 0 ? void 0 : adapted.computedMap) === null || _a === void 0 ? void 0 : _a.size)
|
|
284
|
-
return adapted.computedMap;
|
|
285
|
-
return buildLlmComputed(llmStrategies);
|
|
286
|
-
}, [hasLlm, adapted, llmStrategies]);
|
|
287
|
-
const computed = (0, react_1.useMemo)(() => (hasLlm ? llmComputed : (0, compute_1.computeAllStrategies)(profile)), [hasLlm, llmComputed, profile]);
|
|
288
|
-
const dashEligible = (0, react_1.useMemo)(() => (hasLlm ? llmStrategies : (0, compute_1.filterEligibleStrategies)(profile)), [hasLlm, llmStrategies, profile]);
|
|
47
|
+
const computed = (0, react_1.useMemo)(() => (0, compute_1.computeAllStrategies)(profile), [profile]);
|
|
48
|
+
const dashEligible = (0, react_1.useMemo)(() => (0, compute_1.filterEligibleStrategies)(profile), [profile]);
|
|
289
49
|
const maxSavings = Math.max(...dashEligible.map((s) => { var _a, _b; return (_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : s.hi; }), 1);
|
|
290
50
|
// ─── State ─────────────────────────────────────────────────────
|
|
291
|
-
|
|
292
|
-
const [topTab, setTopTab] = (0, react_1.useState)(hasLlm ? "report" : "extraction");
|
|
51
|
+
const [topTab, setTopTab] = (0, react_1.useState)("extraction");
|
|
293
52
|
const [reportTab, setReportTab] = (0, react_1.useState)("report");
|
|
294
53
|
const [chartExpanded, setChartExpanded] = (0, react_1.useState)(false);
|
|
295
54
|
const [selected, setSelected] = (0, react_1.useState)(null);
|
|
296
|
-
|
|
297
|
-
const [dataConfirmed, setDataConfirmed] = (0, react_1.useState)(hasLlm);
|
|
55
|
+
const [dataConfirmed, setDataConfirmed] = (0, react_1.useState)(false);
|
|
298
56
|
const [reviewStatus, setReviewStatus] = (0, react_1.useState)({
|
|
299
|
-
unreviewed:
|
|
57
|
+
unreviewed: data_1.EXTRACTED_DATA.reduce((a, d) => a + d.flagCount, 0),
|
|
300
58
|
edits: 0,
|
|
301
59
|
});
|
|
302
|
-
// Keep review count in sync when live docs arrive after initial render
|
|
303
|
-
(0, react_1.useEffect)(() => {
|
|
304
|
-
setReviewStatus((prev) => (Object.assign(Object.assign({}, prev), { unreviewed: extractionDocs.reduce((a, d) => a + d.flagCount, 0) })));
|
|
305
|
-
}, [extractionDocs]);
|
|
306
60
|
// Restore confirmed state on mount — flag persists until session reset
|
|
307
61
|
(0, react_1.useEffect)(() => {
|
|
308
62
|
if (typeof window !== "undefined" && sessionStorage.getItem("taxAxisDataConfirmed") === "true") {
|
|
@@ -323,58 +77,15 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
323
77
|
const c = computed.get(selected.rank);
|
|
324
78
|
return Object.assign(Object.assign({}, selected), { lo: (_a = c === null || c === void 0 ? void 0 : c.lo) !== null && _a !== void 0 ? _a : selected.lo, hi: (_b = c === null || c === void 0 ? void 0 : c.hi) !== null && _b !== void 0 ? _b : selected.hi, sources: (_c = c === null || c === void 0 ? void 0 : c.sources) !== null && _c !== void 0 ? _c : selected.sources, trace: (_d = c === null || c === void 0 ? void 0 : c.trace) !== null && _d !== void 0 ? _d : selected.trace });
|
|
325
79
|
}, [selected, computed]);
|
|
326
|
-
//
|
|
327
|
-
const
|
|
328
|
-
const uncalculated = (0, react_1.useMemo)(() => dashEligible.filter((s) => { var _a, _b; return ((_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : s.hi) === 0; }), [dashEligible, computed]);
|
|
329
|
-
// Sorted calculable strategies for impact distribution
|
|
330
|
-
const sortedByImpact = (0, react_1.useMemo)(() => [...calculable].sort((a, b) => { var _a, _b, _c, _d; return ((_b = (_a = computed.get(b.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : b.hi) - ((_d = (_c = computed.get(a.rank)) === null || _c === void 0 ? void 0 : _c.hi) !== null && _d !== void 0 ? _d : a.hi); }), [calculable, computed]);
|
|
331
|
-
// Reverse-map: strategy name → document names needed (from DOC_SPECS_BASE)
|
|
332
|
-
const strategyDocNeeds = (0, react_1.useMemo)(() => {
|
|
333
|
-
const map = new Map();
|
|
334
|
-
uncalculated.forEach((s) => {
|
|
335
|
-
const docs = data_1.DOC_SPECS_BASE
|
|
336
|
-
.filter((d) => d.strategies.some((st) => s.name.includes(st) || st.includes(s.code)))
|
|
337
|
-
.map((d) => d.name);
|
|
338
|
-
map.set(s.name, docs.length > 0 ? docs : ["Upload additional documents"]);
|
|
339
|
-
});
|
|
340
|
-
return map;
|
|
341
|
-
}, [uncalculated]);
|
|
342
|
-
const [uncalcExpanded, setUncalcExpanded] = (0, react_1.useState)(false);
|
|
80
|
+
// Sorted strategies for impact distribution
|
|
81
|
+
const sortedByImpact = (0, react_1.useMemo)(() => [...dashEligible].sort((a, b) => { var _a, _b, _c, _d; return ((_b = (_a = computed.get(b.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : b.hi) - ((_d = (_c = computed.get(a.rank)) === null || _c === void 0 ? void 0 : _c.hi) !== null && _d !== void 0 ? _d : a.hi); }), [dashEligible, computed]);
|
|
343
82
|
return (react_1.default.createElement("div", null,
|
|
344
|
-
|
|
345
|
-
background: "rgba(36,131,132,0.06)",
|
|
346
|
-
border: "1px solid rgba(36,131,132,0.15)",
|
|
347
|
-
color: "#9498B8",
|
|
348
|
-
} },
|
|
349
|
-
react_1.default.createElement("span", null,
|
|
350
|
-
"Source: ",
|
|
351
|
-
react_1.default.createElement("strong", { className: "text-tax-axis-teal-light" }, llmResult.meta.provider),
|
|
352
|
-
" · ",
|
|
353
|
-
llmResult.meta.parsedDocumentCount,
|
|
354
|
-
" documents parsed",
|
|
355
|
-
" · ",
|
|
356
|
-
((_v = llmResult.meta.detectedDocumentTypes) === null || _v === void 0 ? void 0 : _v.length) || 0,
|
|
357
|
-
" document types detected"),
|
|
358
|
-
react_1.default.createElement("span", { className: "text-tax-axis-text-4" }, (() => {
|
|
359
|
-
var _a, _b;
|
|
360
|
-
const tokens = (_b = (_a = llmResult.meta.totalTokens) !== null && _a !== void 0 ? _a : llmResult.meta.tokenCount) !== null && _b !== void 0 ? _b : 0;
|
|
361
|
-
return tokens > 0 ? `${tokens} tokens` : "";
|
|
362
|
-
})()))),
|
|
363
|
-
react_1.default.createElement(DashboardSummary_1.DashboardSummary, { profile: profile, dashEligible: dashEligible, computed: computed, dataConfirmed: dataConfirmed, reviewUnreviewed: reviewStatus.unreviewed, liveSavingsMin: hasLlm ? llmResult.summary.estimatedSavingsMin : undefined, liveSavingsMax: hasLlm ? llmResult.summary.estimatedSavingsMax : undefined, liveStrategyCount: hasLlm ? llmResult.summary.applicableCount : undefined, confidenceTier: businessProfile === null || businessProfile === void 0 ? void 0 : businessProfile.confidence_tier, dataYears: businessProfile === null || businessProfile === void 0 ? void 0 : businessProfile.data_years }),
|
|
83
|
+
react_1.default.createElement(DashboardSummary_1.DashboardSummary, { profile: profile, dashEligible: dashEligible, computed: computed, dataConfirmed: dataConfirmed, reviewUnreviewed: reviewStatus.unreviewed }),
|
|
364
84
|
react_1.default.createElement(DashboardTopBar_1.DashboardTopBar, { topTab: topTab, setTopTab: setTopTab, dataConfirmed: dataConfirmed, reviewUnreviewed: reviewStatus.unreviewed }),
|
|
365
85
|
topTab === "extraction" && (react_1.default.createElement("div", null,
|
|
366
|
-
dataQualityFlags.length > 0 && (react_1.default.createElement("div", { className: "rounded-[14px] mb-4", style: { background: "rgba(251,154,29,0.04)", border: "1px solid rgba(251,154,29,0.2)", padding: "16px 20px" } },
|
|
367
|
-
react_1.default.createElement("div", { className: "text-[11px] font-bold text-white uppercase tracking-widest font-tax-axis-mono mb-2.5 flex items-center gap-2" },
|
|
368
|
-
react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" },
|
|
369
|
-
react_1.default.createElement("path", { d: "M6 1.5l5 9H1L6 1.5z", stroke: "#FB9A1D", strokeWidth: "1.2", fill: "none" }),
|
|
370
|
-
react_1.default.createElement("path", { d: "M6 5v2.5M6 9h.005", stroke: "#FB9A1D", strokeWidth: "1.2", strokeLinecap: "round" })),
|
|
371
|
-
"Data Quality Flags"),
|
|
372
|
-
dataQualityFlags.map((flag, i) => (react_1.default.createElement("div", { key: i, className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body py-1.5", style: { borderTop: i > 0 ? "1px solid rgba(251,154,29,0.1)" : "none" } }, flag))))),
|
|
373
86
|
react_1.default.createElement("div", { className: "rounded-[14px] mb-4", style: { background: "#0E1132", border: "1px solid rgba(36,131,132,0.12)", padding: "20px 24px" } },
|
|
374
87
|
react_1.default.createElement("div", { className: "text-[13px] font-bold text-white uppercase tracking-widest font-tax-axis-head mb-3" }, "Document Extraction Summary"),
|
|
375
|
-
|
|
376
|
-
? "Parsed document data is loading..."
|
|
377
|
-
: "No documents have been parsed yet.")) : (extractionDocs.map((doc) => (react_1.default.createElement("div", { key: doc.docId, className: "flex items-center justify-between py-2.5", style: { borderTop: "1px solid rgba(36,131,132,0.08)" } },
|
|
88
|
+
data_1.EXTRACTED_DATA.map((doc) => (react_1.default.createElement("div", { key: doc.docId, className: "flex items-center justify-between py-2.5", style: { borderTop: "1px solid rgba(36,131,132,0.08)" } },
|
|
378
89
|
react_1.default.createElement("div", { className: "flex items-center gap-3" },
|
|
379
90
|
react_1.default.createElement("span", { className: "text-[11px] font-tax-axis-mono text-tax-axis-teal-light bg-tax-axis-teal-bg px-2 py-0.5 rounded" }, doc.code),
|
|
380
91
|
react_1.default.createElement("span", { className: "text-[13px] text-tax-axis-text font-tax-axis-body" }, doc.docName)),
|
|
@@ -382,8 +93,9 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
382
93
|
react_1.default.createElement("span", { className: "text-[11px] font-tax-axis-mono text-tax-axis-text-3" },
|
|
383
94
|
doc.fields.length,
|
|
384
95
|
" fields"),
|
|
385
|
-
doc.flagCount > 0
|
|
386
|
-
|
|
96
|
+
doc.flagCount > 0 && (react_1.default.createElement("span", { className: "text-[10px] font-semibold font-tax-axis-mono rounded-full min-w-[18px] text-center px-1.5 py-0.5", style: { color: "#FB9A1D", background: "rgba(251,154,29,0.06)" } }, doc.flagCount)),
|
|
97
|
+
doc.flagCount === 0 && (react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" },
|
|
98
|
+
react_1.default.createElement("path", { d: "M2.5 6l3 3 4.5-5", stroke: "#0F6E56", strokeWidth: "1.5", strokeLinecap: "round" })))))))),
|
|
387
99
|
!dataConfirmed ? (react_1.default.createElement("div", { className: "rounded-[14px]", style: {
|
|
388
100
|
background: "linear-gradient(135deg, rgba(36,131,132,0.12), rgba(36,131,132,0.06))",
|
|
389
101
|
border: "1px solid rgba(36,131,132,0.3)",
|
|
@@ -427,23 +139,6 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
427
139
|
marginBottom: "-1px",
|
|
428
140
|
} }, lbl)))),
|
|
429
141
|
reportTab === "report" ? (react_1.default.createElement("div", null,
|
|
430
|
-
reviewStatus.unreviewed > 0 && (react_1.default.createElement("div", { className: "rounded-[14px] mb-4 flex items-center gap-3", style: {
|
|
431
|
-
background: "rgba(251,154,29,0.06)",
|
|
432
|
-
border: "1px solid rgba(251,154,29,0.20)",
|
|
433
|
-
borderLeft: "4px solid #FB9A1D",
|
|
434
|
-
padding: "14px 20px",
|
|
435
|
-
} },
|
|
436
|
-
react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "flex-shrink-0" },
|
|
437
|
-
react_1.default.createElement("path", { d: "M8 1.5l6.5 12H1.5L8 1.5z", stroke: "#FB9A1D", strokeWidth: "1.3", fill: "none" }),
|
|
438
|
-
react_1.default.createElement("path", { d: "M8 6.5v3M8 11h.005", stroke: "#FB9A1D", strokeWidth: "1.3", strokeLinecap: "round" })),
|
|
439
|
-
react_1.default.createElement("div", { className: "flex-1" },
|
|
440
|
-
react_1.default.createElement("span", { className: "text-[13px] font-semibold text-white font-tax-axis-body" },
|
|
441
|
-
reviewStatus.unreviewed,
|
|
442
|
-
" extracted value",
|
|
443
|
-
reviewStatus.unreviewed > 1 ? "s" : "",
|
|
444
|
-
" flagged for review"),
|
|
445
|
-
react_1.default.createElement("span", { className: "text-[12px] text-tax-axis-text-2 font-tax-axis-body ml-2" }, "\u2014 strategy savings may shift after corrections")),
|
|
446
|
-
onReviewData && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onReviewData, className: "flex-shrink-0" }, "Review Extracted Values")))),
|
|
447
142
|
react_1.default.createElement("div", { className: "rounded-[14px] mb-4", style: {
|
|
448
143
|
background: "#0E1132",
|
|
449
144
|
border: "1px solid rgba(36,131,132,0.12)",
|
|
@@ -459,7 +154,7 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
459
154
|
color: "#9498B8",
|
|
460
155
|
} }, chartExpanded ? "Collapse \u2191" : "Expand \u2193")),
|
|
461
156
|
sortedByImpact
|
|
462
|
-
.slice(0, chartExpanded ?
|
|
157
|
+
.slice(0, chartExpanded ? dashEligible.length : 12)
|
|
463
158
|
.map((s, i) => {
|
|
464
159
|
var _a, _b, _c, _d;
|
|
465
160
|
const chi = (_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : s.hi;
|
|
@@ -484,75 +179,25 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
484
179
|
"\u2013",
|
|
485
180
|
fmtK(chi))));
|
|
486
181
|
}),
|
|
487
|
-
!chartExpanded &&
|
|
182
|
+
!chartExpanded && dashEligible.length > 12 && (react_1.default.createElement("div", { onClick: () => setChartExpanded(true), className: "text-[11px] text-tax-axis-teal-light font-tax-axis-mono mt-1 cursor-pointer hover:underline" },
|
|
488
183
|
"+ ",
|
|
489
|
-
|
|
184
|
+
dashEligible.length - 12,
|
|
490
185
|
" more strategies \u2014 click to view all")),
|
|
491
186
|
chartExpanded && (react_1.default.createElement("div", { onClick: () => setChartExpanded(false), className: "text-[11px] text-tax-axis-text-3 font-tax-axis-mono mt-1 cursor-pointer hover:text-tax-axis-teal" },
|
|
492
187
|
"Showing all ",
|
|
493
|
-
|
|
188
|
+
dashEligible.length,
|
|
494
189
|
" strategies \u2014 click to collapse"))),
|
|
495
190
|
react_1.default.createElement("div", { className: "text-[13px] font-bold text-white uppercase tracking-widest mb-2.5 font-tax-axis-head flex justify-between items-center" },
|
|
496
191
|
react_1.default.createElement("span", null,
|
|
497
192
|
dashEligible.length,
|
|
498
193
|
" Strategies"),
|
|
499
194
|
react_1.default.createElement("span", { className: "font-normal normal-case tracking-normal text-tax-axis-text-2 text-xs font-tax-axis-body" }, "Click to explore")),
|
|
500
|
-
react_1.default.createElement("div", { className: "grid grid-cols-2 gap-2.5 mb-4" },
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
hasLlm && uncalculated.map((s, i) => (react_1.default.createElement("div", { key: s.rank, onClick: () => setSelected(s), className: "rounded-[14px] p-4 cursor-pointer", style: {
|
|
507
|
-
background: "#0E1132",
|
|
508
|
-
border: "1px solid rgba(36,131,132,0.12)",
|
|
509
|
-
boxShadow: "0 2px 8px rgba(6,8,33,0.3)",
|
|
510
|
-
animationDelay: `${0.2 + (calculable.length + i) * 0.06}s`,
|
|
511
|
-
} },
|
|
512
|
-
react_1.default.createElement("div", { className: "flex items-start justify-between gap-2 mb-2" },
|
|
513
|
-
react_1.default.createElement("div", { className: "flex items-center gap-2 flex-wrap" },
|
|
514
|
-
react_1.default.createElement("span", { className: "text-[10px] font-semibold font-tax-axis-mono px-2 py-0.5 rounded", style: { background: "rgba(36,131,132,0.12)", color: "#A1E5E6", border: "1px solid rgba(36,131,132,0.2)" } }, s.code),
|
|
515
|
-
react_1.default.createElement("span", { className: "text-[10px] font-semibold font-tax-axis-mono px-2 py-0.5 rounded", style: { background: "rgba(148,152,184,0.1)", color: "#9498B8", border: "1px solid rgba(148,152,184,0.15)" } }, "Qualitative")),
|
|
516
|
-
react_1.default.createElement("div", { className: "w-8 h-8 rounded-full flex items-center justify-center text-[12px] font-bold font-tax-axis-mono flex-shrink-0", style: {
|
|
517
|
-
background: "conic-gradient(#248384 0%, #248384 55%, #1A1D3A 55%)",
|
|
518
|
-
color: "#A1E5E6",
|
|
519
|
-
} }, s.score)),
|
|
520
|
-
react_1.default.createElement("div", { className: "text-[14px] font-semibold text-white font-tax-axis-head mb-1 leading-tight" }, s.name),
|
|
521
|
-
react_1.default.createElement("div", { className: "text-[12px] text-tax-axis-teal-light font-tax-axis-mono mb-2" }, s.timeline),
|
|
522
|
-
react_1.default.createElement("div", { className: "h-0.5 w-full rounded-sm mb-2", style: { background: "rgba(36,131,132,0.2)" } }),
|
|
523
|
-
react_1.default.createElement("p", { className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body leading-relaxed line-clamp-2" }, s.abstract || s.clientBrief))))),
|
|
524
|
-
uncalculated.length > 0 && !hasLlm && (react_1.default.createElement("div", { className: "rounded-[14px] overflow-hidden mb-4", style: {
|
|
525
|
-
background: "#0E1132",
|
|
526
|
-
border: "1px solid rgba(251,154,29,0.15)",
|
|
527
|
-
boxShadow: "0 2px 8px rgba(6,8,33,0.3)",
|
|
528
|
-
} },
|
|
529
|
-
react_1.default.createElement("div", { onClick: () => setUncalcExpanded((p) => !p), className: "px-5 py-3.5 flex items-center gap-3 cursor-pointer" },
|
|
530
|
-
react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", className: "flex-shrink-0" },
|
|
531
|
-
react_1.default.createElement("circle", { cx: "7", cy: "7", r: "5.5", stroke: "#FB9A1D", strokeWidth: "1.2" }),
|
|
532
|
-
react_1.default.createElement("path", { d: "M7 4.5v3M7 9.5h.005", stroke: "#FB9A1D", strokeWidth: "1.2", strokeLinecap: "round" })),
|
|
533
|
-
react_1.default.createElement("span", { className: "text-[13px] font-semibold text-white font-tax-axis-body flex-1" }, hasLlm
|
|
534
|
-
? `${uncalculated.length} qualitative strateg${uncalculated.length > 1 ? "ies" : "y"} — CPA review recommended`
|
|
535
|
-
: `${uncalculated.length} strateg${uncalculated.length > 1 ? "ies" : "y"} need more data to calculate savings`),
|
|
536
|
-
react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: {
|
|
537
|
-
transform: uncalcExpanded ? "rotate(180deg)" : "none",
|
|
538
|
-
transition: "transform .2s",
|
|
539
|
-
} },
|
|
540
|
-
react_1.default.createElement("path", { d: "M3 4.5l3 3 3-3", stroke: "#9498B8", strokeWidth: "1.5", strokeLinecap: "round" }))),
|
|
541
|
-
uncalcExpanded && (react_1.default.createElement("div", { style: { borderTop: "1px solid rgba(251,154,29,0.12)", padding: "12px 20px" } },
|
|
542
|
-
uncalculated.map((s, i) => (react_1.default.createElement("div", { key: s.rank, className: "py-2.5 cursor-pointer", style: {
|
|
543
|
-
borderBottom: i < uncalculated.length - 1
|
|
544
|
-
? "1px solid rgba(36,131,132,0.08)"
|
|
545
|
-
: "none",
|
|
546
|
-
}, onClick: () => setSelected(s) },
|
|
547
|
-
react_1.default.createElement("div", { className: "flex items-center gap-2.5 mb-1" },
|
|
548
|
-
react_1.default.createElement("span", { className: "text-[11px] font-tax-axis-mono px-2 py-0.5 rounded", style: { color: "#FB9A1D", background: "rgba(251,154,29,0.08)", border: "1px solid rgba(251,154,29,0.15)" } }, s.code),
|
|
549
|
-
react_1.default.createElement("span", { className: "text-[13px] text-white font-tax-axis-body font-semibold" }, s.name)),
|
|
550
|
-
react_1.default.createElement("div", { className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body pl-0.5" }, hasLlm
|
|
551
|
-
? (s.abstract || s.clientBrief || "See CPA for details")
|
|
552
|
-
: `Needs: ${(strategyDocNeeds.get(s.name) || ["Upload additional documents"]).join(", ")}`)))),
|
|
553
|
-
!hasLlm && onUploadMore && (react_1.default.createElement("div", { className: "pt-3 mt-1", style: { borderTop: "1px solid rgba(251,154,29,0.12)" } },
|
|
554
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onUploadMore }, "Upload Documents"))))))),
|
|
555
|
-
!hasLlm && (react_1.default.createElement("div", { className: "rounded-[14px] overflow-hidden mb-4", style: {
|
|
195
|
+
react_1.default.createElement("div", { className: "grid grid-cols-2 gap-2.5 mb-4" }, dashEligible.map((s, i) => {
|
|
196
|
+
var _a, _b;
|
|
197
|
+
const c = computed.get(s.rank);
|
|
198
|
+
return (react_1.default.createElement(StrategyTile_1.StrategyTile, { key: s.rank, s: Object.assign(Object.assign({}, s), { lo: (_a = c === null || c === void 0 ? void 0 : c.lo) !== null && _a !== void 0 ? _a : s.lo, hi: (_b = c === null || c === void 0 ? void 0 : c.hi) !== null && _b !== void 0 ? _b : s.hi }), delay: 0.2 + i * 0.06, onClick: () => setSelected(s), maxSavings: maxSavings }));
|
|
199
|
+
})),
|
|
200
|
+
react_1.default.createElement("div", { className: "rounded-[14px] overflow-hidden mb-4", style: {
|
|
556
201
|
background: "#0E1132",
|
|
557
202
|
border: "1px solid rgba(36,131,132,0.12)",
|
|
558
203
|
boxShadow: "0 2px 8px rgba(6,8,33,0.3)",
|
|
@@ -565,33 +210,19 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
565
210
|
react_1.default.createElement("span", { className: "text-[13px] text-tax-axis-text" }, a.name),
|
|
566
211
|
react_1.default.createElement("div", { className: "flex items-center gap-2.5" },
|
|
567
212
|
react_1.default.createElement("span", { className: "text-[11px] font-tax-axis-mono text-tax-axis-text-2" }, a.savings),
|
|
568
|
-
react_1.default.createElement(TaxAxisBadge_1.TaxAxisBadge, { color: a.priority === "MEDIUM" ? "orange" : "neutral", size: "xs" }, a.priority))))))
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
react_1.default.createElement("
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
riskDisclosures.length > 0 && (react_1.default.createElement("div", { className: "rounded-[14px] mb-4", style: { background: "rgba(251,154,29,0.04)", border: "1px solid rgba(251,154,29,0.15)", padding: "16px 20px" } },
|
|
579
|
-
react_1.default.createElement("div", { className: "text-[11px] font-bold text-white uppercase tracking-widest font-tax-axis-mono mb-2.5" }, "Risk Disclosures"),
|
|
580
|
-
riskDisclosures.map((r, i) => (react_1.default.createElement("div", { key: i, className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body py-1.5", style: { borderTop: i > 0 ? "1px solid rgba(251,154,29,0.08)" : "none" } }, r))))),
|
|
581
|
-
excludedStrategies.length > 0 && (react_1.default.createElement("div", { className: "rounded-[14px] mb-4 overflow-hidden", style: { background: "#0E1132", border: "1px solid rgba(148,152,184,0.15)" } },
|
|
582
|
-
react_1.default.createElement("div", { className: "px-5 py-3.5", style: { borderBottom: "1px solid rgba(148,152,184,0.1)" } },
|
|
583
|
-
react_1.default.createElement("span", { className: "text-[13px] font-bold text-white uppercase tracking-widest font-tax-axis-head" },
|
|
584
|
-
excludedStrategies.length,
|
|
585
|
-
" Strategies Not Applicable")),
|
|
586
|
-
excludedStrategies.map((ex, i) => (react_1.default.createElement("div", { key: i, className: "px-5 py-2.5 flex items-start gap-3", style: { borderTop: i > 0 ? "1px solid rgba(148,152,184,0.08)" : "none" } },
|
|
587
|
-
react_1.default.createElement("span", { className: "text-[10px] font-semibold font-tax-axis-mono text-tax-axis-text-3 bg-tax-axis-surface px-2 py-0.5 rounded flex-shrink-0 mt-0.5" }, ex.strategy_id),
|
|
588
|
-
react_1.default.createElement("div", { className: "flex-1" },
|
|
589
|
-
react_1.default.createElement("div", { className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body" }, ex.reason),
|
|
590
|
-
ex.irs_cite && (react_1.default.createElement("div", { className: "text-[10px] text-tax-axis-text-3 font-tax-axis-mono mt-0.5" }, ex.irs_cite)))))))),
|
|
591
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onDownloadPreparer, className: "w-full" }, "Download Full Preparer Report"))) : (
|
|
213
|
+
react_1.default.createElement(TaxAxisBadge_1.TaxAxisBadge, { color: a.priority === "MEDIUM" ? "orange" : "neutral", size: "xs" }, a.priority)))))),
|
|
214
|
+
react_1.default.createElement("div", { className: "rounded-[10px] mb-4 text-xs text-tax-axis-text leading-[1.7] font-tax-axis-body", style: {
|
|
215
|
+
padding: "14px 18px",
|
|
216
|
+
background: "#0E1132",
|
|
217
|
+
border: "1px solid rgba(36,131,132,0.12)",
|
|
218
|
+
} },
|
|
219
|
+
react_1.default.createElement("strong", null, "\u00A76694 Preparer Compliance \u2014 "),
|
|
220
|
+
"All HIGH priority strategies hold Substantial Authority (established IRS guidance supporting the position). No elevated preparer penalty exposure for positions taken on these strategies. OBBBA strategies default to Reasonable Basis pending IRS guidance \u2014 CPA verification required before filing."),
|
|
221
|
+
react_1.default.createElement("div", { style: { position: "sticky", bottom: 24, zIndex: 10, paddingTop: 12, background: "linear-gradient(to bottom, transparent 0%, #060821 24%)" } },
|
|
222
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onDownloadPreparer, className: "w-full" }, "Download Full Preparer Report")))) : (
|
|
592
223
|
/* ═══ CLIENT SUMMARY — Timeline View ═══ */
|
|
593
224
|
react_1.default.createElement("div", null,
|
|
594
|
-
|
|
225
|
+
react_1.default.createElement("p", { className: "text-sm text-tax-axis-text leading-[1.7] mb-6 font-tax-axis-body" },
|
|
595
226
|
profile.bizName || "Client",
|
|
596
227
|
", here's your action plan organized by urgency.",
|
|
597
228
|
" ",
|
|
@@ -599,13 +230,7 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
599
230
|
dashEligible.length,
|
|
600
231
|
" strategies"),
|
|
601
232
|
" ",
|
|
602
|
-
"identified.")
|
|
603
|
-
dataQualityNote && (react_1.default.createElement("div", { className: "rounded-[10px] mb-5 text-[11px] text-tax-axis-text-2 font-tax-axis-body flex items-start gap-2", style: { background: "rgba(251,154,29,0.04)", border: "1px solid rgba(251,154,29,0.15)", padding: "10px 14px" } },
|
|
604
|
-
react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", className: "flex-shrink-0 mt-0.5" },
|
|
605
|
-
react_1.default.createElement("circle", { cx: "6", cy: "6", r: "5", stroke: "#FB9A1D", strokeWidth: "1" }),
|
|
606
|
-
react_1.default.createElement("path", { d: "M6 4v2.5M6 8h.005", stroke: "#FB9A1D", strokeWidth: "1", strokeLinecap: "round" })),
|
|
607
|
-
dataQualityNote)),
|
|
608
|
-
interactionWarning && (react_1.default.createElement("div", { className: "rounded-[10px] mb-5 text-[11px] text-tax-axis-text-2 font-tax-axis-body", style: { background: "rgba(251,154,29,0.04)", border: "1px solid rgba(251,154,29,0.15)", padding: "10px 14px" } }, interactionWarning)),
|
|
233
|
+
"identified."),
|
|
609
234
|
BUCKETS.map(({ key, label, desc }) => {
|
|
610
235
|
const items = dashEligible.filter((s) => s.timelineBucket === key);
|
|
611
236
|
if (!items.length)
|
|
@@ -654,8 +279,7 @@ function TaxAxisDashboard({ profile, llmResult, parsedDocuments, onDownloadClien
|
|
|
654
279
|
s.cost && s.cost !== "$0" && (react_1.default.createElement("span", { className: "text-[11px] font-semibold font-tax-axis-mono", style: { color: "#FB9A1D" } }, s.cost)))));
|
|
655
280
|
})));
|
|
656
281
|
}),
|
|
657
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onDownloadClient, className: "w-full mt-1.5" }, "Download Client Summary"),
|
|
658
|
-
clientSummaryClosing && (react_1.default.createElement("div", { className: "mt-4 text-[11px] text-tax-axis-text-3 leading-[1.65] font-tax-axis-body", style: { borderTop: "1px solid rgba(36,131,132,0.08)", paddingTop: 14 } }, clientSummaryClosing)))),
|
|
282
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onDownloadClient, className: "w-full mt-1.5" }, "Download Client Summary"))),
|
|
659
283
|
react_1.default.createElement(DashboardActions_1.DashboardActions, { profile: profile, dashEligible: dashEligible, computed: computed, onDownloadPreparer: onDownloadPreparer, onPresent: onPresent, onSend: onSend, onReset: onReset }))),
|
|
660
284
|
enrichedSelected && (react_1.default.createElement(StrategyDetailPanel_1.StrategyDetailPanel, { s: enrichedSelected, profile: profile, computed: computed, onClose: () => setSelected(null) }))));
|
|
661
285
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { DocSpec } from "../../lib/types";
|
|
3
|
-
export type DocStatus = "empty" | "validating" | "
|
|
3
|
+
export type DocStatus = "empty" | "validating" | "valid";
|
|
4
4
|
export interface DocState extends DocSpec {
|
|
5
5
|
status: DocStatus;
|
|
6
6
|
fileName: string | null;
|
|
7
|
-
parseError?: string | null;
|
|
8
7
|
}
|
|
9
8
|
interface DocumentCardProps {
|
|
10
9
|
doc: DocState;
|
|
@@ -12,11 +11,8 @@ interface DocumentCardProps {
|
|
|
12
11
|
tierBadgeColor: "red" | "orange" | "neutral";
|
|
13
12
|
tierBadgeText: string;
|
|
14
13
|
helpOverride?: string;
|
|
15
|
-
|
|
16
|
-
onUpload: (file: File) => void;
|
|
14
|
+
onUpload: () => void;
|
|
17
15
|
onClear: () => void;
|
|
18
|
-
onRemove?: () => void;
|
|
19
|
-
onReview?: () => void;
|
|
20
16
|
}
|
|
21
|
-
export declare function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride,
|
|
17
|
+
export declare function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride, onUpload, onClear, }: DocumentCardProps): React.JSX.Element;
|
|
22
18
|
export {};
|