@paro.io/expert-shared-components 1.14.77 → 1.14.79
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/TaxAxisShell.d.ts +1 -1
- package/lib/components/TaxAxis/TaxAxisShell.js +6 -4
- package/lib/components/TaxAxis/types.d.ts +2 -0
- package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +2 -1
- package/lib/tax-axis/components/documents/TaxAxisDocuments.js +3 -2
- package/lib/tax-axis/components/documents/qbo/types.d.ts +2 -0
- package/lib/tax-axis/components/documents/qbo/useQboFlow.d.ts +3 -3
- package/lib/tax-axis/components/documents/qbo/useQboFlow.js +36 -41
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TaxAxisShellProps } from './types';
|
|
2
|
-
export declare const TaxAxisShell: ({ taxAxisApi, userContext, initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, qboAuthorizeUrl, expertId, qboConnected, qboCompanyName, }: TaxAxisShellProps) => JSX.Element;
|
|
2
|
+
export declare const TaxAxisShell: ({ taxAxisApi, userContext, initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, qboAuthorizeUrl, qboRedirectUri, onQboDisconnect, expertId, qboConnected, qboCompanyName, }: TaxAxisShellProps) => JSX.Element;
|
|
3
3
|
export default TaxAxisShell;
|
|
@@ -148,7 +148,7 @@ function ShellContainer({ children, fullWidth = false, }) {
|
|
|
148
148
|
return (react_1.default.createElement("div", { className: 'min-h-screen bg-tax-axis-navy text-white font-tax-axis-body' },
|
|
149
149
|
react_1.default.createElement("div", { className: 'max-w-[960px] mx-auto px-5 py-7' }, children)));
|
|
150
150
|
}
|
|
151
|
-
const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, qboAuthorizeUrl, expertId, qboConnected, qboCompanyName, }) => {
|
|
151
|
+
const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, initialProfile, onSessionChange, documentUploadUrl, uploadBucketName, sessionDefaults, qboAuthorizeUrl, qboRedirectUri, onQboDisconnect, expertId, qboConnected, qboCompanyName, }) => {
|
|
152
152
|
const [step, setStep] = (0, react_1.useState)('SESSION_SETUP');
|
|
153
153
|
const [profile, setProfile] = (0, react_1.useState)(initialProfile ? Object.assign({}, initialProfile) : null);
|
|
154
154
|
const [sessionId, setSessionId] = (0, react_1.useState)(initialSessionId || null);
|
|
@@ -556,13 +556,15 @@ const TaxAxisShell = ({ taxAxisApi, userContext = 'expert', initialSessionId, in
|
|
|
556
556
|
});
|
|
557
557
|
}), jobId: sessionId || undefined, onSaveReviewedField: (documentId, reviewedData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
558
558
|
yield taxAxisApi.saveReviewedData(documentId, reviewedData);
|
|
559
|
-
}), onContinue: handleAnalyzeDocuments, onBack: () => isProspectFlow ? setStep('PROSPECT_REPORT') : setStep('SESSION_SETUP'), qboConnected: qboConnectedState, qboCompanyName: qboCompanyNameState, qboAuthorizeUrl: qboAuthorizeUrl, qboClientConfirmed: qboConnectedState, onImportQboReport: taxAxisApi.importQboReport ? handleImportQboReport : undefined, onQboConnected: (companyName) => {
|
|
559
|
+
}), onContinue: handleAnalyzeDocuments, onBack: () => isProspectFlow ? setStep('PROSPECT_REPORT') : setStep('SESSION_SETUP'), qboConnected: qboConnectedState, qboCompanyName: qboCompanyNameState, qboAuthorizeUrl: qboAuthorizeUrl, qboRedirectUri: qboRedirectUri, qboClientConfirmed: qboConnectedState, onImportQboReport: taxAxisApi.importQboReport ? handleImportQboReport : undefined, onQboConnected: (companyName) => {
|
|
560
560
|
setQboConnectedState(true);
|
|
561
561
|
setQboCompanyNameState(companyName);
|
|
562
|
-
}, onQboDisconnected: () => {
|
|
562
|
+
}, onQboDisconnected: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
563
|
+
if (onQboDisconnect)
|
|
564
|
+
yield onQboDisconnect();
|
|
563
565
|
setQboConnectedState(false);
|
|
564
566
|
setQboCompanyNameState(null);
|
|
565
|
-
} })));
|
|
567
|
+
}) })));
|
|
566
568
|
case 'PROCESSING':
|
|
567
569
|
return (react_1.default.createElement(ShellContainer, null,
|
|
568
570
|
react_1.default.createElement(TaxAxisProcessing_1.TaxAxisProcessing, { profile: profile, userContext: userContext, reportReady: reportReady, onComplete: () => setStep('DASHBOARD') })));
|
|
@@ -31,6 +31,7 @@ export interface TaxAxisDocumentsProps extends TaxAxisScreenProps {
|
|
|
31
31
|
qboConnected?: boolean;
|
|
32
32
|
qboCompanyName?: string | null;
|
|
33
33
|
qboAuthorizeUrl?: string;
|
|
34
|
+
qboRedirectUri?: string;
|
|
34
35
|
onImportQboReport?: (sessionId: string, realmId: string, reportType: string, accountingMethod: string) => Promise<any>;
|
|
35
36
|
onQboConnected?: (companyName: string) => void;
|
|
36
37
|
onQboDisconnected?: () => void;
|
|
@@ -40,4 +41,4 @@ export interface TaxAxisDocumentsProps extends TaxAxisScreenProps {
|
|
|
40
41
|
}[]) => void;
|
|
41
42
|
qboClientConfirmed?: boolean;
|
|
42
43
|
}
|
|
43
|
-
export declare function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDocument, onDeleteDocument, fetchUploadedDocuments, parsedFieldCounts, jobId, onSaveReviewedField, userContext: _userContext, qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQboReport, onQboConnected, onQboDisconnected, onQboImport, qboClientConfirmed, }: TaxAxisDocumentsProps): React.JSX.Element;
|
|
44
|
+
export declare function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDocument, onDeleteDocument, fetchUploadedDocuments, parsedFieldCounts, jobId, onSaveReviewedField, userContext: _userContext, qboConnected, qboCompanyName, qboAuthorizeUrl, qboRedirectUri, onImportQboReport, onQboConnected, onQboDisconnected, onQboImport, qboClientConfirmed: _qboClientConfirmed, }: TaxAxisDocumentsProps): React.JSX.Element;
|
|
@@ -77,7 +77,7 @@ const TIER_DEFS = [
|
|
|
77
77
|
ids: [],
|
|
78
78
|
},
|
|
79
79
|
];
|
|
80
|
-
function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDocument, onDeleteDocument, fetchUploadedDocuments, parsedFieldCounts, jobId = "stub-job-id", onSaveReviewedField, userContext: _userContext = "expert", qboConnected = false, qboCompanyName, qboAuthorizeUrl, onImportQboReport, onQboConnected, onQboDisconnected, onQboImport, qboClientConfirmed, }) {
|
|
80
|
+
function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDocument, onDeleteDocument, fetchUploadedDocuments, parsedFieldCounts, jobId = "stub-job-id", onSaveReviewedField, userContext: _userContext = "expert", qboConnected = false, qboCompanyName, qboAuthorizeUrl, qboRedirectUri, onImportQboReport, onQboConnected, onQboDisconnected, onQboImport, qboClientConfirmed: _qboClientConfirmed, }) {
|
|
81
81
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
82
82
|
const docSpecs = (0, react_1.useMemo)(() => (0, documents_1.getDocSpecs)(entityType !== null && entityType !== void 0 ? entityType : undefined), [entityType]);
|
|
83
83
|
// Build tier defs dynamically from the doc spec list so they're always in sync.
|
|
@@ -124,6 +124,7 @@ function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDoc
|
|
|
124
124
|
qboConnected,
|
|
125
125
|
qboCompanyName,
|
|
126
126
|
qboAuthorizeUrl,
|
|
127
|
+
qboRedirectUri,
|
|
127
128
|
onImportQboReport,
|
|
128
129
|
fetchUploadedDocuments,
|
|
129
130
|
sessionId: jobId,
|
|
@@ -134,7 +135,7 @@ function TaxAxisDocuments({ profile, entityType, onContinue, onBack, onUploadDoc
|
|
|
134
135
|
});
|
|
135
136
|
const showQboBanner = !!qboAuthorizeUrl || qboConnected;
|
|
136
137
|
// FIX B: gate document list behind QBO client confirmation or manual skip
|
|
137
|
-
const [clientConfirmed, setClientConfirmed] = (0, react_1.useState)(
|
|
138
|
+
const [clientConfirmed, setClientConfirmed] = (0, react_1.useState)(true);
|
|
138
139
|
// Sync when qboConnected prop updates (e.g. localStorage restore in parent)
|
|
139
140
|
(0, react_1.useEffect)(() => {
|
|
140
141
|
if (qboConnected)
|
|
@@ -29,6 +29,8 @@ export interface QboFlowProps {
|
|
|
29
29
|
qboCompanyName?: string | null;
|
|
30
30
|
qboAuthorizeUrl?: string;
|
|
31
31
|
qboGetClientsUrl?: string;
|
|
32
|
+
/** Override the OAuth redirect URI (e.g. /tax-axis/quickbooks for in-context connect) */
|
|
33
|
+
qboRedirectUri?: string;
|
|
32
34
|
/** Selected tax year from the session profile — pre-fills the year dropdown */
|
|
33
35
|
profileYear?: number;
|
|
34
36
|
onImportQboReport?: (sessionId: string, realmId: string, reportType: string, accountingMethod: string, year?: number) => Promise<any>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { QboCompany, QboModalStep, QboFlowProps } from "./types";
|
|
2
|
-
export declare function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQboReport, fetchUploadedDocuments, sessionId, profileYear, onQboConnected, onQboDisconnected, onQboImportComplete, }: QboFlowProps): {
|
|
2
|
+
export declare function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, qboRedirectUri, onImportQboReport, fetchUploadedDocuments, sessionId, profileYear, onQboConnected, onQboDisconnected, onQboImportComplete, }: QboFlowProps): {
|
|
3
3
|
modalStep: QboModalStep;
|
|
4
4
|
selectedCompany: QboCompany | null;
|
|
5
5
|
selectedReports: string[];
|
|
@@ -10,10 +10,10 @@ export declare function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeU
|
|
|
10
10
|
companies: QboCompany[];
|
|
11
11
|
openPermissions: () => void;
|
|
12
12
|
openImport: () => void;
|
|
13
|
-
handlePermissionsContinue: () => void
|
|
13
|
+
handlePermissionsContinue: () => Promise<void>;
|
|
14
14
|
handleCompanySelected: (company: QboCompany) => void;
|
|
15
15
|
handleReportsConfirmed: (reportIds: string[]) => Promise<void>;
|
|
16
16
|
handleMappingConfirm: () => Promise<void>;
|
|
17
|
-
handleDisconnect: () => void
|
|
17
|
+
handleDisconnect: () => Promise<void>;
|
|
18
18
|
closeModal: () => void;
|
|
19
19
|
};
|
|
@@ -21,14 +21,13 @@ function buildCompany(companyName) {
|
|
|
21
21
|
.join("");
|
|
22
22
|
return { id: "connected", name, initials, color: "#2CA01C" };
|
|
23
23
|
}
|
|
24
|
-
function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQboReport, fetchUploadedDocuments, sessionId, profileYear, onQboConnected, onQboDisconnected, onQboImportComplete, }) {
|
|
24
|
+
function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, qboRedirectUri, onImportQboReport, fetchUploadedDocuments, sessionId, profileYear, onQboConnected, onQboDisconnected, onQboImportComplete, }) {
|
|
25
25
|
const [modalStep, setModalStep] = (0, react_1.useState)("closed");
|
|
26
26
|
const [selectedCompany, setSelectedCompany] = (0, react_1.useState)(qboConnected ? buildCompany(qboCompanyName) : null);
|
|
27
27
|
const [selectedReports, setSelectedReports] = (0, react_1.useState)([]);
|
|
28
28
|
const [selectedYear, setSelectedYear] = (0, react_1.useState)(profileYear !== null && profileYear !== void 0 ? profileYear : new Date().getFullYear());
|
|
29
29
|
const [importStepIndex, setImportStepIndex] = (0, react_1.useState)(0);
|
|
30
30
|
const [error, setError] = (0, react_1.useState)(null);
|
|
31
|
-
const pollTimerRef = (0, react_1.useRef)(null);
|
|
32
31
|
// Keep selectedYear in sync if profileYear prop changes
|
|
33
32
|
const prevProfileYear = (0, react_1.useRef)(profileYear);
|
|
34
33
|
if (profileYear !== prevProfileYear.current) {
|
|
@@ -41,13 +40,6 @@ function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQbo
|
|
|
41
40
|
if (qboConnected)
|
|
42
41
|
setSelectedCompany(buildCompany(qboCompanyName));
|
|
43
42
|
}, [qboConnected, qboCompanyName]);
|
|
44
|
-
// Cleanup poll timer on unmount
|
|
45
|
-
(0, react_1.useEffect)(() => {
|
|
46
|
-
return () => {
|
|
47
|
-
if (pollTimerRef.current)
|
|
48
|
-
clearInterval(pollTimerRef.current);
|
|
49
|
-
};
|
|
50
|
-
}, []);
|
|
51
43
|
// ── Already connected: skip straight to report selection ──
|
|
52
44
|
const openImport = (0, react_1.useCallback)(() => {
|
|
53
45
|
setError(null);
|
|
@@ -59,40 +51,41 @@ function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQbo
|
|
|
59
51
|
setError(null);
|
|
60
52
|
setModalStep("permissions");
|
|
61
53
|
}, []);
|
|
62
|
-
// ── After permissions:
|
|
63
|
-
const handlePermissionsContinue = (0, react_1.useCallback)(() => {
|
|
64
|
-
|
|
65
|
-
(
|
|
66
|
-
if (isDemoMode) {
|
|
67
|
-
setSelectedCompany(buildCompany(qboCompanyName));
|
|
68
|
-
setModalStep("client_selector");
|
|
54
|
+
// ── After permissions: POST to authorize endpoint to get Intuit OAuth URL, then open popup ──
|
|
55
|
+
const handlePermissionsContinue = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
if (!qboAuthorizeUrl) {
|
|
57
|
+
setError("QuickBooks authorization URL is not configured.");
|
|
69
58
|
return;
|
|
70
59
|
}
|
|
71
60
|
setModalStep("oauth_pending");
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
elapsed += 500;
|
|
82
|
-
if (popup && popup.closed) {
|
|
83
|
-
if (pollTimerRef.current)
|
|
84
|
-
clearInterval(pollTimerRef.current);
|
|
85
|
-
// Parent prop update will trigger the useEffect above to set selectedCompany
|
|
86
|
-
setModalStep("client_selector");
|
|
61
|
+
try {
|
|
62
|
+
const redirectUri = qboRedirectUri !== null && qboRedirectUri !== void 0 ? qboRedirectUri : `${window.location.origin}/integrations-hub/callback`;
|
|
63
|
+
const res = yield fetch(qboAuthorizeUrl, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify({ redirectUri, environment: "sandbox" }),
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
throw new Error(`Authorization request failed: ${res.status}`);
|
|
87
70
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
setError("QuickBooks authorization timed out. Please try again.");
|
|
92
|
-
setModalStep("closed");
|
|
71
|
+
const data = yield res.json();
|
|
72
|
+
if (!data.authUri) {
|
|
73
|
+
throw new Error("No authorization URL returned.");
|
|
93
74
|
}
|
|
94
|
-
|
|
95
|
-
|
|
75
|
+
// Persist session context so the callback page can resume the correct session
|
|
76
|
+
if (sessionId) {
|
|
77
|
+
localStorage.setItem("taxaxis_pending_session", JSON.stringify({ sessionId, ts: Date.now() }));
|
|
78
|
+
}
|
|
79
|
+
localStorage.setItem("current_integration", "quickbooks");
|
|
80
|
+
// Full-page redirect — same as integrations hub. Intuit will redirect back
|
|
81
|
+
// to the registered redirectUri (/tax-axis/quickbooks) when complete.
|
|
82
|
+
window.location.href = data.authUri;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
setError(err.message || "Failed to start QuickBooks authorization.");
|
|
86
|
+
setModalStep("closed");
|
|
87
|
+
}
|
|
88
|
+
}), [qboAuthorizeUrl, qboRedirectUri, sessionId]);
|
|
96
89
|
// ── Company selected ──
|
|
97
90
|
const handleCompanySelected = (0, react_1.useCallback)((company) => {
|
|
98
91
|
setSelectedCompany(company);
|
|
@@ -173,14 +166,16 @@ function useQboFlow({ qboConnected, qboCompanyName, qboAuthorizeUrl, onImportQbo
|
|
|
173
166
|
const handleMappingConfirm = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
|
|
174
167
|
yield handleReportsConfirmed(selectedReports);
|
|
175
168
|
}), [handleReportsConfirmed, selectedReports]);
|
|
176
|
-
const handleDisconnect = (0, react_1.useCallback)(() => {
|
|
169
|
+
const handleDisconnect = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
if (!window.confirm("Are you sure you want to disconnect QuickBooks? This will stop data imports for this account."))
|
|
171
|
+
return;
|
|
177
172
|
setSelectedCompany(null);
|
|
178
173
|
setSelectedReports([]);
|
|
179
174
|
setImportStepIndex(0);
|
|
180
175
|
setModalStep("closed");
|
|
181
176
|
if (onQboDisconnected)
|
|
182
|
-
onQboDisconnected();
|
|
183
|
-
}, [onQboDisconnected]);
|
|
177
|
+
yield onQboDisconnected();
|
|
178
|
+
}), [onQboDisconnected]);
|
|
184
179
|
const closeModal = (0, react_1.useCallback)(() => {
|
|
185
180
|
setModalStep("closed");
|
|
186
181
|
setError(null);
|