@paro.io/expert-shared-components 1.14.48 → 1.14.50
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/TaxAxis/TaxAxisApi.d.ts +54 -0
- package/lib/components/TaxAxis/TaxAxisApi.js +2 -0
- package/lib/components/TaxAxis/TaxAxisShell.d.ts +3 -0
- package/lib/components/TaxAxis/TaxAxisShell.js +318 -0
- package/lib/components/TaxAxis/index.d.ts +3 -0
- package/lib/components/TaxAxis/index.js +8 -0
- package/lib/components/TaxAxis/types.d.ts +16 -0
- package/lib/components/TaxAxis/types.js +2 -0
- package/lib/components/shared/UploadClient.d.ts +2 -1
- package/lib/components/shared/UploadClient.js +6 -2
- package/lib/index.d.ts +3 -1
- package/lib/index.js +3 -1
- package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +1 -1
- package/lib/tax-axis/components/dashboard/DashboardActions.js +5 -4
- package/lib/tax-axis/components/dashboard/DashboardSummary.js +1 -1
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +33 -1
- package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +83 -7
- package/lib/tax-axis/components/documents/DocumentCard.d.ts +5 -3
- package/lib/tax-axis/components/documents/DocumentCard.js +53 -12
- package/lib/tax-axis/components/documents/DocumentTier.d.ts +3 -2
- package/lib/tax-axis/components/documents/DocumentTier.js +2 -2
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +17 -1
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +136 -20
- package/lib/tax-axis/components/intake/IntakeCtaCards.js +1 -1
- package/lib/tax-axis/components/intake/TaxAxisIntake.js +1 -1
- package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +1 -1
- package/lib/tax-axis/components/prospectReport/ProspectPrintView.js +0 -2
- package/lib/tax-axis/lib/data/documents.js +8 -8
- package/lib/tax-axis/lib/data/strategies.js +9 -9
- package/package.json +1 -1
- package/lib/README.md +0 -2
- package/lib/package.json +0 -68
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type TaxAxisSessionInput = {
|
|
2
|
+
clientId?: number | null;
|
|
3
|
+
freelancerId: number;
|
|
4
|
+
taxYear: number;
|
|
5
|
+
businessName?: string;
|
|
6
|
+
entityType?: string;
|
|
7
|
+
industry?: string;
|
|
8
|
+
annualRevenue?: number;
|
|
9
|
+
w2Compensation?: number;
|
|
10
|
+
employeeCount?: number;
|
|
11
|
+
states?: string[];
|
|
12
|
+
};
|
|
13
|
+
export type TaxAxisUploadInput = {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
clientId?: number | null;
|
|
16
|
+
freelancerId?: number;
|
|
17
|
+
fileName: string;
|
|
18
|
+
fileType: string;
|
|
19
|
+
data?: string;
|
|
20
|
+
fileSize?: number;
|
|
21
|
+
documentType?: string;
|
|
22
|
+
s3Key: string;
|
|
23
|
+
};
|
|
24
|
+
export type TaxAxisDocumentRecord = {
|
|
25
|
+
documentId: string;
|
|
26
|
+
sessionId: string;
|
|
27
|
+
fileName: string;
|
|
28
|
+
fileType: string;
|
|
29
|
+
fileSize?: number;
|
|
30
|
+
documentType?: string | null;
|
|
31
|
+
status: string;
|
|
32
|
+
s3Key: string;
|
|
33
|
+
parseError?: string | null;
|
|
34
|
+
parseStageResults?: unknown[] | null;
|
|
35
|
+
createdAt?: string;
|
|
36
|
+
updatedAt?: string;
|
|
37
|
+
};
|
|
38
|
+
export type TaxAxisApi = {
|
|
39
|
+
createSession: (input: TaxAxisSessionInput) => Promise<any>;
|
|
40
|
+
getSession: (sessionId: string) => Promise<any>;
|
|
41
|
+
listSessions: (input?: Record<string, unknown>) => Promise<any[]>;
|
|
42
|
+
uploadFile: (input: TaxAxisUploadInput) => Promise<any>;
|
|
43
|
+
deleteDocument: (documentId: string) => Promise<boolean>;
|
|
44
|
+
getDocuments: (sessionId: string) => Promise<TaxAxisDocumentRecord[]>;
|
|
45
|
+
analyzeDocuments: (sessionId: string) => Promise<any>;
|
|
46
|
+
saveReviewedData: (documentId: string, reviewedData: Record<string, unknown>) => Promise<any>;
|
|
47
|
+
runLlm: (sessionId: string) => Promise<any>;
|
|
48
|
+
runEval: (llmRunId: string) => Promise<any>;
|
|
49
|
+
runReportGateways: (sessionId: string) => Promise<any>;
|
|
50
|
+
getReports: (sessionId: string) => Promise<any[]>;
|
|
51
|
+
updateReport: (reportId: string, reviewedReport: Record<string, unknown>) => Promise<any>;
|
|
52
|
+
generatePdf: (sessionId: string) => Promise<any>;
|
|
53
|
+
getArtifacts: (sessionId: string) => Promise<any[]>;
|
|
54
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { TaxAxisShellProps } from './types';
|
|
2
|
+
export declare const TaxAxisShell: ({ taxAxisApi, userContext, initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, }: TaxAxisShellProps) => JSX.Element;
|
|
3
|
+
export default TaxAxisShell;
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.TaxAxisShell = void 0;
|
|
39
|
+
const react_1 = __importStar(require("react"));
|
|
40
|
+
const TaxAxisIntake_1 = require("../../tax-axis/components/intake/TaxAxisIntake");
|
|
41
|
+
const TaxAxisProspectReport_1 = require("../../tax-axis/components/prospectReport/TaxAxisProspectReport");
|
|
42
|
+
const TaxAxisDocuments_1 = require("../../tax-axis/components/documents/TaxAxisDocuments");
|
|
43
|
+
const TaxAxisProcessing_1 = require("../../tax-axis/components/processing/TaxAxisProcessing");
|
|
44
|
+
const TaxAxisDashboard_1 = require("../../tax-axis/components/dashboard/TaxAxisDashboard");
|
|
45
|
+
const TaxAxisExtractionReview_1 = require("../../tax-axis/components/extractionReview/TaxAxisExtractionReview");
|
|
46
|
+
const TaxAxisClientReport_1 = require("../../tax-axis/components/clientReport/TaxAxisClientReport");
|
|
47
|
+
const TaxAxisPreparerWorkpaper_1 = require("../../tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper");
|
|
48
|
+
const TaxAxisPresentationMode_1 = require("../../tax-axis/components/presentationMode/TaxAxisPresentationMode");
|
|
49
|
+
const UploadClient_1 = __importDefault(require("../shared/UploadClient"));
|
|
50
|
+
function sleep(ms) {
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
setTimeout(resolve, ms);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function toInt(value) {
|
|
56
|
+
const parsed = Number(String(value || '0').replace(/[^\d.-]/g, ''));
|
|
57
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
58
|
+
}
|
|
59
|
+
function buildSessionInput(profile) {
|
|
60
|
+
const taxYear = Number(profile.year) || new Date().getFullYear();
|
|
61
|
+
return {
|
|
62
|
+
clientId: null,
|
|
63
|
+
freelancerId: 0,
|
|
64
|
+
taxYear,
|
|
65
|
+
businessName: profile.bizName,
|
|
66
|
+
entityType: profile.entity,
|
|
67
|
+
industry: profile.industry,
|
|
68
|
+
annualRevenue: toInt(profile.revenue),
|
|
69
|
+
w2Compensation: toInt(profile.ownerComp),
|
|
70
|
+
employeeCount: toInt(profile.employees),
|
|
71
|
+
states: profile.states || [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function ShellContainer({ children, fullWidth = false, }) {
|
|
75
|
+
if (fullWidth) {
|
|
76
|
+
return react_1.default.createElement(react_1.default.Fragment, null, children);
|
|
77
|
+
}
|
|
78
|
+
return (react_1.default.createElement("div", { className: 'min-h-screen bg-tax-axis-navy text-white font-tax-axis-body' },
|
|
79
|
+
react_1.default.createElement("div", { className: 'max-w-[960px] mx-auto px-5 py-7' }, children)));
|
|
80
|
+
}
|
|
81
|
+
const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, }) => {
|
|
82
|
+
const [step, setStep] = (0, react_1.useState)('SESSION_SETUP');
|
|
83
|
+
const [profile, setProfile] = (0, react_1.useState)(initialProfile ? Object.assign({}, initialProfile) : null);
|
|
84
|
+
const [sessionId, setSessionId] = (0, react_1.useState)(initialSessionId || null);
|
|
85
|
+
const [isProspectFlow, setIsProspectFlow] = (0, react_1.useState)(false);
|
|
86
|
+
const [llmResult, setLlmResult] = (0, react_1.useState)(null);
|
|
87
|
+
const [isBusy, setIsBusy] = (0, react_1.useState)(false);
|
|
88
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
89
|
+
const [busyMessage, setBusyMessage] = (0, react_1.useState)('Syncing Tax Axis session...');
|
|
90
|
+
const updateSessionId = (0, react_1.useCallback)((nextSessionId) => {
|
|
91
|
+
setSessionId(nextSessionId);
|
|
92
|
+
if (onSessionChange) {
|
|
93
|
+
onSessionChange(nextSessionId);
|
|
94
|
+
}
|
|
95
|
+
}, [onSessionChange]);
|
|
96
|
+
const createSessionIfNeeded = (0, react_1.useCallback)((nextProfile) => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
|
+
var _a;
|
|
98
|
+
if (sessionId)
|
|
99
|
+
return sessionId;
|
|
100
|
+
try {
|
|
101
|
+
const sessionInput = buildSessionInput(nextProfile);
|
|
102
|
+
const created = yield taxAxisApi.createSession(Object.assign(Object.assign({}, sessionInput), { clientId: (_a = sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.clientId) !== null && _a !== void 0 ? _a : null, freelancerId: (sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.freelancerId) || sessionInput.freelancerId }));
|
|
103
|
+
const maybeSessionId = (created === null || created === void 0 ? void 0 : created.sessionId) || (created === null || created === void 0 ? void 0 : created.id) || null;
|
|
104
|
+
if (maybeSessionId) {
|
|
105
|
+
updateSessionId(maybeSessionId);
|
|
106
|
+
return maybeSessionId;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (requestError) {
|
|
110
|
+
const msg = requestError instanceof Error ? requestError.message : 'Unable to create Tax Axis session right now.';
|
|
111
|
+
setError(msg);
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}), [sessionId, sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.clientId, sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.freelancerId, taxAxisApi, updateSessionId]);
|
|
115
|
+
const handleReset = (0, react_1.useCallback)(() => {
|
|
116
|
+
setStep('SESSION_SETUP');
|
|
117
|
+
setProfile(null);
|
|
118
|
+
setIsProspectFlow(false);
|
|
119
|
+
setError(null);
|
|
120
|
+
updateSessionId(null);
|
|
121
|
+
}, [updateSessionId]);
|
|
122
|
+
const handleProspect = (0, react_1.useCallback)((nextProfile) => {
|
|
123
|
+
setProfile(nextProfile);
|
|
124
|
+
setIsProspectFlow(true);
|
|
125
|
+
setStep('PROSPECT_REPORT');
|
|
126
|
+
}, []);
|
|
127
|
+
const handleFullAnalysis = (0, react_1.useCallback)((nextProfile) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
+
setProfile(nextProfile);
|
|
129
|
+
setIsProspectFlow(false);
|
|
130
|
+
setError(null);
|
|
131
|
+
setBusyMessage('Creating Tax Axis session...');
|
|
132
|
+
setIsBusy(true);
|
|
133
|
+
const createdSessionId = yield createSessionIfNeeded(nextProfile);
|
|
134
|
+
setIsBusy(false);
|
|
135
|
+
if (!createdSessionId) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
setStep('DOCUMENT_UPLOAD');
|
|
139
|
+
}), [createSessionIfNeeded]);
|
|
140
|
+
const handleUploadDocument = (0, react_1.useCallback)((doc, file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
var _a;
|
|
142
|
+
const ensuredSessionId = sessionId || (profile ? yield createSessionIfNeeded(profile) : null);
|
|
143
|
+
if (!ensuredSessionId) {
|
|
144
|
+
throw new Error('Unable to upload without a session.');
|
|
145
|
+
}
|
|
146
|
+
if (!documentUploadUrl) {
|
|
147
|
+
throw new Error('Document upload service URL is missing.');
|
|
148
|
+
}
|
|
149
|
+
if (!uploadBucketName) {
|
|
150
|
+
throw new Error('Tax Axis document bucket is missing.');
|
|
151
|
+
}
|
|
152
|
+
const uploadClient = new UploadClient_1.default({
|
|
153
|
+
fileSelected: file,
|
|
154
|
+
fileName: file.name,
|
|
155
|
+
projectId: 0,
|
|
156
|
+
documentUploadUrl,
|
|
157
|
+
bucketName: uploadBucketName,
|
|
158
|
+
keyPrefix: `tax-axis/${ensuredSessionId}`,
|
|
159
|
+
});
|
|
160
|
+
const uploadResponse = yield uploadClient.triggerMultipartUpload();
|
|
161
|
+
if (!uploadResponse) {
|
|
162
|
+
throw new Error('File upload to storage failed.');
|
|
163
|
+
}
|
|
164
|
+
const uploadInput = {
|
|
165
|
+
sessionId: ensuredSessionId,
|
|
166
|
+
clientId: (_a = sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.clientId) !== null && _a !== void 0 ? _a : null,
|
|
167
|
+
freelancerId: sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.freelancerId,
|
|
168
|
+
fileName: file.name,
|
|
169
|
+
fileType: file.type || 'application/octet-stream',
|
|
170
|
+
fileSize: file.size,
|
|
171
|
+
documentType: doc.id.toUpperCase().replace(/[^A-Z0-9]+/g, '_'),
|
|
172
|
+
s3Key: uploadClient.state.fileName,
|
|
173
|
+
};
|
|
174
|
+
return taxAxisApi.uploadFile(uploadInput);
|
|
175
|
+
}), [
|
|
176
|
+
createSessionIfNeeded,
|
|
177
|
+
documentUploadUrl,
|
|
178
|
+
profile,
|
|
179
|
+
sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.clientId,
|
|
180
|
+
sessionDefaults === null || sessionDefaults === void 0 ? void 0 : sessionDefaults.freelancerId,
|
|
181
|
+
sessionId,
|
|
182
|
+
taxAxisApi,
|
|
183
|
+
uploadBucketName,
|
|
184
|
+
]);
|
|
185
|
+
const handleDeleteDocument = (0, react_1.useCallback)((documentId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
+
yield taxAxisApi.deleteDocument(documentId);
|
|
187
|
+
}), [taxAxisApi]);
|
|
188
|
+
const handleAnalyzeDocuments = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
189
|
+
if (!profile)
|
|
190
|
+
return;
|
|
191
|
+
setError(null);
|
|
192
|
+
setBusyMessage('Preparing documents for analysis...');
|
|
193
|
+
setIsBusy(true);
|
|
194
|
+
const ensuredSessionId = yield createSessionIfNeeded(profile);
|
|
195
|
+
if (!ensuredSessionId) {
|
|
196
|
+
setIsBusy(false);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
setBusyMessage('Verifying all documents are parsed...');
|
|
201
|
+
yield taxAxisApi.analyzeDocuments(ensuredSessionId);
|
|
202
|
+
setBusyMessage('Generating strategy results...');
|
|
203
|
+
setStep('PROCESSING');
|
|
204
|
+
const llmResponse = yield taxAxisApi.runLlm(ensuredSessionId);
|
|
205
|
+
if (llmResponse === null || llmResponse === void 0 ? void 0 : llmResponse.outputPayload) {
|
|
206
|
+
setLlmResult(llmResponse.outputPayload);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (requestError) {
|
|
210
|
+
const msg = requestError instanceof Error
|
|
211
|
+
? requestError.message
|
|
212
|
+
: 'Analysis did not complete successfully. Please review uploaded files.';
|
|
213
|
+
setError(msg);
|
|
214
|
+
setStep('DOCUMENT_UPLOAD');
|
|
215
|
+
setIsBusy(false);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
setIsBusy(false);
|
|
219
|
+
}), [createSessionIfNeeded, profile, taxAxisApi]);
|
|
220
|
+
const handleSendReport = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
221
|
+
if (!sessionId) {
|
|
222
|
+
setError('No session id available for sending report.');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
setError(null);
|
|
226
|
+
setIsBusy(true);
|
|
227
|
+
try {
|
|
228
|
+
yield taxAxisApi.generatePdf(sessionId);
|
|
229
|
+
}
|
|
230
|
+
catch (requestError) {
|
|
231
|
+
const msg = requestError instanceof Error
|
|
232
|
+
? requestError.message
|
|
233
|
+
: 'Failed to request report delivery. Please try again.';
|
|
234
|
+
setError(msg);
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
setIsBusy(false);
|
|
238
|
+
}
|
|
239
|
+
}), [sessionId, taxAxisApi]);
|
|
240
|
+
const currentView = (0, react_1.useMemo)(() => {
|
|
241
|
+
if (step === 'SESSION_SETUP') {
|
|
242
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
243
|
+
react_1.default.createElement(TaxAxisIntake_1.TaxAxisIntake, { userContext: userContext, initialProfile: initialProfile, onProspect: handleProspect, onFullAnalysis: handleFullAnalysis })));
|
|
244
|
+
}
|
|
245
|
+
if (!profile) {
|
|
246
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
247
|
+
react_1.default.createElement("div", { className: 'text-sm text-tax-axis-text' }, "Session expired. Start a new analysis.")));
|
|
248
|
+
}
|
|
249
|
+
switch (step) {
|
|
250
|
+
case 'PROSPECT_REPORT':
|
|
251
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
252
|
+
react_1.default.createElement(TaxAxisProspectReport_1.TaxAxisProspectReport, { profile: profile, userContext: userContext, onUpgrade: () => setStep('DOCUMENT_UPLOAD'), onPresent: () => setStep('PRESENTATION'), onReset: handleReset })));
|
|
253
|
+
case 'DOCUMENT_UPLOAD':
|
|
254
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
255
|
+
react_1.default.createElement(TaxAxisDocuments_1.TaxAxisDocuments, { profile: profile, userContext: userContext, onUploadDocument: handleUploadDocument, onDeleteDocument: handleDeleteDocument, fetchUploadedDocuments: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
256
|
+
const ensuredSessionId = sessionId || (profile ? yield createSessionIfNeeded(profile) : null);
|
|
257
|
+
if (!ensuredSessionId) {
|
|
258
|
+
return [];
|
|
259
|
+
}
|
|
260
|
+
const docs = yield taxAxisApi.getDocuments(ensuredSessionId);
|
|
261
|
+
return docs.map((doc) => ({
|
|
262
|
+
fileName: doc.fileName,
|
|
263
|
+
status: doc.status,
|
|
264
|
+
documentType: doc.documentType,
|
|
265
|
+
parseError: doc.parseError,
|
|
266
|
+
updatedAt: doc.updatedAt,
|
|
267
|
+
}));
|
|
268
|
+
}), onContinue: handleAnalyzeDocuments, onBack: () => isProspectFlow ? setStep('PROSPECT_REPORT') : setStep('SESSION_SETUP') })));
|
|
269
|
+
case 'PROCESSING':
|
|
270
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
271
|
+
react_1.default.createElement(TaxAxisProcessing_1.TaxAxisProcessing, { profile: profile, userContext: userContext, onComplete: () => setStep('DASHBOARD') })));
|
|
272
|
+
case 'PARSED_REVIEW':
|
|
273
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
274
|
+
react_1.default.createElement(TaxAxisExtractionReview_1.TaxAxisExtractionReview, { userContext: userContext, onBack: () => setStep('DASHBOARD'), onConfirmAndUnlock: () => setStep('DASHBOARD') })));
|
|
275
|
+
case 'DASHBOARD':
|
|
276
|
+
return (react_1.default.createElement(ShellContainer, null,
|
|
277
|
+
react_1.default.createElement(TaxAxisDashboard_1.TaxAxisDashboard, { profile: profile, userContext: userContext, llmResult: llmResult, onDownloadClient: () => setStep('CLIENT_REPORT'), onDownloadPreparer: () => setStep('PREPARER_WORKPAPER'), onPresent: () => setStep('PRESENTATION'), onSend: handleSendReport, onReviewData: () => setStep('PARSED_REVIEW'), onReset: handleReset })));
|
|
278
|
+
case 'CLIENT_REPORT':
|
|
279
|
+
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
280
|
+
react_1.default.createElement(TaxAxisClientReport_1.TaxAxisClientReport, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onNavigatePreparer: () => setStep('PREPARER_WORKPAPER') })));
|
|
281
|
+
case 'PREPARER_WORKPAPER':
|
|
282
|
+
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
283
|
+
react_1.default.createElement(TaxAxisPreparerWorkpaper_1.TaxAxisPreparerWorkpaper, { profile: profile, userContext: userContext, onBack: () => setStep('DASHBOARD'), onToggleToClient: () => setStep('CLIENT_REPORT') })));
|
|
284
|
+
case 'PRESENTATION':
|
|
285
|
+
return (react_1.default.createElement(ShellContainer, { fullWidth: true },
|
|
286
|
+
react_1.default.createElement(TaxAxisPresentationMode_1.TaxAxisPresentationMode, { profile: profile, userContext: userContext, onBack: () => setStep(isProspectFlow ? 'PROSPECT_REPORT' : 'DASHBOARD') })));
|
|
287
|
+
default:
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}, [
|
|
291
|
+
step,
|
|
292
|
+
profile,
|
|
293
|
+
userContext,
|
|
294
|
+
initialProfile,
|
|
295
|
+
handleProspect,
|
|
296
|
+
handleFullAnalysis,
|
|
297
|
+
isProspectFlow,
|
|
298
|
+
handleAnalyzeDocuments,
|
|
299
|
+
handleUploadDocument,
|
|
300
|
+
handleDeleteDocument,
|
|
301
|
+
handleReset,
|
|
302
|
+
handleSendReport,
|
|
303
|
+
llmResult,
|
|
304
|
+
]);
|
|
305
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
306
|
+
error && (react_1.default.createElement("div", { className: 'fixed right-4 top-4 z-[200] max-w-sm rounded-lg border border-red-500/30 bg-tax-axis-surface px-4 py-3 text-xs text-red-200 shadow-lg' },
|
|
307
|
+
react_1.default.createElement("div", { className: 'flex items-start gap-2' },
|
|
308
|
+
react_1.default.createElement("span", { className: 'flex-1' }, error),
|
|
309
|
+
react_1.default.createElement("button", { onClick: () => setError(null), className: 'bg-transparent border-none text-red-300 text-sm cursor-pointer p-0 leading-none' }, "\u00D7")))),
|
|
310
|
+
isBusy && (react_1.default.createElement("div", { className: 'fixed inset-0 z-[180] bg-black/25' },
|
|
311
|
+
react_1.default.createElement("div", { className: 'absolute left-1/2 top-6 -translate-x-1/2 rounded-md bg-tax-axis-surface px-4 py-2.5 text-xs text-tax-axis-text shadow-lg border border-tax-axis-border' },
|
|
312
|
+
react_1.default.createElement("div", { className: 'flex items-center gap-2' },
|
|
313
|
+
react_1.default.createElement("div", { className: 'w-3 h-3 rounded-full animate-spin flex-shrink-0', style: { border: '2px solid transparent', borderTopColor: '#248384' } }),
|
|
314
|
+
busyMessage)))),
|
|
315
|
+
currentView));
|
|
316
|
+
};
|
|
317
|
+
exports.TaxAxisShell = TaxAxisShell;
|
|
318
|
+
exports.default = exports.TaxAxisShell;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TaxAxisShell = void 0;
|
|
7
|
+
var TaxAxisShell_1 = require("./TaxAxisShell");
|
|
8
|
+
Object.defineProperty(exports, "TaxAxisShell", { enumerable: true, get: function () { return __importDefault(TaxAxisShell_1).default; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TaxAxisApi } from './TaxAxisApi';
|
|
2
|
+
import type { ClientProfile, UserContext } from '../../tax-axis/lib/types';
|
|
3
|
+
export type TaxAxisStep = 'SESSION_SETUP' | 'PROSPECT_REPORT' | 'DOCUMENT_UPLOAD' | 'PROCESSING' | 'PARSED_REVIEW' | 'DASHBOARD' | 'CLIENT_REPORT' | 'PREPARER_WORKPAPER' | 'PRESENTATION';
|
|
4
|
+
export type TaxAxisShellProps = {
|
|
5
|
+
taxAxisApi: TaxAxisApi;
|
|
6
|
+
userContext?: UserContext;
|
|
7
|
+
initialSessionId?: string;
|
|
8
|
+
initialProfile?: Partial<ClientProfile>;
|
|
9
|
+
onSessionChange?: (sessionId: string | null) => void;
|
|
10
|
+
documentUploadUrl?: string;
|
|
11
|
+
uploadBucketName?: string;
|
|
12
|
+
sessionDefaults?: {
|
|
13
|
+
freelancerId: number;
|
|
14
|
+
clientId?: number | null;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -8,9 +8,10 @@ export default class UploadClient {
|
|
|
8
8
|
bucketName: string;
|
|
9
9
|
escalationId?: string;
|
|
10
10
|
taskId?: string;
|
|
11
|
+
keyPrefix?: string;
|
|
11
12
|
};
|
|
12
13
|
constructor(props: any);
|
|
13
|
-
generateS3Key(projectId: number, escalationId: string, fileName: string, taskId: string): string;
|
|
14
|
+
generateS3Key(projectId: number, escalationId: string, fileName: string, taskId: string, keyPrefix?: string): string;
|
|
14
15
|
triggerMultipartUpload(): Promise<string | undefined>;
|
|
15
16
|
uploadMultiPartFile(): Promise<string | undefined>;
|
|
16
17
|
completeUpload(partsArray: any): Promise<string | undefined>;
|
|
@@ -20,10 +20,14 @@ class UploadClient {
|
|
|
20
20
|
bucketName: props.bucketName,
|
|
21
21
|
escalationId: props.escalationId,
|
|
22
22
|
taskId: props.taskId,
|
|
23
|
+
keyPrefix: props.keyPrefix,
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
generateS3Key(projectId, escalationId, fileName, taskId) {
|
|
26
|
+
generateS3Key(projectId, escalationId, fileName, taskId, keyPrefix) {
|
|
26
27
|
const sanitizedFileName = fileName.replace(/[^a-zA-Z0-9.-]/g, '_');
|
|
28
|
+
if (!!keyPrefix) {
|
|
29
|
+
return `${keyPrefix.replace(/\/+$/, '')}/${sanitizedFileName}`;
|
|
30
|
+
}
|
|
27
31
|
if (!!taskId) {
|
|
28
32
|
return `project-task-${taskId}/${sanitizedFileName}`;
|
|
29
33
|
}
|
|
@@ -37,7 +41,7 @@ class UploadClient {
|
|
|
37
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
42
|
var _a, _b;
|
|
39
43
|
try {
|
|
40
|
-
const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '');
|
|
44
|
+
const fileName = this.generateS3Key(this.state.projectId, (_a = this.state.escalationId) !== null && _a !== void 0 ? _a : '', this.state.fileName, (_b = this.state.taskId) !== null && _b !== void 0 ? _b : '', this.state.keyPrefix);
|
|
41
45
|
this.state = Object.assign(Object.assign({}, this.state), { fileName: fileName });
|
|
42
46
|
const params = {
|
|
43
47
|
fileName: this.state.fileName,
|
package/lib/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { fileUploader } from './components/FileUploader';
|
|
|
15
15
|
export { DiscussionSection } from './components/Invoices/DiscussionSection';
|
|
16
16
|
export { fileDownloader } from './components/FileDownloader';
|
|
17
17
|
export { Escalations } from './components/Escalations';
|
|
18
|
-
export { ProjectIntelligence } from
|
|
18
|
+
export { ProjectIntelligence } from './components/ProjectIntelligence';
|
|
19
19
|
export { SectionHeader } from './tax-axis';
|
|
20
20
|
export { TaxAxisBadge } from './tax-axis';
|
|
21
21
|
export { TaxAxisButton } from './tax-axis';
|
|
@@ -29,3 +29,5 @@ export { TaxAxisPreparerWorkpaper } from './tax-axis';
|
|
|
29
29
|
export { TaxAxisExtractionReview } from './tax-axis';
|
|
30
30
|
export { TaxAxisProspectReport } from './tax-axis';
|
|
31
31
|
export { TaxAxisPresentationMode } from './tax-axis';
|
|
32
|
+
export { TaxAxisShell } from './components/TaxAxis';
|
|
33
|
+
export type { TaxAxisApi, TaxAxisSessionInput, TaxAxisUploadInput } from './components/TaxAxis';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TaxAxisPresentationMode = exports.TaxAxisProspectReport = exports.TaxAxisExtractionReview = exports.TaxAxisPreparerWorkpaper = exports.TaxAxisClientReport = exports.TaxAxisDashboard = exports.TaxAxisProcessing = exports.TaxAxisDocuments = exports.TaxAxisIntake = exports.TaxAxisCard = exports.TaxAxisButton = exports.TaxAxisBadge = exports.SectionHeader = 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;
|
|
3
|
+
exports.TaxAxisShell = exports.TaxAxisPresentationMode = exports.TaxAxisProspectReport = exports.TaxAxisExtractionReview = exports.TaxAxisPreparerWorkpaper = exports.TaxAxisClientReport = exports.TaxAxisDashboard = exports.TaxAxisProcessing = exports.TaxAxisDocuments = exports.TaxAxisIntake = exports.TaxAxisCard = exports.TaxAxisButton = exports.TaxAxisBadge = exports.SectionHeader = 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");
|
|
@@ -63,3 +63,5 @@ var tax_axis_12 = require("./tax-axis");
|
|
|
63
63
|
Object.defineProperty(exports, "TaxAxisProspectReport", { enumerable: true, get: function () { return tax_axis_12.TaxAxisProspectReport; } });
|
|
64
64
|
var tax_axis_13 = require("./tax-axis");
|
|
65
65
|
Object.defineProperty(exports, "TaxAxisPresentationMode", { enumerable: true, get: function () { return tax_axis_13.TaxAxisPresentationMode; } });
|
|
66
|
+
var TaxAxis_1 = require("./components/TaxAxis");
|
|
67
|
+
Object.defineProperty(exports, "TaxAxisShell", { enumerable: true, get: function () { return TaxAxis_1.TaxAxisShell; } });
|
|
@@ -100,7 +100,7 @@ function TaxAxisClientReport({ profile, onBack, onNavigatePreparer }) {
|
|
|
100
100
|
.report-meta { break-inside: avoid; page-break-inside: avoid; }
|
|
101
101
|
.toc-page { break-after: page; page-break-after: always; }
|
|
102
102
|
* { color-adjust: exact; -webkit-print-color-adjust: exact; }
|
|
103
|
-
|
|
103
|
+
p, span, div, td, th, li { color: #212529 !important; }
|
|
104
104
|
h1, h2, h3, h4, h5, h6, strong, b { color: #060821 !important; }
|
|
105
105
|
}
|
|
106
106
|
`),
|
|
@@ -25,7 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.DashboardActions = DashboardActions;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
|
-
const data_1 = require("../../lib/data");
|
|
29
28
|
const compute_1 = require("../../lib/compute");
|
|
30
29
|
const TaxAxisButton_1 = require("../shared/TaxAxisButton");
|
|
31
30
|
function DashboardActions({ profile, dashEligible, computed, onDownloadPreparer, onPresent, onSend, onReset, }) {
|
|
@@ -69,13 +68,15 @@ function DashboardActions({ profile, dashEligible, computed, onDownloadPreparer,
|
|
|
69
68
|
"\u2013",
|
|
70
69
|
(0, compute_1.fmtK)(totalHi),
|
|
71
70
|
"across ",
|
|
72
|
-
|
|
71
|
+
dashEligible.length,
|
|
73
72
|
" strategies \u2014 use this to close the engagement or expand scope."),
|
|
74
73
|
react_1.default.createElement("div", { className: "flex gap-2.5 flex-wrap" },
|
|
75
|
-
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick:
|
|
74
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "orange", onClick: onSend }, "Send Report to Client"),
|
|
75
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { onClick: onPresent }, "Present to Client"),
|
|
76
|
+
react_1.default.createElement(TaxAxisButton_1.TaxAxisButton, { variant: "secondary" }, "Generate Engagement Letter")))),
|
|
76
77
|
react_1.default.createElement("div", { className: "flex gap-4 mt-4 pt-3.5", style: { borderTop: "1px solid rgba(36,131,132,0.15)" } }, [
|
|
77
78
|
{ v: "3x", l: "Faster than Manual" },
|
|
78
|
-
{ v:
|
|
79
|
+
{ v: String(dashEligible.length), l: "Strategies Found" },
|
|
79
80
|
{ v: "100%", l: "IRS-Cited" },
|
|
80
81
|
{ v: String(stateCount), l: `State${stateCount > 1 ? "s" : ""}` },
|
|
81
82
|
].map(({ v, l }) => (react_1.default.createElement("div", { key: l },
|
|
@@ -78,7 +78,7 @@ function DashboardSummary({ profile, dashEligible, computed, dataConfirmed, revi
|
|
|
78
78
|
profile.cpaName)),
|
|
79
79
|
react_1.default.createElement("div", { className: "flex gap-6 mt-[22px] pt-[18px]", style: { borderTop: "1px solid rgba(36,131,132,0.12)" } }, [
|
|
80
80
|
{ v: String(scoreUp), u: "/100", l: "Avg. Confidence", warn: false, ok: false },
|
|
81
|
-
{ v:
|
|
81
|
+
{ v: String(dashEligible.length), u: "", l: "Strategies Identified", warn: false, ok: false },
|
|
82
82
|
{
|
|
83
83
|
v: dataConfirmed ? "Done" : String(reviewUnreviewed),
|
|
84
84
|
u: "",
|
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { ClientProfile, TaxAxisScreenProps } from "../../lib/types";
|
|
3
|
+
export interface LlmStrategy {
|
|
4
|
+
strategyType: string;
|
|
5
|
+
applicable: boolean;
|
|
6
|
+
priority: string;
|
|
7
|
+
estimatedSavings: {
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
};
|
|
11
|
+
summary: string;
|
|
12
|
+
implementationSteps: string[];
|
|
13
|
+
requiredForms: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface LlmResult {
|
|
16
|
+
strategies: LlmStrategy[];
|
|
17
|
+
summary: {
|
|
18
|
+
applicableCount: number;
|
|
19
|
+
totalStrategies: number;
|
|
20
|
+
highPriorityCount: number;
|
|
21
|
+
quickWinCount: number;
|
|
22
|
+
notEligibleCount: number;
|
|
23
|
+
estimatedSavingsMin: number;
|
|
24
|
+
estimatedSavingsMax: number;
|
|
25
|
+
};
|
|
26
|
+
meta: {
|
|
27
|
+
provider: string;
|
|
28
|
+
tokenCount: number;
|
|
29
|
+
sourceDocumentCount: number;
|
|
30
|
+
parsedDocumentCount: number;
|
|
31
|
+
detectedDocumentTypes: string[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
3
34
|
export interface TaxAxisDashboardProps extends TaxAxisScreenProps {
|
|
4
35
|
profile: ClientProfile;
|
|
36
|
+
llmResult?: LlmResult | null;
|
|
5
37
|
onDownloadClient: () => void;
|
|
6
38
|
onDownloadPreparer: () => void;
|
|
7
39
|
onPresent: () => void;
|
|
@@ -9,4 +41,4 @@ export interface TaxAxisDashboardProps extends TaxAxisScreenProps {
|
|
|
9
41
|
onReset: () => void;
|
|
10
42
|
onReviewData?: () => void;
|
|
11
43
|
}
|
|
12
|
-
export declare function TaxAxisDashboard({ profile, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, userContext: _userContext, }: TaxAxisDashboardProps): React.JSX.Element;
|
|
44
|
+
export declare function TaxAxisDashboard({ profile, llmResult, onDownloadClient, onDownloadPreparer, onPresent, onSend, onReset, onReviewData, userContext: _userContext, }: TaxAxisDashboardProps): React.JSX.Element;
|