@layerfi/components 0.1.0

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/index.js ADDED
@@ -0,0 +1,1647 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.tsx
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ BalanceSheet: () => BalanceSheet,
34
+ BankTransactions: () => BankTransactions,
35
+ Hello: () => Hello,
36
+ LayerProvider: () => LayerProvider,
37
+ ProfitAndLoss: () => ProfitAndLoss
38
+ });
39
+ module.exports = __toCommonJS(src_exports);
40
+
41
+ // src/components/BalanceSheet/BalanceSheet.tsx
42
+ var import_react5 = __toESM(require("react"));
43
+
44
+ // src/api/util.ts
45
+ var formStringFromObject = (object) => Object.entries(object).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
46
+
47
+ // src/api/layer/authenticate.ts
48
+ var authenticate = ({
49
+ appId,
50
+ appSecret,
51
+ authenticationUrl = "https://auth.layerfi.com/oauth2/token",
52
+ clientId,
53
+ scope
54
+ }) => () => fetch(authenticationUrl, {
55
+ method: "POST",
56
+ headers: {
57
+ Authorization: "Basic " + btoa(appId + ":" + appSecret),
58
+ "Content-Type": "application/x-www-form-urlencoded"
59
+ },
60
+ body: formStringFromObject({
61
+ grant_type: "client_credentials",
62
+ scope,
63
+ client_id: clientId
64
+ })
65
+ }).then((res) => res.json());
66
+
67
+ // src/api/layer/balance_sheet.json
68
+ var balance_sheet_default = {
69
+ business_id: "05eb0771-ae7d-4cd1-ae7f-cc8765351afc",
70
+ type: "Balance_Sheet",
71
+ start_date: "2023-01-01T00:00:00Z",
72
+ end_date: "2023-01-31T00:00:00Z",
73
+ assets: [
74
+ {
75
+ name: "CURRENT_ASSETS",
76
+ display_name: "Current Assets",
77
+ value: "100000",
78
+ line_items: [
79
+ {
80
+ name: "BANK_ACCOUNTS",
81
+ display_name: "Bank Accounts",
82
+ value: "100000",
83
+ line_items: [
84
+ {
85
+ display_name: "Checking Account 123",
86
+ value: "50000",
87
+ line_items: []
88
+ },
89
+ {
90
+ display_name: "Savings Account 456",
91
+ value: "50000",
92
+ line_items: []
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ name: "ACCOUNTS_RECEIVABLE",
98
+ display_name: "Bank Accounts",
99
+ value: "100000",
100
+ line_items: [
101
+ {
102
+ account_id: "cc7861f7-d8b3-4ab9-b853-6b85838199ef",
103
+ display_name: "Accounts Receivable - Customer A",
104
+ value: "50000",
105
+ line_items: []
106
+ },
107
+ {
108
+ account_id: "23606d6a-4e78-406b-9283-76bfb750639f",
109
+ display_name: "Accounts Receivable - Customer B",
110
+ value: "50000",
111
+ line_items: []
112
+ }
113
+ ]
114
+ },
115
+ {
116
+ name: "OTHER_ASSETS",
117
+ display_name: "Other Assets",
118
+ value: "150",
119
+ line_items: [
120
+ {
121
+ account_id: "40816f76-1409-4727-b733-c4c126f0a725",
122
+ display_name: "Inventory Item A",
123
+ value: "50000",
124
+ line_items: []
125
+ }
126
+ ]
127
+ }
128
+ ]
129
+ }
130
+ ],
131
+ liabilities_and_equity: [
132
+ {
133
+ name: "LIABILITIES",
134
+ display_name: "Liabilities",
135
+ value: "100000",
136
+ line_items: [
137
+ {
138
+ name: "CURRENT_LIABILITIES",
139
+ display_name: "Current Liabilities",
140
+ value: "100000",
141
+ line_items: [
142
+ {
143
+ account_id: "40816f76-1409-4727-b733-c4c126f0a725",
144
+ display_name: "ACCOUNTS_PAYABLE",
145
+ value: "50000",
146
+ line_items: [
147
+ {
148
+ account_id: "261d0ef4-6d35-4081-8c82-685114fd497d",
149
+ display_name: "Supplier A",
150
+ value: "50000",
151
+ line_items: []
152
+ }
153
+ ]
154
+ },
155
+ {
156
+ account_id: "5123c5eb-28ce-4cce-90bd-389e4befb645",
157
+ display_name: "Credit Cards",
158
+ value: "50000",
159
+ line_items: [
160
+ {
161
+ account_id: "beb41e99-0539-4d97-8faf-c8464eac60dc",
162
+ display_name: "Visa 5678",
163
+ value: "50000",
164
+ line_items: []
165
+ }
166
+ ]
167
+ },
168
+ {
169
+ account_id: "7261b324-aa1a-4c03-9ac8-0a40980d5886",
170
+ display_name: "Other current Liabilities",
171
+ value: "2309",
172
+ line_items: []
173
+ }
174
+ ]
175
+ }
176
+ ]
177
+ },
178
+ {
179
+ name: "EQUITY",
180
+ display_name: "Equity",
181
+ value: "100000",
182
+ line_items: [
183
+ {
184
+ name: "OPENING_BALANCE_EQUITY",
185
+ display_name: "Opening Balance Equity",
186
+ value: "50000",
187
+ line_items: []
188
+ },
189
+ {
190
+ name: "RETAINED_EARNINGS",
191
+ display_name: "Retained Earnings",
192
+ value: "50000",
193
+ line_items: []
194
+ },
195
+ {
196
+ name: "NET_INCOME",
197
+ display_name: "Net Income",
198
+ value: "50000",
199
+ line_items: []
200
+ }
201
+ ]
202
+ }
203
+ ],
204
+ fully_categorized: true
205
+ };
206
+
207
+ // src/api/layer/balance_sheet.ts
208
+ var getBalanceSheet = (_token, _params) => () => balance_sheet_default;
209
+
210
+ // src/api/layer/authenticated_http.ts
211
+ var get = (url) => (accessToken, options) => () => fetch(url(options?.params || {}), {
212
+ headers: {
213
+ Authorization: "Bearer " + (accessToken || ""),
214
+ "Content-Type": "application/json"
215
+ },
216
+ method: "GET"
217
+ }).then((res) => res.json());
218
+ var put = (url) => (accessToken, options) => fetch(url(options?.params || {}), {
219
+ headers: {
220
+ Authorization: "Bearer " + (accessToken || ""),
221
+ "Content-Type": "application/json",
222
+ "Cache-Control": "no-cache"
223
+ },
224
+ method: "PUT",
225
+ body: JSON.stringify(options?.body)
226
+ }).then((res) => res.json());
227
+
228
+ // src/api/layer/bankTransactions.ts
229
+ var getBankTransactions = get(
230
+ ({
231
+ businessId,
232
+ sortBy = "date",
233
+ sortOrder = "DESC"
234
+ }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/bank-transactions?sort_by=${sortBy}&sort_order=${sortOrder}`
235
+ );
236
+ var categorizeBankTransaction = put(
237
+ ({ businessId, bankTransactionId }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/categorize`
238
+ );
239
+
240
+ // src/api/layer/categories.ts
241
+ var getCategories = get(
242
+ ({ businessId }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/categories`
243
+ );
244
+
245
+ // src/api/layer/profit_and_loss.ts
246
+ var getProfitAndLoss = get(
247
+ ({ businessId, startDate, endDate }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/reports/profit-and-loss?start_date=${startDate}&end_date=${endDate}`
248
+ );
249
+
250
+ // src/api/layer.ts
251
+ var Layer = {
252
+ authenticate,
253
+ categorizeBankTransaction,
254
+ getBalanceSheet,
255
+ getBankTransactions,
256
+ getCategories,
257
+ getProfitAndLoss
258
+ };
259
+
260
+ // src/hooks/useLayerContext/useLayerContext.tsx
261
+ var import_react2 = require("react");
262
+
263
+ // src/contexts/LayerContext/LayerContext.tsx
264
+ var import_react = require("react");
265
+ var LayerContext = (0, import_react.createContext)({
266
+ auth: { access_token: "", expires_in: -1, token_type: "" },
267
+ businessId: "",
268
+ categories: []
269
+ });
270
+
271
+ // src/hooks/useLayerContext/useLayerContext.tsx
272
+ var useLayerContext = () => (0, import_react2.useContext)(LayerContext);
273
+
274
+ // src/hooks/useBalanceSheet/useBalanceSheet.tsx
275
+ var import_date_fns = require("date-fns");
276
+ var import_swr = __toESM(require("swr"));
277
+ var useBalanceSheet = (date) => {
278
+ const { auth, businessId } = useLayerContext();
279
+ const dateString = (0, import_date_fns.format)((0, import_date_fns.startOfDay)(date), "yyyy-mm-dd");
280
+ const { data, isLoading, error } = (0, import_swr.default)(
281
+ businessId && dateString && auth?.access_token && `balance-sheet-${businessId}-${dateString}`,
282
+ Layer.getBalanceSheet(auth?.access_token, {
283
+ params: { businessId, date: dateString }
284
+ })
285
+ );
286
+ return { data, isLoading, error };
287
+ };
288
+
289
+ // src/icons/DownloadCloud.tsx
290
+ var React = __toESM(require("react"));
291
+ var DownloadCloud = (props) => /* @__PURE__ */ React.createElement(
292
+ "svg",
293
+ {
294
+ xmlns: "http://www.w3.org/2000/svg",
295
+ width: 24,
296
+ height: 24,
297
+ fill: "none",
298
+ ...props
299
+ },
300
+ /* @__PURE__ */ React.createElement(
301
+ "path",
302
+ {
303
+ stroke: "#000",
304
+ strokeLinecap: "round",
305
+ strokeLinejoin: "round",
306
+ strokeWidth: 2,
307
+ d: "M4 16.242A4.5 4.5 0 0 1 6.08 8.02a6.002 6.002 0 0 1 11.84 0A4.5 4.5 0 0 1 20 16.242M8 17l4 4m0 0 4-4m-4 4v-9"
308
+ }
309
+ )
310
+ );
311
+ var DownloadCloud_default = DownloadCloud;
312
+
313
+ // src/components/BalanceSheetDatePicker/BalanceSheetDatePicker.tsx
314
+ var import_react3 = __toESM(require("react"));
315
+
316
+ // src/icons/Calendar.tsx
317
+ var React2 = __toESM(require("react"));
318
+ var Calendar = (props) => /* @__PURE__ */ React2.createElement(
319
+ "svg",
320
+ {
321
+ xmlns: "http://www.w3.org/2000/svg",
322
+ width: 20,
323
+ height: 22,
324
+ fill: "none",
325
+ ...props
326
+ },
327
+ /* @__PURE__ */ React2.createElement(
328
+ "path",
329
+ {
330
+ stroke: "#000",
331
+ strokeLinecap: "round",
332
+ strokeLinejoin: "round",
333
+ strokeWidth: 2,
334
+ d: "M19 9H1m13-8v4M6 1v4m-.2 16h8.4c1.68 0 2.52 0 3.162-.327a3 3 0 0 0 1.311-1.311C19 18.72 19 17.88 19 16.2V7.8c0-1.68 0-2.52-.327-3.162a3 3 0 0 0-1.311-1.311C16.72 3 15.88 3 14.2 3H5.8c-1.68 0-2.52 0-3.162.327a3 3 0 0 0-1.311 1.311C1 5.28 1 6.12 1 7.8v8.4c0 1.68 0 2.52.327 3.162a3 3 0 0 0 1.311 1.311C3.28 21 4.12 21 5.8 21Z"
335
+ }
336
+ )
337
+ );
338
+ var Calendar_default = Calendar;
339
+
340
+ // src/components/BalanceSheetDatePicker/BalanceSheetDatePicker.tsx
341
+ var import_date_fns2 = require("date-fns");
342
+ var BalanceSheetDatePicker = ({ value, onChange }) => {
343
+ const inputRef = (0, import_react3.useRef)(null);
344
+ const showPicker = () => inputRef.current && inputRef.current.showPicker();
345
+ return /* @__PURE__ */ import_react3.default.createElement("span", { className: "Layer__balance-sheet-date-picker" }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: showPicker }, /* @__PURE__ */ import_react3.default.createElement(Calendar_default, null), (0, import_date_fns2.format)(value, "LLLL dd, yyyy"), /* @__PURE__ */ import_react3.default.createElement(
346
+ "input",
347
+ {
348
+ type: "date",
349
+ ref: inputRef,
350
+ value: (0, import_date_fns2.format)(value, "yyyy-MM-dd"),
351
+ onChange
352
+ }
353
+ )));
354
+ };
355
+
356
+ // src/components/BalanceSheetRow/BalanceSheetRow.tsx
357
+ var import_react4 = __toESM(require("react"));
358
+
359
+ // src/icons/ChevronDown.tsx
360
+ var React4 = __toESM(require("react"));
361
+ var ChevronDown = ({ size = 24, ...props }) => /* @__PURE__ */ React4.createElement(
362
+ "svg",
363
+ {
364
+ xmlns: "http://www.w3.org/2000/svg",
365
+ width: size,
366
+ height: size,
367
+ fill: "none",
368
+ viewBox: "0 0 24 24",
369
+ ...props
370
+ },
371
+ /* @__PURE__ */ React4.createElement(
372
+ "path",
373
+ {
374
+ strokeLinecap: "round",
375
+ strokeLinejoin: "round",
376
+ strokeWidth: 2,
377
+ d: "m6 9 6 6 6-6"
378
+ }
379
+ )
380
+ );
381
+ var ChevronDown_default = ChevronDown;
382
+
383
+ // src/icons/ChevronRight.tsx
384
+ var React5 = __toESM(require("react"));
385
+ var ChavronRight = ({ strokeColor, size, ...props }) => /* @__PURE__ */ React5.createElement(
386
+ "svg",
387
+ {
388
+ xmlns: "http://www.w3.org/2000/svg",
389
+ width: size || 24,
390
+ height: size || 24,
391
+ fill: "none",
392
+ viewBox: "0 0 24 24",
393
+ ...props
394
+ },
395
+ /* @__PURE__ */ React5.createElement(
396
+ "path",
397
+ {
398
+ stroke: strokeColor ?? "#000",
399
+ strokeLinecap: "round",
400
+ strokeLinejoin: "round",
401
+ strokeWidth: 2,
402
+ d: "m9 18 6-6-6-6"
403
+ }
404
+ )
405
+ );
406
+ var ChevronRight_default = ChavronRight;
407
+
408
+ // src/models/Money.ts
409
+ var formatter = new Intl.NumberFormat("en-US", {
410
+ minimumIntegerDigits: 1,
411
+ minimumFractionDigits: 2,
412
+ maximumFractionDigits: 2
413
+ });
414
+ var centsToDollars = (cents) => formatter.format(cents / 100);
415
+ var dollarsToCents = (dollars) => Math.round(parseFloat(dollars) * 100);
416
+
417
+ // src/components/BalanceSheetRow/BalanceSheetRow.tsx
418
+ var BalanceSheetRow = ({
419
+ lineItem,
420
+ depth = 0,
421
+ maxDepth = 2
422
+ }) => {
423
+ if (!lineItem) {
424
+ return null;
425
+ }
426
+ const { value, display_name, line_items } = lineItem;
427
+ const [expanded, setExpanded] = (0, import_react4.useState)(true);
428
+ const amount = value || 0;
429
+ const isPositive = amount >= 0;
430
+ const amountString = centsToDollars(Math.abs(amount));
431
+ const labelClasses = [
432
+ "Layer__balance-sheet-row",
433
+ "Layer__balance-sheet-row__label"
434
+ ];
435
+ const valueClasses = [
436
+ "Layer__balance-sheet-row",
437
+ "Layer__balance-sheet-row__value"
438
+ ];
439
+ !!value && valueClasses.push(
440
+ isPositive ? "Layer__balance-sheet-row__value--amount-positive" : "Layer__balance-sheet-row__value--amount-negative"
441
+ );
442
+ labelClasses.push(`Layer__balance-sheet-row__label--depth-${depth}`);
443
+ valueClasses.push(`Layer__balance-sheet-row__value--depth-${depth}`);
444
+ const toggleExpanded = () => setExpanded(!expanded);
445
+ const canGoDeeper = depth < maxDepth;
446
+ const hasChildren = line_items?.length > 0;
447
+ const displayChildren = hasChildren && canGoDeeper;
448
+ labelClasses.push(
449
+ `Layer__balance-sheet-row__label--display-children-${displayChildren}`
450
+ );
451
+ valueClasses.push(
452
+ `Layer__balance-sheet-row__value--display-children-${displayChildren}`
453
+ );
454
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("div", { className: labelClasses.join(" "), onClick: toggleExpanded }, expanded ? /* @__PURE__ */ import_react4.default.createElement(ChevronDown_default, { size: 16 }) : /* @__PURE__ */ import_react4.default.createElement(ChevronRight_default, { size: 16 }), display_name), /* @__PURE__ */ import_react4.default.createElement("div", { className: valueClasses.join(" ") }, !!value && amountString), canGoDeeper && hasChildren && expanded && (line_items || []).map((line_item) => /* @__PURE__ */ import_react4.default.createElement(
455
+ BalanceSheetRow,
456
+ {
457
+ key: line_item.display_name,
458
+ lineItem: line_item,
459
+ depth: depth + 1,
460
+ maxDepth
461
+ }
462
+ )));
463
+ };
464
+
465
+ // src/components/BalanceSheet/BalanceSheet.tsx
466
+ var import_date_fns3 = require("date-fns");
467
+ var BalanceSheet = () => {
468
+ const [effectiveDate, setEffectiveDate] = (0, import_react5.useState)(/* @__PURE__ */ new Date());
469
+ const { data, isLoading } = useBalanceSheet(effectiveDate);
470
+ const assets = {
471
+ name: "Assets",
472
+ display_name: "Assets",
473
+ line_items: data?.assets || [],
474
+ value: void 0
475
+ };
476
+ const lne = {
477
+ name: "LiabilitiesAndEquity",
478
+ display_name: "Liabilities & Equity",
479
+ line_items: data?.liabilities_and_equity || [],
480
+ value: void 0
481
+ };
482
+ const dateString = (0, import_date_fns3.format)(effectiveDate, "LLLL d, yyyy");
483
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet__header" }, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "Layer__balance-sheet__title" }, "Balance Sheet", /* @__PURE__ */ import_react5.default.createElement("span", { className: "Layer__balance-sheet__date" }, dateString)), /* @__PURE__ */ import_react5.default.createElement(
484
+ BalanceSheetDatePicker,
485
+ {
486
+ value: effectiveDate,
487
+ onChange: (event) => setEffectiveDate((0, import_date_fns3.parseISO)(event.target.value))
488
+ }
489
+ ), /* @__PURE__ */ import_react5.default.createElement("button", { className: "Layer__balance-sheet__download-button" }, /* @__PURE__ */ import_react5.default.createElement(DownloadCloud_default, null), "Download")), !data || isLoading ? /* @__PURE__ */ import_react5.default.createElement("div", null, "Loading") : /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet__table" }, /* @__PURE__ */ import_react5.default.createElement(BalanceSheetRow, { key: assets.name, lineItem: assets }), /* @__PURE__ */ import_react5.default.createElement(BalanceSheetRow, { key: lne.name, lineItem: lne })));
490
+ };
491
+
492
+ // src/components/BankTransactions/BankTransactions.tsx
493
+ var import_react12 = __toESM(require("react"));
494
+
495
+ // src/hooks/useBankTransactions/useBankTransactions.tsx
496
+ var import_swr2 = __toESM(require("swr"));
497
+ var useBankTransactions = () => {
498
+ const { auth, businessId } = useLayerContext();
499
+ const {
500
+ data: responseData,
501
+ isLoading,
502
+ error: responseError,
503
+ mutate
504
+ } = (0, import_swr2.default)(
505
+ businessId && auth?.access_token && `bank-transactions-${businessId}`,
506
+ Layer.getBankTransactions(auth?.access_token, { params: { businessId } })
507
+ );
508
+ const {
509
+ data = [],
510
+ meta: metadata = {},
511
+ error = void 0
512
+ } = responseData || {};
513
+ const categorize = (id, newCategory) => Layer.categorizeBankTransaction(auth.access_token, {
514
+ params: { businessId, bankTransactionId: id },
515
+ body: newCategory
516
+ }).then(({ data: transaction, error: error2 }) => {
517
+ if (transaction) {
518
+ mutate();
519
+ }
520
+ if (error2) {
521
+ console.error(error2);
522
+ throw error2;
523
+ }
524
+ });
525
+ return { data, metadata, isLoading, error, categorize };
526
+ };
527
+
528
+ // src/components/BankTransactionRow/BankTransactionRow.tsx
529
+ var import_react11 = __toESM(require("react"));
530
+
531
+ // src/icons/CheckedCircle.tsx
532
+ var React8 = __toESM(require("react"));
533
+ var CheckedCircle = ({
534
+ fillColor = "none",
535
+ strokeColor = "#000",
536
+ size = 24,
537
+ ...props
538
+ }) => /* @__PURE__ */ React8.createElement(
539
+ "svg",
540
+ {
541
+ xmlns: "http://www.w3.org/2000/svg",
542
+ width: size,
543
+ height: size,
544
+ viewBox: "0 0 24 24",
545
+ fill: fillColor,
546
+ ...props
547
+ },
548
+ /* @__PURE__ */ React8.createElement(
549
+ "path",
550
+ {
551
+ stroke: strokeColor,
552
+ strokeLinecap: "round",
553
+ strokeLinejoin: "round",
554
+ strokeWidth: 2,
555
+ d: "m7.5 12 3 3 6-6m5.5 3c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z"
556
+ }
557
+ )
558
+ );
559
+ var CheckedCircle_default = CheckedCircle;
560
+
561
+ // src/icons/ChevronUp.tsx
562
+ var React9 = __toESM(require("react"));
563
+ var ChevronUp = (props) => /* @__PURE__ */ React9.createElement(
564
+ "svg",
565
+ {
566
+ xmlns: "http://www.w3.org/2000/svg",
567
+ width: 24,
568
+ height: 24,
569
+ fill: "none",
570
+ viewBox: "0 0 24 24",
571
+ ...props
572
+ },
573
+ /* @__PURE__ */ React9.createElement(
574
+ "path",
575
+ {
576
+ stroke: "#000",
577
+ strokeLinecap: "round",
578
+ strokeLinejoin: "round",
579
+ strokeWidth: 2,
580
+ d: "m18 15-6-6-6 6"
581
+ }
582
+ )
583
+ );
584
+ var ChevronUp_default = ChevronUp;
585
+
586
+ // src/components/CategoryMenu/CategoryMenu.tsx
587
+ var import_react6 = __toESM(require("react"));
588
+ var import_react_select = __toESM(require("react-select"));
589
+ var CategoryMenu = ({
590
+ bankTransaction,
591
+ name,
592
+ value,
593
+ onChange
594
+ }) => {
595
+ const { categories } = useLayerContext();
596
+ const suggestedOptions = bankTransaction?.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? [
597
+ {
598
+ label: "Suggested",
599
+ options: bankTransaction.categorization_flow.suggestions
600
+ }
601
+ ] : [];
602
+ const categoryOptions = (categories || []).map((category) => {
603
+ if (category?.subCategories && category?.subCategories?.length > 0) {
604
+ return {
605
+ label: category.display_name,
606
+ options: category.subCategories
607
+ };
608
+ }
609
+ return {
610
+ label: category.display_name,
611
+ options: [category]
612
+ };
613
+ }).filter((x) => x);
614
+ const options = [...suggestedOptions, ...categoryOptions];
615
+ return /* @__PURE__ */ import_react6.default.createElement(
616
+ import_react_select.default,
617
+ {
618
+ name,
619
+ className: "Layer__category-menu",
620
+ options,
621
+ isSearchable: true,
622
+ value,
623
+ onChange: (newValue) => newValue && onChange(newValue),
624
+ getOptionLabel: (category) => category.display_name,
625
+ getOptionValue: (category) => category.stable_name || category.category,
626
+ menuPortalTarget: document.body,
627
+ styles: { menuPortal: (base) => ({ ...base, zIndex: 9999 }) }
628
+ }
629
+ );
630
+ };
631
+
632
+ // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
633
+ var import_react9 = __toESM(require("react"));
634
+
635
+ // src/icons/Link.tsx
636
+ var React11 = __toESM(require("react"));
637
+ var Link = ({ size = 24, ...props }) => /* @__PURE__ */ React11.createElement(
638
+ "svg",
639
+ {
640
+ xmlns: "http://www.w3.org/2000/svg",
641
+ width: size,
642
+ height: size,
643
+ fill: "none",
644
+ viewBox: "0 0 24 24",
645
+ ...props
646
+ },
647
+ /* @__PURE__ */ React11.createElement(
648
+ "path",
649
+ {
650
+ stroke: "#000",
651
+ strokeLinecap: "round",
652
+ strokeLinejoin: "round",
653
+ strokeWidth: 2,
654
+ d: "m12.708 18.364-1.415 1.414a5 5 0 1 1-7.07-7.07l1.413-1.415m12.728 1.414 1.415-1.414a5 5 0 0 0-7.071-7.071l-1.415 1.414M8.5 15.5l7-7"
655
+ }
656
+ )
657
+ );
658
+ var Link_default = Link;
659
+
660
+ // src/icons/LinkBroken.tsx
661
+ var React12 = __toESM(require("react"));
662
+ var LinkBroken = ({ size = 24, ...props }) => /* @__PURE__ */ React12.createElement(
663
+ "svg",
664
+ {
665
+ xmlns: "http://www.w3.org/2000/svg",
666
+ width: size,
667
+ height: size,
668
+ fill: "none",
669
+ viewBox: "0 0 24 24",
670
+ ...props
671
+ },
672
+ /* @__PURE__ */ React12.createElement(
673
+ "path",
674
+ {
675
+ stroke: "#000",
676
+ strokeLinecap: "round",
677
+ strokeLinejoin: "round",
678
+ strokeWidth: 2,
679
+ d: "m8.5 15.5 7-7M9 4V2m6 18v2M4 9H2m18 6h2M4.914 4.914 3.5 3.5m15.586 15.586L20.5 20.5M12 17.657l-2.121 2.121a4 4 0 1 1-5.657-5.657L6.343 12m11.314 0 2.121-2.121a4 4 0 0 0-5.657-5.657L12 6.343"
680
+ }
681
+ )
682
+ );
683
+ var LinkBroken_default = LinkBroken;
684
+
685
+ // src/components/RadioButtonGroup/RadioButtonGroup.tsx
686
+ var import_react8 = __toESM(require("react"));
687
+
688
+ // src/components/RadioButtonGroup/RadioButton.tsx
689
+ var import_react7 = __toESM(require("react"));
690
+ var RadioButton = ({
691
+ checked,
692
+ label,
693
+ name,
694
+ onChange,
695
+ value,
696
+ disabled,
697
+ size
698
+ }) => {
699
+ return /* @__PURE__ */ import_react7.default.createElement(
700
+ "label",
701
+ {
702
+ className: `Layer__radio-button-group__radio-button Layer__radio-button-group__radio-button--size-${size}`
703
+ },
704
+ /* @__PURE__ */ import_react7.default.createElement(
705
+ "input",
706
+ {
707
+ type: "radio",
708
+ checked,
709
+ name,
710
+ onChange,
711
+ value,
712
+ disabled: disabled ?? false
713
+ }
714
+ ),
715
+ /* @__PURE__ */ import_react7.default.createElement("div", null, label)
716
+ );
717
+ };
718
+
719
+ // src/components/RadioButtonGroup/RadioButtonGroup.tsx
720
+ var RadioButtonGroup = ({
721
+ name,
722
+ size = "large",
723
+ buttons,
724
+ onChange,
725
+ selected
726
+ }) => {
727
+ const selectedValue = selected || buttons[0].value;
728
+ return /* @__PURE__ */ import_react8.default.createElement(
729
+ "div",
730
+ {
731
+ className: `Layer__radio-button-group Layer__radio-button-group--size-${size}`
732
+ },
733
+ buttons.map((button) => /* @__PURE__ */ import_react8.default.createElement(
734
+ RadioButton,
735
+ {
736
+ ...button,
737
+ key: button.value,
738
+ name,
739
+ size,
740
+ checked: selectedValue === button.value,
741
+ onChange,
742
+ disabled: button.disabled ?? false
743
+ }
744
+ ))
745
+ );
746
+ };
747
+
748
+ // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
749
+ var ExpandedBankTransactionRow = ({
750
+ bankTransaction,
751
+ close
752
+ }) => {
753
+ const { categorize: categorizeBankTransaction2 } = useBankTransactions();
754
+ const [purpose, setPurpose] = (0, import_react9.useState)("categorize" /* categorize */);
755
+ const defaultCategory = bankTransaction.category || bankTransaction.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ && bankTransaction.categorization_flow?.suggestions?.[0];
756
+ const [rowState, updateRowState] = (0, import_react9.useState)({
757
+ splits: [
758
+ {
759
+ amount: bankTransaction.amount,
760
+ inputValue: centsToDollars(bankTransaction.amount),
761
+ category: defaultCategory
762
+ }
763
+ ],
764
+ description: "",
765
+ file: void 0
766
+ });
767
+ const addSplit = () => updateRowState({
768
+ ...rowState,
769
+ splits: [
770
+ ...rowState.splits,
771
+ { amount: 0, inputValue: "0.00", category: defaultCategory }
772
+ ]
773
+ });
774
+ const removeSplit = () => updateRowState({
775
+ ...rowState,
776
+ splits: rowState.splits.slice(0, -1)
777
+ });
778
+ const updateAmounts = (rowNumber) => (event) => {
779
+ const newAmount = dollarsToCents(event.target.value) || 0;
780
+ const newDisplaying = event.target.value;
781
+ const splitTotal = rowState.splits.slice(0, -1).reduce((sum, split, index) => {
782
+ const amount = index === rowNumber ? newAmount : split.amount;
783
+ return sum + amount;
784
+ }, 0);
785
+ const remaining = bankTransaction.amount - splitTotal;
786
+ rowState.splits[rowNumber].amount = newAmount;
787
+ rowState.splits[rowNumber].inputValue = newDisplaying;
788
+ rowState.splits[rowState.splits.length - 1].amount = remaining;
789
+ rowState.splits[rowState.splits.length - 1].inputValue = centsToDollars(remaining);
790
+ updateRowState({ ...rowState });
791
+ };
792
+ const onBlur = (event) => {
793
+ if (event.target.value === "") {
794
+ const [_, index] = event.target.name.split("-");
795
+ rowState.splits[parseInt(index)].inputValue = "0.00";
796
+ updateRowState({ ...rowState });
797
+ }
798
+ };
799
+ const onChangePurpose = (event) => setPurpose(
800
+ event.target.value === "match" /* match */ ? "match" /* match */ : "categorize" /* categorize */
801
+ );
802
+ const changeCategory = (index, newValue) => {
803
+ rowState.splits[index].category = newValue;
804
+ updateRowState({ ...rowState });
805
+ };
806
+ const save = () => categorizeBankTransaction2(
807
+ bankTransaction.id,
808
+ rowState.splits.length === 1 ? {
809
+ type: "Category",
810
+ category: {
811
+ type: "StableName",
812
+ stable_name: rowState?.splits[0].category?.stable_name || rowState?.splits[0].category?.category
813
+ }
814
+ } : {
815
+ type: "Split",
816
+ entries: rowState.splits.map((split) => ({
817
+ category: split.category?.stable_name || split.category?.category,
818
+ amount: split.amount
819
+ }))
820
+ }
821
+ ).then(close);
822
+ const className = "Layer__expanded-bank-transaction-row";
823
+ return /* @__PURE__ */ import_react9.default.createElement("div", { className }, /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__purpose-button` }, /* @__PURE__ */ import_react9.default.createElement(
824
+ RadioButtonGroup,
825
+ {
826
+ name: `purpose-${bankTransaction.id}`,
827
+ size: "small",
828
+ buttons: [
829
+ { value: "categorize", label: "Categorize" },
830
+ { value: "match", label: "Match", disabled: true }
831
+ ],
832
+ selected: purpose,
833
+ onChange: onChangePurpose
834
+ }
835
+ )), /* @__PURE__ */ import_react9.default.createElement(
836
+ "div",
837
+ {
838
+ className: `${className}__content`,
839
+ id: `expanded-${bankTransaction.id}`
840
+ },
841
+ /* @__PURE__ */ import_react9.default.createElement(
842
+ "div",
843
+ {
844
+ className: `${className}__table-cell ${className}__table-cell--header`
845
+ }
846
+ ),
847
+ /* @__PURE__ */ import_react9.default.createElement(
848
+ "div",
849
+ {
850
+ className: `${className}__table-cell ${className}__table-cell--header`
851
+ },
852
+ "Category"
853
+ ),
854
+ /* @__PURE__ */ import_react9.default.createElement(
855
+ "div",
856
+ {
857
+ className: `${className}__table-cell ${className}__table-cell--header`
858
+ },
859
+ "Description"
860
+ ),
861
+ /* @__PURE__ */ import_react9.default.createElement(
862
+ "div",
863
+ {
864
+ className: `${className}__table-cell ${className}__table-cell--header`
865
+ },
866
+ "Receipt"
867
+ ),
868
+ /* @__PURE__ */ import_react9.default.createElement(
869
+ "div",
870
+ {
871
+ className: `${className}__table-cell ${className}__table-cell--header`
872
+ }
873
+ ),
874
+ /* @__PURE__ */ import_react9.default.createElement(
875
+ "div",
876
+ {
877
+ className: `${className}__table-cell ${className}__table-cell--header`
878
+ }
879
+ ),
880
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, rowState.splits.length === 1 ? /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__button--split`, onClick: addSplit }, /* @__PURE__ */ import_react9.default.createElement(LinkBroken_default, { className: `${className}__svg`, size: 18 }), "Split") : /* @__PURE__ */ import_react9.default.createElement(
881
+ "div",
882
+ {
883
+ className: `${className}__button--merge`,
884
+ onClick: removeSplit
885
+ },
886
+ /* @__PURE__ */ import_react9.default.createElement(Link_default, { className: `${className}__svg`, size: 18 }),
887
+ "Merge"
888
+ )),
889
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, rowState.splits.map((split, index) => /* @__PURE__ */ import_react9.default.createElement(
890
+ "div",
891
+ {
892
+ className: `${className}__table-cell--split-entry`,
893
+ key: `split-${index}`
894
+ },
895
+ /* @__PURE__ */ import_react9.default.createElement(
896
+ CategoryMenu,
897
+ {
898
+ bankTransaction,
899
+ name: `category-${index}`,
900
+ value: split.category,
901
+ onChange: (value) => changeCategory(index, value)
902
+ }
903
+ ),
904
+ rowState.splits.length > 1 && /* @__PURE__ */ import_react9.default.createElement(
905
+ "input",
906
+ {
907
+ type: "text",
908
+ name: `split-${index}`,
909
+ disabled: index + 1 === rowState.splits.length,
910
+ onChange: updateAmounts(index),
911
+ value: split.inputValue,
912
+ onBlur,
913
+ className: `${className}__split-amount${split.amount < 0 ? "--negative" : ""}`
914
+ }
915
+ )
916
+ ))),
917
+ /* @__PURE__ */ import_react9.default.createElement(
918
+ "div",
919
+ {
920
+ className: `${className}__table-cell ${className}__table-cell--description`
921
+ },
922
+ /* @__PURE__ */ import_react9.default.createElement("textarea", null)
923
+ ),
924
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, /* @__PURE__ */ import_react9.default.createElement("input", { type: "file" })),
925
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }),
926
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, /* @__PURE__ */ import_react9.default.createElement("button", { onClick: save, className: `${className}__button--save` }, "Save"))
927
+ ));
928
+ };
929
+
930
+ // src/components/Pill/Pill.tsx
931
+ var import_react10 = __toESM(require("react"));
932
+ var Pill = ({ children }) => /* @__PURE__ */ import_react10.default.createElement("span", { className: "Layer__pill" }, children);
933
+
934
+ // src/components/BankTransactionRow/BankTransactionRow.tsx
935
+ var import_date_fns4 = require("date-fns");
936
+ var isCredit = ({ direction }) => direction === "CREDIT" /* CREDIT */;
937
+ var BankTransactionRow = ({
938
+ dateFormat: dateFormat2,
939
+ bankTransaction,
940
+ isOpen,
941
+ toggleOpen,
942
+ editable
943
+ }) => {
944
+ const { categorize: categorizeBankTransaction2 } = useBankTransactions();
945
+ const [selectedCategory, setSelectedCategory] = (0, import_react11.useState)(
946
+ bankTransaction.categorization_flow.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? bankTransaction.categorization_flow.suggestions[0] : void 0
947
+ );
948
+ const className = "Layer__bank-transaction-row__table-cell";
949
+ const openClassName = isOpen ? `${className}--expanded` : "";
950
+ const save = () => categorizeBankTransaction2(bankTransaction.id, {
951
+ type: "Category",
952
+ category: {
953
+ type: "StableName",
954
+ stable_name: selectedCategory?.stable_name || selectedCategory?.category || ""
955
+ }
956
+ });
957
+ return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName} ${className}--date` }, (0, import_date_fns4.format)((0, import_date_fns4.parseISO)(bankTransaction.date), dateFormat2)), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, bankTransaction.counterparty_name), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, "Business Checking"), /* @__PURE__ */ import_react11.default.createElement(
958
+ "div",
959
+ {
960
+ className: `${className} ${openClassName} ${className}--amount-${isCredit(bankTransaction) ? "credit" : "debit"}`
961
+ },
962
+ centsToDollars(bankTransaction.amount)
963
+ ), isOpen ? /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }) : /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, editable ? /* @__PURE__ */ import_react11.default.createElement(
964
+ CategoryMenu,
965
+ {
966
+ bankTransaction,
967
+ name: `category-${bankTransaction.id}`,
968
+ value: selectedCategory,
969
+ onChange: setSelectedCategory
970
+ }
971
+ ) : /* @__PURE__ */ import_react11.default.createElement(Pill, null, bankTransaction?.category?.display_name)), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName} ${className}--actions` }, /* @__PURE__ */ import_react11.default.createElement(
972
+ "div",
973
+ {
974
+ className: "Layer__bank-transaction-row__save-button",
975
+ onClick: () => save()
976
+ },
977
+ editable && !isOpen && /* @__PURE__ */ import_react11.default.createElement(
978
+ CheckedCircle_default,
979
+ {
980
+ size: 28,
981
+ strokeColor: "#0C48E5",
982
+ fillColor: "#e0e9ff"
983
+ }
984
+ )
985
+ ), /* @__PURE__ */ import_react11.default.createElement(
986
+ "div",
987
+ {
988
+ onClick: () => toggleOpen(bankTransaction.id),
989
+ className: "Layer__bank-transaction-row__expand-button"
990
+ },
991
+ isOpen ? /* @__PURE__ */ import_react11.default.createElement(ChevronUp_default, null) : /* @__PURE__ */ import_react11.default.createElement(ChevronDown_default, null)
992
+ )), isOpen && /* @__PURE__ */ import_react11.default.createElement(
993
+ ExpandedBankTransactionRow,
994
+ {
995
+ bankTransaction,
996
+ close: () => toggleOpen(bankTransaction.id)
997
+ }
998
+ ));
999
+ };
1000
+
1001
+ // src/components/BankTransactions/BankTransactions.tsx
1002
+ var dateFormat = "MM/dd/yyyy";
1003
+ var CategorizedCategories = [
1004
+ "CATEGORIZED" /* CATEGORIZED */,
1005
+ "JOURNALING" /* JOURNALING */,
1006
+ "SPLIT" /* SPLIT */
1007
+ ];
1008
+ var ReviewCategories = [
1009
+ "READY_FOR_INPUT" /* READY_FOR_INPUT */,
1010
+ "LAYER_REVIEW" /* LAYER_REVIEW */
1011
+ ];
1012
+ var filterVisibility = (display) => (bankTransaction) => {
1013
+ const categorized = CategorizedCategories.includes(
1014
+ bankTransaction.categorization_status
1015
+ );
1016
+ const inReview = ReviewCategories.includes(
1017
+ bankTransaction.categorization_status
1018
+ );
1019
+ return display === "review" /* review */ && inReview || display === "categorized" /* categorized */ && categorized;
1020
+ };
1021
+ var BankTransactions = () => {
1022
+ const [display, setDisplay] = (0, import_react12.useState)("review" /* review */);
1023
+ const { data } = useBankTransactions();
1024
+ const bankTransactions = data.filter(filterVisibility(display));
1025
+ const onCategorizationDisplayChange = (event) => setDisplay(
1026
+ event.target.value === "categorized" /* categorized */ ? "categorized" /* categorized */ : "review" /* review */
1027
+ );
1028
+ const [openRows, setOpenRows] = (0, import_react12.useState)({});
1029
+ const toggleOpen = (id) => setOpenRows({ ...openRows, [id]: !openRows[id] });
1030
+ return /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions", "data-display": display }, /* @__PURE__ */ import_react12.default.createElement("header", { className: "Layer__bank-transactions__header" }, /* @__PURE__ */ import_react12.default.createElement("h2", { className: "Layer__bank-transactions__title" }, "Transactions"), /* @__PURE__ */ import_react12.default.createElement(
1031
+ RadioButtonGroup,
1032
+ {
1033
+ name: "bank-transaction-display",
1034
+ buttons: [
1035
+ { label: "To Review", value: "review" /* review */ },
1036
+ { label: "Categorized", value: "categorized" /* categorized */ }
1037
+ ],
1038
+ selected: display,
1039
+ onChange: onCategorizationDisplayChange
1040
+ }
1041
+ )), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Date"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Transaction"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Account"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header Layer__bank-transactions__table-cell--header-amount" }, "Amount"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Category"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Actions"), bankTransactions.map((bankTransaction) => /* @__PURE__ */ import_react12.default.createElement(
1042
+ BankTransactionRow,
1043
+ {
1044
+ key: bankTransaction.id,
1045
+ dateFormat,
1046
+ bankTransaction,
1047
+ isOpen: openRows[bankTransaction.id],
1048
+ toggleOpen,
1049
+ editable: display === "review" /* review */
1050
+ }
1051
+ ))));
1052
+ };
1053
+
1054
+ // src/components/Hello/Hello.tsx
1055
+ var import_react13 = __toESM(require("react"));
1056
+ var import_swr3 = __toESM(require("swr"));
1057
+ var fetcher = (url) => fetch(url).then((res) => res.json());
1058
+ var Hello = ({ user }) => {
1059
+ const { data, isLoading } = (0, import_swr3.default)(
1060
+ `https://api.github.com/users/${user || "jyurek"}`,
1061
+ fetcher
1062
+ );
1063
+ const name = (isLoading ? "..." : data?.name) || "User";
1064
+ return /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, /* @__PURE__ */ import_react13.default.createElement("div", { className: "hello" }, "Hello, ", name, "!"));
1065
+ };
1066
+
1067
+ // src/components/ProfitAndLoss/ProfitAndLoss.tsx
1068
+ var import_react21 = __toESM(require("react"));
1069
+
1070
+ // src/hooks/useProfitAndLoss/useProfitAndLoss.tsx
1071
+ var import_react14 = require("react");
1072
+ var import_date_fns5 = require("date-fns");
1073
+ var import_swr4 = __toESM(require("swr"));
1074
+ var useProfitAndLoss = ({ startDate: initialStartDate, endDate: initialEndDate } = {
1075
+ startDate: (0, import_date_fns5.startOfMonth)(/* @__PURE__ */ new Date()),
1076
+ endDate: (0, import_date_fns5.endOfMonth)(/* @__PURE__ */ new Date())
1077
+ }) => {
1078
+ const { auth, businessId } = useLayerContext();
1079
+ const [startDate, setStartDate] = (0, import_react14.useState)(
1080
+ initialStartDate || (0, import_date_fns5.startOfMonth)(Date.now())
1081
+ );
1082
+ const [endDate, setEndDate] = (0, import_react14.useState)(
1083
+ initialEndDate || (0, import_date_fns5.endOfMonth)(Date.now())
1084
+ );
1085
+ const {
1086
+ data: rawData,
1087
+ isLoading,
1088
+ error: rawError
1089
+ } = (0, import_swr4.default)(
1090
+ businessId && startDate && endDate && auth?.access_token && `profit-and-loss-${businessId}-${startDate.valueOf()}-${endDate.valueOf()}`,
1091
+ Layer.getProfitAndLoss(auth?.access_token, {
1092
+ params: {
1093
+ businessId,
1094
+ startDate: (0, import_date_fns5.formatISO)(startDate),
1095
+ endDate: (0, import_date_fns5.formatISO)(endDate)
1096
+ }
1097
+ })
1098
+ );
1099
+ const { data, error } = rawData || {};
1100
+ const changeDateRange = ({
1101
+ startDate: newStartDate,
1102
+ endDate: newEndDate
1103
+ }) => {
1104
+ newStartDate && setStartDate(newStartDate);
1105
+ newEndDate && setEndDate(newEndDate);
1106
+ };
1107
+ return {
1108
+ data,
1109
+ isLoading,
1110
+ error: error || rawError,
1111
+ dateRange: { startDate, endDate },
1112
+ changeDateRange
1113
+ };
1114
+ };
1115
+
1116
+ // src/components/ProfitAndLossChart/ProfitAndLossChart.tsx
1117
+ var import_react16 = __toESM(require("react"));
1118
+
1119
+ // src/components/ProfitAndLossChart/Indicator.tsx
1120
+ var import_react15 = __toESM(require("react"));
1121
+ var emptyViewBox = { x: 0, y: 0, width: 0, height: 0 };
1122
+ var Indicator = ({
1123
+ viewBox = {},
1124
+ className,
1125
+ animateFrom,
1126
+ setAnimateFrom
1127
+ }) => {
1128
+ if (!className?.match(/selected/)) {
1129
+ return null;
1130
+ }
1131
+ const {
1132
+ x: animateTo = 0,
1133
+ y = 0,
1134
+ width = 0,
1135
+ height = 0
1136
+ } = "x" in viewBox ? viewBox : emptyViewBox;
1137
+ const boxWidth = width * 2 + 4;
1138
+ const multiplier = 1.5;
1139
+ const xOffset = (boxWidth * multiplier - boxWidth) / 2;
1140
+ (0, import_react15.useEffect)(() => {
1141
+ setAnimateFrom(animateTo);
1142
+ }, [animateTo]);
1143
+ const actualX = animateFrom === -1 ? animateTo : animateFrom;
1144
+ return /* @__PURE__ */ import_react15.default.createElement(
1145
+ "rect",
1146
+ {
1147
+ className: "Layer__profit-and-loss-chart__selection-indicator",
1148
+ style: {
1149
+ width: `${boxWidth * multiplier}px`,
1150
+ x: actualX - xOffset,
1151
+ y: y + height
1152
+ }
1153
+ }
1154
+ );
1155
+ };
1156
+
1157
+ // src/components/ProfitAndLossChart/ProfitAndLossChart.tsx
1158
+ var import_date_fns6 = require("date-fns");
1159
+ var import_recharts = require("recharts");
1160
+ var barGap = 4;
1161
+ var barSize = 20;
1162
+ var ProfitAndLossChart = () => {
1163
+ const { changeDateRange, dateRange } = (0, import_react16.useContext)(ProfitAndLoss.Context);
1164
+ const thisMonth = (0, import_date_fns6.startOfMonth)(Date.now());
1165
+ const startSelectionMonth = dateRange.startDate.getMonth();
1166
+ const endSelectionMonth = dateRange.endDate.getMonth();
1167
+ const monthData = [];
1168
+ monthData.push(
1169
+ useProfitAndLoss({
1170
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 11 })),
1171
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 11 }))
1172
+ })?.data
1173
+ );
1174
+ monthData.push(
1175
+ useProfitAndLoss({
1176
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 10 })),
1177
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 10 }))
1178
+ })?.data
1179
+ );
1180
+ monthData.push(
1181
+ useProfitAndLoss({
1182
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 9 })),
1183
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 9 }))
1184
+ })?.data
1185
+ );
1186
+ monthData.push(
1187
+ useProfitAndLoss({
1188
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 8 })),
1189
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 8 }))
1190
+ })?.data
1191
+ );
1192
+ monthData.push(
1193
+ useProfitAndLoss({
1194
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 7 })),
1195
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 7 }))
1196
+ })?.data
1197
+ );
1198
+ monthData.push(
1199
+ useProfitAndLoss({
1200
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 6 })),
1201
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 6 }))
1202
+ })?.data
1203
+ );
1204
+ monthData.push(
1205
+ useProfitAndLoss({
1206
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 5 })),
1207
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 5 }))
1208
+ })?.data
1209
+ );
1210
+ monthData.push(
1211
+ useProfitAndLoss({
1212
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 4 })),
1213
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 4 }))
1214
+ })?.data
1215
+ );
1216
+ monthData.push(
1217
+ useProfitAndLoss({
1218
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 3 })),
1219
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 3 }))
1220
+ })?.data
1221
+ );
1222
+ monthData.push(
1223
+ useProfitAndLoss({
1224
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 2 })),
1225
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 2 }))
1226
+ })?.data
1227
+ );
1228
+ monthData.push(
1229
+ useProfitAndLoss({
1230
+ startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 1 })),
1231
+ endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 1 }))
1232
+ })?.data
1233
+ );
1234
+ monthData.push(
1235
+ useProfitAndLoss({
1236
+ startDate: thisMonth,
1237
+ endDate: (0, import_date_fns6.endOfMonth)(thisMonth)
1238
+ })?.data
1239
+ );
1240
+ const getMonthName = (pnl) => !!pnl ? (0, import_date_fns6.format)((0, import_date_fns6.parseISO)(pnl.start_date), "LLL") : "";
1241
+ const summarizePnL = (pnl) => ({
1242
+ name: getMonthName(pnl),
1243
+ revenue: pnl?.income.value || 0,
1244
+ expenses: (pnl?.income.value || 0) - (pnl?.net_profit || 0),
1245
+ selected: !!pnl && (0, import_date_fns6.parseISO)(pnl.start_date).getMonth() >= startSelectionMonth && (0, import_date_fns6.parseISO)(pnl.end_date).getMonth() <= endSelectionMonth
1246
+ });
1247
+ const onClick = ({ activeTooltipIndex }) => {
1248
+ const selection = monthData[activeTooltipIndex || -1];
1249
+ if (selection) {
1250
+ const { start_date: startDate, end_date: endDate } = selection;
1251
+ changeDateRange({
1252
+ startDate: (0, import_date_fns6.parseISO)(startDate),
1253
+ endDate: (0, import_date_fns6.parseISO)(endDate)
1254
+ });
1255
+ }
1256
+ };
1257
+ const data = (0, import_react16.useMemo)(
1258
+ () => monthData.map(summarizePnL),
1259
+ [
1260
+ startSelectionMonth,
1261
+ endSelectionMonth,
1262
+ ...monthData.map((m) => m?.net_profit)
1263
+ ]
1264
+ );
1265
+ const [animateFrom, setAnimateFrom] = (0, import_react16.useState)(-1);
1266
+ return /* @__PURE__ */ import_react16.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: 250 }, /* @__PURE__ */ import_react16.default.createElement(
1267
+ import_recharts.BarChart,
1268
+ {
1269
+ margin: { left: 24, right: 24, bottom: 24 },
1270
+ data,
1271
+ onClick,
1272
+ barGap,
1273
+ className: "Layer__profit-and-loss-chart"
1274
+ },
1275
+ /* @__PURE__ */ import_react16.default.createElement(import_recharts.CartesianGrid, { vertical: false }),
1276
+ /* @__PURE__ */ import_react16.default.createElement(
1277
+ import_recharts.Legend,
1278
+ {
1279
+ verticalAlign: "top",
1280
+ align: "left",
1281
+ payload: [
1282
+ { value: "Income", type: "circle", id: "IncomeLegend" },
1283
+ { value: "Expenses", type: "circle", id: "ExpensesLegend" }
1284
+ ]
1285
+ }
1286
+ ),
1287
+ /* @__PURE__ */ import_react16.default.createElement(import_recharts.XAxis, { dataKey: "name", tickLine: false }),
1288
+ /* @__PURE__ */ import_react16.default.createElement(
1289
+ import_recharts.Bar,
1290
+ {
1291
+ dataKey: "revenue",
1292
+ barSize,
1293
+ isAnimationActive: false,
1294
+ radius: [barSize / 4, barSize / 4, 0, 0],
1295
+ className: "Layer__profit-and-loss-chart__bar--income"
1296
+ },
1297
+ /* @__PURE__ */ import_react16.default.createElement(
1298
+ import_recharts.LabelList,
1299
+ {
1300
+ content: /* @__PURE__ */ import_react16.default.createElement(
1301
+ Indicator,
1302
+ {
1303
+ animateFrom,
1304
+ setAnimateFrom
1305
+ }
1306
+ )
1307
+ }
1308
+ ),
1309
+ data.map((entry) => /* @__PURE__ */ import_react16.default.createElement(
1310
+ import_recharts.Cell,
1311
+ {
1312
+ key: entry.name,
1313
+ className: entry.selected ? "Layer__profit-and-loss-chart__cell--selected" : ""
1314
+ }
1315
+ ))
1316
+ ),
1317
+ /* @__PURE__ */ import_react16.default.createElement(
1318
+ import_recharts.Bar,
1319
+ {
1320
+ dataKey: "expenses",
1321
+ barSize,
1322
+ isAnimationActive: false,
1323
+ radius: [barSize / 4, barSize / 4, 0, 0],
1324
+ className: "Layer__profit-and-loss-chart__bar--expenses"
1325
+ },
1326
+ data.map((entry) => /* @__PURE__ */ import_react16.default.createElement(
1327
+ import_recharts.Cell,
1328
+ {
1329
+ key: entry.name,
1330
+ className: entry.selected ? "Layer__profit-and-loss-chart__cell--selected" : ""
1331
+ }
1332
+ ))
1333
+ )
1334
+ ));
1335
+ };
1336
+
1337
+ // src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx
1338
+ var import_react17 = __toESM(require("react"));
1339
+
1340
+ // src/icons/ChevronLeft.tsx
1341
+ var React22 = __toESM(require("react"));
1342
+ var ChevronLeft = ({
1343
+ strokeColor,
1344
+ size,
1345
+ ...props
1346
+ }) => /* @__PURE__ */ React22.createElement(
1347
+ "svg",
1348
+ {
1349
+ xmlns: "http://www.w3.org/2000/svg",
1350
+ width: size || 24,
1351
+ height: size || 24,
1352
+ fill: "none",
1353
+ viewBox: "0 0 24 24",
1354
+ ...props
1355
+ },
1356
+ /* @__PURE__ */ React22.createElement(
1357
+ "path",
1358
+ {
1359
+ stroke: strokeColor ?? "#000",
1360
+ strokeLinecap: "round",
1361
+ strokeLinejoin: "round",
1362
+ strokeWidth: 2,
1363
+ d: "m15 18-6-6 6-6"
1364
+ }
1365
+ )
1366
+ );
1367
+ var ChevronLeft_default = ChevronLeft;
1368
+
1369
+ // src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx
1370
+ var import_date_fns7 = require("date-fns");
1371
+ var ProfitAndLossDatePicker = () => {
1372
+ const { changeDateRange, dateRange } = (0, import_react17.useContext)(ProfitAndLoss.Context);
1373
+ const date = dateRange.startDate;
1374
+ const label = (0, import_date_fns7.format)(date, "LLLL y");
1375
+ const change = (duration) => {
1376
+ const newDate = (0, import_date_fns7.add)(date, duration);
1377
+ changeDateRange({
1378
+ startDate: (0, import_date_fns7.startOfMonth)(newDate),
1379
+ endDate: (0, import_date_fns7.endOfMonth)(newDate)
1380
+ });
1381
+ };
1382
+ const previousMonth = () => change({ months: -1 });
1383
+ const nextMonth = () => change({ months: 1 });
1384
+ return /* @__PURE__ */ import_react17.default.createElement("div", { className: "Layer__profit-and-loss-date-picker" }, /* @__PURE__ */ import_react17.default.createElement(
1385
+ "button",
1386
+ {
1387
+ "aria-label": "View Previous Month",
1388
+ className: "Layer__profit-and-loss-date-picker__button",
1389
+ onClick: previousMonth
1390
+ },
1391
+ /* @__PURE__ */ import_react17.default.createElement(
1392
+ ChevronLeft_default,
1393
+ {
1394
+ className: "Layer__profit-and-loss-date-picker__button-icon",
1395
+ size: 18
1396
+ }
1397
+ )
1398
+ ), /* @__PURE__ */ import_react17.default.createElement("span", { className: "Layer__profit-and-loss-date-picker__label" }, label), /* @__PURE__ */ import_react17.default.createElement(
1399
+ "button",
1400
+ {
1401
+ "aria-label": "View Next Month",
1402
+ className: "Layer__profit-and-loss-date-picker__button",
1403
+ onClick: nextMonth
1404
+ },
1405
+ /* @__PURE__ */ import_react17.default.createElement(
1406
+ ChevronRight_default,
1407
+ {
1408
+ className: "Layer__profit-and-loss-date-picker__button-icon",
1409
+ size: 18
1410
+ }
1411
+ )
1412
+ ));
1413
+ };
1414
+
1415
+ // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
1416
+ var import_react18 = __toESM(require("react"));
1417
+ var import_date_fns8 = require("date-fns");
1418
+ var ProfitAndLossSummaries = () => {
1419
+ const { data } = (0, import_react18.useContext)(ProfitAndLoss.Context);
1420
+ if (!data) {
1421
+ return null;
1422
+ }
1423
+ const monthName = (0, import_date_fns8.format)((0, import_date_fns8.parseISO)(data?.start_date), "LLLL");
1424
+ return /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--income" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Revenue"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(data.income.value))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--expenses" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Expenses"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(Math.abs(data.income.value - data.net_profit)))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--net-profit" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Net Profit"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(data.net_profit))));
1425
+ };
1426
+
1427
+ // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
1428
+ var import_react20 = __toESM(require("react"));
1429
+
1430
+ // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
1431
+ var import_react19 = __toESM(require("react"));
1432
+ var ProfitAndLossRow = ({
1433
+ variant,
1434
+ lineItem,
1435
+ depth = 0,
1436
+ maxDepth = 1,
1437
+ direction = "DEBIT" /* DEBIT */
1438
+ }) => {
1439
+ if (!lineItem) {
1440
+ return null;
1441
+ }
1442
+ const { value, display_name, line_items, name } = lineItem;
1443
+ const variantName = variant || name;
1444
+ const amount = value || 0;
1445
+ const amountString = centsToDollars(Math.abs(amount));
1446
+ const labelClasses = [
1447
+ "Layer__profit-and-loss-row",
1448
+ "Layer__profit-and-loss-row__label"
1449
+ ];
1450
+ const valueClasses = [
1451
+ "Layer__profit-and-loss-row",
1452
+ "Layer__profit-and-loss-row__value"
1453
+ ];
1454
+ valueClasses.push(
1455
+ direction === "CREDIT" /* CREDIT */ ? "Layer__profit-and-loss-row__value--amount-positive" : "Layer__profit-and-loss-row__value--amount-negative"
1456
+ );
1457
+ labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`);
1458
+ valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`);
1459
+ variantName && labelClasses.push(
1460
+ `Layer__profit-and-loss-row__label--variant-${variantName}`
1461
+ );
1462
+ variantName && valueClasses.push(
1463
+ `Layer__profit-and-loss-row__value--variant-${variantName}`
1464
+ );
1465
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: labelClasses.join(" ") }, display_name), /* @__PURE__ */ import_react19.default.createElement("div", { className: valueClasses.join(" ") }, amountString), depth < maxDepth && (line_items || []).map((line_item) => /* @__PURE__ */ import_react19.default.createElement(
1466
+ ProfitAndLossRow,
1467
+ {
1468
+ key: line_item.display_name,
1469
+ lineItem: line_item,
1470
+ depth: depth + 1,
1471
+ maxDepth,
1472
+ direction
1473
+ }
1474
+ )));
1475
+ };
1476
+
1477
+ // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
1478
+ var ProfitAndLossTable = () => {
1479
+ const { data, isLoading } = (0, import_react20.useContext)(ProfitAndLoss.Context);
1480
+ return /* @__PURE__ */ import_react20.default.createElement("div", { className: "Layer__profit-and-loss-table" }, !data || isLoading ? /* @__PURE__ */ import_react20.default.createElement("div", null, "Loading") : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement(
1481
+ ProfitAndLossRow,
1482
+ {
1483
+ lineItem: data.income,
1484
+ direction: "CREDIT" /* CREDIT */
1485
+ }
1486
+ ), /* @__PURE__ */ import_react20.default.createElement(
1487
+ ProfitAndLossRow,
1488
+ {
1489
+ lineItem: data.cost_of_goods_sold,
1490
+ direction: "DEBIT" /* DEBIT */
1491
+ }
1492
+ ), /* @__PURE__ */ import_react20.default.createElement(
1493
+ ProfitAndLossRow,
1494
+ {
1495
+ lineItem: {
1496
+ value: data.gross_profit,
1497
+ display_name: "Gross Profit"
1498
+ },
1499
+ variant: "GROSS",
1500
+ direction: "CREDIT" /* CREDIT */
1501
+ }
1502
+ ), /* @__PURE__ */ import_react20.default.createElement(
1503
+ ProfitAndLossRow,
1504
+ {
1505
+ lineItem: data.expenses,
1506
+ direction: "DEBIT" /* DEBIT */
1507
+ }
1508
+ ), /* @__PURE__ */ import_react20.default.createElement(
1509
+ ProfitAndLossRow,
1510
+ {
1511
+ lineItem: {
1512
+ value: data.profit_before_taxes,
1513
+ display_name: "Profit Before Taxes"
1514
+ },
1515
+ variant: "BEFORETAX",
1516
+ direction: "CREDIT" /* CREDIT */
1517
+ }
1518
+ ), /* @__PURE__ */ import_react20.default.createElement(ProfitAndLossRow, { lineItem: data.taxes, direction: "DEBIT" /* DEBIT */ }), /* @__PURE__ */ import_react20.default.createElement(
1519
+ ProfitAndLossRow,
1520
+ {
1521
+ lineItem: {
1522
+ value: data.net_profit,
1523
+ display_name: "Net Profit"
1524
+ },
1525
+ variant: "NETPROFIT",
1526
+ direction: "CREDIT" /* CREDIT */
1527
+ }
1528
+ ), /* @__PURE__ */ import_react20.default.createElement(
1529
+ ProfitAndLossRow,
1530
+ {
1531
+ lineItem: data.other_outflows,
1532
+ direction: "DEBIT" /* DEBIT */
1533
+ }
1534
+ ), /* @__PURE__ */ import_react20.default.createElement(
1535
+ ProfitAndLossRow,
1536
+ {
1537
+ lineItem: data.personal_expenses,
1538
+ direction: "DEBIT" /* DEBIT */
1539
+ }
1540
+ )));
1541
+ };
1542
+
1543
+ // src/components/ProfitAndLoss/ProfitAndLoss.tsx
1544
+ var import_date_fns9 = require("date-fns");
1545
+ var PNLContext = (0, import_react21.createContext)({
1546
+ data: void 0,
1547
+ isLoading: true,
1548
+ error: void 0,
1549
+ dateRange: {
1550
+ startDate: (0, import_date_fns9.startOfMonth)(/* @__PURE__ */ new Date()),
1551
+ endDate: (0, import_date_fns9.endOfMonth)(/* @__PURE__ */ new Date())
1552
+ },
1553
+ changeDateRange: () => {
1554
+ }
1555
+ });
1556
+ var ProfitAndLoss = ({ children }) => {
1557
+ const contextData = useProfitAndLoss();
1558
+ return /* @__PURE__ */ import_react21.default.createElement(PNLContext.Provider, { value: contextData }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "Layer__profit-and-loss" }, /* @__PURE__ */ import_react21.default.createElement("h2", { className: "Layer__profit-and-loss__title" }, "Profit & Loss"), children));
1559
+ };
1560
+ ProfitAndLoss.Chart = ProfitAndLossChart;
1561
+ ProfitAndLoss.Context = PNLContext;
1562
+ ProfitAndLoss.DatePicker = ProfitAndLossDatePicker;
1563
+ ProfitAndLoss.Summaries = ProfitAndLossSummaries;
1564
+ ProfitAndLoss.Table = ProfitAndLossTable;
1565
+
1566
+ // src/providers/LayerProvider/LayerProvider.tsx
1567
+ var import_react22 = __toESM(require("react"));
1568
+ var import_swr5 = __toESM(require("swr"));
1569
+ var reducer = (state, action) => {
1570
+ switch (action.type) {
1571
+ case "LayerContext.setAuth" /* setAuth */:
1572
+ case "LayerContext.setCategories" /* setCategories */:
1573
+ return { ...state, ...action.payload };
1574
+ default:
1575
+ return state;
1576
+ }
1577
+ };
1578
+ var LayerEnvironment = {
1579
+ production: {
1580
+ url: "not defined yet",
1581
+ scope: "not defined yet"
1582
+ },
1583
+ staging: {
1584
+ url: "https://auth.layerfi.com/oauth2/token",
1585
+ scope: "https://sandbox.layerfi.com/sandbox"
1586
+ }
1587
+ };
1588
+ var LayerProvider = ({
1589
+ appId,
1590
+ appSecret,
1591
+ businessId,
1592
+ children,
1593
+ clientId,
1594
+ environment = "production"
1595
+ }) => {
1596
+ const defaultSWRConfig = {
1597
+ revalidateInterval: 0,
1598
+ revalidateOnFocus: false,
1599
+ revalidateOnReconnect: false,
1600
+ revalidateIfStale: false
1601
+ };
1602
+ const { url, scope } = LayerEnvironment[environment];
1603
+ const [state, dispatch] = (0, import_react22.useReducer)(reducer, {
1604
+ auth: { access_token: "", token_type: "", expires_in: 0 },
1605
+ businessId,
1606
+ categories: []
1607
+ });
1608
+ const { data: auth } = (0, import_swr5.default)(
1609
+ "authenticate",
1610
+ Layer.authenticate({
1611
+ appId,
1612
+ appSecret,
1613
+ authenticationUrl: url,
1614
+ scope,
1615
+ clientId
1616
+ }),
1617
+ defaultSWRConfig
1618
+ );
1619
+ (0, import_react22.useEffect)(() => {
1620
+ if (!!auth?.access_token) {
1621
+ dispatch({ type: "LayerContext.setAuth" /* setAuth */, payload: { auth } });
1622
+ }
1623
+ }, [auth?.access_token]);
1624
+ const { data: categories } = (0, import_swr5.default)(
1625
+ businessId && auth?.access_token && `categories-${businessId}`,
1626
+ Layer.getCategories(auth?.access_token, { params: { businessId } }),
1627
+ defaultSWRConfig
1628
+ );
1629
+ (0, import_react22.useEffect)(() => {
1630
+ if (!!categories?.data?.categories?.length) {
1631
+ dispatch({
1632
+ type: "LayerContext.setCategories" /* setCategories */,
1633
+ payload: { categories: categories.data.categories || [] }
1634
+ });
1635
+ }
1636
+ }, [categories?.data?.categories?.length]);
1637
+ return /* @__PURE__ */ import_react22.default.createElement(import_swr5.SWRConfig, { value: defaultSWRConfig }, /* @__PURE__ */ import_react22.default.createElement(LayerContext.Provider, { value: state }, children));
1638
+ };
1639
+ // Annotate the CommonJS export names for ESM import in node:
1640
+ 0 && (module.exports = {
1641
+ BalanceSheet,
1642
+ BankTransactions,
1643
+ Hello,
1644
+ LayerProvider,
1645
+ ProfitAndLoss
1646
+ });
1647
+ //# sourceMappingURL=index.js.map