@paro.io/expert-shared-components 1.14.62 → 1.14.64

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.
Files changed (35) hide show
  1. package/lib/components/TaxAxis/TaxAxisShell.js +31 -5
  2. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +2 -1
  3. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +74 -9
  4. package/lib/tax-axis/components/documents/DocumentCard.d.ts +3 -1
  5. package/lib/tax-axis/components/documents/DocumentCard.js +15 -3
  6. package/lib/tax-axis/components/documents/DocumentReviewModal.d.ts +1 -3
  7. package/lib/tax-axis/components/documents/DocumentReviewModal.js +263 -113
  8. package/lib/tax-axis/components/documents/DocumentTier.d.ts +3 -1
  9. package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
  10. package/lib/tax-axis/components/documents/TaxAxisDocuments.js +21 -2
  11. package/lib/tax-axis/components/extractionReview/TaxAxisExtractionReview.js +17 -17
  12. package/lib/tax-axis/components/intake/TaxAxisIntake.js +11 -23
  13. package/lib/tax-axis/index.d.ts +2 -0
  14. package/lib/tax-axis/index.js +5 -1
  15. package/package.json +1 -1
  16. package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.d.ts +0 -13
  17. package/lib/tax-axis/components/documents/qbo/QboAvailableReportsModal.js +0 -180
  18. package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.d.ts +0 -10
  19. package/lib/tax-axis/components/documents/qbo/QboClientSelectorModal.js +0 -155
  20. package/lib/tax-axis/components/documents/qbo/QboConnectBanner.d.ts +0 -9
  21. package/lib/tax-axis/components/documents/qbo/QboConnectBanner.js +0 -55
  22. package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.d.ts +0 -10
  23. package/lib/tax-axis/components/documents/qbo/QboDocumentMappingModal.js +0 -202
  24. package/lib/tax-axis/components/documents/qbo/QboImportingModal.d.ts +0 -8
  25. package/lib/tax-axis/components/documents/qbo/QboImportingModal.js +0 -75
  26. package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.d.ts +0 -8
  27. package/lib/tax-axis/components/documents/qbo/QboPermissionsModal.js +0 -126
  28. package/lib/tax-axis/components/documents/qbo/index.d.ts +0 -8
  29. package/lib/tax-axis/components/documents/qbo/index.js +0 -17
  30. package/lib/tax-axis/components/documents/qbo/qboConstants.d.ts +0 -24
  31. package/lib/tax-axis/components/documents/qbo/qboConstants.js +0 -71
  32. package/lib/tax-axis/components/documents/qbo/types.d.ts +0 -43
  33. package/lib/tax-axis/components/documents/qbo/types.js +0 -3
  34. package/lib/tax-axis/components/documents/qbo/useQboFlow.d.ts +0 -19
  35. package/lib/tax-axis/components/documents/qbo/useQboFlow.js +0 -207
@@ -22,21 +22,19 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  Object.defineProperty(exports, "__esModule", { value: true });
35
26
  exports.SAVE_FIELD_EDIT_MUTATION = exports.EXTRACTED_FIELDS_QUERY = void 0;
36
27
  exports.DocumentReviewModal = DocumentReviewModal;
37
28
  const react_1 = __importStar(require("react"));
38
29
  const extractedData_1 = require("../../lib/data/extractedData");
39
- const documentFieldCatalog_1 = require("../../lib/documentFieldCatalog");
30
+ // ═══════════════════════════════════════════════════════════════════
31
+ // DocumentReviewModal — inspect and edit parser-extracted fields.
32
+ // Opens from the document row "Review" button. Sections, flagged
33
+ // fields, inline editing with debounced auto-save.
34
+ //
35
+ // Data: stub-backed from EXTRACTED_DATA for now. GraphQL query and
36
+ // mutation constants are exported for future wiring by consuming apps.
37
+ // ═══════════════════════════════════════════════════════════════════
40
38
  // ── GraphQL contracts (for consuming apps to use once resolvers land) ──
41
39
  exports.EXTRACTED_FIELDS_QUERY = `
42
40
  query ExtractedDocumentFields($jobId: ID!, $documentId: ID!) {
@@ -66,58 +64,69 @@ exports.SAVE_FIELD_EDIT_MUTATION = `
66
64
  }
67
65
  }
