@paro.io/expert-shared-components 1.14.51 → 1.14.53
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 +1 -0
- package/lib/components/TaxAxis/TaxAxisShell.js +55 -12
- package/lib/index.d.ts +1 -14
- package/lib/index.js +1 -27
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +6 -2
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +5 -3
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +2 -1
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +163 -34
- package/lib/tax-axis/components/documents/DocumentCard.d.ts +3 -1
- package/lib/tax-axis/components/documents/DocumentCard.js +17 -5
- package/lib/tax-axis/components/documents/DocumentReviewModal.d.ts +13 -0
- package/lib/tax-axis/components/documents/DocumentReviewModal.js +248 -0
- package/lib/tax-axis/components/documents/DocumentTier.d.ts +3 -1
- package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +7 -1
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +116 -53
- package/lib/tax-axis/components/extractionReview/TaxAxisExtractionReview.js +17 -17
- package/lib/tax-axis/components/intake/ClientParametersSection.js +1 -1
- package/lib/tax-axis/components/intake/intakeSchema.js +1 -1
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +6 -2
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +5 -3
- package/lib/tax-axis/index.d.ts +4 -0
- package/lib/tax-axis/index.js +6 -1
- package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +144 -0
- package/lib/tax-axis/lib/adapters/useEngineOutput.js +155 -0
- 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/documentFieldCatalog.d.ts +13 -0
- package/lib/tax-axis/lib/documentFieldCatalog.js +808 -0
- package/lib/tax-axis/lib/types/index.d.ts +3 -0
- package/package.json +1 -1
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; } });
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { ClientProfile } from "../../lib/types";
|
|
2
|
+
import type { ClientProfile, Strategy, ComputedMap } from "../../lib/types";
|
|
3
3
|
import type { TaxAxisScreenProps } from "../../lib/types";
|
|
4
4
|
export interface TaxAxisClientReportProps extends TaxAxisScreenProps {
|
|
5
5
|
profile: ClientProfile;
|
|
6
6
|
onBack: () => void;
|
|
7
7
|
onNavigatePreparer?: () => void;
|
|
8
|
+
/** When provided, bypasses local filterEligibleStrategies + computeAllStrategies. */
|
|
9
|
+
liveStrategies?: Strategy[];
|
|
10
|
+
/** When provided, bypasses local computeAllStrategies. Must accompany liveStrategies. */
|
|
11
|
+
liveComputedMap?: ComputedMap;
|
|
8
12
|
}
|
|
9
|
-
export declare function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }: TaxAxisClientReportProps): React.JSX.Element;
|
|
13
|
+
export declare function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategies, liveComputedMap }: 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 }) {
|
|
37
|
+
function TaxAxisClientReport({ profile, onBack, onNavigatePreparer, liveStrategies, liveComputedMap }) {
|
|
38
38
|
var _a, _b, _c;
|
|
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);
|
|
@@ -63,5 +63,6 @@ export interface TaxAxisDashboardProps extends TaxAxisScreenProps {
|
|
|
63
63
|
onSend: () => void;
|
|
64
64
|
onReset: () => void;
|
|
65
65
|
onReviewData?: () => void;
|
|
66
|
+
onUploadMore?: () => void;
|
|
66
67
|
}
|
|
67
|
-
export declare function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, userContext: _userContext, }: TaxAxisDashboardProps): React.JSX.Element;
|
|
68
|
+
export declare function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, onUploadMore, userContext: _userContext, }: TaxAxisDashboardProps): React.JSX.Element;
|
|
@@ -61,29 +61,74 @@ function humanizeStrategyType(raw) {
|
|
|
61
61
|
.replace(/_/g, " ")
|
|
62
62
|
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
63
63
|
}
|
|
64
|
+
// Build a lookup from strategy_id → strategy_name using engineOutput.strategy_analysis
|
|
65
|
+
function buildEngineNameLookup(llm) {
|
|
66
|
+
var _a;
|
|
67
|
+
const map = new Map();
|
|
68
|
+
const analysis = (_a = llm.engineOutput) === null || _a === void 0 ? void 0 : _a.strategy_analysis;
|
|
69
|
+
if (Array.isArray(analysis)) {
|
|
70
|
+
for (const a of analysis) {
|
|
71
|
+
if (a.strategy_id && a.strategy_name)
|
|
72
|
+
map.set(a.strategy_id, a.strategy_name);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return map;
|
|
76
|
+
}
|
|
77
|
+
// Build a lookup from strategy_id → roadmap bucket using engineOutput.implementation_roadmap
|
|
78
|
+
function buildRoadmapBucketLookup(llm) {
|
|
79
|
+
var _a, _b;
|
|
80
|
+
const map = new Map();
|
|
81
|
+
const roadmap = (_a = llm.engineOutput) === null || _a === void 0 ? void 0 : _a.implementation_roadmap;
|
|
82
|
+
if (!roadmap)
|
|
83
|
+
return map;
|
|
84
|
+
const bucketKeys = [
|
|
85
|
+
{ key: "quick_wins", bucket: "now" },
|
|
86
|
+
{ key: "immediate", bucket: "now" },
|
|
87
|
+
{ key: "thirty_day", bucket: "30d" },
|
|
88
|
+
{ key: "ninety_day", bucket: "90d" },
|
|
89
|
+
{ key: "annual", bucket: "filing" },
|
|
90
|
+
];
|
|
91
|
+
for (const { key, bucket } of bucketKeys) {
|
|
92
|
+
for (const item of (_b = roadmap[key]) !== null && _b !== void 0 ? _b : []) {
|
|
93
|
+
if (item.strategy_id)
|
|
94
|
+
map.set(item.strategy_id, bucket);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return map;
|
|
98
|
+
}
|
|
64
99
|
function mapLlmToStrategies(llm) {
|
|
100
|
+
const nameLookup = buildEngineNameLookup(llm);
|
|
101
|
+
const bucketLookup = buildRoadmapBucketLookup(llm);
|
|
65
102
|
return llm.strategies
|
|
66
103
|
.filter((s) => s.applicable)
|
|
67
|
-
.map((s, idx) =>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
104
|
+
.map((s, idx) => {
|
|
105
|
+
var _a, _b, _c, _d, _e;
|
|
106
|
+
const id = (_a = s.strategyId) !== null && _a !== void 0 ? _a : s.strategyType;
|
|
107
|
+
// Prefer the real strategy_name from engineOutput, fall back to humanized strategyType
|
|
108
|
+
const name = (_b = nameLookup.get(id)) !== null && _b !== void 0 ? _b : humanizeStrategyType(s.strategyType);
|
|
109
|
+
const timelineBucket = (_c = bucketLookup.get(id)) !== null && _c !== void 0 ? _c : (s.priority === "HIGH" ? "now" : "90d");
|
|
110
|
+
const weightedScore = (_d = s.weightedScore) !== null && _d !== void 0 ? _d : (s.priority === "HIGH" ? 85 : s.priority === "MEDIUM" ? 70 : 55);
|
|
111
|
+
return {
|
|
112
|
+
rank: idx + 1,
|
|
113
|
+
code: id,
|
|
114
|
+
name,
|
|
115
|
+
cat: "income",
|
|
116
|
+
priority: (s.priority || "MEDIUM").toUpperCase(),
|
|
117
|
+
score: Math.round(weightedScore),
|
|
118
|
+
entities: [],
|
|
119
|
+
lo: s.estimatedSavings.min,
|
|
120
|
+
hi: s.estimatedSavings.max,
|
|
121
|
+
timeline: timelineBucket === "now" ? "Act now" : timelineBucket === "30d" ? "Within 30 days" : "Within 90 days",
|
|
122
|
+
timelineBucket,
|
|
123
|
+
clientBrief: s.summary,
|
|
124
|
+
action: (_e = s.implementationSteps[0]) !== null && _e !== void 0 ? _e : s.summary,
|
|
125
|
+
forms: s.requiredForms.join(", "),
|
|
126
|
+
abstract: s.summary,
|
|
127
|
+
sources: [],
|
|
128
|
+
trace: [],
|
|
129
|
+
cost: undefined,
|
|
130
|
+
};
|
|
131
|
+
});
|
|
87
132
|
}
|
|
88
133
|
function buildLlmComputed(strategies) {
|
|
89
134
|
const map = new Map();
|
|
@@ -100,7 +145,7 @@ const BUCKETS = [
|
|
|
100
145
|
{ key: "30d", label: "Within 30 Days", desc: "Documentation or payroll changes" },
|
|
101
146
|
{ key: "90d", label: "Within 90 Days", desc: "Structural changes — new accounts or plan setup" },
|
|
102
147
|
];
|
|
103
|
-
function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, userContext: _userContext = "expert", }) {
|
|
148
|
+
function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, onUploadMore, userContext: _userContext = "expert", }) {
|
|
104
149
|
var _a, _b;
|
|
105
150
|
const hasLlm = !!((_a = llmResult === null || llmResult === void 0 ? void 0 : llmResult.strategies) === null || _a === void 0 ? void 0 : _a.length);
|
|
106
151
|
// ─── Derived data ──────────────────────────────────────────────
|
|
@@ -110,11 +155,13 @@ function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPrep
|
|
|
110
155
|
const dashEligible = (0, react_1.useMemo)(() => (hasLlm ? llmStrategies : (0, compute_1.filterEligibleStrategies)(profile)), [hasLlm, llmStrategies, profile]);
|
|
111
156
|
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);
|
|
112
157
|
// ─── State ─────────────────────────────────────────────────────
|
|
113
|
-
|
|
158
|
+
// When LLM result is present, land directly on the Intelligence Report tab
|
|
159
|
+
const [topTab, setTopTab] = (0, react_1.useState)(hasLlm ? "report" : "extraction");
|
|
114
160
|
const [reportTab, setReportTab] = (0, react_1.useState)("report");
|
|
115
161
|
const [chartExpanded, setChartExpanded] = (0, react_1.useState)(false);
|
|
116
162
|
const [selected, setSelected] = (0, react_1.useState)(null);
|
|
117
|
-
|
|
163
|
+
// When LLM result is present, data is implicitly confirmed — skip the gate
|
|
164
|
+
const [dataConfirmed, setDataConfirmed] = (0, react_1.useState)(hasLlm);
|
|
118
165
|
const [reviewStatus, setReviewStatus] = (0, react_1.useState)({
|
|
119
166
|
unreviewed: data_1.EXTRACTED_DATA.reduce((a, d) => a + d.flagCount, 0),
|
|
120
167
|
edits: 0,
|
|
@@ -139,8 +186,23 @@ function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPrep
|
|
|
139
186
|
const c = computed.get(selected.rank);
|
|
140
187
|
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 });
|
|
141
188
|
}, [selected, computed]);
|
|
142
|
-
//
|
|
143
|
-
const
|
|
189
|
+
// Split eligible strategies into calculable (hi > 0) vs uncalculated ($0K)
|
|
190
|
+
const calculable = (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]);
|
|
191
|
+
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]);
|
|
192
|
+
// Sorted calculable strategies for impact distribution
|
|
193
|
+
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]);
|
|
194
|
+
// Reverse-map: strategy name → document names needed (from DOC_SPECS_BASE)
|
|
195
|
+
const strategyDocNeeds = (0, react_1.useMemo)(() => {
|
|
196
|
+
const map = new Map();
|
|
197
|
+
uncalculated.forEach((s) => {
|
|
198
|
+
const docs = data_1.DOC_SPECS_BASE
|
|
199
|
+
.filter((d) => d.strategies.some((st) => s.name.includes(st) || st.includes(s.code)))
|
|
200
|
+
.map((d) => d.name);
|
|
201
|
+
map.set(s.name, docs.length > 0 ? docs : ["Upload additional documents"]);
|
|
202
|
+
});
|
|
203
|
+
return map;
|
|
204
|
+
}, [uncalculated]);
|
|
205
|
+
const [uncalcExpanded, setUncalcExpanded] = (0, react_1.useState)(false);
|
|
144
206
|
return (react_1.default.createElement("div", null,
|
|
145
207
|
hasLlm && (llmResult === null || llmResult === void 0 ? void 0 : llmResult.meta) && (react_1.default.createElement("div", { className: "rounded-lg mb-3 px-4 py-2.5 flex items-center justify-between text-[11px] font-tax-axis-mono", style: {
|
|
146
208
|
background: "rgba(36,131,132,0.06)",
|
|
@@ -220,6 +282,23 @@ function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPrep
|
|
|
220
282
|
marginBottom: "-1px",
|
|
221
283
|
} }, lbl)))),
|
|
222
284
|
reportTab === "report" ? (react_1.default.createElement("div", null,
|
|
285
|
+
reviewStatus.unreviewed > 0 && (react_1.default.createElement("div", { className: "rounded-[14px] mb-4 flex items-center gap-3", style: {
|
|
286
|
+
background: "rgba(251,154,29,0.06)",
|
|
287
|
+
border: "1px solid rgba(251,154,29,0.20)",
|
|
288
|
+
borderLeft: "4px solid #FB9A1D",
|
|
289
|
+
padding: "14px 20px",
|
|
290
|
+
} },
|
|
291
|
+
react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "flex-shrink-0" },
|
|
292
|
+
react_1.default.createElement("path", { d: "M8 1.5l6.5 12H1.5L8 1.5z", stroke: "#FB9A1D", strokeWidth: "1.3", fill: "none" }),
|
|
293
|
+
react_1.default.createElement("path", { d: "M8 6.5v3M8 11h.005", stroke: "#FB9A1D", strokeWidth: "1.3", strokeLinecap: "round" })),
|
|
294
|
+
react_1.default.createElement("div", { className: "flex-1" },
|
|
295
|
+
react_1.default.createElement("span", { className: "text-[13px] font-semibold text-white font-tax-axis-body" },
|
|
296
|
+
reviewStatus.unreviewed,
|
|
297
|
+
" extracted value",
|
|
298
|
+
reviewStatus.unreviewed > 1 ? "s" : "",
|
|
299
|
+
" flagged for review"),
|
|
300
|
+
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")),
|
|
301
|
+
onReviewData && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onReviewData, className: "flex-shrink-0" }, "Review Extracted Values")))),
|
|
223
302
|
react_1.default.createElement("div", { className: "rounded-[14px] mb-4", style: {
|
|
224
303
|
background: "#0E1132",
|
|
225
304
|
border: "1px solid rgba(36,131,132,0.12)",
|
|
@@ -235,7 +314,7 @@ function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPrep
|
|
|
235
314
|
color: "#9498B8",
|
|
236
315
|
} }, chartExpanded ? "Collapse \u2191" : "Expand \u2193")),
|
|
237
316
|
sortedByImpact
|
|
238
|
-
.slice(0, chartExpanded ?
|
|
317
|
+
.slice(0, chartExpanded ? calculable.length : 12)
|
|
239
318
|
.map((s, i) => {
|
|
240
319
|
var _a, _b, _c, _d;
|
|
241
320
|
const chi = (_b = (_a = computed.get(s.rank)) === null || _a === void 0 ? void 0 : _a.hi) !== null && _b !== void 0 ? _b : s.hi;
|
|
@@ -260,24 +339,74 @@ function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPrep
|
|
|
260
339
|
"\u2013",
|
|
261
340
|
fmtK(chi))));
|
|
262
341
|
}),
|
|
263
|
-
!chartExpanded &&
|
|
342
|
+
!chartExpanded && calculable.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" },
|
|
264
343
|
"+ ",
|
|
265
|
-
|
|
344
|
+
calculable.length - 12,
|
|
266
345
|
" more strategies \u2014 click to view all")),
|
|
267
346
|
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" },
|
|
268
347
|
"Showing all ",
|
|
269
|
-
|
|
348
|
+
calculable.length,
|
|
270
349
|
" strategies \u2014 click to collapse"))),
|
|
271
350
|
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" },
|
|
272
351
|
react_1.default.createElement("span", null,
|
|
273
352
|
dashEligible.length,
|
|
274
353
|
" Strategies"),
|
|
275
354
|
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")),
|
|
276
|
-
react_1.default.createElement("div", { className: "grid grid-cols-2 gap-2.5 mb-4" },
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
355
|
+
react_1.default.createElement("div", { className: "grid grid-cols-2 gap-2.5 mb-4" },
|
|
356
|
+
calculable.map((s, i) => {
|
|
357
|
+
var _a, _b;
|
|
358
|
+
const c = computed.get(s.rank);
|
|
359
|
+
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 }));
|
|
360
|
+
}),
|
|
361
|
+
hasLlm && uncalculated.map((s, i) => (react_1.default.createElement("div", { key: s.rank, onClick: () => setSelected(s), className: "rounded-[14px] p-4 cursor-pointer", style: {
|
|
362
|
+
background: "#0E1132",
|
|
363
|
+
border: "1px solid rgba(36,131,132,0.12)",
|
|
364
|
+
boxShadow: "0 2px 8px rgba(6,8,33,0.3)",
|
|
365
|
+
animationDelay: `${0.2 + (calculable.length + i) * 0.06}s`,
|
|
366
|
+
} },
|
|
367
|
+
react_1.default.createElement("div", { className: "flex items-start justify-between gap-2 mb-2" },
|
|
368
|
+
react_1.default.createElement("div", { className: "flex items-center gap-2 flex-wrap" },
|
|
369
|
+
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),
|
|
370
|
+
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")),
|
|
371
|
+
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: {
|
|
372
|
+
background: "conic-gradient(#248384 0%, #248384 55%, #1A1D3A 55%)",
|
|
373
|
+
color: "#A1E5E6",
|
|
374
|
+
} }, s.score)),
|
|
375
|
+
react_1.default.createElement("div", { className: "text-[14px] font-semibold text-white font-tax-axis-head mb-1 leading-tight" }, s.name),
|
|
376
|
+
react_1.default.createElement("div", { className: "text-[12px] text-tax-axis-teal-light font-tax-axis-mono mb-2" }, s.timeline),
|
|
377
|
+
react_1.default.createElement("div", { className: "h-0.5 w-full rounded-sm mb-2", style: { background: "rgba(36,131,132,0.2)" } }),
|
|
378
|
+
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))))),
|
|
379
|
+
uncalculated.length > 0 && !hasLlm && (react_1.default.createElement("div", { className: "rounded-[14px] overflow-hidden mb-4", style: {
|
|
380
|
+
background: "#0E1132",
|
|
381
|
+
border: "1px solid rgba(251,154,29,0.15)",
|
|
382
|
+
boxShadow: "0 2px 8px rgba(6,8,33,0.3)",
|
|
383
|
+
} },
|
|
384
|
+
react_1.default.createElement("div", { onClick: () => setUncalcExpanded((p) => !p), className: "px-5 py-3.5 flex items-center gap-3 cursor-pointer" },
|
|
385
|
+
react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", className: "flex-shrink-0" },
|
|
386
|
+
react_1.default.createElement("circle", { cx: "7", cy: "7", r: "5.5", stroke: "#FB9A1D", strokeWidth: "1.2" }),
|
|
387
|
+
react_1.default.createElement("path", { d: "M7 4.5v3M7 9.5h.005", stroke: "#FB9A1D", strokeWidth: "1.2", strokeLinecap: "round" })),
|
|
388
|
+
react_1.default.createElement("span", { className: "text-[13px] font-semibold text-white font-tax-axis-body flex-1" }, hasLlm
|
|
389
|
+
? `${uncalculated.length} qualitative strateg${uncalculated.length > 1 ? "ies" : "y"} — CPA review recommended`
|
|
390
|
+
: `${uncalculated.length} strateg${uncalculated.length > 1 ? "ies" : "y"} need more data to calculate savings`),
|
|
391
|
+
react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: {
|
|
392
|
+
transform: uncalcExpanded ? "rotate(180deg)" : "none",
|
|
393
|
+
transition: "transform .2s",
|
|
394
|
+
} },
|
|
395
|
+
react_1.default.createElement("path", { d: "M3 4.5l3 3 3-3", stroke: "#9498B8", strokeWidth: "1.5", strokeLinecap: "round" }))),
|
|
396
|
+
uncalcExpanded && (react_1.default.createElement("div", { style: { borderTop: "1px solid rgba(251,154,29,0.12)", padding: "12px 20px" } },
|
|
397
|
+
uncalculated.map((s, i) => (react_1.default.createElement("div", { key: s.rank, className: "py-2.5 cursor-pointer", style: {
|
|
398
|
+
borderBottom: i < uncalculated.length - 1
|
|
399
|
+
? "1px solid rgba(36,131,132,0.08)"
|
|
400
|
+
: "none",
|
|
401
|
+
}, onClick: () => setSelected(s) },
|
|
402
|
+
react_1.default.createElement("div", { className: "flex items-center gap-2.5 mb-1" },
|
|
403
|
+
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),
|
|
404
|
+
react_1.default.createElement("span", { className: "text-[13px] text-white font-tax-axis-body font-semibold" }, s.name)),
|
|
405
|
+
react_1.default.createElement("div", { className: "text-[11px] text-tax-axis-text-2 font-tax-axis-body pl-0.5" }, hasLlm
|
|
406
|
+
? (s.abstract || s.clientBrief || "See CPA for details")
|
|
407
|
+
: `Needs: ${(strategyDocNeeds.get(s.name) || ["Upload additional documents"]).join(", ")}`)))),
|
|
408
|
+
!hasLlm && onUploadMore && (react_1.default.createElement("div", { className: "pt-3 mt-1", style: { borderTop: "1px solid rgba(251,154,29,0.12)" } },
|
|
409
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onUploadMore }, "Upload Documents"))))))),
|
|
281
410
|
!hasLlm && (react_1.default.createElement("div", { className: "rounded-[14px] overflow-hidden mb-4", style: {
|
|
282
411
|
background: "#0E1132",
|
|
283
412
|
border: "1px solid rgba(36,131,132,0.12)",
|
|
@@ -12,9 +12,11 @@ interface DocumentCardProps {
|
|
|
12
12
|
tierBadgeColor: "red" | "orange" | "neutral";
|
|
13
13
|
tierBadgeText: string;
|
|
14
14
|
helpOverride?: string;
|
|
15
|
+
fieldCount?: number;
|
|
15
16
|
onUpload: (file: File) => void;
|
|
16
17
|
onClear: () => void;
|
|
17
18
|
onRemove?: () => void;
|
|
19
|
+
onReview?: () => void;
|
|
18
20
|
}
|
|
19
|
-
export declare function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride, onUpload, onClear, onRemove, }: DocumentCardProps): React.JSX.Element;
|
|
21
|
+
export declare function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride, fieldCount, onUpload, onClear, onRemove, onReview, }: DocumentCardProps): React.JSX.Element;
|
|
20
22
|
export {};
|
|
@@ -33,7 +33,7 @@ const STATUS_STYLES = {
|
|
|
33
33
|
cardBorder: "rgba(15,110,86,0.25)",
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
|
-
function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride, onUpload, onClear, onRemove, }) {
|
|
36
|
+
function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, helpOverride, fieldCount, onUpload, onClear, onRemove, onReview, }) {
|
|
37
37
|
var _a, _b, _c;
|
|
38
38
|
const ss = STATUS_STYLES[doc.status];
|
|
39
39
|
const leftBorder = doc.status === "valid" ? "rgba(15,110,86,0.6)" : tierBorderColor;
|
|
@@ -64,12 +64,24 @@ function DocumentCard({ doc, tierBorderColor, tierBadgeColor, tierBadgeText, hel
|
|
|
64
64
|
react_1.default.createElement("span", { className: "text-[13px] font-medium text-white font-tax-axis-body" }, doc.name),
|
|
65
65
|
doc.status === "empty" && (react_1.default.createElement(TaxAxisBadge_1.TaxAxisBadge, { color: tierBadgeColor, size: "xs" }, tierBadgeText)),
|
|
66
66
|
doc.status === "failed" && (react_1.default.createElement(TaxAxisBadge_1.TaxAxisBadge, { color: "red", size: "xs" }, "FAILED"))),
|
|
67
|
-
react_1.default.createElement("div", { className: "text-[11px] text-tax-axis-text-3 font-tax-axis-body mt-0.5" }, doc.status === "
|
|
68
|
-
? doc.
|
|
69
|
-
:
|
|
67
|
+
react_1.default.createElement("div", { className: "text-[11px] text-tax-axis-text-3 font-tax-axis-body mt-0.5" }, doc.status === "valid" && doc.fileName
|
|
68
|
+
? `${doc.fileName}${fieldCount ? ` \u00b7 ${fieldCount} fields extracted` : ""}`
|
|
69
|
+
: doc.status === "failed" && doc.parseError
|
|
70
|
+
? doc.parseError
|
|
71
|
+
: ((_a = doc.fileName) !== null && _a !== void 0 ? _a : (helpOverride !== null && helpOverride !== void 0 ? helpOverride : doc.help)))),
|
|
70
72
|
react_1.default.createElement("div", { className: "flex items-center gap-2 flex-shrink-0" },
|
|
71
73
|
doc.status === "valid" && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
72
|
-
react_1.default.createElement("
|
|
74
|
+
react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none" },
|
|
75
|
+
react_1.default.createElement("path", { d: "M2.5 7l3.5 3.5 5.5-6", stroke: "#0F6E56", strokeWidth: "2", strokeLinecap: "round" })),
|
|
76
|
+
onReview && (react_1.default.createElement("button", { onClick: onReview, className: "rounded-md px-3 py-1 text-[11px] font-semibold font-tax-axis-mono cursor-pointer flex items-center gap-1.5", style: {
|
|
77
|
+
background: "rgba(99,102,241,0.12)",
|
|
78
|
+
border: "1px solid rgba(99,102,241,0.30)",
|
|
79
|
+
color: "#a5b4fc",
|
|
80
|
+
} },
|
|
81
|
+
react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" },
|
|
82
|
+
react_1.default.createElement("rect", { x: "2", y: "1.5", width: "8", height: "9", rx: "1.5", stroke: "#a5b4fc", strokeWidth: "1.2" }),
|
|
83
|
+
react_1.default.createElement("path", { d: "M4 4.5h4M4 6.5h4M4 8.5h2", stroke: "#a5b4fc", strokeWidth: "0.9", strokeLinecap: "round" })),
|
|
84
|
+
"Review")),
|
|
73
85
|
react_1.default.createElement("button", { onClick: onClear, className: "bg-transparent border-none p-1 text-tax-axis-text-4 text-sm cursor-pointer" }, "\u00D7"))),
|
|
74
86
|
(doc.status === "parsing" || doc.status === "validating") && (react_1.default.createElement("span", { className: "text-[10px] font-semibold font-tax-axis-mono", style: { color: doc.status === "parsing" ? "#248384" : "#FB9A1D" } }, doc.status === "parsing" ? "Parsing…" : "Uploading…")),
|
|
75
87
|
doc.status === "failed" && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export declare const EXTRACTED_FIELDS_QUERY = "\n query ExtractedDocumentFields($jobId: ID!, $documentId: ID!) {\n extractedDocumentFields(jobId: $jobId, documentId: $documentId) {\n documentId\n documentName\n fileName\n sections {\n head\n fields {\n key\n label\n value\n sourceRef\n confidence\n }\n }\n }\n }\n";
|
|
3
|
+
export declare const SAVE_FIELD_EDIT_MUTATION = "\n mutation SaveExtractedFieldEdit($jobId: ID!, $documentId: ID!, $fieldKey: String!, $value: String!) {\n saveExtractedFieldEdit(jobId: $jobId, documentId: $documentId, fieldKey: $fieldKey, value: $value) {\n success\n fieldKey\n savedValue\n }\n }\n";
|
|
4
|
+
export interface DocumentReviewModalProps {
|
|
5
|
+
documentId: string;
|
|
6
|
+
documentName: string;
|
|
7
|
+
fileName: string;
|
|
8
|
+
jobId: string;
|
|
9
|
+
parsedData?: Record<string, unknown> | null;
|
|
10
|
+
onSaveReviewedData?: (fields: Record<string, string>) => Promise<void>;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, parsedData, onSaveReviewedData, onClose, }: DocumentReviewModalProps): React.JSX.Element;
|