@paro.io/expert-shared-components 1.14.65 → 1.14.66

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.
@@ -7,5 +7,6 @@ export interface DocumentReviewModalProps {
7
7
  fileName: string;
8
8
  jobId: string;
9
9
  onClose: () => void;
10
+ parsedData?: Record<string, unknown> | null;
10
11
  }
11
- export declare function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, onClose, }: DocumentReviewModalProps): React.JSX.Element;
12
+ export declare function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, onClose, parsedData, }: DocumentReviewModalProps): React.JSX.Element;
@@ -143,23 +143,59 @@ function getStubSections(documentId) {
143
143
  },
144
144
  ];
145
145
  }
146
+ function humanizeFieldKey(key) {
147
+ return key.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
148
+ }
149
+ function formatFieldValue(value) {
150
+ if (typeof value === 'number') {
151
+ return Math.abs(value) >= 1
152
+ ? `$${value.toLocaleString('en-US', { maximumFractionDigits: 0 })}`
153
+ : String(value);
154
+ }
155
+ return String(value !== null && value !== void 0 ? value : '');
156
+ }
157
+ function parsedDataToSections(data) {
158
+ const fields = data.fields;
159
+ if (!fields || typeof fields !== 'object')
160
+ return [];
161
+ const entries = Object.entries(fields)
162
+ .filter(([key]) => !key.startsWith('_'));
163
+ if (entries.length === 0)
164
+ return [];
165
+ return [{
166
+ head: humanizeFieldKey(String(data.documentType || 'Extracted Fields')),
167
+ fields: entries.map(([key, value]) => ({
168
+ key,
169
+ label: humanizeFieldKey(key),
170
+ value: formatFieldValue(value),
171
+ sourceRef: 'Extracted',
172
+ confidence: 0.92,
173
+ })),
174
+ }];
175
+ }
146
176
  function getTotalFieldCount(sections) {
147
177
  return sections.reduce((sum, s) => sum + s.fields.length, 0);
148
178
  }
149
179
  // ── Component ──