68
66
  `;
69
- // ── Format a raw value for display ──
70
- function formatValue(v) {
71
- if (v === null || v === undefined)
72
- return "";
73
- if (typeof v === "number")
74
- return `$${v.toLocaleString()}`;
75
- if (typeof v === "boolean")
76
- return v ? "Yes" : "No";
77
- return String(v);
78
- }
79
- // ── Build ReviewSection[] from real parsedData using the catalog ──
80
- function buildSectionsFromCatalog(documentType, fields) {
81
- const catalog = documentFieldCatalog_1.DOCUMENT_FIELD_CATALOG[documentType];
82
- if (!catalog) {
83
- // Unknown doc type — render all non-null scalar fields in one flat section
84
- const flatFields = Object.entries(fields)
85
- .filter(([, v]) => v !== null && v !== undefined && typeof v !== "object")
86
- .map(([key, val]) => ({
87
- key,
88
- label: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
89
- value: formatValue(val),
90
- sourceRef: "",
91
- confidence: 0.9,
92
- }));
93
- return flatFields.length > 0 ? [{ head: "Extracted Fields", fields: flatFields }] : [];
94
- }
95
- return catalog.sections
96
- .map((section) => {
97
- const sectionFields = section.fields
98
- .filter((key) => {
99
- const v = fields[key];
100
- // Include all scalar fields from the catalog — show empty string for null/undefined.
101
- // Skip only object/array values (dicts, arrays) which can't be inline-edited.
102
- return typeof v !== "object" || v === null || v === undefined;
103
- })
104
- .map((key) => {
105
- var _a, _b;
106
- const def = catalog.fields[key];
107
- return {
108
- key,
109
- label: (_a = def === null || def === void 0 ? void 0 : def.label) !== null && _a !== void 0 ? _a : key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
110
- value: formatValue(fields[key]),
111
- sourceRef: (_b = def === null || def === void 0 ? void 0 : def.sourceRef) !== null && _b !== void 0 ? _b : "",
112
- confidence: 0.9,
113
- };
114
- });
115
- return { head: section.head, fields: sectionFields };
116
- })
117
- .filter((s) => s.fields.length > 0);
118
- }
119
- // ── Stub fallback when no real parsedData is available ──
67
+ // ── Stub section data (maps EXTRACTED_DATA grouped sections) ──
68
+ const STUB_SECTIONS = {
69
+ pnl: [
70
+ {
71
+ head: "Revenue",
72
+ fields: [
73
+ { key: "pnl-gross-revenue", label: "Gross Revenue", value: "$1,847,200", sourceRef: "Line 1a", confidence: 0.95 },
74
+ { key: "pnl-cogs", label: "Cost of Goods Sold", value: "$412,500", sourceRef: "Line 2", confidence: 0.92 },
75
+ { key: "pnl-gross-profit", label: "Gross Profit", value: "$1,434,700", sourceRef: "Computed", confidence: 0.99 },
76
+ { key: "pnl-other-income", label: "Other Income", value: "$18,400", sourceRef: "Line 6", confidence: 0.62 },
77
+ ],
78
+ },
79
+ {
80
+ head: "Operating Expenses",
81
+ fields: [
82
+ { key: "pnl-wages", label: "Wages & Salaries", value: "$487,000", sourceRef: "Line 13", confidence: 0.94 },
83
+ { key: "pnl-officer-comp", label: "Officer Compensation", value: "$180,000", sourceRef: "Line 7", confidence: 0.91 },
84
+ { key: "pnl-rent", label: "Rent / Lease", value: "$84,000", sourceRef: "Line 15", confidence: 0.88 },
85
+ { key: "pnl-meals", label: "Meals & Entertainment", value: "$8,400", sourceRef: "Line 19", confidence: 0.85 },
86
+ { key: "pnl-prof-fees", label: "Professional Fees", value: "$24,000", sourceRef: "Line 17", confidence: 0.93 },
87
+ { key: "pnl-depreciation", label: "Depreciation", value: "$62,300", sourceRef: "Line 14", confidence: 0.96 },
88
+ ],
89
+ },
90
+ {
91
+ head: "Net Income",
92
+ fields: [
93
+ { key: "pnl-net-ordinary", label: "Net Ordinary Income", value: "$598,000", sourceRef: "Line 21", confidence: 0.97 },
94
+ { key: "pnl-tax-income", label: "Taxable Income", value: "$580,200", sourceRef: "Line 28", confidence: 0.90 },
95
+ { key: "pnl-net-income", label: "Net Income", value: "$142,000", sourceRef: "Line 30", confidence: 0.93 },
96
+ ],
97
+ },
98
+ ],
99
+ balance: [
100
+ {
101
+ head: "Assets",
102
+ fields: [
103
+ { key: "bs-cash", label: "Cash & Equivalents", value: "$128,400", sourceRef: "Line 1", confidence: 0.97 },
104
+ { key: "bs-ar", label: "Accounts Receivable", value: "$42,000", sourceRef: "Line 2", confidence: 0.94 },
105
+ { key: "bs-inventory", label: "Inventory", value: "$45,000", sourceRef: "Line 3", confidence: 0.91 },
106
+ { key: "bs-total-assets", label: "Total Assets", value: "$340,000", sourceRef: "Line 11", confidence: 0.98 },
107
+ ],
108
+ },
109
+ {
110
+ head: "Liabilities",
111
+ fields: [
112
+ { key: "bs-ap", label: "Accounts Payable", value: "$31,200", sourceRef: "Line 15", confidence: 0.93 },
113
+ { key: "bs-loans", label: "Loans Payable", value: "$78,000", sourceRef: "Line 17", confidence: 0.90 },
114
+ { key: "bs-total-liab", label: "Total Liabilities", value: "$109,200", sourceRef: "Line 22", confidence: 0.96 },
115
+ ],
116
+ },
117
+ {
118
+ head: "Equity",
119
+ fields: [
120
+ { key: "bs-retained", label: "Retained Earnings", value: "$188,800", sourceRef: "Line 24", confidence: 0.92 },
121
+ { key: "bs-total-equity", label: "Total Equity", value: "$230,800", sourceRef: "Line 27", confidence: 0.95 },
122
+ ],
123
+ },
124
+ ],
125
+ };
120
126
  function getStubSections(documentId) {
127
+ if (STUB_SECTIONS[documentId])
128
+ return STUB_SECTIONS[documentId];
129
+ // Fallback: build sections from EXTRACTED_DATA if available
121
130
  const doc = extractedData_1.EXTRACTED_DATA.find((d) => d.docId === documentId);
122
131
  if (!doc)
123
132
  return [];
@@ -138,110 +147,251 @@ function getTotalFieldCount(sections) {
138
147
  return sections.reduce((sum, s) => sum + s.fields.length, 0);
139
148
  }
140
149
  // ── Component ──
141
- function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, parsedData, onSaveReviewedData, onClose, }) {
150
+ function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, onClose, }) {
142
151
  const [loading, setLoading] = (0, react_1.useState)(true);
143
152
  const [sections, setSections] = (0, react_1.useState)([]);
144
153
  const [saveStatus, setSaveStatus] = (0, react_1.useState)("idle");
145
154
  const debounceTimers = (0, react_1.useRef)({});
155
+ // Stub fetch: simulate loading delay
146
156
  (0, react_1.useEffect)(() => {
147
- var _a;
148
- if (parsedData && typeof parsedData === "object") {
149
- const fields = ((_a = parsedData.fields) !== null && _a !== void 0 ? _a : parsedData);
150
- const documentType = parsedData.documentType || documentId;
151
- setSections(buildSectionsFromCatalog(documentType, fields));
152
- setLoading(false);
153
- return;
154
- }
155
- // Fallback: stub loading delay
156
157
  const t = setTimeout(() => {
157
158
  setSections(getStubSections(documentId));
158
159
  setLoading(false);
159
160
  }, 400);
160
161
  return () => clearTimeout(t);
161
- }, [documentId, parsedData]);
162
+ }, [documentId]);
162
163
  const handleFieldChange = (0, react_1.useCallback)((sectionIdx, fieldIdx, newValue) => {
163
164
  setSections((prev) => prev.map((sec, si) => si === sectionIdx
164
165
  ? Object.assign(Object.assign({}, sec), { fields: sec.fields.map((f, fi) => fi === fieldIdx ? Object.assign(Object.assign({}, f), { value: newValue }) : f) }) : sec));
165
166
  const timerKey = `${sectionIdx}-${fieldIdx}`;
166
- clearTimeout(debounceTimers.current[timerKey]);
167
+ if (debounceTimers.current[timerKey]) {
168
+ clearTimeout(debounceTimers.current[timerKey]);
169
+ }
167
170
  setSaveStatus("saving");
168
171
  debounceTimers.current[timerKey] = setTimeout(() => {
172
+ // Stub save — replace with GraphQL mutation when resolvers are ready
169
173
  setSaveStatus("saved");
170
174
  setTimeout(() => setSaveStatus("idle"), 1500);
171
175
  }, 900);
172
- }, [sections]);
173
- const handleDone = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
174
- if (onSaveReviewedData && sections.length > 0) {
175
- const allFields = {};
176
- sections.forEach((sec) => sec.fields.forEach((f) => { allFields[f.key] = f.value; }));
177
- try {
178
- yield onSaveReviewedData(allFields);
179
- }
180
- catch ( /* non-fatal */_a) { /* non-fatal */ }
181
- }
182
- onClose();
183
- }), [onSaveReviewedData, sections, onClose]);
176
+ }, []);
177
+ // Cleanup debounce timers on unmount
184
178
  (0, react_1.useEffect)(() => {
185
179
  const timers = debounceTimers.current;
186
- return () => { Object.values(timers).forEach(clearTimeout); };
180
+ return () => {
181
+ Object.values(timers).forEach(clearTimeout);
182
+ };
187
183
  }, []);
188
184
  const totalFields = getTotalFieldCount(sections);
189
185
  const isFlagged = (f) => f.confidence < 0.8;
190
- return (react_1.default.createElement("div", { onClick: onClose, style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,0.65)", display: "flex", alignItems: "center", justifyContent: "center" } },
191
- react_1.default.createElement("div", { onClick: (e) => e.stopPropagation(), style: { width: 520, maxHeight: "85vh", background: "#111827", border: "1px solid #1f2937", borderRadius: 16, display: "flex", flexDirection: "column", boxShadow: "0 25px 60px rgba(0,0,0,0.5)" } },
192
- react_1.default.createElement("div", { style: { padding: "20px 24px 16px", borderBottom: "1px solid #1f2937", display: "flex", alignItems: "flex-start", gap: 14 } },
193
- react_1.default.createElement("div", { style: { width: 40, height: 40, borderRadius: 10, background: "rgba(99,102,241,0.12)", border: "1px solid rgba(99,102,241,0.25)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 } },
186
+ return (
187
+ // Overlay
188
+ react_1.default.createElement("div", { onClick: onClose, style: {
189
+ position: "fixed",
190
+ inset: 0,
191
+ zIndex: 9999,
192
+ background: "rgba(0,0,0,0.65)",
193
+ display: "flex",
194
+ alignItems: "center",
195
+ justifyContent: "center",
196
+ } },
197
+ react_1.default.createElement("div", { onClick: (e) => e.stopPropagation(), style: {
198
+ width: 520,
199
+ maxHeight: "85vh",
200
+ background: "#111827",
201
+ border: "1px solid #1f2937",
202
+ borderRadius: 16,
203
+ display: "flex",
204
+ flexDirection: "column",
205
+ boxShadow: "0 25px 60px rgba(0,0,0,0.5)",
206
+ } },
207
+ react_1.default.createElement("div", { style: {
208
+ padding: "20px 24px 16px",
209
+ borderBottom: "1px solid #1f2937",
210
+ display: "flex",
211
+ alignItems: "flex-start",
212
+ gap: 14,
213
+ } },
214
+ react_1.default.createElement("div", { style: {
215
+ width: 40,
216
+ height: 40,
217
+ borderRadius: 10,
218
+ background: "rgba(99,102,241,0.12)",
219
+ border: "1px solid rgba(99,102,241,0.25)",
220
+ display: "flex",
221
+ alignItems: "center",
222
+ justifyContent: "center",
223
+ flexShrink: 0,
224
+ } },
194
225
  react_1.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" },
195
226
  react_1.default.createElement("rect", { x: "3", y: "2", width: "12", height: "14", rx: "2", stroke: "#818cf8", strokeWidth: "1.5" }),
196
227
  react_1.default.createElement("path", { d: "M6 6h6M6 9h6M6 12h4", stroke: "#818cf8", strokeWidth: "1.2", strokeLinecap: "round" }))),
197
228
  react_1.default.createElement("div", { style: { flex: 1, minWidth: 0 } },
198
- react_1.default.createElement("div", { className: "font-tax-axis-body", style: { fontSize: 15, fontWeight: 600, color: "#f3f4f6", marginBottom: 3 } },
229
+ react_1.default.createElement("div", { className: "font-tax-axis-body", style: {
230
+ fontSize: 15,
231
+ fontWeight: 600,
232
+ color: "#f3f4f6",
233
+ marginBottom: 3,
234
+ } },
199
235
  documentName,
200
236
  " \u2014 Extracted Fields"),
201
237
  react_1.default.createElement("div", { className: "font-tax-axis-body", style: { fontSize: 12, color: "#9ca3af" } },
202
238
  fileName,
203
- !loading && react_1.default.createElement(react_1.default.Fragment, null,
239
+ !loading && (react_1.default.createElement(react_1.default.Fragment, null,
204
240
  " ",
205
241
  "\u00B7 ",
206
242
  totalFields,
207
- " fields \u00B7 Review and correct parsed values"))),
208
- react_1.default.createElement("button", { onClick: onClose, style: { background: "transparent", border: "none", color: "#6b7280", fontSize: 20, cursor: "pointer", padding: "2px 6px", lineHeight: 1 } }, "\u00D7")),
209
- react_1.default.createElement("div", { style: { flex: 1, overflowY: "auto", padding: "16px 24px 8px" } }, loading ? (react_1.default.createElement(LoadingSkeleton, null)) : sections.length === 0 ? (react_1.default.createElement("div", { style: { color: "#6b7280", fontSize: 13, textAlign: "center", padding: "32px 0" } }, "No extracted fields available for this document.")) : (sections.map((section, si) => (react_1.default.createElement("div", { key: section.head, style: { marginBottom: 20 } },
210
- react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 10 } },
211
- react_1.default.createElement("span", { className: "font-tax-axis-mono", style: { fontSize: 10, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", color: "#6b7280" } }, section.head),
212
- react_1.default.createElement("div", { style: { flex: 1, height: 1, background: "#1f2937" } })),
213
- react_1.default.createElement("div", { style: { background: "#0d1117", borderRadius: 10, border: "1px solid #1f2937", overflow: "hidden" } }, section.fields.map((field, fi) => {
243
+ " fields \u00B7 Review and correct parsed values")))),
244
+ react_1.default.createElement("button", { onClick: onClose, style: {
245
+ background: "transparent",
246
+ border: "none",
247
+ color: "#6b7280",
248
+ fontSize: 20,
249
+ cursor: "pointer",
250
+ padding: "2px 6px",
251
+ lineHeight: 1,
252
+ } }, "\u00D7")),
253
+ react_1.default.createElement("div", { style: {
254
+ flex: 1,
255
+ overflowY: "auto",
256
+ padding: "16px 24px 8px",
257
+ } }, loading ? (react_1.default.createElement(LoadingSkeleton, null)) : (sections.map((section, si) => (react_1.default.createElement("div", { key: section.head, style: { marginBottom: 20 } },
258
+ react_1.default.createElement("div", { style: {
259
+ display: "flex",
260
+ alignItems: "center",
261
+ gap: 10,
262
+ marginBottom: 10,
263
+ } },
264
+ react_1.default.createElement("span", { className: "font-tax-axis-mono", style: {
265
+ fontSize: 10,
266
+ fontWeight: 700,
267
+ letterSpacing: "0.08em",
268
+ textTransform: "uppercase",
269
+ color: "#6b7280",
270
+ } }, section.head),
271
+ react_1.default.createElement("div", { style: {
272
+ flex: 1,
273
+ height: 1,
274
+ background: "#1f2937",
275
+ } })),
276
+ react_1.default.createElement("div", { style: {
277
+ background: "#0d1117",
278
+ borderRadius: 10,
279
+ border: "1px solid #1f2937",
280
+ overflow: "hidden",
281
+ } }, section.fields.map((field, fi) => {
214
282
  const flagged = isFlagged(field);
215
- return (react_1.default.createElement("div", { key: field.key, style: { display: "grid", gridTemplateColumns: "160px 1fr auto", alignItems: "center", padding: "10px 14px", borderBottom: fi < section.fields.length - 1 ? "1px solid #1f2937" : "none", gap: 12 } },
216
- react_1.default.createElement("span", { className: "font-tax-axis-body", style: { fontSize: 12, color: flagged ? "#fbbf24" : "#9ca3af", display: "flex", alignItems: "center", gap: 5 } },
283
+ return (react_1.default.createElement("div", { key: field.key, style: {
284
+ display: "grid",
285
+ gridTemplateColumns: "140px 1fr auto",
286
+ alignItems: "center",
287
+ padding: "10px 14px",
288
+ borderBottom: fi < section.fields.length - 1
289
+ ? "1px solid #1f2937"
290
+ : "none",
291
+ gap: 12,
292
+ } },
293
+ react_1.default.createElement("span", { className: "font-tax-axis-body", style: {
294
+ fontSize: 12,
295
+ color: flagged ? "#fbbf24" : "#9ca3af",
296
+ display: "flex",
297
+ alignItems: "center",
298
+ gap: 5,
299
+ } },
217
300
  flagged && (react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" },
218
301
  react_1.default.createElement("path", { d: "M6 1L11 10H1L6 1Z", stroke: "#fbbf24", strokeWidth: "1.2", strokeLinejoin: "round" }),
219
302
  react_1.default.createElement("path", { d: "M6 4.5V6.5M6 8V8.01", stroke: "#fbbf24", strokeWidth: "1.1", strokeLinecap: "round" }))),
220
303
  field.label),
221
- react_1.default.createElement("input", { type: "text", value: field.value, onChange: (e) => handleFieldChange(si, fi, e.target.value), style: { background: "#0d1117", border: `1px solid ${flagged ? "rgba(251,191,36,0.4)" : "#1f2937"}`, borderRadius: 6, padding: "7px 10px", color: "#e5e7eb", fontSize: 13, fontFamily: "monospace", outline: "none", width: "100%", boxSizing: "border-box" } }),
222
- react_1.default.createElement("span", { className: "font-tax-axis-mono", style: { fontSize: 11, color: flagged ? "#fbbf24" : "#4ade80", whiteSpace: "nowrap", display: "flex", alignItems: "center", gap: 4 } },
223
- field.sourceRef || "",
304
+ react_1.default.createElement("input", { type: "text", value: field.value, onChange: (e) => handleFieldChange(si, fi, e.target.value), style: {
305
+ background: "#0d1117",
306
+ border: `1px solid ${flagged ? "rgba(251,191,36,0.4)" : "#1f2937"}`,
307
+ borderRadius: 6,
308
+ padding: "7px 10px",
309
+ color: "#e5e7eb",
310
+ fontSize: 13,
311
+ fontFamily: "monospace",
312
+ outline: "none",
313
+ width: "100%",
314
+ boxSizing: "border-box",
315
+ } }),
316
+ react_1.default.createElement("span", { className: "font-tax-axis-mono", style: {
317
+ fontSize: 11,
318
+ color: flagged ? "#fbbf24" : "#4ade80",
319
+ whiteSpace: "nowrap",
320
+ display: "flex",
321
+ alignItems: "center",
322
+ gap: 4,
323
+ } },
324
+ field.sourceRef,
224
325
  " ",
225
- flagged ? react_1.default.createElement("span", { style: { fontSize: 10 } }, "\u25B2") : react_1.default.createElement("span", { style: { fontSize: 12 } }, "\u2713"))));
326
+ flagged ? (react_1.default.createElement("span", { style: { fontSize: 10 } }, "\u25B2")) : (react_1.default.createElement("span", { style: { color: "#4ade80", fontSize: 12 } }, "\u2713")))));
226
327
  }))))))),
227
- react_1.default.createElement("div", { style: { padding: "14px 24px", borderTop: "1px solid #1f2937", display: "flex", alignItems: "center", justifyContent: "space-between" } },
228
- react_1.default.createElement("span", { className: "font-tax-axis-body", style: { fontSize: 11, color: "#6b7280", display: "flex", alignItems: "center", gap: 6 } },
328
+ react_1.default.createElement("div", { style: {
329
+ padding: "14px 24px",
330
+ borderTop: "1px solid #1f2937",
331
+ display: "flex",
332
+ alignItems: "center",
333
+ justifyContent: "space-between",
334
+ } },
335
+ react_1.default.createElement("span", { className: "font-tax-axis-body", style: {
336
+ fontSize: 11,
337
+ color: "#6b7280",
338
+ display: "flex",
339
+ alignItems: "center",
340
+ gap: 6,
341
+ } },
229
342
  saveStatus === "idle" && (react_1.default.createElement(react_1.default.Fragment, null,
230
343
  react_1.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" },
231
344
  react_1.default.createElement("circle", { cx: "6", cy: "6", r: "5", stroke: "#6b7280", strokeWidth: "1.2" }),
232
345
  react_1.default.createElement("path", { d: "M6 3.5V6.5L8 7.5", stroke: "#6b7280", strokeWidth: "1.1", strokeLinecap: "round" })),
233
346
  "Changes save automatically")),
234
347
  saveStatus === "saving" && (react_1.default.createElement(react_1.default.Fragment, null,
235
- react_1.default.createElement("div", { style: { width: 10, height: 10, borderRadius: "50%", border: "2px solid transparent", borderTopColor: "#818cf8", animation: "spin 0.6s linear infinite" } }),
348
+ react_1.default.createElement("div", { style: {
349
+ width: 10,
350
+ height: 10,
351
+ borderRadius: "50%",
352
+ border: "2px solid transparent",
353
+ borderTopColor: "#818cf8",
354
+ animation: "spin 0.6s linear infinite",
355
+ } }),
236
356
  "Saving\u2026")),
237
- saveStatus === "saved" && react_1.default.createElement("span", { style: { color: "#4ade80" } }, "Saved \u2713")),
238
- react_1.default.createElement("button", { onClick: handleDone, className: "font-tax-axis-body", style: { background: "rgba(99,102,241,0.9)", border: "none", borderRadius: 8, padding: "9px 28px", color: "#fff", fontSize: 13, fontWeight: 600, cursor: "pointer" } }, "Done"))),
239
- react_1.default.createElement("style", null, `@keyframes spin { to { transform: rotate(360deg); } }`)));
357
+ saveStatus === "saved" && (react_1.default.createElement("span", { style: { color: "#4ade80" } }, "Saved \u2713"))),
358
+ react_1.default.createElement("button", { onClick: onClose, className: "font-tax-axis-body", style: {
359
+ background: "rgba(99,102,241,0.9)",
360
+ border: "none",
361
+ borderRadius: 8,
362
+ padding: "9px 28px",
363
+ color: "#fff",
364
+ fontSize: 13,
365
+ fontWeight: 600,
366
+ cursor: "pointer",
367
+ } }, "Done"))),
368
+ react_1.default.createElement("style", null, `
369
+ @keyframes spin {
370
+ to { transform: rotate(360deg); }
371
+ }
372
+ `)));
240
373
  }
374
+ // ── Loading skeleton ──
241
375
  function LoadingSkeleton() {
242
376
  return (react_1.default.createElement("div", null, [1, 2].map((i) => (react_1.default.createElement("div", { key: i, style: { marginBottom: 20 } },
243
- react_1.default.createElement("div", { style: { width: 100, height: 10, background: "#1f2937", borderRadius: 4, marginBottom: 10 } }),
244
- react_1.default.createElement("div", { style: { background: "#0d1117", borderRadius: 10, border: "1px solid #1f2937", padding: 14 } }, [1, 2, 3].map((j) => (react_1.default.createElement("div", { key: j, style: { display: "grid", gridTemplateColumns: "160px 1fr 60px", gap: 12, marginBottom: j < 3 ? 12 : 0 } },
377
+ react_1.default.createElement("div", { style: {
378
+ width: 100,
379
+ height: 10,
380
+ background: "#1f2937",
381
+ borderRadius: 4,
382
+ marginBottom: 10,
383
+ } }),
384
+ react_1.default.createElement("div", { style: {
385
+ background: "#0d1117",
386
+ borderRadius: 10,
387
+ border: "1px solid #1f2937",
388
+ padding: 14,
389
+ } }, [1, 2, 3].map((j) => (react_1.default.createElement("div", { key: j, style: {
390
+ display: "grid",
391
+ gridTemplateColumns: "140px 1fr 60px",
392
+ gap: 12,
393
+ marginBottom: j < 3 ? 12 : 0,
394
+ } },
245
395
  react_1.default.createElement("div", { style: { height: 14, background: "#1f2937", borderRadius: 4 } }),
246
396
  react_1.default.createElement("div", { style: { height: 32, background: "#1f2937", borderRadius: 6 } }),
247
397
  react_1.default.createElement("div", { style: { height: 14, background: "#1f2937", borderRadius: 4 } }))))))))));
@@ -14,8 +14,10 @@ interface DocumentTierProps {
14
14
  tier: TierDef;
15
15
  docs: DocState[];
16
16
  helpOverrides: Record<string, string>;
17
+ fieldCounts: Record<string, number>;
17
18
  onUpload: (idx: number) => void;
18
19
  onClear: (idx: number) => void;
20
+ onReview: (docId: string) => void;
19
21
  }
20
- export declare function DocumentTier({ tier, docs, helpOverrides, onUpload, onClear, }: DocumentTierProps): React.JSX.Element | null;
22
+ export declare function DocumentTier({ tier, docs, helpOverrides, fieldCounts, onUpload, onClear, onReview, }: DocumentTierProps): React.JSX.Element | null;
21
23
  export {};
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DocumentTier = DocumentTier;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const DocumentCard_1 = require("./DocumentCard");
9
- function DocumentTier({ tier, docs, helpOverrides, onUpload, onClear, }) {
9
+ function DocumentTier({ tier, docs, helpOverrides, fieldCounts, onUpload, onClear, onReview, }) {
10
10
  const tierDocs = tier.ids
11
11
  .map((id) => {
12
12
  const idx = docs.findIndex((d) => d.id === id);
@@ -19,5 +19,5 @@ function DocumentTier({ tier, docs, helpOverrides, onUpload, onClear, }) {
19
19
  react_1.default.createElement("div", { className: "flex items-center gap-2 mb-2" },
20
20
  react_1.default.createElement("span", { className: "text-[10px] font-bold uppercase tracking-widest font-tax-axis-mono", style: { color: tier.labelColor } }, tier.label),
21
21
  react_1.default.createElement("span", { className: "text-[10px] text-tax-axis-text-4 font-tax-axis-body" }, tier.sublabel)),
22
- react_1.default.createElement("div", { className: "grid gap-1.5" }, tierDocs.map(({ doc, idx }) => (react_1.default.createElement(DocumentCard_1.DocumentCard, { key: doc.id, doc: doc, tierBorderColor: tier.borderColor, tierBadgeColor: tier.badgeColor, tierBadgeText: tier.badgeText, helpOverride: helpOverrides[doc.id], onUpload: () => onUpload(idx), onClear: () => onClear(idx) }))))));
22
+ react_1.default.createElement("div", { className: "grid gap-1.5" }, tierDocs.map(({ doc, idx }) => (react_1.default.createElement(DocumentCard_1.DocumentCard, { key: doc.id, doc: doc, tierBorderColor: tier.borderColor, tierBadgeColor: tier.badgeColor, tierBadgeText: tier.badgeText, helpOverride: helpOverrides[doc.id], fieldCount: fieldCounts[doc.id], onUpload: () => onUpload(idx), onClear: () => onClear(idx), onReview: () => onReview(doc.id) }))))));
23
23
  }
@@ -28,6 +28,7 @@ const react_1 = __importStar(require("react"));
28
28
  const documents_1 = require("../../lib/data/documents");
29
29
  const TaxAxisButton_1 = require("../shared/TaxAxisButton");
30
30
  const DocumentTier_1 = require("./DocumentTier");
31
+ const DocumentReviewModal_1 = require("./DocumentReviewModal");
31
32
  // Stub filenames assigned when the user clicks "Upload" (mock App.jsx:1237)
32
33
  const STUB_FILENAMES = {
33
34
  "1120s": "2025_1120S.pdf",
@@ -39,6 +40,17 @@ const STUB_FILENAMES = {
39
40
  "fixed-assets": "Fixed_Assets.xlsx",
40
41
  "prior-returns": "Prior_Returns.pdf",
41
42
  };
43
+ // Stub field counts per doc (mirrors STUB_SECTIONS in DocumentReviewModal)
44
+ const STUB_FIELD_COUNTS = {
45
+ pnl: 13,
46
+ balance: 9,
47
+ "1120s": 3,
48
+ payroll: 3,
49
+ "state-return": 2,
50
+ cashflow: 1,
51
+ "fixed-assets": 1,
52
+ "prior-returns": 1,
53
+ };
42
54
  // Short help text shown below each doc name when not yet uploaded
43
55
  // (mock App.jsx:1384). Overrides the longer DOC_SPECS_BASE.help.
44
56
  const HELP_OVERRIDES = {
@@ -83,8 +95,14 @@ const TIER_DEFS = [
83
95
  },
84
96
  ];
85
97
  function TaxAxisDocuments({ profile, onContinue, onBack, userContext: _userContext = "expert", }) {
98
+ var _a;
86
99
  const docSpecs = (0, react_1.useMemo)(() => (0, documents_1.getDocSpecs)(profile), [profile]);
87
100
  const [docs, setDocs] = (0, react_1.useState)(() => docSpecs.map((s) => (Object.assign(Object.assign({}, s), { status: "empty", fileName: null }))));
101
+ // Review modal state
102
+ const [reviewDocId, setReviewDocId] = (0, react_1.useState)(null);
103
+ const reviewDoc = reviewDocId
104
+ ? (_a = docs.find((d) => d.id === reviewDocId)) !== null && _a !== void 0 ? _a : null
105
+ : null;
88
106
  // Stub upload: empty -> validating -> valid after a short delay
89
107
  // (mock App.jsx:1238-1241)
90
108
  const handleUpload = (idx) => {
@@ -148,10 +166,11 @@ function TaxAxisDocuments({ profile, onContinue, onBack, userContext: _userConte
148
166
  coveragePct,
149
167
  "% coverage"),
150
168
  validCount < docs.length && (react_1.default.createElement("span", { className: "text-[10px] text-tax-axis-text-4 font-tax-axis-body" }, "Upload more documents to increase strategy coverage")))),
151
- TIER_DEFS.map((tier) => (react_1.default.createElement(DocumentTier_1.DocumentTier, { key: tier.key, tier: tier, docs: docs, helpOverrides: HELP_OVERRIDES, onUpload: handleUpload, onClear: handleClear }))),
169
+ TIER_DEFS.map((tier) => (react_1.default.createElement(DocumentTier_1.DocumentTier, { key: tier.key, tier: tier, docs: docs, helpOverrides: HELP_OVERRIDES, fieldCounts: STUB_FIELD_COUNTS, onUpload: handleUpload, onClear: handleClear, onReview: (docId) => setReviewDocId(docId) }))),
152
170
  react_1.default.createElement("div", { className: "flex gap-3 mt-6" },
153
171
  react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back"),
154
172
  react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onContinue, disabled: requiredCount > requiredValid, className: "flex-1" }, requiredCount > requiredValid
155
173
  ? `Upload ${requiredCount - requiredValid} more required doc${requiredCount - requiredValid > 1 ? "s" : ""}`
156
- : "Run Analysis"))));
174
+ : "Run Analysis")),
175
+ reviewDoc && (react_1.default.createElement(DocumentReviewModal_1.DocumentReviewModal, { documentId: reviewDoc.id, documentName: reviewDoc.name, fileName: reviewDoc.fileName || "", jobId: "stub-job-id", onClose: () => setReviewDocId(null) }))));
157
176
  }
@@ -89,6 +89,22 @@ function TaxAxisExtractionReview({ onStatusChange, onConfirmAndUnlock, onBack, }
89
89
  return (react_1.default.createElement("div", null,
90
90
  react_1.default.createElement("style", null, `@keyframes spin{to{transform:rotate(360deg)}}`),
91
91
  react_1.default.createElement(PurposeBlock_1.PurposeBlock, { totalFields: totalFields, totalDocs: data_1.EXTRACTED_DATA.length }),
92
+ onConfirmAndUnlock && (react_1.default.createElement("div", { style: {
93
+ marginBottom: 16,
94
+ background: "linear-gradient(135deg, rgba(36,131,132,0.12), rgba(36,131,132,0.06))",
95
+ border: "1px solid rgba(36,131,132,0.3)",
96
+ borderRadius: 12,
97
+ padding: "18px 20px",
98
+ } },
99
+ react_1.default.createElement("div", { className: "flex items-center gap-4" },
100
+ react_1.default.createElement("div", { className: "flex-1" },
101
+ react_1.default.createElement("div", { className: "text-[15px] font-bold text-white font-tax-axis-head mb-1" }, "Ready to view your report?"),
102
+ react_1.default.createElement("div", { className: "text-[13px] text-tax-axis-text leading-relaxed font-tax-axis-body" }, totalFlags - totalEdits > 0
103
+ ? (totalFlags - totalEdits) + " value" + (totalFlags - totalEdits > 1 ? "s" : "") + " still flagged. You can confirm now or correct values first."
104
+ : "All extracted values look good. Confirm to unlock the Intelligence Report.")),
105
+ react_1.default.createElement("div", { className: "flex gap-2.5" },
106
+ onBack && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back to Dashboard")),
107
+ react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onConfirmAndUnlock }, totalFlags - totalEdits > 0 ? "Confirm & Unlock Report" : "Confirm & View Report"))))),
92
108
  react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 12 } },
93
109
  react_1.default.createElement("div", { style: {
94
110
  width: 8,
@@ -166,21 +182,5 @@ function TaxAxisExtractionReview({ onStatusChange, onConfirmAndUnlock, onBack, }
166
182
  borderRadius: 4,
167
183
  border: "1px solid #2E3160",
168
184
  } }, d.code))))))),
169
- react_1.default.createElement(RerunFooter_1.RerunFooter, { totalEdits: totalEdits, rerunning: rerunning, onRerun: handleRerun }),
170
- onConfirmAndUnlock && (react_1.default.createElement("div", { style: {
171
- marginTop: 16,
172
- background: "linear-gradient(135deg, rgba(36,131,132,0.12), rgba(36,131,132,0.06))",
173
- border: "1px solid rgba(36,131,132,0.3)",
174
- borderRadius: 12,
175
- padding: "18px 20px",
176
- } },
177
- react_1.default.createElement("div", { className: "flex items-center gap-4" },
178
- react_1.default.createElement("div", { className: "flex-1" },
179
- react_1.default.createElement("div", { className: "text-[15px] font-bold text-white font-tax-axis-head mb-1" }, "Ready to view your report?"),
180
- react_1.default.createElement("div", { className: "text-[13px] text-tax-axis-text leading-relaxed font-tax-axis-body" }, totalFlags - totalEdits > 0
181
- ? (totalFlags - totalEdits) + " value" + (totalFlags - totalEdits > 1 ? "s" : "") + " still flagged. You can confirm now or correct values first."
182
- : "All extracted values look good. Confirm to unlock the Intelligence Report.")),
183
- react_1.default.createElement("div", { className: "flex gap-2.5" },
184
- onBack && (react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back to Dashboard")),
185
- react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onConfirmAndUnlock }, totalFlags - totalEdits > 0 ? "Confirm & Unlock Report" : "Confirm & View Report")))))));
185
+ react_1.default.createElement(RerunFooter_1.RerunFooter, { totalEdits: totalEdits, rerunning: rerunning, onRerun: handleRerun })));
186
186
  }