@musetax/compass-widget 0.1.218 → 0.2.218

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/dist/App.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ import 'react-toastify/dist/ReactToastify.css';
1
2
  declare function App(): import("react/jsx-runtime").JSX.Element;
2
3
  export default App;
package/dist/App.js CHANGED
@@ -1,5 +1,7 @@
1
- import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { ToastContainer } from 'react-toastify';
3
+ import 'react-toastify/dist/ReactToastify.css';
2
4
  function App() {
3
- return _jsx(_Fragment, {});
5
+ return _jsx(_Fragment, { children: _jsx(ToastContainer, {}) });
4
6
  }
5
7
  export default App;
@@ -0,0 +1,2 @@
1
+ declare const api: import("axios").AxiosInstance;
2
+ export default api;
@@ -0,0 +1,25 @@
1
+ // api.ts
2
+ import axios from "axios";
3
+ import { toast } from "react-toastify";
4
+ const API_BASE_URL = "https://dev-categorization.musetax.com/v2/api";
5
+ // Create Axios instance
6
+ const api = axios.create({
7
+ baseURL: API_BASE_URL,
8
+ headers: {
9
+ Accept: "application/json",
10
+ "Content-Type": "application/json",
11
+ },
12
+ });
13
+ // Response interceptor for centralized error handling
14
+ api.interceptors.response.use((response) => response, (error) => {
15
+ var _a, _b;
16
+ const status = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status;
17
+ if (status === 401) {
18
+ console.warn("Unauthorized (401) - refreshing page...");
19
+ toast.error("Token Expired.", { toastId: "Token Expired." });
20
+ window.location.reload(); // reload the page
21
+ }
22
+ console.error("API error:", ((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) || error.message);
23
+ return Promise.reject(error);
24
+ });
25
+ export default api;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface AddTransactionFormProps {
3
+ userId: string;
4
+ accessToken: string;
5
+ onSuccess: () => void;
6
+ onError?: (msg: string) => void;
7
+ }
8
+ declare const AddTransactionForm: React.FC<AddTransactionFormProps>;
9
+ export default AddTransactionForm;
@@ -0,0 +1,330 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { useState } from "react";
12
+ import api from "../api/api";
13
+ import { toast } from "react-toastify";
14
+ const defaultFormData = {
15
+ account_id: "",
16
+ amount: "",
17
+ iso_currency_code: "USD",
18
+ datetime: new Date().toISOString(),
19
+ date: new Date().toISOString(),
20
+ name: "",
21
+ merchant_name: "",
22
+ payment_channel: "",
23
+ transaction_id: "",
24
+ transaction_type: "",
25
+ personal_finance_category: {
26
+ primary: "",
27
+ detailed: "",
28
+ },
29
+ };
30
+ const AddTransactionForm = ({ userId, accessToken, onSuccess, onError, }) => {
31
+ const [formData, setFormData] = useState(defaultFormData);
32
+ const [submitting, setSubmitting] = useState(false);
33
+ const [error, setError] = useState("");
34
+ const [fieldErrors, setFieldErrors] = useState({});
35
+ const validate = () => {
36
+ const amountNum = Number(formData.amount);
37
+ const errors = {};
38
+ if (!formData.name.trim())
39
+ errors.name = "Transaction name is required.";
40
+ if (!formData.merchant_name.trim())
41
+ errors.merchant_name = "Merchant name is required.";
42
+ if (!amountNum || Number(amountNum <= 0))
43
+ errors.amount = "Amount must be greater than 0.";
44
+ if (!formData.account_id.trim())
45
+ errors.account_id = "Account ID is required.";
46
+ if (!formData.transaction_id.trim())
47
+ errors.transaction_id = "Transaction ID is required.";
48
+ if (!formData.payment_channel.trim())
49
+ errors.payment_channel = "Payment channel is required.";
50
+ if (!formData.transaction_type.trim())
51
+ errors.transaction_type = "Transaction type is required.";
52
+ if (!formData.personal_finance_category.primary.trim())
53
+ errors.primary = "Primary category is required.";
54
+ if (!formData.personal_finance_category.detailed.trim())
55
+ errors.detailed = "Detailed category is required.";
56
+ setFieldErrors(errors);
57
+ return Object.keys(errors).length === 0;
58
+ };
59
+ const clearError = (field) => {
60
+ if (fieldErrors[field]) {
61
+ setFieldErrors((prev) => (Object.assign(Object.assign({}, prev), { [field]: "" })));
62
+ }
63
+ };
64
+ const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
65
+ var _a, _b;
66
+ if (!validate())
67
+ return;
68
+ setSubmitting(true);
69
+ setError("");
70
+ const payload = {
71
+ user_id: userId,
72
+ transactions: [formData],
73
+ };
74
+ try {
75
+ const response = yield api.post("/transactions", payload);
76
+ const data = response.data;
77
+ setFormData(defaultFormData);
78
+ setFieldErrors({});
79
+ onSuccess();
80
+ toast.success("Transaction added successfully", { toastId: "Transaction added successfully" });
81
+ }
82
+ catch (err) {
83
+ const msg = ((_b = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.detail) || "Failed to add transaction";
84
+ setError(msg);
85
+ onError === null || onError === void 0 ? void 0 : onError(msg);
86
+ toast.error(msg, { toastId: "error-msg" });
87
+ }
88
+ finally {
89
+ setSubmitting(false);
90
+ }
91
+ });
92
+ return (_jsxs("div", Object.assign({ style: {
93
+ width: "100%",
94
+ maxHeight: "70vh",
95
+ backgroundColor: "#fff",
96
+ borderRadius: "12px",
97
+ boxShadow: "0 0 2px rgba(0,0,0,0.2)",
98
+ margin: "auto",
99
+ zIndex: 9998,
100
+ padding: "0",
101
+ overflowY: "auto",
102
+ } }, { children: [_jsx("h2", Object.assign({ style: {
103
+ fontSize: "1.125rem",
104
+ fontWeight: "500",
105
+ color: "#042567",
106
+ margin: "0px",
107
+ backgroundColor: "#F1F7FB",
108
+ padding: "16px 24px",
109
+ display: "flex",
110
+ justifyContent: "space-between",
111
+ alignItems: "center",
112
+ borderBottom: "1px solid #BFDBFE",
113
+ marginBottom: "18px",
114
+ } }, { children: "Add New Transaction" })), _jsxs("div", Object.assign({ style: { padding: "8px 16px" } }, { children: [error && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: error }))), _jsxs("div", Object.assign({ style: {
115
+ display: "flex",
116
+ alignItems: "start",
117
+ gap: "16px",
118
+ marginBottom: "12px",
119
+ } }, { children: [_jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
120
+ fontSize: "14px",
121
+ fontWeight: "500",
122
+ color: "#042567",
123
+ marginBottom: "5px",
124
+ display: "block",
125
+ } }, { children: "Transaction Name" })), _jsx("input", { type: "text", placeholder: "Transaction Name", value: formData.name, onChange: (e) => {
126
+ setFormData(Object.assign(Object.assign({}, formData), { name: e.target.value }));
127
+ clearError("name");
128
+ }, style: {
129
+ width: "calc(100% - 35px)",
130
+ padding: "10px 16px",
131
+ border: "1px solid #E6E7EA",
132
+ borderRadius: "10px",
133
+ fontSize: "0.875rem",
134
+ color: "#042567",
135
+ outline: "none",
136
+ } })] })), fieldErrors.name && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.name })))] })), _jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
137
+ fontSize: "14px",
138
+ fontWeight: "500",
139
+ color: "#042567",
140
+ marginBottom: "5px",
141
+ display: "block",
142
+ } }, { children: "Merchant Name" })), _jsx("input", { placeholder: "Merchant Name", value: formData.merchant_name, onChange: (e) => {
143
+ setFormData(Object.assign(Object.assign({}, formData), { merchant_name: e.target.value }));
144
+ clearError("merchant_name");
145
+ }, style: {
146
+ width: "calc(100% - 35px)",
147
+ padding: "10px 16px",
148
+ border: "1px solid #E6E7EA",
149
+ borderRadius: "10px",
150
+ fontSize: "0.875rem",
151
+ color: "#042567",
152
+ outline: "none",
153
+ } })] })), fieldErrors.merchant_name && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.merchant_name })))] }))] })), _jsxs("div", Object.assign({ style: {
154
+ display: "flex",
155
+ alignItems: "start",
156
+ gap: "16px",
157
+ marginBottom: "12px",
158
+ } }, { children: [_jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
159
+ fontSize: "14px",
160
+ fontWeight: "500",
161
+ color: "#042567",
162
+ marginBottom: "5px",
163
+ display: "block",
164
+ } }, { children: "Amount" })), _jsx("input", { placeholder: "Amount", type: "text", value: formData.amount, onChange: (e) => {
165
+ const value = e.target.value;
166
+ // Allow empty input
167
+ if (value === "") {
168
+ setFormData(Object.assign(Object.assign({}, formData), { amount: "" }));
169
+ clearError("amount");
170
+ return;
171
+ }
172
+ // Regex: start with optional digits, optional single decimal, optional digits after decimal
173
+ // Prevent multiple decimals, letters, or invalid characters
174
+ const valid = /^(\d+(\.\d*)?|\.\d*)$/;
175
+ if (valid.test(value)) {
176
+ setFormData(Object.assign(Object.assign({}, formData), { amount: value }));
177
+ clearError("amount");
178
+ }
179
+ }, style: {
180
+ width: "calc(100% - 35px)",
181
+ padding: "10px 16px",
182
+ border: "1px solid #E6E7EA",
183
+ borderRadius: "10px",
184
+ fontSize: "0.875rem",
185
+ color: "#042567",
186
+ outline: "none",
187
+ } })] })), fieldErrors.amount && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.amount })))] })), _jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
188
+ fontSize: "14px",
189
+ fontWeight: "500",
190
+ color: "#042567",
191
+ marginBottom: "5px",
192
+ display: "block",
193
+ } }, { children: "Account ID" })), _jsx("input", { placeholder: "Account ID", value: formData.account_id, onChange: (e) => {
194
+ setFormData(Object.assign(Object.assign({}, formData), { account_id: e.target.value }));
195
+ clearError("account_id");
196
+ }, style: {
197
+ width: "calc(100% - 35px)",
198
+ padding: "10px 16px",
199
+ border: "1px solid #E6E7EA",
200
+ borderRadius: "10px",
201
+ fontSize: "0.875rem",
202
+ color: "#042567",
203
+ outline: "none",
204
+ } })] })), fieldErrors.account_id && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.account_id })))] }))] })), _jsxs("div", Object.assign({ style: {
205
+ display: "flex",
206
+ alignItems: "start",
207
+ gap: "16px",
208
+ marginBottom: "12px",
209
+ } }, { children: [_jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
210
+ fontSize: "14px",
211
+ fontWeight: "500",
212
+ color: "#042567",
213
+ marginBottom: "5px",
214
+ display: "block",
215
+ } }, { children: "Transaction ID" })), _jsx("input", { placeholder: "Transaction ID", value: formData.transaction_id, onChange: (e) => {
216
+ setFormData(Object.assign(Object.assign({}, formData), { transaction_id: e.target.value }));
217
+ clearError("transaction_id");
218
+ }, style: {
219
+ width: "calc(100% - 35px)",
220
+ padding: "10px 16px",
221
+ border: "1px solid #E6E7EA",
222
+ borderRadius: "10px",
223
+ fontSize: "0.875rem",
224
+ color: "#042567",
225
+ outline: "none",
226
+ } })] })), fieldErrors.transaction_id && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.transaction_id })))] })), _jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
227
+ fontSize: "14px",
228
+ fontWeight: "500",
229
+ color: "#042567",
230
+ marginBottom: "5px",
231
+ display: "block",
232
+ } }, { children: "Payment Channel" })), _jsx("input", { placeholder: "Payment Channel", value: formData.payment_channel, onChange: (e) => {
233
+ setFormData(Object.assign(Object.assign({}, formData), { payment_channel: e.target.value }));
234
+ clearError("payment_channel");
235
+ }, style: {
236
+ width: "calc(100% - 35px)",
237
+ padding: "10px 16px",
238
+ border: "1px solid #E6E7EA",
239
+ borderRadius: "10px",
240
+ fontSize: "0.875rem",
241
+ color: "#042567",
242
+ outline: "none",
243
+ } })] })), fieldErrors.payment_channel && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.payment_channel })))] }))] })), _jsxs("div", Object.assign({ style: {
244
+ display: "flex",
245
+ alignItems: "start",
246
+ gap: "16px",
247
+ marginBottom: "12px",
248
+ } }, { children: [_jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
249
+ fontSize: "14px",
250
+ fontWeight: "500",
251
+ color: "#042567",
252
+ marginBottom: "5px",
253
+ display: "block",
254
+ } }, { children: "Transaction Type" })), _jsx("input", { placeholder: "Transaction Type", value: formData.transaction_type, onChange: (e) => {
255
+ setFormData(Object.assign(Object.assign({}, formData), { transaction_type: e.target.value }));
256
+ clearError("transaction_type");
257
+ }, style: {
258
+ width: "calc(100% - 35px)",
259
+ padding: "10px 16px",
260
+ border: "1px solid #E6E7EA",
261
+ borderRadius: "10px",
262
+ fontSize: "0.875rem",
263
+ color: "#042567",
264
+ outline: "none",
265
+ } })] })), fieldErrors.transaction_type && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.transaction_type })))] })), _jsxs("div", Object.assign({ style: { width: "49%" } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
266
+ fontSize: "14px",
267
+ fontWeight: "500",
268
+ color: "#042567",
269
+ marginBottom: "5px",
270
+ display: "block",
271
+ } }, { children: "Primary Category" })), _jsx("input", { placeholder: "Primary Category", value: formData.personal_finance_category.primary, onChange: (e) => {
272
+ setFormData(Object.assign(Object.assign({}, formData), { personal_finance_category: Object.assign(Object.assign({}, formData.personal_finance_category), { primary: e.target.value }) }));
273
+ clearError("primary");
274
+ }, style: {
275
+ width: "calc(100% - 35px)",
276
+ padding: "10px 16px",
277
+ border: "1px solid #E6E7EA",
278
+ borderRadius: "10px",
279
+ fontSize: "0.875rem",
280
+ color: "#042567",
281
+ outline: "none",
282
+ } })] })), fieldErrors.primary && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.primary })))] }))] })), _jsxs("div", Object.assign({ style: {
283
+ display: "block",
284
+ marginBottom: "0px",
285
+ } }, { children: [_jsxs("div", Object.assign({ style: { width: "100%" } }, { children: [_jsx("label", Object.assign({ style: {
286
+ fontSize: "14px",
287
+ fontWeight: "500",
288
+ color: "#042567",
289
+ marginBottom: "5px",
290
+ display: "block",
291
+ } }, { children: "Detailed Category" })), _jsx("input", { placeholder: "Detailed Category", value: formData.personal_finance_category.detailed, onChange: (e) => {
292
+ setFormData(Object.assign(Object.assign({}, formData), { personal_finance_category: Object.assign(Object.assign({}, formData.personal_finance_category), { detailed: e.target.value }) }));
293
+ clearError("detailed");
294
+ }, style: {
295
+ width: "calc(100% - 35px)",
296
+ padding: "10px 16px",
297
+ border: "1px solid #E6E7EA",
298
+ borderRadius: "10px",
299
+ fontSize: "0.875rem",
300
+ color: "#042567",
301
+ outline: "none",
302
+ } })] })), fieldErrors.detailed && (_jsx("p", Object.assign({ style: { color: "red", fontSize: "12px", fontWeight: "400" } }, { children: fieldErrors.detailed })))] }))] })), _jsxs("div", Object.assign({ style: {
303
+ display: "flex",
304
+ alignItems: "center",
305
+ justifyContent: "center",
306
+ marginTop: "20px",
307
+ marginBottom: "20px",
308
+ gap: "10px",
309
+ } }, { children: [_jsx("button", Object.assign({ disabled: submitting, onClick: onSuccess, style: {
310
+ border: "1px solid #5387F1",
311
+ backgroundColor: "white",
312
+ color: "#5387F1",
313
+ fontSize: "0.875rem",
314
+ fontWeight: 500,
315
+ padding: "8px 16px",
316
+ borderRadius: 8,
317
+ cursor: "pointer",
318
+ } }, { children: "Cancel" })), _jsx("button", Object.assign({ onClick: handleSubmit, disabled: submitting, style: {
319
+ backgroundColor: "#5387F1",
320
+ border: "1px solid #5387F1",
321
+ color: "white",
322
+ fontSize: "0.875rem",
323
+ fontWeight: 500,
324
+ padding: "8px 16px",
325
+ borderRadius: 8,
326
+ marginRight: 8,
327
+ cursor: "pointer",
328
+ } }, { children: submitting ? "Submitting..." : "Submit" }))] }))] })));
329
+ };
330
+ export default AddTransactionForm;
@@ -0,0 +1,12 @@
1
+ interface CommonParams {
2
+ onError?: (msg: string) => void;
3
+ setLoading?: (val: boolean) => void;
4
+ setError?: (val: string) => void;
5
+ }
6
+ interface GetAuthSessionTokenParams extends CommonParams {
7
+ session_token: string;
8
+ userId: string;
9
+ onSuccess: (data: any) => void;
10
+ }
11
+ export declare const getAuthSessionToken: ({ session_token, userId, onSuccess, onError, setLoading, setError, }: GetAuthSessionTokenParams) => Promise<void>;
12
+ export {};
@@ -0,0 +1,42 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ // sessionHelpers.ts
11
+ import { toast } from "react-toastify";
12
+ import api from "../api/api";
13
+ export const getAuthSessionToken = ({ session_token, userId, onSuccess, onError, setLoading, setError, }) => __awaiter(void 0, void 0, void 0, function* () {
14
+ var _a, _b;
15
+ try {
16
+ setError === null || setError === void 0 ? void 0 : setError("");
17
+ const response = yield api.get("/widgets/auth/token", {
18
+ headers: {
19
+ Accept: "application/json",
20
+ Authorization: `Bearer ${session_token}`,
21
+ },
22
+ });
23
+ const data = response.data;
24
+ if (data.domain_urls) {
25
+ onSuccess(data);
26
+ }
27
+ else {
28
+ const errorMsg = (data === null || data === void 0 ? void 0 : data.detail) || "Invalid auth session token";
29
+ setError === null || setError === void 0 ? void 0 : setError(errorMsg);
30
+ onError === null || onError === void 0 ? void 0 : onError(errorMsg);
31
+ toast.error(errorMsg, { toastId: "error-errorMsg" });
32
+ setLoading === null || setLoading === void 0 ? void 0 : setLoading(false);
33
+ }
34
+ }
35
+ catch (err) {
36
+ const msg = ((_b = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.detail) || "Error while fetching auth token";
37
+ setError === null || setError === void 0 ? void 0 : setError(msg);
38
+ onError === null || onError === void 0 ? void 0 : onError(msg);
39
+ toast.error(msg, { toastId: "msg-error-errorMsg" });
40
+ setLoading === null || setLoading === void 0 ? void 0 : setLoading(false);
41
+ }
42
+ });
@@ -0,0 +1,2 @@
1
+ declare const ErrorWidget: ({ message, onClose }: any) => import("react/jsx-runtime").JSX.Element;
2
+ export default ErrorWidget;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const ErrorWidget = ({ message, onClose }) => {
3
+ console.log(message, 'messagemessagemessage');
4
+ return (_jsxs("div", Object.assign({ style: {
5
+ display: "flex",
6
+ alignItems: "center",
7
+ flexDirection: "column",
8
+ justifyContent: "center",
9
+ height: "100%",
10
+ } }, { children: [_jsx("h2", Object.assign({ style: {
11
+ color: "#000000",
12
+ margin: "0px 0px 10px 0px",
13
+ fontSize: "22px",
14
+ } }, { children: "Oops! Something went wrong" })), _jsx("p", Object.assign({ style: {
15
+ fontSize: "16px",
16
+ color: "#333333",
17
+ textAlign: "center",
18
+ margin: "0px",
19
+ } }, { children: message })), _jsxs("button", Object.assign({ id: "close-widget-btn", onClick: () => onClose(), style: {
20
+ background: "#333333",
21
+ padding: "6px 16px",
22
+ color: "#ffffff",
23
+ borderRadius: "8px",
24
+ textAlign: "center",
25
+ fontSize: "16px",
26
+ margin: "20px 0px 0px 0px",
27
+ border: "none",
28
+ cursor: "pointer",
29
+ display: "flex",
30
+ alignItems: "center",
31
+ gap: "8px",
32
+ } }, { children: [_jsx("i", { className: "fas fa-times" }), " Close"] }))] })));
33
+ };
34
+ export default ErrorWidget;
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { default as ClientAuthForm } from './ClientAuthForm';
1
+ export { default as ClientAuthForm } from './transactionReviewWidget/ClientAuthForm';
2
+ export { default as PotentialDeductions } from "./potentialDeductionsWidget/PotentialDeductions";
package/dist/index.js CHANGED
@@ -1,18 +1,2 @@
1
- export { default as ClientAuthForm } from './ClientAuthForm';
2
- // import React from "react";
3
- // import ReactDOM from "react-dom/client";
4
- // import "./index.css";
5
- // import reportWebVitals from "./reportWebVitals";
6
- // import App from "./App";
7
- // const root = ReactDOM.createRoot(
8
- // document.getElementById("root") as HTMLElement
9
- // );
10
- // root.render(
11
- // <React.StrictMode>
12
- // <App />
13
- // </React.StrictMode>
14
- // );
15
- // // If you want to start measuring performance in your app, pass a function
16
- // // to log results (for example: reportWebVitals(console.log))
17
- // // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
18
- // reportWebVitals();
1
+ export { default as ClientAuthForm } from './transactionReviewWidget/ClientAuthForm';
2
+ export { default as PotentialDeductions } from "./potentialDeductionsWidget/PotentialDeductions";
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface Props {
3
+ userId: string;
4
+ access_token: string;
5
+ session_token: string;
6
+ onError?: (msg: string) => void;
7
+ }
8
+ declare const PotentialDeductions: React.FC<Props>;
9
+ export default PotentialDeductions;
@@ -0,0 +1,181 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { useEffect, useState } from "react";
12
+ import api from "../api/api";
13
+ import { getAuthSessionToken } from "../helper/AuthHelper";
14
+ import ErrorWidget from "../helper/Error";
15
+ import { toast } from "react-toastify";
16
+ const PotentialDeductions = ({ userId, access_token, session_token, onError, }) => {
17
+ var _a, _b;
18
+ const [transactions, setTransactions] = useState([]);
19
+ const [activeCategoryIndex, setActiveCategoryIndex] = useState(0);
20
+ const [isOpen, setIsOpen] = useState(false);
21
+ const [loading, setLoading] = useState(false);
22
+ const [error, setError] = useState("");
23
+ const groupByField = (dataArray, groupKey) => {
24
+ if (!Array.isArray(dataArray)) {
25
+ throw new Error("First argument must be an array");
26
+ }
27
+ const grouped = [];
28
+ dataArray.forEach((item) => {
29
+ const key = item[groupKey] || "schedule C";
30
+ if (!grouped[key]) {
31
+ grouped[key] = [];
32
+ }
33
+ grouped[key].push(item);
34
+ });
35
+ return grouped;
36
+ };
37
+ const fetchTransactions = (userId) => __awaiter(void 0, void 0, void 0, function* () {
38
+ var _c;
39
+ setLoading(true);
40
+ try {
41
+ const { data } = yield api.get(`/potential-deductions/${userId}`);
42
+ console.log(data, "datadatadatadatadatadatadatadata");
43
+ if (data === null || data === void 0 ? void 0 : data.detail) {
44
+ const msg = data.detail;
45
+ setError(msg);
46
+ onError === null || onError === void 0 ? void 0 : onError(msg);
47
+ toast.error(msg, { toastId: "msg-error-msg-errorMsg" });
48
+ }
49
+ else {
50
+ console.log(data, "datadatadata");
51
+ const scheduleData = groupByField(data.deductions, ((_c = data.deductions[0]) === null || _c === void 0 ? void 0 : _c.schedule) || "schedule c");
52
+ setTransactions(scheduleData);
53
+ }
54
+ }
55
+ catch (error) {
56
+ const msg = "Failed to fetch transactions.";
57
+ setError(msg);
58
+ onError === null || onError === void 0 ? void 0 : onError(msg);
59
+ toast.error(msg, { toastId: "msg-error-msg-error-Msg" });
60
+ }
61
+ finally {
62
+ setLoading(false);
63
+ }
64
+ });
65
+ useEffect(() => {
66
+ if (access_token && session_token) {
67
+ getAuthSessionToken({
68
+ session_token,
69
+ userId,
70
+ onSuccess: (data) => {
71
+ console.log("Auth token fetched, domain URLs:", data.domain_urls);
72
+ fetchTransactions(userId);
73
+ },
74
+ onError,
75
+ setLoading,
76
+ setError,
77
+ });
78
+ }
79
+ }, [access_token, session_token]);
80
+ const objectKey = Object.keys(transactions);
81
+ const activeDeductions = transactions[objectKey[activeCategoryIndex]];
82
+ let total = 0;
83
+ let savings = 0;
84
+ if (activeDeductions) {
85
+ activeDeductions.forEach((d) => {
86
+ console.log(d);
87
+ total += d.total_amount || 0;
88
+ savings += d.potential_deduction || 0;
89
+ });
90
+ }
91
+ return (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({ style: {
92
+ position: "fixed",
93
+ bottom: "20px",
94
+ right: "20px",
95
+ width: "60px",
96
+ height: "60px",
97
+ backgroundColor: "#007bff",
98
+ borderRadius: "50%",
99
+ display: "flex",
100
+ justifyContent: "center",
101
+ alignItems: "center",
102
+ cursor: "pointer",
103
+ zIndex: 9999,
104
+ color: "#fff",
105
+ fontSize: "28px",
106
+ boxShadow: "0 4px 5px rgba(0, 0, 0, 0.3)",
107
+ }, onClick: () => setIsOpen(!isOpen), title: "Open Auth Widget" }, { children: "\uD83D\uDCAC" })), isOpen && (_jsx("div", Object.assign({ style: {
108
+ position: "fixed",
109
+ bottom: "90px",
110
+ right: "20px",
111
+ width: "68rem",
112
+ maxHeight: "70vh",
113
+ zIndex: 9998,
114
+ overflowY: "auto",
115
+ } }, { children: error ? (_jsx("div", Object.assign({ style: {
116
+ paddingTop: "200px",
117
+ minHeight: "500px",
118
+ } }, { children: _jsx(ErrorWidget, { message: error, onClose: () => setIsOpen(false) }) }))) : (_jsxs("div", Object.assign({ style: {
119
+ maxWidth: 1200,
120
+ margin: "auto",
121
+ border: "1px solid #ccc",
122
+ borderRadius: 16,
123
+ overflow: "hidden",
124
+ } }, { children: [_jsxs("div", Object.assign({ style: {
125
+ backgroundColor: "#F1F7FB",
126
+ padding: "16px 24px",
127
+ display: "flex",
128
+ justifyContent: "space-between",
129
+ alignItems: "center",
130
+ borderBottom: "1px solid #BFDBFE",
131
+ } }, { children: [_jsx("h2", Object.assign({ style: {
132
+ fontSize: 20,
133
+ fontWeight: 500,
134
+ color: "#042567",
135
+ margin: 0,
136
+ } }, { children: "Potential Deductions Analysis" })), _jsxs("span", Object.assign({ style: {
137
+ fontSize: 14,
138
+ color: "#6B7280",
139
+ display: "flex",
140
+ alignItems: "center",
141
+ gap: 4,
142
+ } }, { children: [_jsx("span", { style: {
143
+ width: 8,
144
+ height: 8,
145
+ borderRadius: "50%",
146
+ backgroundColor: "#687DF7",
147
+ display: "inline-block",
148
+ } }), "Analysis complete"] }))] })), loading ? (_jsx("p", Object.assign({ style: {
149
+ fontSize: "0.875rem",
150
+ color: "#526282",
151
+ margin: 0,
152
+ display: "flex",
153
+ justifyContent: "center",
154
+ width: "100%",
155
+ } }, { children: "Loading\u2026" }))) : (_jsx("div", Object.assign({ style: { padding: 24 } }, { children: transactions && ((_a = Object.keys(transactions)) === null || _a === void 0 ? void 0 : _a.length) > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({ style: { marginBottom: 24, display: "flex", gap: 8 } }, { children: Object.keys(transactions) &&
156
+ ((_b = Object.keys(transactions)) === null || _b === void 0 ? void 0 : _b.map((cat, index) => (_jsx("button", Object.assign({ onClick: () => setActiveCategoryIndex(index), style: {
157
+ border: "1px solid #5387F1",
158
+ padding: "12px 16px",
159
+ fontSize: 14,
160
+ fontWeight: 500,
161
+ borderRadius: 8,
162
+ backgroundColor: activeCategoryIndex === index
163
+ ? "#5387F1"
164
+ : "white",
165
+ color: activeCategoryIndex === index
166
+ ? "white"
167
+ : "#5387F1",
168
+ cursor: "pointer",
169
+ } }, { children: cat }), index)))) })), (activeDeductions === null || activeDeductions === void 0 ? void 0 : activeDeductions.length) > 0 &&
170
+ (activeDeductions === null || activeDeductions === void 0 ? void 0 : activeDeductions.map((activeDeduction) => (_jsx(_Fragment, { children: _jsxs("div", Object.assign({ style: {
171
+ border: "1px solid rgba(30, 64, 175, 0.1)",
172
+ borderRadius: 16,
173
+ padding: 16,
174
+ margin: "12px 0",
175
+ } }, { children: [_jsx("h3", Object.assign({ style: { marginBottom: 8, color: "#042567" } }, { children: activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.title })), _jsx("p", Object.assign({ style: { color: "#526282", marginBottom: 4 } }, { children: activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.description })), _jsxs("p", Object.assign({ style: { color: "#5A83F3", fontSize: 12 } }, { children: ["Debit transactions:", " ", activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.debit_transaction_count, ", Credit transactions:", " ", activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.credit_transaction_count] })), _jsxs("div", Object.assign({ style: {
176
+ marginTop: 16,
177
+ display: "flex",
178
+ justifyContent: "space-between",
179
+ } }, { children: [_jsxs("div", Object.assign({ style: { fontWeight: 500, color: "#5A83F3" } }, { children: ["Total Spent: $", activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.total_amount] })), _jsxs("div", Object.assign({ style: { fontWeight: 500, color: "#5387F1" } }, { children: ["Potential Deduction: $", activeDeduction === null || activeDeduction === void 0 ? void 0 : activeDeduction.potential_deduction] }))] }))] })) })))), _jsx("div", Object.assign({ className: "px-6 my-4" }, { children: _jsxs("div", Object.assign({ className: "bg-[#5387F1] px-6 py-8 rounded-xl text-center" }, { children: [_jsx("h3", Object.assign({ className: "text-white font-semibold text-3xl" }, { children: "$6,350" })), _jsxs("div", Object.assign({ className: "text-center my-3" }, { children: [_jsxs("p", Object.assign({ className: "text-base font-medium text-white mb-0" }, { children: [" ", "Total potenial deduction: $", savings] })), _jsxs("p", Object.assign({ className: "text-white text-sm font-normal mt-0" }, { children: [" ", "Total amount: $", total] }))] })), _jsx("button", Object.assign({ className: "border bg-white text-[#5387F1] text-sm font-medium px-4 py-2 rounded-lg" }, { children: "Get Insights" }))] })) }))] })) : (_jsx("p", Object.assign({ className: "flex justify-center items-center text-center" }, { children: "No Data found." }))) })))] }))) })))] }));
180
+ };
181
+ export default PotentialDeductions;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface Props {
3
+ userId: string;
4
+ access_token: string;
5
+ session_token: string;
6
+ onError?: (msg: string) => void;
7
+ }
8
+ declare const ClientAuthForm: React.FC<Props>;
9
+ export default ClientAuthForm;
@@ -0,0 +1,437 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ import React, { useEffect, useMemo, useState } from "react";
12
+ import AddTransactionForm from "../helper/AddTransactionForm";
13
+ import api from "../api/api";
14
+ import ErrorWidget from "../helper/Error";
15
+ import { getAuthSessionToken } from "../helper/AuthHelper";
16
+ import { toast } from "react-toastify";
17
+ const { CiSearch } = require("react-icons/ci");
18
+ const { FaPlus, FaCaretDown } = require("react-icons/fa6");
19
+ const { HiOutlineArrowSmLeft } = require("react-icons/hi");
20
+ const ClientAuthForm = ({ userId, access_token, session_token, onError, }) => {
21
+ var _a, _b;
22
+ const [isOpen, setIsOpen] = useState(false);
23
+ const [selected, setSelected] = useState(null);
24
+ const [search, setSearch] = useState("");
25
+ const [loading, setLoading] = useState(false);
26
+ const [error, setError] = useState("");
27
+ const [transactions, setTransactions] = useState([]);
28
+ const [showAddForm, setShowAddForm] = useState(false);
29
+ const [categoryNames, setCategoryNames] = useState([]);
30
+ // done
31
+ const fetchTransactions = (userId) => __awaiter(void 0, void 0, void 0, function* () {
32
+ var _c, _d, _e, _f, _g;
33
+ setLoading(true);
34
+ try {
35
+ const { data } = yield api.get(`/transaction/categorize/${userId}`);
36
+ console.log(data, "transactions");
37
+ if (data === null || data === void 0 ? void 0 : data.detail) {
38
+ setError(data === null || data === void 0 ? void 0 : data.detail);
39
+ onError === null || onError === void 0 ? void 0 : onError(data.detail);
40
+ toast.error(data.detail, { toastId: " data.detail-error-msg-error-Msg" });
41
+ setLoading(false);
42
+ }
43
+ else {
44
+ setTransactions(data || []);
45
+ setLoading(false);
46
+ }
47
+ }
48
+ catch (error) {
49
+ console.log(error, 'errorerrorerrorerror', (_d = (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.detail);
50
+ console.log((_e = error === null || error === void 0 ? void 0 : error.response) === null || _e === void 0 ? void 0 : _e.data, 'error?.response?.data?.detail ');
51
+ const msg = ((_g = (_f = error === null || error === void 0 ? void 0 : error.response) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.detail) || "Failed to fetch transactions.";
52
+ setError(msg);
53
+ onError === null || onError === void 0 ? void 0 : onError(msg);
54
+ toast.error(msg, { toastId: "-msg-error-Msg" });
55
+ setLoading(false);
56
+ }
57
+ });
58
+ //done
59
+ const getAllUserCategory = () => __awaiter(void 0, void 0, void 0, function* () {
60
+ var _h, _j;
61
+ try {
62
+ const response = yield api.get(`/categorized/data/${userId}`);
63
+ const data = response.data;
64
+ setCategoryNames(data); // 🔥 Save to state
65
+ }
66
+ catch (err) {
67
+ console.error("Error fetching categories:", err);
68
+ const msg = ((_j = (_h = err === null || err === void 0 ? void 0 : err.response) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.detail) || "Error fetching categories";
69
+ toast.error(msg, { toastId: "e-msg-error-Msg" });
70
+ }
71
+ });
72
+ // done
73
+ const updateTransactionCategory = (payload) => __awaiter(void 0, void 0, void 0, function* () {
74
+ try {
75
+ console.log(payload, "payloadpayloadpayloadpayload");
76
+ const response = yield api.put("/transaction/update/category", payload);
77
+ console.log(response, "responseresponseresponse");
78
+ if ((response === null || response === void 0 ? void 0 : response.status) == 200) {
79
+ setSelected(null);
80
+ toast.success("Category updated successfully", { toastId: "Category updated successfully" });
81
+ yield fetchTransactions(userId);
82
+ }
83
+ else {
84
+ toast.error("Something went wrong", { toastId: "Something went wrong" });
85
+ }
86
+ }
87
+ catch (err) {
88
+ toast.error("Failed to update category", { toastId: "Failed to update category" });
89
+ }
90
+ });
91
+ const filtered = useMemo(() => {
92
+ if (!search.trim())
93
+ return transactions;
94
+ const s = search.toLowerCase();
95
+ return transactions.filter((g) => { var _a; return (_a = g.category) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(s); });
96
+ }, [transactions, search]);
97
+ const taxSavings = filtered.reduce((sum, g) => {
98
+ var _a, _b;
99
+ const deductible = ((g === null || g === void 0 ? void 0 : g.category) && ((_a = g === null || g === void 0 ? void 0 : g.category) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === "LOAN_PAYMENTS") ||
100
+ ((g === null || g === void 0 ? void 0 : g.category) && ((_b = g === null || g === void 0 ? void 0 : g.category) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === "TRAVEL");
101
+ return deductible ? sum + g.total_amount * 0.1 : sum;
102
+ }, 0);
103
+ useEffect(() => {
104
+ if (access_token && session_token) {
105
+ getAuthSessionToken({
106
+ session_token,
107
+ userId,
108
+ onSuccess: (data) => {
109
+ console.log("Auth token fetched, domain URLs:", data.domain_urls);
110
+ fetchTransactions(userId);
111
+ getAllUserCategory();
112
+ },
113
+ onError,
114
+ setLoading,
115
+ setError,
116
+ });
117
+ }
118
+ }, [access_token, session_token]);
119
+ return (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({ style: {
120
+ position: "fixed",
121
+ bottom: "20px",
122
+ right: "20px",
123
+ width: "60px",
124
+ height: "60px",
125
+ backgroundColor: "#007bff",
126
+ borderRadius: "50%",
127
+ display: "flex",
128
+ justifyContent: "center",
129
+ alignItems: "center",
130
+ cursor: "pointer",
131
+ zIndex: 9999,
132
+ color: "#fff",
133
+ fontSize: "28px",
134
+ boxShadow: "0 4px 5px rgba(0, 0, 0, 0.3)",
135
+ }, onClick: () => setIsOpen(!isOpen), title: "Open Auth Widget" }, { children: "\uD83D\uDCAC" })), isOpen && (_jsx("div", Object.assign({ style: {
136
+ position: "fixed",
137
+ bottom: "90px",
138
+ right: "20px",
139
+ width: "50rem",
140
+ maxHeight: "70vh",
141
+ backgroundColor: "#fff",
142
+ borderRadius: "12px",
143
+ boxShadow: "0 0 5px rgba(0,0,0,0.2)",
144
+ zIndex: 9998,
145
+ padding: "0",
146
+ overflowY: "auto",
147
+ } }, { children: error ? (_jsx("div", Object.assign({ style: {
148
+ padding: "0",
149
+ minHeight: "500px",
150
+ paddingTop: "200px",
151
+ } }, { children: _jsx(ErrorWidget, { message: error, onClose: () => setIsOpen(false) }) }))) : (_jsxs("div", Object.assign({ style: {
152
+ padding: "0",
153
+ minHeight: "500px",
154
+ } }, { children: [_jsx("h2", Object.assign({ style: {
155
+ fontSize: "1.125rem",
156
+ fontWeight: "500",
157
+ color: "#042567",
158
+ margin: "0px",
159
+ backgroundColor: "#F1F7FB",
160
+ padding: "16px 24px",
161
+ display: "flex",
162
+ justifyContent: "space-between",
163
+ alignItems: "center",
164
+ borderBottom: "1px solid #BFDBFE",
165
+ marginBottom: "18px",
166
+ } }, { children: "Review & Categorize" })), !selected && (_jsxs("div", Object.assign({ style: { padding: "0px 24px 16px", position: "relative" } }, { children: [_jsx("span", Object.assign({ style: { position: "absolute", top: "9px", left: "40px" } }, { children: _jsx(CiSearch, { style: { color: "#526282", fontSize: "20px" } }) })), _jsx("input", { type: "text", value: search, onChange: (e) => setSearch(e.target.value), placeholder: "Search\u2026", style: {
167
+ width: "calc(100% - 70px)",
168
+ padding: "10px 16px 10px 44px",
169
+ border: "1px solid #E6E7EA",
170
+ borderRadius: "9999px",
171
+ fontSize: "0.875rem",
172
+ color: "#042567",
173
+ outline: "none",
174
+ } })] }))), _jsxs("div", Object.assign({ style: { padding: "0 24px 10px" } }, { children: [!loading && (_jsxs("div", Object.assign({ style: {
175
+ display: "flex",
176
+ alignItems: "center",
177
+ gap: "10px",
178
+ marginBottom: "10px",
179
+ } }, { children: [(filtered === null || filtered === void 0 ? void 0 : filtered.length) == 0 ? ("") : (_jsxs("span", Object.assign({ style: {
180
+ fontSize: "14px",
181
+ color: "rgb(82, 98, 130)",
182
+ margin: "0px",
183
+ display: "flex",
184
+ alignItems: "center",
185
+ gap: 6,
186
+ } }, { children: ["Number of Review & Categorize :", " ", _jsx("span", Object.assign({ style: {
187
+ color: "#042567",
188
+ fontSize: "16px",
189
+ fontWeight: 500,
190
+ } }, { children: filtered ? filtered === null || filtered === void 0 ? void 0 : filtered.length : "0" }))] }))), (filtered === null || filtered === void 0 ? void 0 : filtered.reduce((sum, item) => sum + item.transactions.length, 0)) === 0 ? ("") : (_jsxs("span", Object.assign({ style: {
191
+ fontSize: "14px",
192
+ color: "rgb(82, 98, 130)",
193
+ margin: "0px",
194
+ display: "flex",
195
+ alignItems: "center",
196
+ gap: 6,
197
+ } }, { children: ["Number of transaction", " ", _jsx("span", Object.assign({ style: {
198
+ color: "#042567",
199
+ fontSize: "16px",
200
+ fontWeight: 500,
201
+ } }, { children: filtered
202
+ ? filtered === null || filtered === void 0 ? void 0 : filtered.reduce((sum, item) => sum + item.transactions.length, 0)
203
+ : "0" }))] })))] }))), showAddForm ? (_jsx(AddTransactionForm, { userId: userId, accessToken: access_token, onSuccess: () => __awaiter(void 0, void 0, void 0, function* () {
204
+ // await handleAddTransaction();
205
+ setShowAddForm(false);
206
+ yield fetchTransactions(userId);
207
+ }), onError: onError })) : loading ? (_jsx("p", Object.assign({ style: {
208
+ fontSize: "0.875rem",
209
+ color: "#526282",
210
+ margin: 0,
211
+ display: "flex",
212
+ justifyContent: "center",
213
+ width: "100%",
214
+ } }, { children: "Loading\u2026" }))) : !selected ? (filtered.length === 0 ? (_jsx("p", Object.assign({ style: {
215
+ fontSize: "0.875rem",
216
+ color: "#526282",
217
+ margin: 0,
218
+ display: "flex",
219
+ justifyContent: "center",
220
+ width: "100%",
221
+ } }, { children: "No transactions match." }))) : (filtered.map((g) => {
222
+ var _a, _b;
223
+ return (_jsxs("div", Object.assign({ onClick: () => setSelected(g), style: {
224
+ cursor: "pointer",
225
+ display: "flex",
226
+ justifyContent: "space-between",
227
+ alignItems: "center",
228
+ padding: "16px 20px",
229
+ border: "1px solid #1E40AF1A",
230
+ borderRadius: 12,
231
+ marginBottom: "12px",
232
+ } }, { children: [_jsxs("div", { children: [_jsx("h3", Object.assign({ style: {
233
+ fontSize: "15px",
234
+ fontWeight: 500,
235
+ color: "#042567",
236
+ margin: "0 0 6px 0",
237
+ } }, { children: (_a = g === null || g === void 0 ? void 0 : g.category) !== null && _a !== void 0 ? _a : "NA" })), _jsx("span", Object.assign({ style: {
238
+ fontSize: "0.75rem",
239
+ backgroundColor: "#4A6CF71F",
240
+ color: "#4A6CF7",
241
+ borderRadius: 9999,
242
+ padding: "4px 16px",
243
+ display: "inline-block",
244
+ border: "1px solid #4A6CF71A",
245
+ } }, { children: ((_b = g === null || g === void 0 ? void 0 : g.schedule) !== null && _b !== void 0 ? _b : "") !== "" ? g.schedule : "N/A" }))] }), _jsxs("div", Object.assign({ style: { textAlign: "right" } }, { children: [_jsxs("p", Object.assign({ style: {
246
+ color: "#042567",
247
+ fontSize: "16px",
248
+ fontWeight: 500,
249
+ margin: "0 0 4px",
250
+ display: "flex",
251
+ alignItems: "center",
252
+ gap: 6,
253
+ } }, { children: ["$", g.total_amount.toFixed(2), " ", _jsx(FaCaretDown, {})] })), _jsxs("p", Object.assign({ style: {
254
+ fontSize: "0.875rem",
255
+ color: "#526282",
256
+ margin: 0,
257
+ } }, { children: [" ", g.transactions.length, " transactions"] }))] }))] }), g.category));
258
+ }))) : (_jsx(_Fragment, { children: _jsxs("div", Object.assign({ style: {
259
+ backgroundColor: "#fff",
260
+ color: "#000",
261
+ borderRadius: "12px",
262
+ padding: "1rem 0px",
263
+ maxWidth: "100%",
264
+ margin: "1rem auto",
265
+ fontFamily: "sans-serif",
266
+ fontSize: "0.9rem",
267
+ } }, { children: [_jsxs("button", Object.assign({ onClick: () => {
268
+ setSelected(null);
269
+ setSearch("");
270
+ }, style: {
271
+ background: "transparent",
272
+ border: "none",
273
+ color: "#2094EA",
274
+ marginBottom: "1rem",
275
+ cursor: "pointer",
276
+ fontWeight: 500,
277
+ fontSize: "1rem",
278
+ display: "flex",
279
+ alignItems: "center",
280
+ gap: "5px",
281
+ } }, { children: [_jsx(HiOutlineArrowSmLeft, { style: { fontSize: "22px" } }), "Back"] })), _jsxs("div", Object.assign({ style: {
282
+ padding: "0px",
283
+ } }, { children: [_jsxs("div", Object.assign({ style: {
284
+ backgroundColor: "#F1F7FB",
285
+ borderRadius: "8px",
286
+ padding: "1rem",
287
+ display: "flex",
288
+ justifyContent: "space-between",
289
+ alignItems: "center",
290
+ marginBottom: "14px",
291
+ flexWrap: "wrap",
292
+ } }, { children: [_jsxs("div", Object.assign({ style: { display: "flex", flexDirection: "column" } }, { children: [_jsx("h2", Object.assign({ style: {
293
+ color: "#042567",
294
+ fontSize: "16px",
295
+ fontWeight: "500",
296
+ margin: 0,
297
+ textTransform: "capitalize",
298
+ } }, { children: selected === null || selected === void 0 ? void 0 : selected.category })), _jsx("span", Object.assign({ style: {
299
+ backgroundColor: "#67DC791F",
300
+ color: "#15803D",
301
+ padding: "6px 16px",
302
+ border: "1px solid #4EC7601A",
303
+ borderRadius: "50px",
304
+ fontSize: "0.85rem",
305
+ marginTop: "6px",
306
+ textAlign: "center",
307
+ } }, { children: ((_a = selected === null || selected === void 0 ? void 0 : selected.schedule) !== null && _a !== void 0 ? _a : "") !== ""
308
+ ? selected.schedule
309
+ : "N/A" }))] })), _jsxs("div", Object.assign({ style: { textAlign: "right" } }, { children: [_jsxs("p", Object.assign({ style: {
310
+ color: "#042567",
311
+ fontSize: "17px",
312
+ fontWeight: "500",
313
+ margin: 0,
314
+ } }, { children: ["$", selected.total_amount.toFixed(2)] })), _jsxs("span", Object.assign({ style: { fontSize: "14px", color: "#526282" } }, { children: [selected.transactions.length, " transactions"] }))] }))] })), _jsx("div", Object.assign({ style: {
315
+ border: "1px solid #E4EEF4",
316
+ borderRadius: "12px",
317
+ overflow: "hidden",
318
+ } }, { children: _jsxs("table", Object.assign({ style: {
319
+ width: "100%",
320
+ borderCollapse: "collapse",
321
+ background: "#fff",
322
+ borderRadius: "8px",
323
+ overflow: "hidden",
324
+ } }, { children: [_jsx("thead", Object.assign({ style: {
325
+ backgroundColor: "#f1f5f9",
326
+ textAlign: "left",
327
+ } }, { children: _jsxs("tr", { children: [_jsx("th", Object.assign({ style: {
328
+ padding: "12px 16px",
329
+ color: "#042567",
330
+ textAlign: "left",
331
+ fontWeight: "500",
332
+ } }, { children: "Description" })), _jsx("th", Object.assign({ style: {
333
+ padding: "12px 16px",
334
+ color: "#042567",
335
+ textAlign: "left",
336
+ fontWeight: "500",
337
+ } }, { children: "Type" })), _jsx("th", Object.assign({ style: {
338
+ padding: "12px 16px",
339
+ color: "#042567",
340
+ textAlign: "left",
341
+ fontWeight: "500",
342
+ } }, { children: "Amount" })), _jsx("th", Object.assign({ style: {
343
+ padding: "12px 16px",
344
+ color: "#042567",
345
+ textAlign: "left",
346
+ fontWeight: "500",
347
+ } }, { children: "Category" }))] }) })), _jsx("tbody", { children: (_b = selected === null || selected === void 0 ? void 0 : selected.transactions) === null || _b === void 0 ? void 0 : _b.map((t) => {
348
+ var _a, _b, _c;
349
+ const transactionId = (t === null || t === void 0 ? void 0 : t.transaction_id) || (t === null || t === void 0 ? void 0 : t.description);
350
+ // Deduplicate category names by category_details.name
351
+ const uniqueCategories = Array.from(new Map(categoryNames.map((item) => [
352
+ item === null || item === void 0 ? void 0 : item.category,
353
+ item,
354
+ ])).values());
355
+ console.log(selected, "selected.categoryselected.categoryselected.category");
356
+ return (_jsx(React.Fragment, { children: _jsxs("tr", Object.assign({ style: {
357
+ borderBottom: "1px solid #e0e0e0",
358
+ } }, { children: [_jsx("td", Object.assign({ style: {
359
+ padding: "12px",
360
+ color: "#444",
361
+ textAlign: "left",
362
+ } }, { children: (_a = t.description) !== null && _a !== void 0 ? _a : t.merchant_name })), _jsx("td", Object.assign({ style: {
363
+ padding: "12px",
364
+ textAlign: "left",
365
+ } }, { children: ((_b = t.schedule) !== null && _b !== void 0 ? _b : "") !== ""
366
+ ? t.schedule
367
+ : ((_c = selected === null || selected === void 0 ? void 0 : selected.schedule) !== null && _c !== void 0 ? _c : "") !== ""
368
+ ? selected.schedule
369
+ : "N/A" })), _jsx("td", Object.assign({ style: {
370
+ padding: "12px",
371
+ textAlign: "left",
372
+ color: t.amount < 0
373
+ ? "#d32f2f"
374
+ : "#2e7d32",
375
+ } }, { children: t.amount < 0
376
+ ? `-$${Math.abs(t.amount).toFixed(2)}`
377
+ : `$${t.amount.toFixed(2)}` })), _jsx("td", Object.assign({ style: {
378
+ padding: "12px",
379
+ textAlign: "left",
380
+ } }, { children: _jsxs("select", Object.assign({ value: selected.category || "", onChange: (e) => {
381
+ var _a, _b, _c, _d;
382
+ const selectedCategory = uniqueCategories.find((c) => (c === null || c === void 0 ? void 0 : c.category) === e.target.value);
383
+ if (selectedCategory) {
384
+ console.log(selectedCategory, "selectedCategoryselectedCategory");
385
+ const payload = {
386
+ transaction_id: t === null || t === void 0 ? void 0 : t.transaction_id,
387
+ category: selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category,
388
+ category_name: selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category,
389
+ schedule: (_a = selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category_details) === null || _a === void 0 ? void 0 : _a.schedule,
390
+ line: (_b = selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category_details) === null || _b === void 0 ? void 0 : _b.line,
391
+ deductible: (_c = selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category_details) === null || _c === void 0 ? void 0 : _c.deductible,
392
+ taxable: (_d = selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.category_details) === null || _d === void 0 ? void 0 : _d.taxable,
393
+ confidence_score: 1,
394
+ };
395
+ updateTransactionCategory(payload);
396
+ }
397
+ }, style: {
398
+ padding: "8px 16px",
399
+ border: "1px solid #E6E7EA",
400
+ borderRadius: "9999px",
401
+ fontSize: "0.875rem",
402
+ color: "#042567",
403
+ outline: "none",
404
+ } }, { children: [_jsx("option", Object.assign({ value: "" }, { children: "Select Category" })), uniqueCategories.map((data, index) => (_jsx("option", Object.assign({ value: data === null || data === void 0 ? void 0 : data.category }, { children: data === null || data === void 0 ? void 0 : data.category }), index)))] })) }))] })) }, transactionId));
405
+ }) })] })) }))] }))] })) }))] })), !selected && filtered.length > 0 && !showAddForm && !loading && (_jsx("div", Object.assign({ style: { padding: "0 24px 24px" } }, { children: _jsxs("div", Object.assign({ style: {
406
+ backgroundColor: "#F1F7FB",
407
+ padding: "32px 24px",
408
+ borderRadius: 16,
409
+ textAlign: "center",
410
+ } }, { children: [_jsxs("p", Object.assign({ style: {
411
+ fontSize: "14px",
412
+ fontWeight: 500,
413
+ color: "#042567",
414
+ marginBottom: 16,
415
+ marginTop: 0,
416
+ } }, { children: ["Potential Tax Savings from Reviewed Transactions: \u00A0", _jsxs("span", Object.assign({ style: { color: "#042567", fontWeight: "bold" } }, { children: ["$", taxSavings.toFixed(2)] }))] })), _jsx("button", Object.assign({ style: {
417
+ backgroundColor: "#5387F1",
418
+ border: "1px solid #5387F1",
419
+ color: "white",
420
+ fontSize: "0.875rem",
421
+ fontWeight: 500,
422
+ padding: "8px 16px",
423
+ borderRadius: 8,
424
+ marginRight: 8,
425
+ cursor: "pointer",
426
+ } }, { children: "Proceed" })), _jsx("button", Object.assign({ style: {
427
+ border: "1px solid #5387F1",
428
+ backgroundColor: "white",
429
+ color: "#5387F1",
430
+ fontSize: "0.875rem",
431
+ fontWeight: 500,
432
+ padding: "8px 16px",
433
+ borderRadius: 8,
434
+ cursor: "pointer",
435
+ } }, { children: "Review More" }))] })) })))] }))) })))] }));
436
+ };
437
+ export default ClientAuthForm;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@musetax/compass-widget",
3
- "version": "0.1.218",
3
+ "version": "0.2.218",
4
4
  "dependencies": {
5
5
  "@testing-library/dom": "^10.4.0",
6
6
  "@testing-library/jest-dom": "^6.6.3",
@@ -17,6 +17,7 @@
17
17
  "react-dom": "^19.1.0",
18
18
  "react-icons": "^5.5.0",
19
19
  "react-scripts": "5.0.1",
20
+ "react-toastify": "^11.0.5",
20
21
  "typescript": "^4.9.5",
21
22
  "web-vitals": "^2.1.4"
22
23
  },