150
- function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, onClose, }) {
180
+ function DocumentReviewModal({ documentId, documentName, fileName, jobId: _jobId, onClose, parsedData, }) {
151
181
  const [loading, setLoading] = (0, react_1.useState)(true);
152
182
  const [sections, setSections] = (0, react_1.useState)([]);
153
183
  const [saveStatus, setSaveStatus] = (0, react_1.useState)("idle");
154
184
  const debounceTimers = (0, react_1.useRef)({});
155
- // Stub fetch: simulate loading delay
185
+ // Load sections from real parsedData when available, fall back to stubs
156
186
  (0, react_1.useEffect)(() => {
187
+ if (parsedData && typeof parsedData === 'object' && parsedData.fields) {
188
+ setSections(parsedDataToSections(parsedData));
189
+ setLoading(false);
190
+ return;
191
+ }
192
+ // Fallback: stub data with simulated delay
157
193
  const t = setTimeout(() => {
158
194
  setSections(getStubSections(documentId));
159
195
  setLoading(false);
160
196
  }, 400);
161
197
  return () => clearTimeout(t);
162
- }, [documentId]);
198
+ }, [documentId, parsedData]);
163
199
  const handleFieldChange = (0, react_1.useCallback)((sectionIdx, fieldIdx, newValue) => {
164
200
  setSections((prev) => prev.map((sec, si) => si === sectionIdx
165
201
  ? Object.assign(Object.assign({}, sec), { fields: sec.fields.map((f, fi) => fi === fieldIdx ? Object.assign(Object.assign({}, f), { value: newValue }) : f) }) : sec));
@@ -49,17 +49,11 @@ const DocumentReviewModal_1 = require("./DocumentReviewModal");
49
49
  // "fixed-assets": "Fixed_Assets.xlsx",
50
50
  // "prior-returns": "Prior_Returns.pdf",
51
51
  // };
52
- // Stub field counts per doc (mirrors STUB_SECTIONS in DocumentReviewModal)
53
- const STUB_FIELD_COUNTS = {
54
- pnl: 13,
55
- balance: 9,
56
- "1120s": 3,
57
- payroll: 3,
58
- "state-return": 2,
59
- cashflow: 1,
60
- "fixed-assets": 1,
61
- "prior-returns": 1,
62
- };
52
+ // Stub field counts from original mock retained for reference.
53
+ // const STUB_FIELD_COUNTS: Record<string, number> = {
54
+ // pnl: 13, balance: 9, "1120s": 3, payroll: 3,
55
+ // "state-return": 2, cashflow: 1, "fixed-assets": 1, "prior-returns": 1,
56
+ // };
63
57
  // Short help text shown below each doc name when not yet uploaded
64
58
  // (mock App.jsx:1384). Overrides the longer DOC_SPECS_BASE.help.
65
59
  const HELP_OVERRIDES = {
@@ -116,6 +110,7 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
116
110
  const fileInputRef = (0, react_1.useRef)(null);
117
111
  const uploadTargetIdx = (0, react_1.useRef)(-1);
118
112
  const documentIdMap = (0, react_1.useRef)({});
113
+ const [parsedDataMap, setParsedDataMap] = (0, react_1.useState)({});
119
114
  // Load previously uploaded documents on mount
120
115
  (0, react_1.useEffect)(() => {
121
116
  if (!fetchUploadedDocuments)
@@ -124,12 +119,15 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
124
119
  .then((uploaded) => {
125
120
  if (!uploaded || uploaded.length === 0)
126
121
  return;
122
+ const newParsed = {};
127
123
  setDocs((prev) => prev.map((d) => {
128
124
  const match = uploaded.find((u) => u.documentType === d.id);
129
125
  if (!match)
130
126
  return d;
131
127
  if (match.documentId)
132
128
  documentIdMap.current[d.id] = match.documentId;
129
+ if (match.parsedData)
130
+ newParsed[d.id] = match.parsedData;
133
131
  const status = match.status === 'PARSED' || match.status === 'valid'
134
132
  ? 'valid'
135
133
  : match.status === 'FAILED'
@@ -137,12 +135,14 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
137
135
  : 'validating';
138
136
  return Object.assign(Object.assign({}, d), { status, fileName: match.fileName || d.fileName });
139
137
  }));
138
+ if (Object.keys(newParsed).length > 0) {
139
+ setParsedDataMap((prev) => (Object.assign(Object.assign({}, prev), newParsed)));
140
+ }
140
141
  })
141
142
  .catch((err) => console.error('[TaxAxisDocuments] Failed to fetch uploaded documents:', err));
142
143
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
143
144
  // Open native file picker for the target document slot
144
145
  const handleUpload = (idx) => {
145
- var _a;
146
146
  if (!onUploadDocument) {
147
147
  console.warn('[TaxAxisDocuments] No onUploadDocument handler provided');
148
148
  return;
@@ -150,7 +150,7 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
150
150
  uploadTargetIdx.current = idx;
151
151
  if (fileInputRef.current) {
152
152
  const doc = docs[idx];
153
- fileInputRef.current.accept = ((_a = doc.accept) === null || _a === void 0 ? void 0 : _a.join(',')) || '.pdf,.docx,.xlsx,.csv';
153
+ fileInputRef.current.accept = '.pdf,.doc,.docx,.xlsx,.xls,.csv';
154
154
  fileInputRef.current.value = '';
155
155
  fileInputRef.current.click();
156
156
  }
@@ -170,6 +170,9 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
170
170
  if (result === null || result === void 0 ? void 0 : result.documentId) {
171
171
  documentIdMap.current[doc.id] = result.documentId;
172
172
  }
173
+ if (result === null || result === void 0 ? void 0 : result.parsedData) {
174
+ setParsedDataMap((prev) => (Object.assign(Object.assign({}, prev), { [doc.id]: result.parsedData })));
175
+ }
173
176
  setDocs((prev) => prev.map((d, i) => i === idx ? Object.assign(Object.assign({}, d), { status: 'valid', fileName: file.name }) : d));
174
177
  }
175
178
  catch (err) {
@@ -184,9 +187,27 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
184
187
  onDeleteDocument(backendDocId).catch((err) => console.error('[TaxAxisDocuments] Delete failed:', err));
185
188
  delete documentIdMap.current[doc.id];
186
189
  }
190
+ setParsedDataMap((prev) => {
191
+ const next = Object.assign({}, prev);
192
+ delete next[doc.id];
193
+ return next;
194
+ });
187
195
  setDocs((prev) => prev.map((d, i) => i === idx
188
196
  ? Object.assign(Object.assign({}, d), { status: "empty", fileName: null }) : d));
189
197
  };
198
+ // Compute real field counts from parsed data
199
+ const fieldCounts = (0, react_1.useMemo)(() => {
200
+ const counts = {};
201
+ for (const doc of docs) {
202
+ const pd = parsedDataMap[doc.id];
203
+ const fields = pd === null || pd === void 0 ? void 0 : pd.fields;
204
+ if (fields && typeof fields === 'object') {
205
+ counts[doc.id] = Object.keys(fields)
206
+ .filter((k) => !k.startsWith('_')).length;
207
+ }
208
+ }
209
+ return counts;
210
+ }, [docs, parsedDataMap]);
190
211
  const validCount = docs.filter((d) => d.status === "valid").length;
191
212
  const requiredCount = docs.filter((d) => d.required === true).length;
192
213
  const requiredValid = docs.filter((d) => d.required === true && d.status === "valid").length;
@@ -239,12 +260,12 @@ function TaxAxisDocuments({ profile, onContinue, onBack, onUploadDocument, onDel
239
260
  coveragePct,
240
261
  "% coverage"),
241
262
  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")))),
242
- 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) }))),
263
+ TIER_DEFS.map((tier) => (react_1.default.createElement(DocumentTier_1.DocumentTier, { key: tier.key, tier: tier, docs: docs, helpOverrides: HELP_OVERRIDES, fieldCounts: fieldCounts, onUpload: handleUpload, onClear: handleClear, onReview: (docId) => setReviewDocId(docId) }))),
243
264
  react_1.default.createElement("div", { className: "flex gap-3 mt-6" },
244
265
  react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary", onClick: onBack }, "Back"),
245
266
  react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onContinue, disabled: requiredCount > requiredValid, className: "flex-1" }, requiredCount > requiredValid
246
267
  ? `Upload ${requiredCount - requiredValid} more required doc${requiredCount - requiredValid > 1 ? "s" : ""}`
247
268
  : "Run Analysis")),
248
269
  react_1.default.createElement("input", { ref: fileInputRef, type: "file", style: { display: 'none' }, onChange: handleFileSelected }),
249
- reviewDoc && (react_1.default.createElement(DocumentReviewModal_1.DocumentReviewModal, { documentId: documentIdMap.current[reviewDoc.id] || reviewDoc.id, documentName: reviewDoc.name, fileName: reviewDoc.fileName || "", jobId: jobId || "", onClose: () => setReviewDocId(null) }))));
270
+ reviewDoc && (react_1.default.createElement(DocumentReviewModal_1.DocumentReviewModal, { documentId: documentIdMap.current[reviewDoc.id] || reviewDoc.id, documentName: reviewDoc.name, fileName: reviewDoc.fileName || "", jobId: jobId || "", onClose: () => setReviewDocId(null), parsedData: parsedDataMap[reviewDoc.id] || null }))));
250
271
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.14.65",
3
+ "version": "1.14.66",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {