@layerfi/components 0.1.10 → 0.1.11

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/esm/index.js CHANGED
@@ -202,6 +202,7 @@ var request = (verb) => (url) => (baseUrl, accessToken, options) => fetch(`${bas
202
202
  }).then((res) => handleResponse(res)).catch((error) => handleException(error));
203
203
  var post = request("post");
204
204
  var put = request("put");
205
+ var deleteRequest = request("delete");
205
206
  var handleResponse = async (res) => {
206
207
  if (!res.ok) {
207
208
  const errors = await tryToReadErrorsFromResponse(res);
@@ -261,13 +262,8 @@ var matchBankTransaction = put(
261
262
  // src/api/layer/categories.ts
262
263
  var getCategories = get(({ businessId }) => `/v1/businesses/${businessId}/categories`);
263
264
 
264
- // src/api/layer/linked_accounts.ts
265
- var getLinkedAccounts = get(
266
- ({ businessId }) => `/v1/businesses/${businessId}/external-accounts`
267
- );
268
-
269
- // src/api/layer/ledger_accounts.ts
270
- var getLedgerAccounts = get(
265
+ // src/api/layer/chart_of_accounts.ts
266
+ var getChartOfAccounts = get(
271
267
  ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`
272
268
  );
273
269
  var createAccount = post(
@@ -276,6 +272,25 @@ var createAccount = post(
276
272
  var updateAccount = put(
277
273
  ({ businessId, accountId }) => `/v1/businesses/${businessId}/ledger/accounts/${accountId}`
278
274
  );
275
+ var getLedgerAccountsLines = get(
276
+ ({ businessId, accountId }) => `/v1/businesses/${businessId}/ledger/accounts/${accountId}/lines`
277
+ );
278
+ var getLedgerAccountsEntry = get(
279
+ ({ businessId, entryId }) => `/v1/businesses/${businessId}/ledger/entries/${entryId}`
280
+ );
281
+
282
+ // src/api/layer/linked_accounts.ts
283
+ var getLinkedAccounts = get(
284
+ ({ businessId }) => `/v1/businesses/${businessId}/external-accounts`
285
+ );
286
+ var getPlaidLinkToken = post(({ businessId }) => `/v1/businesses/${businessId}/plaid/link`);
287
+ var exchangePlaidPublicToken = post(({ businessId }) => `/v1/businesses/${businessId}/plaid/link/exchange`);
288
+ var unlinkPlaidItem = deleteRequest(
289
+ ({ businessId, plaidItemId }) => `/v1/businesses/${businessId}/plaid/items/${plaidItemId}`
290
+ );
291
+ var unlinkPlaidAccount = post(
292
+ ({ businessId, accountId }) => `/v1/businesses/${businessId}/plaid/accounts/${accountId}/archive`
293
+ );
279
294
 
280
295
  // src/api/layer/profit_and_loss.ts
281
296
  var getProfitAndLoss = get(
@@ -292,9 +307,15 @@ var Layer = {
292
307
  getBalanceSheet,
293
308
  getBankTransactions,
294
309
  getCategories,
295
- getLedgerAccounts,
310
+ getChartOfAccounts,
311
+ getLedgerAccountsLines,
312
+ getLedgerAccountsEntry,
296
313
  getProfitAndLoss,
297
- getLinkedAccounts
314
+ getLinkedAccounts,
315
+ getPlaidLinkToken,
316
+ exchangePlaidPublicToken,
317
+ unlinkPlaidAccount,
318
+ unlinkPlaidItem
298
319
  };
299
320
 
300
321
  // src/hooks/useLayerContext/useLayerContext.tsx
@@ -315,7 +336,10 @@ var LayerContext = createContext({
315
336
  theme: void 0,
316
337
  colors: {},
317
338
  setTheme: () => void 0,
318
- getColor: (_shade) => void 0
339
+ getColor: (_shade) => void 0,
340
+ setLightColor: () => void 0,
341
+ setDarkColor: () => void 0,
342
+ setColors: () => void 0
319
343
  });
320
344
 
321
345
  // src/hooks/useLayerContext/useLayerContext.tsx
@@ -595,6 +619,11 @@ import React56, { useState as useState10, useMemo as useMemo2, useEffect as useE
595
619
 
596
620
  // src/config/general.ts
597
621
  var DATE_FORMAT = "LLL d, yyyy";
622
+ var TIME_FORMAT = "p";
623
+ var BREAKPOINTS = {
624
+ TABLET: 760,
625
+ MOBILE: 500
626
+ };
598
627
 
599
628
  // src/hooks/useBankTransactions/useBankTransactions.tsx
600
629
  import useSWR2 from "swr";
@@ -715,7 +744,9 @@ var useElementSize = (callback) => {
715
744
  const observer = new ResizeObserver((entries) => {
716
745
  callback(element, entries[0], {
717
746
  width: element.offsetWidth,
718
- height: element.offsetHeight
747
+ height: element.offsetHeight,
748
+ clientWidth: element.clientWidth,
749
+ clientHeight: element.clientHeight
719
750
  });
720
751
  });
721
752
  observer.observe(element);
@@ -1532,13 +1563,17 @@ var Badge = ({
1532
1563
  onClick,
1533
1564
  children,
1534
1565
  tooltip,
1535
- size = "medium" /* MEDIUM */
1566
+ size = "medium" /* MEDIUM */,
1567
+ variant = "default" /* DEFAULT */,
1568
+ hoverable = false
1536
1569
  }) => {
1537
1570
  const baseProps = {
1538
1571
  className: classNames7(
1539
1572
  "Layer__badge",
1573
+ hoverable && !tooltip ? "Layer__badge--with-hover" : "",
1540
1574
  onClick || tooltip ? "Layer__badge--clickable" : "",
1541
- `Layer__badge--${size}`
1575
+ `Layer__badge--${size}`,
1576
+ `Layer__badge--${variant}`
1542
1577
  ),
1543
1578
  onClick,
1544
1579
  children
@@ -2181,7 +2216,8 @@ var Select2 = ({
2181
2216
  classNamePrefix = "Layer__select",
2182
2217
  value,
2183
2218
  onChange,
2184
- disabled
2219
+ disabled,
2220
+ placeholder
2185
2221
  }) => {
2186
2222
  return /* @__PURE__ */ React37.createElement(
2187
2223
  ReactSelect,
@@ -2189,6 +2225,7 @@ var Select2 = ({
2189
2225
  name,
2190
2226
  className: `Layer__select ${className ?? ""}`,
2191
2227
  classNamePrefix,
2228
+ placeholder: placeholder ?? "Select...",
2192
2229
  options,
2193
2230
  value,
2194
2231
  onChange: (newValue) => newValue && onChange(newValue),
@@ -2394,6 +2431,7 @@ var Toggle = ({
2394
2431
  checked: selectedValue === option.value,
2395
2432
  onChange: handleChange,
2396
2433
  disabled: option.disabled ?? false,
2434
+ disabledMessage: option.disabledMessage,
2397
2435
  index
2398
2436
  }
2399
2437
  )), /* @__PURE__ */ React41.createElement("span", { className: "Layer__toggle__thumb", style: { ...thumbPos } }));
@@ -2407,6 +2445,7 @@ var ToggleOption = ({
2407
2445
  size,
2408
2446
  leftIcon,
2409
2447
  disabled,
2448
+ disabledMessage = "Disabled",
2410
2449
  index
2411
2450
  }) => {
2412
2451
  if (disabled) {
@@ -2421,7 +2460,7 @@ var ToggleOption = ({
2421
2460
  disabled: disabled ?? false,
2422
2461
  "data-idx": index
2423
2462
  }
2424
- ), /* @__PURE__ */ React41.createElement("span", { className: "Layer__toggle-option-content" }, leftIcon && /* @__PURE__ */ React41.createElement("span", { className: "Layer__toggle-option__icon" }, leftIcon), /* @__PURE__ */ React41.createElement("span", null, label)))), /* @__PURE__ */ React41.createElement(TooltipContent, { className: "Layer__tooltip" }, "We could not find matching transactions"));
2463
+ ), /* @__PURE__ */ React41.createElement("span", { className: "Layer__toggle-option-content" }, leftIcon && /* @__PURE__ */ React41.createElement("span", { className: "Layer__toggle-option__icon" }, leftIcon), /* @__PURE__ */ React41.createElement("span", null, label)))), /* @__PURE__ */ React41.createElement(TooltipContent, { className: "Layer__tooltip" }, disabledMessage));
2425
2464
  }
2426
2465
  return /* @__PURE__ */ React41.createElement("label", { className: `Layer__toggle-option`, "data-checked": checked }, /* @__PURE__ */ React41.createElement(
2427
2466
  "input",
@@ -2822,7 +2861,8 @@ var ExpandedBankTransactionRow = forwardRef2(
2822
2861
  {
2823
2862
  value: "match",
2824
2863
  label: "Match",
2825
- disabled: !hasMatch(bankTransaction)
2864
+ disabled: !hasMatch(bankTransaction),
2865
+ disabledMessage: "We could not find matching transactions"
2826
2866
  }
2827
2867
  ],
2828
2868
  selected: purpose,
@@ -3686,11 +3726,12 @@ var hslToHex = (hsl) => {
3686
3726
  // src/components/Container/Container.tsx
3687
3727
  import classNames20 from "classnames";
3688
3728
  var Container = forwardRef3(
3689
- ({ name, className, children, asWidget }, ref) => {
3729
+ ({ name, className, children, asWidget, elevated = false }, ref) => {
3690
3730
  const baseClassName = classNames20(
3691
3731
  "Layer__component Layer__component-container",
3692
3732
  `Layer__${name}`,
3693
- asWidget ? "Layer__component--as-widget" : "",
3733
+ elevated && "Layer__component--elevated",
3734
+ asWidget && "Layer__component--as-widget",
3694
3735
  className
3695
3736
  );
3696
3737
  const { theme } = useLayerContext();
@@ -4022,7 +4063,14 @@ var BankTransactions = ({
4022
4063
  className: "Layer__bank-transactions__header",
4023
4064
  style: { top: shiftStickyHeader }
4024
4065
  },
4025
- /* @__PURE__ */ React56.createElement(Heading, { className: "Layer__bank-transactions__title" }, "Transactions"),
4066
+ /* @__PURE__ */ React56.createElement(
4067
+ Heading,
4068
+ {
4069
+ className: "Layer__bank-transactions__title",
4070
+ size: asWidget ? "secondary" /* secondary */ : "secondary" /* secondary */
4071
+ },
4072
+ "Transactions"
4073
+ ),
4026
4074
  !categorizedOnly && /* @__PURE__ */ React56.createElement(
4027
4075
  Toggle,
4028
4076
  {
@@ -4123,12 +4171,17 @@ var Hello = ({ user }) => {
4123
4171
  import React64 from "react";
4124
4172
 
4125
4173
  // src/hooks/useLinkedAccounts/useLinkedAccounts.ts
4126
- import useSWR4 from "swr";
4127
- var MOCK_DATA = [
4174
+ import { useEffect as useEffect8, useState as useState11 } from "react";
4175
+ import { usePlaidLink } from "react-plaid-link";
4176
+
4177
+ // src/hooks/useLinkedAccounts/mockData.ts
4178
+ var LINKED_ACCOUNTS_MOCK_DATA = [
4128
4179
  {
4129
4180
  id: "1",
4181
+ external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4182
+ external_account_source: "PLAID",
4130
4183
  external_account_name: "Citi Double Cash\xAE Card",
4131
- external_account_number: "1234",
4184
+ //external_account_number: '1234',
4132
4185
  latest_balance_timestamp: {
4133
4186
  external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4134
4187
  external_account_source: "PLAID",
@@ -4137,13 +4190,19 @@ var MOCK_DATA = [
4137
4190
  created_at: "2024-04-06T16:44:35.715458Z"
4138
4191
  },
4139
4192
  current_ledger_balance: 373717,
4140
- institution: "Chase",
4141
- institutionLogo: ""
4193
+ institution: {
4194
+ name: "Chase",
4195
+ logo: ""
4196
+ }
4197
+ //connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',
4198
+ //connection_status: 'OK',
4142
4199
  },
4143
4200
  {
4144
4201
  id: "2",
4202
+ external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4203
+ external_account_source: "PLAID",
4145
4204
  external_account_name: "Citi Double Cash\xAE Card",
4146
- external_account_number: "1234",
4205
+ //external_account_number: '1234',
4147
4206
  latest_balance_timestamp: {
4148
4207
  external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4149
4208
  external_account_source: "PLAID",
@@ -4152,13 +4211,19 @@ var MOCK_DATA = [
4152
4211
  created_at: "2024-04-06T16:44:35.715458Z"
4153
4212
  },
4154
4213
  current_ledger_balance: 373717,
4155
- institution: "Chase",
4156
- institutionLogo: ""
4214
+ institution: {
4215
+ name: "Chase",
4216
+ logo: ""
4217
+ }
4218
+ //connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',
4219
+ //connection_status: 'OK',
4157
4220
  },
4158
4221
  {
4159
4222
  id: "3",
4223
+ external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4224
+ external_account_source: "PLAID",
4160
4225
  external_account_name: "Citi Double Cash\xAE Card",
4161
- external_account_number: "1234",
4226
+ //external_account_number: '1234',
4162
4227
  latest_balance_timestamp: {
4163
4228
  external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4164
4229
  external_account_source: "PLAID",
@@ -4167,13 +4232,19 @@ var MOCK_DATA = [
4167
4232
  created_at: "2024-04-06T16:44:35.715458Z"
4168
4233
  },
4169
4234
  current_ledger_balance: 373717,
4170
- institution: "Chase",
4171
- institutionLogo: ""
4235
+ institution: {
4236
+ name: "Chase",
4237
+ logo: ""
4238
+ }
4239
+ //connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',
4240
+ //connection_status: 'OK',
4172
4241
  },
4173
4242
  {
4174
4243
  id: "4",
4244
+ external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4245
+ external_account_source: "PLAID",
4175
4246
  external_account_name: "Citi Double Cash\xAE Card",
4176
- external_account_number: "1234",
4247
+ //external_account_number: '1234',
4177
4248
  latest_balance_timestamp: {
4178
4249
  external_account_external_id: "0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq",
4179
4250
  external_account_source: "PLAID",
@@ -4182,14 +4253,25 @@ var MOCK_DATA = [
4182
4253
  created_at: "2024-04-06T16:44:35.715458Z"
4183
4254
  },
4184
4255
  current_ledger_balance: 373717,
4185
- institution: "Chase",
4186
- institutionLogo: ""
4256
+ institution: {
4257
+ name: "Chase",
4258
+ logo: ""
4259
+ }
4260
+ //connection_id: '0Br385JmgbTryJn8nEBnUb4A5ydv06U9Vbqqq',
4261
+ //connection_status: 'OK',
4187
4262
  }
4188
4263
  ];
4264
+
4265
+ // src/hooks/useLinkedAccounts/useLinkedAccounts.ts
4266
+ import useSWR4 from "swr";
4267
+ var DEBUG = true;
4268
+ var USE_MOCK_RESPONSE_DATA = false;
4269
+ var USE_PLAID_SANDBOX = true;
4189
4270
  var useLinkedAccounts = () => {
4190
4271
  const { auth, businessId, apiUrl } = useLayerContext();
4272
+ const [linkToken, setLinkToken] = useState11(null);
4191
4273
  const {
4192
- // data: responseData,
4274
+ data: responseData,
4193
4275
  isLoading,
4194
4276
  isValidating,
4195
4277
  error: responseError,
@@ -4200,27 +4282,80 @@ var useLinkedAccounts = () => {
4200
4282
  params: { businessId }
4201
4283
  })
4202
4284
  );
4203
- const responseData = { data: MOCK_DATA, meta: {}, error: void 0 };
4204
- const addAccount = () => {
4205
- console.log("add account...");
4285
+ useEffect8(() => {
4286
+ const getLinkToken = async () => {
4287
+ if (auth?.access_token) {
4288
+ const linkToken2 = (await Layer.getPlaidLinkToken(apiUrl, auth.access_token, {
4289
+ params: { businessId }
4290
+ })).data.link_token;
4291
+ setLinkToken(linkToken2);
4292
+ }
4293
+ };
4294
+ getLinkToken();
4295
+ }, [setLinkToken, auth?.access_token]);
4296
+ const exchangePublicToken = async (publicToken, metadata) => {
4297
+ await Layer.exchangePlaidPublicToken(apiUrl, auth?.access_token, {
4298
+ params: { businessId },
4299
+ body: { public_token: publicToken, institution_id: metadata.institution }
4300
+ });
4301
+ refetchAccounts();
4302
+ };
4303
+ const { open: plaidLinkStart, ready: plaidLinkReady } = usePlaidLink({
4304
+ token: linkToken,
4305
+ onSuccess: exchangePublicToken,
4306
+ env: USE_PLAID_SANDBOX ? "sandbox" : void 0
4307
+ });
4308
+ const mockResponseData = {
4309
+ data: LINKED_ACCOUNTS_MOCK_DATA,
4310
+ meta: {},
4311
+ error: void 0
4312
+ };
4313
+ const addConnection = (source) => {
4314
+ if (source === "PLAID") {
4315
+ linkPlaidItem();
4316
+ } else {
4317
+ console.error(`Connection with source ${source} not yet supported`);
4318
+ }
4319
+ };
4320
+ const removeConnection = (source, connectionId) => {
4321
+ if (source === "PLAID") {
4322
+ unlinkPlaidItem2(connectionId);
4323
+ } else {
4324
+ console.error(`Connection with source ${source} not yet supported`);
4325
+ }
4326
+ };
4327
+ const linkPlaidItem = async () => {
4328
+ DEBUG && console.log("add account...");
4329
+ console.log("plaidLinkReady", plaidLinkReady);
4330
+ plaidLinkReady && plaidLinkStart();
4331
+ };
4332
+ const unlinkPlaidItem2 = (plaidItemId) => {
4333
+ DEBUG && console.log("unlinking plaid item");
4334
+ Layer.unlinkPlaidItem(apiUrl, auth?.access_token, {
4335
+ params: { businessId, plaidItemId }
4336
+ });
4206
4337
  };
4207
- const unlinkAccount = () => {
4208
- console.log("unlink account...");
4338
+ const unlinkAccount = (plaidAccountId) => {
4339
+ DEBUG && console.log("unlinking account");
4340
+ Layer.unlinkPlaidAccount(apiUrl, auth?.access_token, {
4341
+ params: { businessId, accountId: plaidAccountId }
4342
+ });
4209
4343
  };
4210
4344
  const renewLinkAccount = () => {
4211
- console.log("relink account...");
4345
+ DEBUG && console.log("relink account...");
4212
4346
  };
4213
- const refetch = () => {
4214
- console.log("refetch...");
4347
+ const refetchAccounts = () => {
4348
+ DEBUG && console.log("refetching plaid accounts...");
4349
+ mutate();
4215
4350
  };
4216
4351
  return {
4217
- // data: responseData?.data.external_accounts,
4218
- data: responseData.data,
4352
+ data: USE_MOCK_RESPONSE_DATA ? mockResponseData.data : responseData?.data.external_accounts,
4219
4353
  isLoading,
4220
4354
  isValidating,
4221
4355
  error: responseError,
4222
- refetch,
4223
- addAccount,
4356
+ addConnection,
4357
+ removeConnection,
4358
+ refetchAccounts,
4224
4359
  unlinkAccount,
4225
4360
  renewLinkAccount
4226
4361
  };
@@ -4319,16 +4454,21 @@ var MoreVertical = ({ size = 18, ...props }) => {
4319
4454
  var MoreVertical_default = MoreVertical;
4320
4455
 
4321
4456
  // src/components/HoverMenu/HoverMenu.tsx
4322
- import React60, { useEffect as useEffect8, useRef as useRef12, useState as useState11 } from "react";
4457
+ import React60, { useEffect as useEffect9, useRef as useRef12, useState as useState12 } from "react";
4323
4458
  import classNames22 from "classnames";
4324
- var HoverMenu = ({ children, config }) => {
4325
- const [openMenu, setOpenMenu] = useState11(false);
4459
+ var HoverMenu = ({
4460
+ children,
4461
+ config,
4462
+ plaidItemId,
4463
+ accountId
4464
+ }) => {
4465
+ const [openMenu, setOpenMenu] = useState12(false);
4326
4466
  const hoverMenuRef = useRef12(null);
4327
4467
  const hoverMenuClassName = classNames22(
4328
4468
  "Layer__hover-menu",
4329
- openMenu && "--open"
4469
+ openMenu && "Layer__hover-menu--open"
4330
4470
  );
4331
- useEffect8(() => {
4471
+ useEffect9(() => {
4332
4472
  function handleClickOutside(event) {
4333
4473
  if (hoverMenuRef.current && !hoverMenuRef.current.contains(event.target)) {
4334
4474
  setOpenMenu(false);
@@ -4366,7 +4506,7 @@ var HoverMenu = ({ children, config }) => {
4366
4506
  "button",
4367
4507
  {
4368
4508
  className: "Layer__hover-menu__list-item-button",
4369
- onClick: () => item.action()
4509
+ onClick: () => item.action(plaidItemId, accountId)
4370
4510
  },
4371
4511
  item.name
4372
4512
  )
@@ -4377,9 +4517,19 @@ var HoverMenu = ({ children, config }) => {
4377
4517
  // src/components/LinkedAccountOptions/LinkedAccountOptions.tsx
4378
4518
  var LinkedAccountOptions = ({
4379
4519
  children,
4380
- config
4520
+ config,
4521
+ accountId,
4522
+ plaidItemId
4381
4523
  }) => {
4382
- return /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options" }, /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options-overlay" }, /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options-overlay-button" }, /* @__PURE__ */ React61.createElement(HoverMenu, { config }, /* @__PURE__ */ React61.createElement(MoreVertical_default, { size: 16 })))), children);
4524
+ return /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options" }, /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options-overlay" }, /* @__PURE__ */ React61.createElement("div", { className: "Layer__linked-accounts__options-overlay-button" }, /* @__PURE__ */ React61.createElement(
4525
+ HoverMenu,
4526
+ {
4527
+ config,
4528
+ accountId,
4529
+ plaidItemId
4530
+ },
4531
+ /* @__PURE__ */ React61.createElement(MoreVertical_default, { size: 16 })
4532
+ ))), children);
4383
4533
  };
4384
4534
 
4385
4535
  // src/components/LinkedAccountThumb/LinkedAccountThumb.tsx
@@ -4687,15 +4837,20 @@ var LinkedAccountThumb = ({
4687
4837
  "Layer__linked-account-thumb",
4688
4838
  asWidget && "--as-widget"
4689
4839
  );
4690
- return /* @__PURE__ */ React63.createElement("div", { className: linkedAccountThumbClassName }, /* @__PURE__ */ React63.createElement("div", { className: "topbar" }, /* @__PURE__ */ React63.createElement("div", { className: "topbar-details" }, /* @__PURE__ */ React63.createElement(Text, { as: "span", className: "account-name" }, account.external_account_name), !asWidget && /* @__PURE__ */ React63.createElement(AccountNumber, { accountNumber: account.external_account_number }), /* @__PURE__ */ React63.createElement(
4840
+ return /* @__PURE__ */ React63.createElement("div", { className: linkedAccountThumbClassName }, /* @__PURE__ */ React63.createElement("div", { className: "topbar" }, /* @__PURE__ */ React63.createElement("div", { className: "topbar-details" }, /* @__PURE__ */ React63.createElement(Text, { as: "span", className: "account-name" }, account.external_account_name), !asWidget && /* @__PURE__ */ React63.createElement(
4841
+ AccountNumber,
4842
+ {
4843
+ accountNumber: "TODO"
4844
+ }
4845
+ ), /* @__PURE__ */ React63.createElement(
4691
4846
  Text,
4692
4847
  {
4693
4848
  as: "span",
4694
4849
  className: "account-institution",
4695
4850
  size: "sm"
4696
4851
  },
4697
- account.institution
4698
- )), /* @__PURE__ */ React63.createElement("div", { className: "topbar-logo" }, !account.institutionLogo && /* @__PURE__ */ React63.createElement(InstitutionIcon_default, null))), !asWidget && /* @__PURE__ */ React63.createElement("div", { className: "middlebar" }, /* @__PURE__ */ React63.createElement(
4852
+ account.institution?.name
4853
+ )), /* @__PURE__ */ React63.createElement("div", { className: "topbar-logo" }, !account.institution?.logo && /* @__PURE__ */ React63.createElement(InstitutionIcon_default, null))), !asWidget && /* @__PURE__ */ React63.createElement("div", { className: "middlebar" }, /* @__PURE__ */ React63.createElement(
4699
4854
  Text,
4700
4855
  {
4701
4856
  as: "span",
@@ -4703,7 +4858,12 @@ var LinkedAccountThumb = ({
4703
4858
  size: "sm"
4704
4859
  },
4705
4860
  "Bank balance"
4706
- ), /* @__PURE__ */ React63.createElement(Text, { as: "span", className: "account-balance" }, "$", centsToDollars(account.latest_balance_timestamp.balance))), /* @__PURE__ */ React63.createElement("div", { className: "bottombar" }, asWidget ? /* @__PURE__ */ React63.createElement(AccountNumber, { accountNumber: account.external_account_number }) : /* @__PURE__ */ React63.createElement(
4861
+ ), /* @__PURE__ */ React63.createElement(Text, { as: "span", className: "account-balance" }, "$", centsToDollars(account.latest_balance_timestamp.balance))), /* @__PURE__ */ React63.createElement("div", { className: "bottombar" }, asWidget ? /* @__PURE__ */ React63.createElement(
4862
+ AccountNumber,
4863
+ {
4864
+ accountNumber: "TODO"
4865
+ }
4866
+ ) : /* @__PURE__ */ React63.createElement(
4707
4867
  Text,
4708
4868
  {
4709
4869
  as: "span",
@@ -4717,14 +4877,14 @@ var LinkedAccountThumb = ({
4717
4877
  // src/components/LinkedAccounts/LinkedAccounts.tsx
4718
4878
  import classNames24 from "classnames";
4719
4879
  var COMPONENT_NAME2 = "linked-accounts";
4720
- var LinkedAccounts = ({ asWidget }) => {
4880
+ var LinkedAccounts = ({ asWidget, elevated }) => {
4721
4881
  const {
4722
4882
  data,
4723
4883
  isLoading,
4724
4884
  error,
4725
4885
  isValidating,
4726
- refetch,
4727
- addAccount,
4886
+ refetchAccounts,
4887
+ addConnection,
4728
4888
  unlinkAccount,
4729
4889
  renewLinkAccount
4730
4890
  } = useLinkedAccounts();
@@ -4736,7 +4896,7 @@ var LinkedAccounts = ({ asWidget }) => {
4736
4896
  "Layer__linked-accounts__new-account",
4737
4897
  asWidget && "--as-widget"
4738
4898
  );
4739
- return /* @__PURE__ */ React64.createElement(Container, { name: COMPONENT_NAME2 }, /* @__PURE__ */ React64.createElement(Header, { className: "Layer__linked-accounts__header" }, /* @__PURE__ */ React64.createElement(
4899
+ return /* @__PURE__ */ React64.createElement(Container, { name: COMPONENT_NAME2, elevated }, /* @__PURE__ */ React64.createElement(Header, { className: "Layer__linked-accounts__header" }, /* @__PURE__ */ React64.createElement(
4740
4900
  Heading,
4741
4901
  {
4742
4902
  className: "Layer__linked-accounts__title",
@@ -4749,14 +4909,16 @@ var LinkedAccounts = ({ asWidget }) => {
4749
4909
  status: "failed" /* failed */,
4750
4910
  title: "Something went wrong",
4751
4911
  description: "We couldn\u2019t load your data.",
4752
- onRefresh: () => refetch(),
4912
+ onRefresh: () => refetchAccounts(),
4753
4913
  isLoading: isValidating
4754
4914
  }
4755
4915
  ) : null, !error && !isLoading ? /* @__PURE__ */ React64.createElement("div", { className: "Layer__linked-accounts__list" }, data?.map((account, index) => /* @__PURE__ */ React64.createElement(
4756
4916
  LinkedAccountOptions,
4757
4917
  {
4758
4918
  key: `linked-acc-${index}`,
4759
- config: linkedAccountOptionsConfig
4919
+ config: linkedAccountOptionsConfig,
4920
+ accountId: account.external_account_external_id,
4921
+ plaidItemId: "TODO"
4760
4922
  },
4761
4923
  /* @__PURE__ */ React64.createElement(LinkedAccountThumb, { account, asWidget })
4762
4924
  )), /* @__PURE__ */ React64.createElement(
@@ -4765,18 +4927,18 @@ var LinkedAccounts = ({ asWidget }) => {
4765
4927
  role: "button",
4766
4928
  tabIndex: 0,
4767
4929
  "aria-label": "new-account",
4768
- onClick: () => addAccount(),
4930
+ onClick: () => addConnection("PLAID"),
4769
4931
  className: linkedAccountsNewAccountClassName
4770
4932
  },
4771
- /* @__PURE__ */ React64.createElement("div", { className: "Layer__linked-accounts__new-account-label" }, /* @__PURE__ */ React64.createElement(PlusIcon_default, { size: 15 }), /* @__PURE__ */ React64.createElement(Text, { as: "span", size: "sm" }, "New account"))
4933
+ /* @__PURE__ */ React64.createElement("div", { className: "Layer__linked-accounts__new-account-label" }, /* @__PURE__ */ React64.createElement(PlusIcon_default, { size: 15 }), /* @__PURE__ */ React64.createElement(Text, { as: "span", size: "sm" }, "Add Account"))
4772
4934
  )) : null);
4773
4935
  };
4774
4936
 
4775
4937
  // src/components/ProfitAndLoss/ProfitAndLoss.tsx
4776
- import React74, { createContext as createContext2 } from "react";
4938
+ import React80, { createContext as createContext2 } from "react";
4777
4939
 
4778
4940
  // src/hooks/useProfitAndLoss/useProfitAndLoss.tsx
4779
- import { useMemo as useMemo3, useState as useState12 } from "react";
4941
+ import { useMemo as useMemo3, useState as useState13 } from "react";
4780
4942
 
4781
4943
  // src/utils/profitAndLossUtils.ts
4782
4944
  var doesLineItemQualifies = (item) => {
@@ -4844,17 +5006,17 @@ var useProfitAndLoss = ({
4844
5006
  endDate: endOfMonth(/* @__PURE__ */ new Date())
4845
5007
  }) => {
4846
5008
  const { auth, businessId, apiUrl } = useLayerContext();
4847
- const [startDate, setStartDate] = useState12(
5009
+ const [startDate, setStartDate] = useState13(
4848
5010
  initialStartDate || startOfMonth(Date.now())
4849
5011
  );
4850
- const [endDate, setEndDate] = useState12(
5012
+ const [endDate, setEndDate] = useState13(
4851
5013
  initialEndDate || endOfMonth(Date.now())
4852
5014
  );
4853
- const [filters, setFilters] = useState12({
5015
+ const [filters, setFilters] = useState13({
4854
5016
  expenses: void 0,
4855
5017
  revenue: void 0
4856
5018
  });
4857
- const [sidebarScope, setSidebarScope] = useState12(void 0);
5019
+ const [sidebarScope, setSidebarScope] = useState13(void 0);
4858
5020
  const {
4859
5021
  data: rawData,
4860
5022
  isLoading,
@@ -4877,13 +5039,50 @@ var useProfitAndLoss = ({
4877
5039
  })
4878
5040
  );
4879
5041
  const { data, error } = rawData || {};
4880
- const { filteredData, filteredTotal } = useMemo3(() => {
5042
+ const { filteredDataRevenue, filteredTotalRevenue } = useMemo3(() => {
5043
+ if (!data) {
5044
+ return { filteredDataRevenue: [], filteredTotalRevenue: void 0 };
5045
+ }
5046
+ const items = collectRevenueItems(data);
5047
+ const filtered = items.map((x) => {
5048
+ if (filters["revenue"]?.types && filters["revenue"].types.length > 0 && !filters["revenue"]?.types?.includes(x.type)) {
5049
+ return {
5050
+ ...x,
5051
+ hidden: true
5052
+ };
5053
+ }
5054
+ return x;
5055
+ });
5056
+ const sorted = filtered.sort((a, b) => {
5057
+ switch (filters["revenue"]?.sortBy) {
5058
+ case "category":
5059
+ if (filters["revenue"]?.sortDirection === "asc") {
5060
+ return a.display_name.localeCompare(b.display_name);
5061
+ }
5062
+ return b.display_name.localeCompare(a.display_name);
5063
+ case "type":
5064
+ if (filters["revenue"]?.sortDirection === "asc") {
5065
+ return a.type.localeCompare(b.type);
5066
+ }
5067
+ return b.type.localeCompare(a.type);
5068
+ default:
5069
+ if (filters["revenue"]?.sortDirection === "asc") {
5070
+ return a.value - b.value;
5071
+ }
5072
+ return b.value - a.value;
5073
+ }
5074
+ });
5075
+ const total = sorted.filter((x) => !x.hidden).reduce((x, { value }) => x + value, 0);
5076
+ const withShare = applyShare(sorted, total);
5077
+ return { filteredDataRevenue: withShare, filteredTotalRevenue: total };
5078
+ }, [data, startDate, filters, sidebarScope]);
5079
+ const { filteredDataExpenses, filteredTotalExpenses } = useMemo3(() => {
4881
5080
  if (!data) {
4882
- return { filteredData: [], filteredTotal: void 0 };
5081
+ return { filteredDataExpenses: [], filteredTotalExpenses: void 0 };
4883
5082
  }
4884
- const items = sidebarScope === "revenue" ? collectRevenueItems(data) : collectExpensesItems(data);
5083
+ const items = collectExpensesItems(data);
4885
5084
  const filtered = items.map((x) => {
4886
- if (sidebarScope && filters[sidebarScope]?.types && filters[sidebarScope].types.length > 0 && !filters[sidebarScope]?.types?.includes(x.type)) {
5085
+ if (filters["expenses"]?.types && filters["expenses"].types.length > 0 && !filters["expenses"]?.types?.includes(x.type)) {
4887
5086
  return {
4888
5087
  ...x,
4889
5088
  hidden: true
@@ -4892,19 +5091,19 @@ var useProfitAndLoss = ({
4892
5091
  return x;
4893
5092
  });
4894
5093
  const sorted = filtered.sort((a, b) => {
4895
- switch (filters[sidebarScope ?? "expenses"]?.sortBy) {
5094
+ switch (filters["expenses"]?.sortBy) {
4896
5095
  case "category":
4897
- if (filters[sidebarScope ?? "expenses"]?.sortDirection === "asc") {
5096
+ if (filters["expenses"]?.sortDirection === "asc") {
4898
5097
  return a.display_name.localeCompare(b.display_name);
4899
5098
  }
4900
5099
  return b.display_name.localeCompare(a.display_name);
4901
5100
  case "type":
4902
- if (filters[sidebarScope ?? "expenses"]?.sortDirection === "asc") {
5101
+ if (filters["expenses"]?.sortDirection === "asc") {
4903
5102
  return a.type.localeCompare(b.type);
4904
5103
  }
4905
5104
  return b.type.localeCompare(a.type);
4906
5105
  default:
4907
- if (filters[sidebarScope ?? "expenses"]?.sortDirection === "asc") {
5106
+ if (filters["expenses"]?.sortDirection === "asc") {
4908
5107
  return a.value - b.value;
4909
5108
  }
4910
5109
  return b.value - a.value;
@@ -4912,7 +5111,7 @@ var useProfitAndLoss = ({
4912
5111
  });
4913
5112
  const total = sorted.filter((x) => !x.hidden).reduce((x, { value }) => x + value, 0);
4914
5113
  const withShare = applyShare(sorted, total);
4915
- return { filteredData: withShare, filteredTotal: total };
5114
+ return { filteredDataExpenses: withShare, filteredTotalExpenses: total };
4916
5115
  }, [data, startDate, filters, sidebarScope]);
4917
5116
  const changeDateRange = ({
4918
5117
  startDate: newStartDate,
@@ -4945,8 +5144,10 @@ var useProfitAndLoss = ({
4945
5144
  };
4946
5145
  return {
4947
5146
  data,
4948
- filteredData,
4949
- filteredTotal,
5147
+ filteredDataRevenue,
5148
+ filteredTotalRevenue,
5149
+ filteredDataExpenses,
5150
+ filteredTotalExpenses,
4950
5151
  isLoading,
4951
5152
  isValidating,
4952
5153
  error: error || rawError,
@@ -4962,7 +5163,7 @@ var useProfitAndLoss = ({
4962
5163
  };
4963
5164
 
4964
5165
  // src/components/ProfitAndLossChart/ProfitAndLossChart.tsx
4965
- import React66, { useContext as useContext2, useMemo as useMemo4, useState as useState13 } from "react";
5166
+ import React66, { useContext as useContext2, useMemo as useMemo4, useState as useState14 } from "react";
4966
5167
 
4967
5168
  // src/utils/format.ts
4968
5169
  var capitalizeFirstLetter = (text) => text.charAt(0).toUpperCase() + text.slice(1);
@@ -4998,9 +5199,12 @@ var formatPercent = (value, options) => {
4998
5199
  ...options
4999
5200
  });
5000
5201
  };
5202
+ var humanizeEnum = (text) => {
5203
+ return capitalizeFirstLetter(text.replace(/_/gi, " ").toLowerCase());
5204
+ };
5001
5205
 
5002
5206
  // src/components/ProfitAndLossChart/Indicator.tsx
5003
- import React65, { useEffect as useEffect9 } from "react";
5207
+ import React65, { useEffect as useEffect10 } from "react";
5004
5208
  var emptyViewBox = { x: 0, y: 0, width: 0, height: 0 };
5005
5209
  var Indicator = ({
5006
5210
  viewBox = {},
@@ -5017,7 +5221,7 @@ var Indicator = ({
5017
5221
  const multiplier = width > 12 ? 1.2 : 1;
5018
5222
  const xOffset = (boxWidth * multiplier - boxWidth) / 2;
5019
5223
  const borderRadius = width > 16 ? 8 : width / 2;
5020
- useEffect9(() => {
5224
+ useEffect10(() => {
5021
5225
  setAnimateFrom(animateTo);
5022
5226
  }, [animateTo]);
5023
5227
  const actualX = animateFrom === -1 ? animateTo : animateFrom;
@@ -5187,7 +5391,7 @@ var ProfitAndLossChart = () => {
5187
5391
  ...monthData.map((m) => m?.net_profit)
5188
5392
  ]
5189
5393
  );
5190
- const [animateFrom, setAnimateFrom] = useState13(-1);
5394
+ const [animateFrom, setAnimateFrom] = useState14(-1);
5191
5395
  return /* @__PURE__ */ React66.createElement(
5192
5396
  ResponsiveContainer,
5193
5397
  {
@@ -5295,19 +5499,19 @@ var ProfitAndLossChart = () => {
5295
5499
  };
5296
5500
 
5297
5501
  // src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx
5298
- import React67, { useContext as useContext3, useState as useState14, useEffect as useEffect10 } from "react";
5502
+ import React67, { useContext as useContext3, useState as useState15, useEffect as useEffect11 } from "react";
5299
5503
  import { add, endOfMonth as endOfMonth3, format as format5, startOfMonth as startOfMonth3 } from "date-fns";
5300
5504
  var ProfitAndLossDatePicker = () => {
5301
5505
  const { changeDateRange, dateRange } = useContext3(ProfitAndLoss.Context);
5302
- const [isAnimating, setIsAnimating] = useState14(false);
5303
- const [localDate, setLocalDate] = useState14(dateRange.startDate);
5304
- const [nextOpacity, setNextOpacity] = useState14(0);
5305
- const [currentOpacity, setCurrentOpacity] = useState14(1);
5306
- const [transformStyle, setTransformStyle] = useState14({
5506
+ const [isAnimating, setIsAnimating] = useState15(false);
5507
+ const [localDate, setLocalDate] = useState15(dateRange.startDate);
5508
+ const [nextOpacity, setNextOpacity] = useState15(0);
5509
+ const [currentOpacity, setCurrentOpacity] = useState15(1);
5510
+ const [transformStyle, setTransformStyle] = useState15({
5307
5511
  transform: "translateX(33%)",
5308
5512
  transition: "ease"
5309
5513
  });
5310
- useEffect10(() => {
5514
+ useEffect11(() => {
5311
5515
  if (dateRange.startDate !== localDate && !isAnimating) {
5312
5516
  setLocalDate(dateRange.startDate);
5313
5517
  setTransformStyle({ transform: "translateX(33%)", transition: "none" });
@@ -5401,26 +5605,44 @@ var ProfitAndLossDatePicker = () => {
5401
5605
  );
5402
5606
  };
5403
5607
 
5404
- // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
5405
- import React70, { useContext as useContext4, useMemo as useMemo5 } from "react";
5608
+ // src/components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts.tsx
5609
+ import React73, { useContext as useContext4, useState as useState16 } from "react";
5406
5610
 
5407
- // src/components/SkeletonLoader/SkeletonLoader.tsx
5408
- import React68 from "react";
5409
- import classNames25 from "classnames";
5410
- var SkeletonLoader = ({
5411
- height,
5412
- width,
5413
- className
5414
- }) => {
5415
- const baseClassName = classNames25(
5416
- "Layer__skeleton-loader Layer__anim--skeleton-loading",
5417
- className
5418
- );
5419
- return /* @__PURE__ */ React68.createElement("div", { className: baseClassName, style: { width, height } });
5420
- };
5611
+ // src/icons/X.tsx
5612
+ import * as React68 from "react";
5613
+ var X = ({ size = 18, ...props }) => /* @__PURE__ */ React68.createElement(
5614
+ "svg",
5615
+ {
5616
+ xmlns: "http://www.w3.org/2000/svg",
5617
+ viewBox: "0 0 18 18",
5618
+ fill: "none",
5619
+ ...props,
5620
+ width: size,
5621
+ height: size
5622
+ },
5623
+ /* @__PURE__ */ React68.createElement(
5624
+ "path",
5625
+ {
5626
+ d: "M13.5 4.5L4.5 13.5",
5627
+ stroke: "currentColor",
5628
+ strokeLinecap: "round",
5629
+ strokeLinejoin: "round"
5630
+ }
5631
+ ),
5632
+ /* @__PURE__ */ React68.createElement(
5633
+ "path",
5634
+ {
5635
+ d: "M4.5 4.5L13.5 13.5",
5636
+ stroke: "currentColor",
5637
+ strokeLinecap: "round",
5638
+ strokeLinejoin: "round"
5639
+ }
5640
+ )
5641
+ );
5642
+ var X_default = X;
5421
5643
 
5422
- // src/components/ProfitAndLossSummaries/MiniChart.tsx
5423
- import React69 from "react";
5644
+ // src/components/ProfitAndLossDetailedCharts/DetailedChart.tsx
5645
+ import React69, { useMemo as useMemo5 } from "react";
5424
5646
 
5425
5647
  // src/config/charts.ts
5426
5648
  var INACTIVE_OPACITY_LEVELS = [
@@ -5508,912 +5730,1100 @@ var DEFAULT_CHART_COLORS = [
5508
5730
  }
5509
5731
  ];
5510
5732
 
5511
- // src/components/ProfitAndLossSummaries/MiniChart.tsx
5512
- import { PieChart, Pie, Cell as Cell2 } from "recharts";
5513
- var MiniChart = ({ data }) => {
5514
- return /* @__PURE__ */ React69.createElement(PieChart, { width: 48, height: 48, className: "mini-chart" }, /* @__PURE__ */ React69.createElement(
5733
+ // src/components/ProfitAndLossDetailedCharts/DetailedChart.tsx
5734
+ import {
5735
+ PieChart,
5736
+ Pie,
5737
+ Cell as Cell2,
5738
+ ResponsiveContainer as ResponsiveContainer2,
5739
+ Label,
5740
+ Text as ChartText
5741
+ } from "recharts";
5742
+ var DetailedChart = ({
5743
+ filteredData,
5744
+ filteredTotal,
5745
+ hoveredItem,
5746
+ setHoveredItem,
5747
+ sidebarScope,
5748
+ date,
5749
+ isLoading
5750
+ }) => {
5751
+ const chartData = useMemo5(() => {
5752
+ if (!filteredData) {
5753
+ return [];
5754
+ }
5755
+ return filteredData.map((x) => {
5756
+ if (x.hidden) {
5757
+ return {
5758
+ name: x.display_name,
5759
+ value: 0
5760
+ };
5761
+ }
5762
+ return {
5763
+ name: x.display_name,
5764
+ value: x.value
5765
+ };
5766
+ });
5767
+ }, [filteredData, isLoading]);
5768
+ const noValue = chartData.length === 0 || !chartData.find((x) => x.value !== 0);
5769
+ return /* @__PURE__ */ React69.createElement("div", { className: "chart-field" }, /* @__PURE__ */ React69.createElement("div", { className: "header--tablet" }, /* @__PURE__ */ React69.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, humanizeTitle(sidebarScope)), /* @__PURE__ */ React69.createElement(ProfitAndLossDatePicker, null)), /* @__PURE__ */ React69.createElement("div", { className: "chart-container" }, /* @__PURE__ */ React69.createElement(ResponsiveContainer2, null, /* @__PURE__ */ React69.createElement(PieChart, null, !isLoading && !noValue ? /* @__PURE__ */ React69.createElement(
5515
5770
  Pie,
5516
5771
  {
5517
- data,
5772
+ data: chartData,
5518
5773
  dataKey: "value",
5519
5774
  nameKey: "name",
5520
5775
  cx: "50%",
5521
5776
  cy: "50%",
5522
- innerRadius: 10,
5523
- outerRadius: 16,
5524
- paddingAngle: 0.2,
5777
+ innerRadius: 105,
5778
+ outerRadius: 120,
5779
+ paddingAngle: 0.5,
5525
5780
  fill: "#8884d8",
5526
- width: 24,
5527
- height: 24,
5528
- animationDuration: 250,
5781
+ animationDuration: 200,
5529
5782
  animationEasing: "ease-in-out"
5530
5783
  },
5531
- data.map((entry, index) => {
5784
+ chartData.map((entry, index) => {
5532
5785
  const colorConfig = DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length];
5786
+ let fill = colorConfig.color;
5787
+ let opacity = colorConfig.opacity;
5788
+ let active = true;
5789
+ if (hoveredItem && entry.name !== hoveredItem) {
5790
+ active = false;
5791
+ fill = void 0;
5792
+ opacity = INACTIVE_OPACITY_LEVELS[index % INACTIVE_OPACITY_LEVELS.length];
5793
+ }
5533
5794
  return /* @__PURE__ */ React69.createElement(
5534
5795
  Cell2,
5535
5796
  {
5536
5797
  key: `cell-${index}`,
5537
- className: `Layer__profit-and-loss-detailed-charts__pie`,
5538
- fill: entry.name === "placeholder" ? "#e6e6e6" : colorConfig.color,
5539
- opacity: colorConfig.opacity
5798
+ className: `Layer__profit-and-loss-detailed-charts__pie ${hoveredItem && active ? "active" : "inactive"}`,
5799
+ style: { fill },
5800
+ opacity,
5801
+ onMouseEnter: () => setHoveredItem(entry.name),
5802
+ onMouseLeave: () => setHoveredItem(void 0)
5540
5803
  }
5541
5804
  );
5542
- })
5543
- ));
5544
- };
5545
-
5546
- // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
5547
- import classNames26 from "classnames";
5548
- var CHART_PLACEHOLDER = [
5549
- {
5550
- name: "placeholder",
5551
- display_name: "placeholder",
5552
- value: 1,
5553
- type: "placeholder",
5554
- share: 1
5555
- }
5556
- ];
5557
- var buildMiniChartData = (scope, data) => {
5558
- if (!data) {
5559
- return CHART_PLACEHOLDER;
5560
- }
5561
- let items = [];
5562
- switch (scope) {
5563
- case "revenue":
5564
- items = collectRevenueItems(data);
5565
- break;
5566
- default:
5567
- items = collectExpensesItems(data);
5568
- }
5569
- if (!items || items.length === 0 || !items.find((x) => Math.abs(x.value) !== 0)) {
5570
- return CHART_PLACEHOLDER;
5571
- }
5572
- return items.slice();
5573
- };
5574
- var ProfitAndLossSummaries = ({
5575
- vertical,
5576
- revenueLabel = "Revenue"
5577
- }) => {
5578
- const {
5579
- data: storedData,
5580
- isLoading,
5581
- setSidebarScope,
5582
- sidebarScope
5583
- } = useContext4(ProfitAndLoss.Context);
5584
- const expensesChartData = useMemo5(() => {
5585
- return buildMiniChartData("expenses", storedData);
5586
- }, [storedData]);
5587
- const revenueChartData = useMemo5(() => {
5588
- return buildMiniChartData("revenue", storedData);
5589
- }, [storedData]);
5590
- const data = storedData ? storedData : { income: { value: NaN }, net_profit: NaN };
5591
- const incomeDirectionClass = (data.income.value ?? NaN) < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
5592
- const expensesDirectionClass = (data?.income?.value ?? NaN) - data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
5593
- const netProfitDirectionClass = data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
5594
- return /* @__PURE__ */ React70.createElement(
5595
- "div",
5596
- {
5597
- className: `Layer__profit-and-loss-summaries ${vertical ? "flex-col" : ""}`
5598
- },
5599
- /* @__PURE__ */ React70.createElement(
5600
- "div",
5805
+ }),
5806
+ /* @__PURE__ */ React69.createElement(
5807
+ Label,
5601
5808
  {
5602
- className: classNames26(
5603
- "Layer__profit-and-loss-summaries__summary Layer__actionable",
5604
- "Layer__profit-and-loss-summaries__summary--income",
5605
- sidebarScope === "revenue" ? "active" : ""
5606
- ),
5607
- onClick: () => setSidebarScope("revenue")
5608
- },
5609
- /* @__PURE__ */ React70.createElement(MiniChart, { data: revenueChartData }),
5610
- /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React70.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, revenueLabel), isLoading || storedData === void 0 ? /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React70.createElement(SkeletonLoader, null)) : /* @__PURE__ */ React70.createElement(
5611
- "span",
5612
- {
5613
- className: `Layer__profit-and-loss-summaries__amount ${incomeDirectionClass}`
5614
- },
5615
- centsToDollars(Math.abs(data?.income?.value ?? NaN))
5616
- ))
5809
+ position: "center",
5810
+ value: "Total",
5811
+ className: "pie-center-label-title",
5812
+ content: (props) => {
5813
+ const { cx, cy } = props.viewBox ?? {
5814
+ cx: 0,
5815
+ cy: 0
5816
+ };
5817
+ const positioningProps = {
5818
+ x: cx,
5819
+ y: (cy || 0) - 15,
5820
+ textAnchor: "middle",
5821
+ verticalAnchor: "middle"
5822
+ };
5823
+ let text = "Total";
5824
+ if (hoveredItem) {
5825
+ text = hoveredItem;
5826
+ }
5827
+ return /* @__PURE__ */ React69.createElement(
5828
+ ChartText,
5829
+ {
5830
+ ...positioningProps,
5831
+ className: "pie-center-label__title"
5832
+ },
5833
+ text
5834
+ );
5835
+ }
5836
+ }
5617
5837
  ),
5618
- /* @__PURE__ */ React70.createElement(
5619
- "div",
5838
+ /* @__PURE__ */ React69.createElement(
5839
+ Label,
5620
5840
  {
5621
- className: classNames26(
5622
- "Layer__profit-and-loss-summaries__summary Layer__actionable",
5623
- "Layer__profit-and-loss-summaries__summary--expenses",
5624
- sidebarScope === "expenses" ? "active" : ""
5625
- ),
5626
- onClick: () => setSidebarScope("expenses")
5627
- },
5628
- /* @__PURE__ */ React70.createElement(MiniChart, { data: expensesChartData }),
5629
- /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React70.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Expenses"), isLoading || storedData === void 0 ? /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React70.createElement(SkeletonLoader, { className: "Layer__profit-and-loss-summaries__loader" })) : /* @__PURE__ */ React70.createElement(
5630
- "span",
5631
- {
5632
- className: `Layer__profit-and-loss-summaries__amount ${expensesDirectionClass}`
5633
- },
5634
- centsToDollars(
5635
- Math.abs((data.income.value ?? 0) - data.net_profit)
5636
- )
5637
- ))
5841
+ position: "center",
5842
+ value: "Total",
5843
+ className: "pie-center-label-title",
5844
+ content: (props) => {
5845
+ const { cx, cy } = props.viewBox ?? {
5846
+ cx: 0,
5847
+ cy: 0
5848
+ };
5849
+ const positioningProps = {
5850
+ x: cx,
5851
+ y: (cy || 0) + 5,
5852
+ textAnchor: "middle",
5853
+ verticalAnchor: "middle"
5854
+ };
5855
+ let value = filteredTotal;
5856
+ if (hoveredItem) {
5857
+ value = filteredData.find(
5858
+ (x) => x.display_name === hoveredItem
5859
+ )?.value;
5860
+ }
5861
+ return /* @__PURE__ */ React69.createElement(
5862
+ ChartText,
5863
+ {
5864
+ ...positioningProps,
5865
+ className: "pie-center-label__value"
5866
+ },
5867
+ `$${centsToDollars(value)}`
5868
+ );
5869
+ }
5870
+ }
5638
5871
  ),
5639
- /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__summary net-profit Layer__profit-and-loss-summaries__summary--net-profit" }, /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React70.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Net Profit"), isLoading || storedData === void 0 ? /* @__PURE__ */ React70.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React70.createElement(SkeletonLoader, { className: "Layer__profit-and-loss-summaries__loader" })) : /* @__PURE__ */ React70.createElement(
5640
- "span",
5872
+ /* @__PURE__ */ React69.createElement(
5873
+ Label,
5641
5874
  {
5642
- className: `Layer__profit-and-loss-summaries__amount ${netProfitDirectionClass}`
5643
- },
5644
- centsToDollars(Math.abs(data.net_profit))
5645
- )))
5646
- );
5875
+ position: "center",
5876
+ value: "Total",
5877
+ className: "pie-center-label-title",
5878
+ content: (props) => {
5879
+ const { cx, cy } = props.viewBox ?? {
5880
+ cx: 0,
5881
+ cy: 0
5882
+ };
5883
+ const positioningProps = {
5884
+ x: cx,
5885
+ y: (cy || 0) + 25,
5886
+ height: 20,
5887
+ textAnchor: "middle",
5888
+ verticalAnchor: "middle"
5889
+ };
5890
+ if (hoveredItem) {
5891
+ return /* @__PURE__ */ React69.createElement(
5892
+ ChartText,
5893
+ {
5894
+ ...positioningProps,
5895
+ className: "pie-center-label__share"
5896
+ },
5897
+ `${formatPercent(
5898
+ filteredData.find(
5899
+ (x) => x.display_name === hoveredItem
5900
+ )?.share
5901
+ )}%`
5902
+ );
5903
+ }
5904
+ return;
5905
+ }
5906
+ }
5907
+ )
5908
+ ) : null, !isLoading && noValue ? /* @__PURE__ */ React69.createElement(
5909
+ Pie,
5910
+ {
5911
+ data: [{ name: "Total", value: 1 }],
5912
+ dataKey: "value",
5913
+ nameKey: "name",
5914
+ cx: "50%",
5915
+ cy: "50%",
5916
+ innerRadius: 105,
5917
+ outerRadius: 120,
5918
+ paddingAngle: 0,
5919
+ fill: "#F8F8FA",
5920
+ animationDuration: 200,
5921
+ animationEasing: "ease-in-out"
5922
+ },
5923
+ /* @__PURE__ */ React69.createElement(
5924
+ Label,
5925
+ {
5926
+ position: "center",
5927
+ value: "Total",
5928
+ className: "pie-center-label-title",
5929
+ content: (props) => {
5930
+ const { cx, cy } = props.viewBox ?? {
5931
+ cx: 0,
5932
+ cy: 0
5933
+ };
5934
+ const positioningProps = {
5935
+ x: cx,
5936
+ y: (cy || 0) - 15,
5937
+ textAnchor: "middle",
5938
+ verticalAnchor: "middle"
5939
+ };
5940
+ let text = "Total";
5941
+ if (hoveredItem) {
5942
+ text = hoveredItem;
5943
+ }
5944
+ return /* @__PURE__ */ React69.createElement(
5945
+ ChartText,
5946
+ {
5947
+ ...positioningProps,
5948
+ className: "pie-center-label__title"
5949
+ },
5950
+ text
5951
+ );
5952
+ }
5953
+ }
5954
+ ),
5955
+ /* @__PURE__ */ React69.createElement(
5956
+ Label,
5957
+ {
5958
+ position: "center",
5959
+ value: "Total",
5960
+ className: "pie-center-label-title",
5961
+ content: (props) => {
5962
+ const { cx, cy } = props.viewBox ?? {
5963
+ cx: 0,
5964
+ cy: 0
5965
+ };
5966
+ const positioningProps = {
5967
+ x: cx,
5968
+ y: (cy || 0) + 5,
5969
+ textAnchor: "middle",
5970
+ verticalAnchor: "middle"
5971
+ };
5972
+ let value = filteredTotal;
5973
+ if (hoveredItem) {
5974
+ value = filteredData.find(
5975
+ (x) => x.display_name === hoveredItem
5976
+ )?.value;
5977
+ }
5978
+ return /* @__PURE__ */ React69.createElement(
5979
+ ChartText,
5980
+ {
5981
+ ...positioningProps,
5982
+ className: "pie-center-label__value"
5983
+ },
5984
+ `$${centsToDollars(value)}`
5985
+ );
5986
+ }
5987
+ }
5988
+ )
5989
+ ) : null, isLoading ? /* @__PURE__ */ React69.createElement(
5990
+ Pie,
5991
+ {
5992
+ data: [{ name: "loading...", value: 1 }],
5993
+ dataKey: "value",
5994
+ nameKey: "name",
5995
+ cx: "50%",
5996
+ cy: "50%",
5997
+ innerRadius: 105,
5998
+ outerRadius: 120,
5999
+ paddingAngle: 0,
6000
+ fill: "#F8F8FA",
6001
+ animationDuration: 200,
6002
+ animationEasing: "ease-in-out"
6003
+ }
6004
+ ) : null))));
5647
6005
  };
5648
6006
 
5649
- // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
5650
- import React73, { useContext as useContext5 } from "react";
5651
-
5652
- // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
5653
- import React72, { useState as useState15 } from "react";
6007
+ // src/components/ProfitAndLossDetailedCharts/DetailedTable.tsx
6008
+ import React71 from "react";
5654
6009
 
5655
- // src/icons/PieChart.tsx
5656
- import * as React71 from "react";
5657
- var PieChart2 = ({ size = 12, ...props }) => /* @__PURE__ */ React71.createElement(
6010
+ // src/icons/SortArrows.tsx
6011
+ import * as React70 from "react";
6012
+ var SortArrows = ({ size = 13, ...props }) => /* @__PURE__ */ React70.createElement(
5658
6013
  "svg",
5659
6014
  {
5660
6015
  xmlns: "http://www.w3.org/2000/svg",
5661
- viewBox: "0 0 12 12",
6016
+ viewBox: "0 0 12 13",
5662
6017
  fill: "none",
5663
6018
  ...props,
5664
6019
  width: size,
5665
6020
  height: size
5666
6021
  },
5667
- /* @__PURE__ */ React71.createElement("g", null, /* @__PURE__ */ React71.createElement(
6022
+ /* @__PURE__ */ React70.createElement("g", { "clip-path": "url(#clip0_1758_75388)" }, /* @__PURE__ */ React70.createElement(
5668
6023
  "path",
5669
6024
  {
5670
- d: "M10.2213 7.78271C9.92969 8.47226 9.47363 9.07989 8.89297 9.55247C8.3123 10.0251 7.62471 10.3482 6.89031 10.4936C6.1559 10.6391 5.39705 10.6024 4.68009 10.3869C3.96313 10.1713 3.30989 9.78337 2.77749 9.25701C2.24509 8.73065 1.84973 8.08189 1.62598 7.36744C1.40223 6.65298 1.3569 5.8946 1.49396 5.15858C1.63102 4.42257 1.94629 3.73133 2.41221 3.14531C2.87813 2.55928 3.48051 2.09631 4.16669 1.79688",
6025
+ d: "M1.33325 8.5L3.99992 11.1667L6.66659 8.5",
5671
6026
  stroke: "currentColor",
5672
6027
  strokeLinecap: "round",
5673
- strokeLinejoin: "round"
6028
+ strokeLinejoin: "round",
6029
+ className: "desc-arrow"
5674
6030
  }
5675
- ), /* @__PURE__ */ React71.createElement(
6031
+ ), /* @__PURE__ */ React70.createElement(
5676
6032
  "path",
5677
6033
  {
5678
- d: "M10.5833 6.00033C10.5833 5.39843 10.4648 4.80244 10.2344 4.24636C10.0041 3.69028 9.66651 3.18502 9.24091 2.75942C8.8153 2.33382 8.31004 1.99621 7.75397 1.76588C7.19789 1.53554 6.60189 1.41699 6 1.41699V6.00033H10.5833Z",
6034
+ d: "M4 2.5L4 11.1667",
5679
6035
  stroke: "currentColor",
5680
6036
  strokeLinecap: "round",
5681
- strokeLinejoin: "round"
6037
+ strokeLinejoin: "round",
6038
+ className: "desc-arrow"
5682
6039
  }
5683
- ))
6040
+ ), /* @__PURE__ */ React70.createElement(
6041
+ "path",
6042
+ {
6043
+ d: "M5.99988 5.16602L8.66654 2.49935L11.3332 5.16602",
6044
+ stroke: "currentColor",
6045
+ strokeLinecap: "round",
6046
+ strokeLinejoin: "round",
6047
+ className: "asc-arrow"
6048
+ }
6049
+ ), /* @__PURE__ */ React70.createElement(
6050
+ "path",
6051
+ {
6052
+ d: "M8.66663 11.166L8.66663 2.49935",
6053
+ stroke: "currentColor",
6054
+ strokeLinecap: "round",
6055
+ strokeLinejoin: "round",
6056
+ className: "asc-arrow"
6057
+ }
6058
+ )),
6059
+ /* @__PURE__ */ React70.createElement("defs", null, /* @__PURE__ */ React70.createElement("clipPath", { id: "clip0_1758_75388" }, /* @__PURE__ */ React70.createElement(
6060
+ "rect",
6061
+ {
6062
+ width: "12",
6063
+ height: "12",
6064
+ fill: "white",
6065
+ transform: "translate(0 0.5)"
6066
+ }
6067
+ )))
5684
6068
  );
5685
- var PieChart_default = PieChart2;
6069
+ var SortArrows_default = SortArrows;
5686
6070
 
5687
- // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
5688
- var ProfitAndLossRow = ({
5689
- variant,
5690
- lineItem,
5691
- depth = 0,
5692
- maxDepth = 1,
5693
- direction = "DEBIT" /* DEBIT */,
5694
- lockExpanded = false,
5695
- scope,
5696
- setSidebarScope
5697
- }) => {
5698
- if (!lineItem) {
5699
- return null;
5700
- }
5701
- const { value, display_name, line_items } = lineItem;
5702
- const [expanded, setExpanded] = useState15(true);
5703
- const amount = value ?? 0;
5704
- const amountString = centsToDollars(Math.abs(amount));
5705
- const labelClasses = [
5706
- "Layer__profit-and-loss-row",
5707
- "Layer__profit-and-loss-row__label"
5708
- ];
5709
- const valueClasses = [
5710
- "Layer__profit-and-loss-row",
5711
- "Layer__profit-and-loss-row__value"
5712
- ];
5713
- const positive = amount === 0 || direction === "CREDIT" /* CREDIT */ && amount > 0 || direction === "DEBIT" /* DEBIT */ && amount < 0;
5714
- valueClasses.push(
5715
- positive ? "Layer__profit-and-loss-row__value--amount-positive" : "Layer__profit-and-loss-row__value--amount-negative"
5716
- );
5717
- labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`);
5718
- valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`);
5719
- variant && labelClasses.push(`Layer__profit-and-loss-row__label--variant-${variant}`);
5720
- variant && valueClasses.push(`Layer__profit-and-loss-row__value--variant-${variant}`);
5721
- const toggleExpanded = () => setExpanded(!expanded);
5722
- const canGoDeeper = depth < maxDepth;
5723
- const hasChildren = (line_items?.length ?? 0) > 0;
5724
- const displayChildren = hasChildren && canGoDeeper;
5725
- labelClasses.push(
5726
- `Layer__profit-and-loss-row__label--display-children-${displayChildren}`
5727
- );
5728
- valueClasses.push(
5729
- `Layer__profit-and-loss-row__value--display-children-${displayChildren}`
5730
- );
5731
- displayChildren && expanded && labelClasses.push("Layer__profit-and-loss-row__label--expanded");
5732
- displayChildren && expanded && valueClasses.push("Layer__profit-and-loss-row__value--expanded");
5733
- return /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement(
5734
- "div",
6071
+ // src/components/ProfitAndLossDetailedCharts/DetailedTable.tsx
6072
+ import classNames25 from "classnames";
6073
+ var DetailedTable = ({
6074
+ filteredData,
6075
+ sidebarScope,
6076
+ filters,
6077
+ sortBy,
6078
+ hoveredItem,
6079
+ setHoveredItem
6080
+ }) => {
6081
+ const buildColClass = (column) => {
6082
+ return classNames25(
6083
+ "Layer__sortable-col",
6084
+ sidebarScope && filters[sidebarScope]?.sortBy === column ? `sort--${(sidebarScope && filters[sidebarScope]?.sortDirection) ?? "desc"}` : ""
6085
+ );
6086
+ };
6087
+ return /* @__PURE__ */ React71.createElement("div", { className: "details-container" }, /* @__PURE__ */ React71.createElement("div", { className: "table" }, /* @__PURE__ */ React71.createElement("table", null, /* @__PURE__ */ React71.createElement("thead", null, /* @__PURE__ */ React71.createElement("tr", null, /* @__PURE__ */ React71.createElement(
6088
+ "th",
5735
6089
  {
5736
- className: labelClasses.join(" "),
5737
- onClick: () => !lockExpanded && toggleExpanded()
6090
+ className: buildColClass("category"),
6091
+ onClick: () => sortBy(sidebarScope ?? "expenses", "category")
5738
6092
  },
5739
- /* @__PURE__ */ React72.createElement("span", { className: "Layer__profit-and-loss-row__label__title" }, !lockExpanded && variant !== "summation" ? /* @__PURE__ */ React72.createElement(
5740
- ChevronDownFill_default,
5741
- {
5742
- size: 16,
5743
- className: "Layer__profit-and-loss-row__label__chevron"
5744
- }
5745
- ) : null, /* @__PURE__ */ React72.createElement(Text, null, display_name)),
5746
- setSidebarScope && /* @__PURE__ */ React72.createElement(
5747
- "span",
5748
- {
5749
- className: "Layer__profit-and-loss-row__detailed-chart-btn",
5750
- onClick: (e) => {
5751
- e.stopPropagation();
5752
- setSidebarScope && setSidebarScope(scope ?? "expenses");
5753
- }
5754
- },
5755
- /* @__PURE__ */ React72.createElement(PieChart_default, null)
5756
- )
5757
- ), /* @__PURE__ */ React72.createElement("div", { className: valueClasses.join(" ") }, /* @__PURE__ */ React72.createElement(Text, null, amountString)), canGoDeeper && hasChildren && /* @__PURE__ */ React72.createElement(
5758
- "div",
6093
+ "Expense/Sale ",
6094
+ /* @__PURE__ */ React71.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6095
+ ), /* @__PURE__ */ React71.createElement(
6096
+ "th",
5759
6097
  {
5760
- className: `Layer__profit-and-loss-row__children ${expanded && "Layer__profit-and-loss-row__children--expanded"}`
6098
+ className: buildColClass("type"),
6099
+ onClick: () => sortBy(sidebarScope ?? "expenses", "type")
5761
6100
  },
5762
- /* @__PURE__ */ React72.createElement("div", { className: "Layer__profit-and-loss-row__children--content" }, (line_items || []).map((line_item) => /* @__PURE__ */ React72.createElement(
5763
- ProfitAndLossRow,
6101
+ "Type ",
6102
+ /* @__PURE__ */ React71.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6103
+ ), /* @__PURE__ */ React71.createElement("th", null), /* @__PURE__ */ React71.createElement(
6104
+ "th",
6105
+ {
6106
+ className: buildColClass("value"),
6107
+ onClick: () => sortBy(sidebarScope ?? "expenses", "value")
6108
+ },
6109
+ "Value ",
6110
+ /* @__PURE__ */ React71.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6111
+ ))), /* @__PURE__ */ React71.createElement("tbody", null, filteredData.filter((x) => !x.hidden).map((item, idx) => {
6112
+ const colorConfig = DEFAULT_CHART_COLORS[idx % DEFAULT_CHART_COLORS.length];
6113
+ return /* @__PURE__ */ React71.createElement(
6114
+ "tr",
5764
6115
  {
5765
- key: line_item.display_name,
5766
- lineItem: line_item,
5767
- depth: depth + 1,
5768
- maxDepth,
5769
- direction
5770
- }
5771
- )))
5772
- ));
6116
+ key: `pl-side-table-item-${idx}`,
6117
+ className: classNames25(
6118
+ "Layer__profit-and-loss-detailed-table__row",
6119
+ hoveredItem && hoveredItem === item.display_name ? "active" : ""
6120
+ ),
6121
+ onMouseEnter: () => setHoveredItem(item.display_name),
6122
+ onMouseLeave: () => setHoveredItem(void 0)
6123
+ },
6124
+ /* @__PURE__ */ React71.createElement("td", { className: "category-col" }, item.display_name),
6125
+ /* @__PURE__ */ React71.createElement("td", { className: "type-col" }, item.type),
6126
+ /* @__PURE__ */ React71.createElement("td", { className: "value-col" }, "$", centsToDollars(item.value)),
6127
+ /* @__PURE__ */ React71.createElement("td", { className: "share-col" }, /* @__PURE__ */ React71.createElement("span", { className: "share-cell-content" }, formatPercent(item.share), "%", /* @__PURE__ */ React71.createElement(
6128
+ "div",
6129
+ {
6130
+ className: "share-icon",
6131
+ style: {
6132
+ background: colorConfig.color,
6133
+ opacity: colorConfig.opacity
6134
+ }
6135
+ }
6136
+ )))
6137
+ );
6138
+ })))));
5773
6139
  };
5774
6140
 
5775
- // src/components/ProfitAndLossTable/empty_profit_and_loss_report.ts
5776
- var empty_profit_and_loss_report_default = {
5777
- type: "Profit_And_Loss",
5778
- business_id: "",
5779
- start_date: "",
5780
- end_date: "",
5781
- income: {
5782
- name: "INCOME",
5783
- display_name: "Income",
5784
- value: NaN,
5785
- line_items: null
5786
- },
5787
- cost_of_goods_sold: {
5788
- display_name: "Cost of Goods Sold",
5789
- name: "COGS",
5790
- value: NaN,
5791
- line_items: null
5792
- },
5793
- gross_profit: NaN,
5794
- expenses: {
5795
- name: "EXPENSES",
5796
- display_name: "Expenses",
5797
- value: NaN,
5798
- line_items: null
5799
- },
5800
- profit_before_taxes: NaN,
5801
- taxes: {
5802
- name: "TAXES",
5803
- display_name: "Taxes",
5804
- value: NaN,
5805
- line_items: null
5806
- },
5807
- net_profit: NaN,
5808
- other_outflows: {
5809
- name: "OTHER_OUTFLOWS",
5810
- display_name: "Other outflows",
5811
- value: NaN,
5812
- line_items: null
5813
- },
5814
- personal_expenses: {
5815
- name: "PERSONAL",
5816
- display_name: "Personal expenses",
5817
- value: NaN,
5818
- line_items: null
5819
- },
5820
- fully_categorized: false
6141
+ // src/components/ProfitAndLossDetailedCharts/Filters.tsx
6142
+ import React72 from "react";
6143
+ import Select3, { components as components3 } from "react-select";
6144
+ var Filters = ({
6145
+ filteredData,
6146
+ sidebarScope,
6147
+ filters,
6148
+ setFilterTypes
6149
+ }) => {
6150
+ return /* @__PURE__ */ React72.createElement("div", { className: "filters" }, /* @__PURE__ */ React72.createElement(Text, { size: "sm" /* sm */, className: "Layer__label" }, "Filters"), /* @__PURE__ */ React72.createElement(
6151
+ Select3,
6152
+ {
6153
+ className: "Layer__select type-select",
6154
+ classNamePrefix: "Layer__select",
6155
+ value: sidebarScope && filters[sidebarScope]?.types ? sidebarScope && filters[sidebarScope]?.types?.map((x) => ({
6156
+ value: x,
6157
+ label: x
6158
+ })) : [],
6159
+ isMulti: true,
6160
+ isClearable: false,
6161
+ options: [...new Set(filteredData?.map((x) => x.type))].map((x) => ({
6162
+ label: x,
6163
+ value: x
6164
+ })),
6165
+ onChange: (selected) => {
6166
+ setFilterTypes(
6167
+ sidebarScope ?? "expenses",
6168
+ selected.map((x) => x.value)
6169
+ );
6170
+ },
6171
+ components: {
6172
+ DropdownIndicator: (props) => /* @__PURE__ */ React72.createElement(components3.DropdownIndicator, { ...props }, /* @__PURE__ */ React72.createElement(ChevronDown_default, null)),
6173
+ Placeholder: (props) => /* @__PURE__ */ React72.createElement(components3.Placeholder, { ...props }, /* @__PURE__ */ React72.createElement("div", { className: "Layer__select__multi-all-placeholder-badge" }, "All"))
6174
+ }
6175
+ }
6176
+ ));
5821
6177
  };
5822
6178
 
5823
- // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
5824
- var ProfitAndLossTable = ({ lockExpanded }) => {
6179
+ // src/components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts.tsx
6180
+ import { format as format6 } from "date-fns";
6181
+ var ProfitAndLossDetailedCharts = ({
6182
+ scope,
6183
+ hideClose = false,
6184
+ showDatePicker = false
6185
+ }) => {
5825
6186
  const {
5826
- data: actualData,
6187
+ filteredDataRevenue,
6188
+ filteredTotalRevenue,
6189
+ filteredDataExpenses,
6190
+ filteredTotalExpenses,
6191
+ sortBy,
5827
6192
  isLoading,
5828
- setSidebarScope
5829
- } = useContext5(ProfitAndLoss.Context);
5830
- const data = !actualData || isLoading ? empty_profit_and_loss_report_default : actualData;
5831
- if (isLoading || actualData === void 0) {
5832
- return /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-table__loader-container" }, /* @__PURE__ */ React73.createElement(Loader2, null));
5833
- }
5834
- return /* @__PURE__ */ React73.createElement(React73.Fragment, null, /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-table Layer__profit-and-loss-table--main" }, /* @__PURE__ */ React73.createElement(
5835
- ProfitAndLossRow,
5836
- {
5837
- lineItem: data.income,
5838
- direction: "CREDIT" /* CREDIT */,
5839
- lockExpanded,
5840
- scope: "revenue",
5841
- setSidebarScope
5842
- }
5843
- ), /* @__PURE__ */ React73.createElement(
5844
- ProfitAndLossRow,
5845
- {
5846
- lineItem: data.cost_of_goods_sold,
5847
- direction: "DEBIT" /* DEBIT */,
5848
- lockExpanded,
5849
- scope: "expenses",
5850
- setSidebarScope
5851
- }
5852
- ), /* @__PURE__ */ React73.createElement(
5853
- ProfitAndLossRow,
5854
- {
5855
- lineItem: {
5856
- value: data.gross_profit,
5857
- display_name: "Gross Profit"
5858
- },
5859
- variant: "summation",
5860
- direction: "CREDIT" /* CREDIT */,
5861
- lockExpanded,
5862
- scope: "revenue",
5863
- setSidebarScope
5864
- }
5865
- ), /* @__PURE__ */ React73.createElement(
5866
- ProfitAndLossRow,
5867
- {
5868
- lineItem: data.expenses,
5869
- direction: "DEBIT" /* DEBIT */,
5870
- lockExpanded,
5871
- scope: "expenses",
5872
- setSidebarScope
5873
- }
5874
- ), /* @__PURE__ */ React73.createElement(
5875
- ProfitAndLossRow,
5876
- {
5877
- lineItem: {
5878
- value: data.profit_before_taxes,
5879
- display_name: "Profit Before Taxes"
5880
- },
5881
- variant: "summation",
5882
- direction: "CREDIT" /* CREDIT */,
5883
- lockExpanded,
5884
- scope: "revenue",
5885
- setSidebarScope
5886
- }
5887
- ), /* @__PURE__ */ React73.createElement(
5888
- ProfitAndLossRow,
6193
+ filters,
6194
+ dateRange,
6195
+ sidebarScope,
6196
+ setSidebarScope,
6197
+ setFilterTypes
6198
+ } = useContext4(ProfitAndLoss.Context);
6199
+ const theScope = scope ? scope : sidebarScope;
6200
+ const data = theScope === "revenue" ? filteredDataRevenue : filteredDataExpenses;
6201
+ const total = theScope === "revenue" ? filteredTotalRevenue : filteredTotalExpenses;
6202
+ const [hoveredItem, setHoveredItem] = useState16();
6203
+ return /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-detailed-charts" }, /* @__PURE__ */ React73.createElement("header", { className: "Layer__profit-and-loss-detailed-charts__header" }, /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__head" }, /* @__PURE__ */ React73.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, humanizeTitle(theScope)), /* @__PURE__ */ React73.createElement(Text, { size: "sm" /* sm */, className: "date" }, format6(dateRange.startDate, "LLLL, y")), showDatePicker && /* @__PURE__ */ React73.createElement(ProfitAndLossDatePicker, null)), !hideClose && /* @__PURE__ */ React73.createElement(
6204
+ Button,
5889
6205
  {
5890
- lineItem: data.taxes,
5891
- direction: "DEBIT" /* DEBIT */,
5892
- lockExpanded,
5893
- scope: "expenses",
5894
- setSidebarScope
6206
+ rightIcon: /* @__PURE__ */ React73.createElement(X_default, null),
6207
+ iconOnly: true,
6208
+ onClick: () => setSidebarScope(void 0),
6209
+ variant: "secondary" /* secondary */
5895
6210
  }
5896
- ), /* @__PURE__ */ React73.createElement(
5897
- ProfitAndLossRow,
6211
+ )), /* @__PURE__ */ React73.createElement("header", { className: "Layer__profit-and-loss-detailed-charts__header--tablet" }, /* @__PURE__ */ React73.createElement(BackButton, { onClick: () => setSidebarScope(void 0) })), /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__content" }, /* @__PURE__ */ React73.createElement(
6212
+ DetailedChart,
5898
6213
  {
5899
- lineItem: {
5900
- value: data.net_profit,
5901
- display_name: "Net Profit"
5902
- },
5903
- variant: "summation",
5904
- direction: "CREDIT" /* CREDIT */,
5905
- lockExpanded
6214
+ filteredData: data,
6215
+ filteredTotal: total,
6216
+ hoveredItem,
6217
+ setHoveredItem,
6218
+ sidebarScope: theScope,
6219
+ date: dateRange.startDate,
6220
+ isLoading
5906
6221
  }
5907
- )), data.other_outflows || data.personal_expenses ? /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-table Layer__profit-and-loss-table__outflows" }, /* @__PURE__ */ React73.createElement(
5908
- ProfitAndLossRow,
6222
+ ), /* @__PURE__ */ React73.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__table-wrapper" }, /* @__PURE__ */ React73.createElement(
6223
+ Filters,
5909
6224
  {
5910
- lineItem: data.other_outflows,
5911
- direction: "DEBIT" /* DEBIT */,
5912
- lockExpanded
6225
+ filteredData: data,
6226
+ sidebarScope: theScope,
6227
+ filters,
6228
+ setFilterTypes
5913
6229
  }
5914
6230
  ), /* @__PURE__ */ React73.createElement(
5915
- ProfitAndLossRow,
6231
+ DetailedTable,
5916
6232
  {
5917
- lineItem: data.personal_expenses,
5918
- direction: "DEBIT" /* DEBIT */,
5919
- lockExpanded
6233
+ filteredData: data,
6234
+ sidebarScope: theScope,
6235
+ filters,
6236
+ sortBy,
6237
+ hoveredItem,
6238
+ setHoveredItem
5920
6239
  }
5921
- )) : null);
6240
+ ))));
5922
6241
  };
5923
6242
 
5924
- // src/components/ProfitAndLoss/ProfitAndLoss.tsx
5925
- import { endOfMonth as endOfMonth4, startOfMonth as startOfMonth4 } from "date-fns";
5926
- var PNLContext = createContext2({
5927
- data: void 0,
5928
- filteredData: [],
5929
- filteredTotal: void 0,
5930
- isLoading: true,
5931
- isValidating: false,
5932
- error: void 0,
5933
- dateRange: {
5934
- startDate: startOfMonth4(/* @__PURE__ */ new Date()),
5935
- endDate: endOfMonth4(/* @__PURE__ */ new Date())
5936
- },
5937
- changeDateRange: () => {
5938
- },
5939
- refetch: () => {
5940
- },
5941
- sidebarScope: void 0,
5942
- setSidebarScope: () => {
5943
- },
5944
- sortBy: () => {
5945
- },
5946
- setFilterTypes: () => {
5947
- },
5948
- filters: {
5949
- expenses: void 0,
5950
- revenue: void 0
6243
+ // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
6244
+ import React76, { useContext as useContext5, useMemo as useMemo6 } from "react";
6245
+
6246
+ // src/components/SkeletonLoader/SkeletonLoader.tsx
6247
+ import React74 from "react";
6248
+ import classNames26 from "classnames";
6249
+ var SkeletonLoader = ({
6250
+ height,
6251
+ width,
6252
+ className
6253
+ }) => {
6254
+ const baseClassName = classNames26(
6255
+ "Layer__skeleton-loader Layer__anim--skeleton-loading",
6256
+ className
6257
+ );
6258
+ return /* @__PURE__ */ React74.createElement("div", { className: baseClassName, style: { width, height } });
6259
+ };
6260
+
6261
+ // src/components/ProfitAndLossSummaries/MiniChart.tsx
6262
+ import React75 from "react";
6263
+ import { PieChart as PieChart2, Pie as Pie2, Cell as Cell3 } from "recharts";
6264
+ var MiniChart = ({ data }) => {
6265
+ return /* @__PURE__ */ React75.createElement(PieChart2, { width: 48, height: 48, className: "mini-chart" }, /* @__PURE__ */ React75.createElement(
6266
+ Pie2,
6267
+ {
6268
+ data,
6269
+ dataKey: "value",
6270
+ nameKey: "name",
6271
+ cx: "50%",
6272
+ cy: "50%",
6273
+ innerRadius: 10,
6274
+ outerRadius: 16,
6275
+ paddingAngle: 0.2,
6276
+ fill: "#8884d8",
6277
+ width: 24,
6278
+ height: 24,
6279
+ animationDuration: 250,
6280
+ animationEasing: "ease-in-out"
6281
+ },
6282
+ data.map((entry, index) => {
6283
+ const colorConfig = DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length];
6284
+ return /* @__PURE__ */ React75.createElement(
6285
+ Cell3,
6286
+ {
6287
+ key: `cell-${index}`,
6288
+ className: `Layer__profit-and-loss-detailed-charts__pie`,
6289
+ fill: entry.name === "placeholder" ? "#e6e6e6" : colorConfig.color,
6290
+ opacity: colorConfig.opacity
6291
+ }
6292
+ );
6293
+ })
6294
+ ));
6295
+ };
6296
+
6297
+ // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
6298
+ import classNames27 from "classnames";
6299
+ var CHART_PLACEHOLDER = [
6300
+ {
6301
+ name: "placeholder",
6302
+ display_name: "placeholder",
6303
+ value: 1,
6304
+ type: "placeholder",
6305
+ share: 1
5951
6306
  }
5952
- });
5953
- var ProfitAndLoss = ({ children, tagFilter, reportingBasis }) => {
5954
- const contextData = useProfitAndLoss({ tagFilter, reportingBasis });
5955
- return /* @__PURE__ */ React74.createElement(PNLContext.Provider, { value: contextData }, /* @__PURE__ */ React74.createElement("div", { className: "Layer__component Layer__profit-and-loss" }, children));
6307
+ ];
6308
+ var buildMiniChartData = (scope, data) => {
6309
+ if (!data) {
6310
+ return CHART_PLACEHOLDER;
6311
+ }
6312
+ let items = [];
6313
+ switch (scope) {
6314
+ case "revenue":
6315
+ items = collectRevenueItems(data);
6316
+ break;
6317
+ default:
6318
+ items = collectExpensesItems(data);
6319
+ }
6320
+ if (!items || items.length === 0 || !items.find((x) => Math.abs(x.value) !== 0)) {
6321
+ return CHART_PLACEHOLDER;
6322
+ }
6323
+ return items.slice();
6324
+ };
6325
+ var ProfitAndLossSummaries = ({
6326
+ vertical,
6327
+ revenueLabel = "Revenue",
6328
+ actionable = true
6329
+ }) => {
6330
+ const {
6331
+ data: storedData,
6332
+ isLoading,
6333
+ setSidebarScope,
6334
+ sidebarScope
6335
+ } = useContext5(ProfitAndLoss.Context);
6336
+ const expensesChartData = useMemo6(() => {
6337
+ return buildMiniChartData("expenses", storedData);
6338
+ }, [storedData]);
6339
+ const revenueChartData = useMemo6(() => {
6340
+ return buildMiniChartData("revenue", storedData);
6341
+ }, [storedData]);
6342
+ const data = storedData ? storedData : { income: { value: NaN }, net_profit: NaN };
6343
+ const incomeDirectionClass = (data.income.value ?? NaN) < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
6344
+ const expensesDirectionClass = (data?.income?.value ?? NaN) - data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
6345
+ const netProfitDirectionClass = data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--positive";
6346
+ return /* @__PURE__ */ React76.createElement(
6347
+ "div",
6348
+ {
6349
+ className: `Layer__profit-and-loss-summaries ${vertical ? "flex-col" : ""}`
6350
+ },
6351
+ /* @__PURE__ */ React76.createElement(
6352
+ "div",
6353
+ {
6354
+ className: classNames27(
6355
+ "Layer__profit-and-loss-summaries__summary",
6356
+ actionable && "Layer__actionable",
6357
+ "Layer__profit-and-loss-summaries__summary--income",
6358
+ sidebarScope === "revenue" ? "active" : ""
6359
+ ),
6360
+ onClick: () => {
6361
+ actionable && setSidebarScope("revenue");
6362
+ }
6363
+ },
6364
+ /* @__PURE__ */ React76.createElement(MiniChart, { data: revenueChartData }),
6365
+ /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React76.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, revenueLabel), isLoading || storedData === void 0 ? /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React76.createElement(SkeletonLoader, null)) : /* @__PURE__ */ React76.createElement(
6366
+ "span",
6367
+ {
6368
+ className: `Layer__profit-and-loss-summaries__amount ${incomeDirectionClass}`
6369
+ },
6370
+ centsToDollars(Math.abs(data?.income?.value ?? NaN))
6371
+ ))
6372
+ ),
6373
+ /* @__PURE__ */ React76.createElement(
6374
+ "div",
6375
+ {
6376
+ className: classNames27(
6377
+ "Layer__profit-and-loss-summaries__summary",
6378
+ actionable && "Layer__actionable",
6379
+ "Layer__profit-and-loss-summaries__summary--expenses",
6380
+ sidebarScope === "expenses" ? "active" : ""
6381
+ ),
6382
+ onClick: () => {
6383
+ actionable && setSidebarScope("expenses");
6384
+ }
6385
+ },
6386
+ /* @__PURE__ */ React76.createElement(MiniChart, { data: expensesChartData }),
6387
+ /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React76.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Expenses"), isLoading || storedData === void 0 ? /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React76.createElement(SkeletonLoader, { className: "Layer__profit-and-loss-summaries__loader" })) : /* @__PURE__ */ React76.createElement(
6388
+ "span",
6389
+ {
6390
+ className: `Layer__profit-and-loss-summaries__amount ${expensesDirectionClass}`
6391
+ },
6392
+ centsToDollars(
6393
+ Math.abs((data.income.value ?? 0) - data.net_profit)
6394
+ )
6395
+ ))
6396
+ ),
6397
+ /* @__PURE__ */ React76.createElement(
6398
+ "div",
6399
+ {
6400
+ className: classNames27(
6401
+ "Layer__profit-and-loss-summaries__summary net-profit Layer__profit-and-loss-summaries__summary--net-profit",
6402
+ actionable && "Layer__actionable"
6403
+ )
6404
+ },
6405
+ /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__text" }, /* @__PURE__ */ React76.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Net Profit"), isLoading || storedData === void 0 ? /* @__PURE__ */ React76.createElement("div", { className: "Layer__profit-and-loss-summaries__loader" }, /* @__PURE__ */ React76.createElement(SkeletonLoader, { className: "Layer__profit-and-loss-summaries__loader" })) : /* @__PURE__ */ React76.createElement(
6406
+ "span",
6407
+ {
6408
+ className: `Layer__profit-and-loss-summaries__amount ${netProfitDirectionClass}`
6409
+ },
6410
+ centsToDollars(Math.abs(data.net_profit))
6411
+ ))
6412
+ )
6413
+ );
5956
6414
  };
5957
- ProfitAndLoss.Chart = ProfitAndLossChart;
5958
- ProfitAndLoss.Context = PNLContext;
5959
- ProfitAndLoss.DatePicker = ProfitAndLossDatePicker;
5960
- ProfitAndLoss.Summaries = ProfitAndLossSummaries;
5961
- ProfitAndLoss.Table = ProfitAndLossTable;
5962
6415
 
5963
- // src/components/ProfitAndLossView/ProfitAndLossView.tsx
5964
- import React81, { useContext as useContext7 } from "react";
6416
+ // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
6417
+ import React79, { useContext as useContext6 } from "react";
5965
6418
 
5966
- // src/components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts.tsx
5967
- import React80, { useContext as useContext6, useState as useState16 } from "react";
6419
+ // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
6420
+ import React78, { useState as useState17 } from "react";
5968
6421
 
5969
- // src/icons/X.tsx
5970
- import * as React75 from "react";
5971
- var X = ({ size = 18, ...props }) => /* @__PURE__ */ React75.createElement(
6422
+ // src/icons/PieChart.tsx
6423
+ import * as React77 from "react";
6424
+ var PieChart3 = ({ size = 12, ...props }) => /* @__PURE__ */ React77.createElement(
5972
6425
  "svg",
5973
6426
  {
5974
6427
  xmlns: "http://www.w3.org/2000/svg",
5975
- viewBox: "0 0 18 18",
6428
+ viewBox: "0 0 12 12",
5976
6429
  fill: "none",
5977
6430
  ...props,
5978
6431
  width: size,
5979
6432
  height: size
5980
6433
  },
5981
- /* @__PURE__ */ React75.createElement(
6434
+ /* @__PURE__ */ React77.createElement("g", null, /* @__PURE__ */ React77.createElement(
5982
6435
  "path",
5983
6436
  {
5984
- d: "M13.5 4.5L4.5 13.5",
6437
+ d: "M10.2213 7.78271C9.92969 8.47226 9.47363 9.07989 8.89297 9.55247C8.3123 10.0251 7.62471 10.3482 6.89031 10.4936C6.1559 10.6391 5.39705 10.6024 4.68009 10.3869C3.96313 10.1713 3.30989 9.78337 2.77749 9.25701C2.24509 8.73065 1.84973 8.08189 1.62598 7.36744C1.40223 6.65298 1.3569 5.8946 1.49396 5.15858C1.63102 4.42257 1.94629 3.73133 2.41221 3.14531C2.87813 2.55928 3.48051 2.09631 4.16669 1.79688",
5985
6438
  stroke: "currentColor",
5986
6439
  strokeLinecap: "round",
5987
6440
  strokeLinejoin: "round"
5988
6441
  }
5989
- ),
5990
- /* @__PURE__ */ React75.createElement(
6442
+ ), /* @__PURE__ */ React77.createElement(
5991
6443
  "path",
5992
6444
  {
5993
- d: "M4.5 4.5L13.5 13.5",
6445
+ d: "M10.5833 6.00033C10.5833 5.39843 10.4648 4.80244 10.2344 4.24636C10.0041 3.69028 9.66651 3.18502 9.24091 2.75942C8.8153 2.33382 8.31004 1.99621 7.75397 1.76588C7.19789 1.53554 6.60189 1.41699 6 1.41699V6.00033H10.5833Z",
5994
6446
  stroke: "currentColor",
5995
6447
  strokeLinecap: "round",
5996
6448
  strokeLinejoin: "round"
5997
6449
  }
5998
- )
6450
+ ))
5999
6451
  );
6000
- var X_default = X;
6452
+ var PieChart_default = PieChart3;
6001
6453
 
6002
- // src/components/ProfitAndLossDetailedCharts/DetailedChart.tsx
6003
- import React76, { useMemo as useMemo6 } from "react";
6004
- import {
6005
- PieChart as PieChart3,
6006
- Pie as Pie2,
6007
- Cell as Cell3,
6008
- ResponsiveContainer as ResponsiveContainer2,
6009
- Label,
6010
- Text as ChartText
6011
- } from "recharts";
6012
- var DetailedChart = ({
6013
- filteredData,
6014
- filteredTotal,
6015
- hoveredItem,
6016
- setHoveredItem,
6017
- sidebarScope,
6018
- date
6454
+ // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
6455
+ var ProfitAndLossRow = ({
6456
+ variant,
6457
+ lineItem,
6458
+ depth = 0,
6459
+ maxDepth = 1,
6460
+ direction = "DEBIT" /* DEBIT */,
6461
+ lockExpanded = false,
6462
+ scope,
6463
+ setSidebarScope
6019
6464
  }) => {
6020
- const chartData = useMemo6(() => {
6021
- if (!filteredData) {
6022
- return [];
6023
- }
6024
- return filteredData.map((x) => {
6025
- if (x.hidden) {
6026
- return {
6027
- name: x.display_name,
6028
- value: 0
6029
- };
6030
- }
6031
- return {
6032
- name: x.display_name,
6033
- value: x.value
6034
- };
6035
- });
6036
- }, [filteredData]);
6037
- return /* @__PURE__ */ React76.createElement("div", { className: "chart-field" }, /* @__PURE__ */ React76.createElement("div", { className: "header--tablet" }, /* @__PURE__ */ React76.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, humanizeTitle(sidebarScope)), /* @__PURE__ */ React76.createElement(ProfitAndLossDatePicker, null)), /* @__PURE__ */ React76.createElement("div", { className: "chart-container" }, /* @__PURE__ */ React76.createElement(ResponsiveContainer2, null, /* @__PURE__ */ React76.createElement(PieChart3, null, /* @__PURE__ */ React76.createElement(
6038
- Pie2,
6465
+ if (!lineItem) {
6466
+ return null;
6467
+ }
6468
+ const { value, display_name, line_items } = lineItem;
6469
+ const [expanded, setExpanded] = useState17(true);
6470
+ const amount = value ?? 0;
6471
+ const amountString = centsToDollars(Math.abs(amount));
6472
+ const labelClasses = [
6473
+ "Layer__profit-and-loss-row",
6474
+ "Layer__profit-and-loss-row__label"
6475
+ ];
6476
+ const valueClasses = [
6477
+ "Layer__profit-and-loss-row",
6478
+ "Layer__profit-and-loss-row__value"
6479
+ ];
6480
+ const positive = amount === 0 || direction === "CREDIT" /* CREDIT */ && amount > 0 || direction === "DEBIT" /* DEBIT */ && amount < 0;
6481
+ valueClasses.push(
6482
+ positive ? "Layer__profit-and-loss-row__value--amount-positive" : "Layer__profit-and-loss-row__value--amount-negative"
6483
+ );
6484
+ labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`);
6485
+ valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`);
6486
+ variant && labelClasses.push(`Layer__profit-and-loss-row__label--variant-${variant}`);
6487
+ variant && valueClasses.push(`Layer__profit-and-loss-row__value--variant-${variant}`);
6488
+ const toggleExpanded = () => setExpanded(!expanded);
6489
+ const canGoDeeper = depth < maxDepth;
6490
+ const hasChildren = (line_items?.length ?? 0) > 0;
6491
+ const displayChildren = hasChildren && canGoDeeper;
6492
+ labelClasses.push(
6493
+ `Layer__profit-and-loss-row__label--display-children-${displayChildren}`
6494
+ );
6495
+ valueClasses.push(
6496
+ `Layer__profit-and-loss-row__value--display-children-${displayChildren}`
6497
+ );
6498
+ displayChildren && expanded && labelClasses.push("Layer__profit-and-loss-row__label--expanded");
6499
+ displayChildren && expanded && valueClasses.push("Layer__profit-and-loss-row__value--expanded");
6500
+ return /* @__PURE__ */ React78.createElement(React78.Fragment, null, /* @__PURE__ */ React78.createElement(
6501
+ "div",
6039
6502
  {
6040
- data: chartData,
6041
- dataKey: "value",
6042
- nameKey: "name",
6043
- cx: "50%",
6044
- cy: "50%",
6045
- innerRadius: 105,
6046
- outerRadius: 120,
6047
- paddingAngle: 0.5,
6048
- fill: "#8884d8",
6049
- animationDuration: 200,
6050
- animationEasing: "ease-in-out"
6503
+ className: labelClasses.join(" "),
6504
+ onClick: () => !lockExpanded && toggleExpanded()
6051
6505
  },
6052
- chartData.map((entry, index) => {
6053
- const colorConfig = DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length];
6054
- let fill = colorConfig.color;
6055
- let opacity = colorConfig.opacity;
6056
- let active = true;
6057
- if (hoveredItem && entry.name !== hoveredItem) {
6058
- active = false;
6059
- fill = void 0;
6060
- opacity = INACTIVE_OPACITY_LEVELS[index % INACTIVE_OPACITY_LEVELS.length];
6061
- }
6062
- return /* @__PURE__ */ React76.createElement(
6063
- Cell3,
6064
- {
6065
- key: `cell-${index}`,
6066
- className: `Layer__profit-and-loss-detailed-charts__pie ${hoveredItem && active ? "active" : "inactive"}`,
6067
- style: { fill },
6068
- opacity,
6069
- onMouseEnter: () => setHoveredItem(entry.name),
6070
- onMouseLeave: () => setHoveredItem(void 0)
6071
- }
6072
- );
6073
- }),
6074
- /* @__PURE__ */ React76.createElement(
6075
- Label,
6506
+ /* @__PURE__ */ React78.createElement("span", { className: "Layer__profit-and-loss-row__label__title" }, !lockExpanded && variant !== "summation" ? /* @__PURE__ */ React78.createElement(
6507
+ ChevronDownFill_default,
6076
6508
  {
6077
- position: "center",
6078
- value: "Total",
6079
- className: "pie-center-label-title",
6080
- content: (props) => {
6081
- const { cx, cy } = props.viewBox ?? {
6082
- cx: 0,
6083
- cy: 0
6084
- };
6085
- const positioningProps = {
6086
- x: cx,
6087
- y: (cy || 0) - 15,
6088
- textAnchor: "middle",
6089
- verticalAnchor: "middle"
6090
- };
6091
- let text = "Total";
6092
- if (hoveredItem) {
6093
- text = hoveredItem;
6094
- }
6095
- return /* @__PURE__ */ React76.createElement(
6096
- ChartText,
6097
- {
6098
- ...positioningProps,
6099
- className: "pie-center-label__title"
6100
- },
6101
- text
6102
- );
6103
- }
6509
+ size: 16,
6510
+ className: "Layer__profit-and-loss-row__label__chevron"
6104
6511
  }
6105
- ),
6106
- /* @__PURE__ */ React76.createElement(
6107
- Label,
6512
+ ) : null, /* @__PURE__ */ React78.createElement(Text, null, display_name)),
6513
+ setSidebarScope && /* @__PURE__ */ React78.createElement(
6514
+ "span",
6108
6515
  {
6109
- position: "center",
6110
- value: "Total",
6111
- className: "pie-center-label-title",
6112
- content: (props) => {
6113
- const { cx, cy } = props.viewBox ?? {
6114
- cx: 0,
6115
- cy: 0
6116
- };
6117
- const positioningProps = {
6118
- x: cx,
6119
- y: (cy || 0) + 5,
6120
- textAnchor: "middle",
6121
- verticalAnchor: "middle"
6122
- };
6123
- let value = filteredTotal;
6124
- if (hoveredItem) {
6125
- value = filteredData.find(
6126
- (x) => x.display_name === hoveredItem
6127
- )?.value;
6128
- }
6129
- return /* @__PURE__ */ React76.createElement(
6130
- ChartText,
6131
- {
6132
- ...positioningProps,
6133
- className: "pie-center-label__value"
6134
- },
6135
- `$${centsToDollars(value)}`
6136
- );
6516
+ className: "Layer__profit-and-loss-row__detailed-chart-btn",
6517
+ onClick: (e) => {
6518
+ e.stopPropagation();
6519
+ setSidebarScope && setSidebarScope(scope ?? "expenses");
6137
6520
  }
6138
- }
6139
- ),
6140
- /* @__PURE__ */ React76.createElement(
6141
- Label,
6521
+ },
6522
+ /* @__PURE__ */ React78.createElement(PieChart_default, null)
6523
+ )
6524
+ ), /* @__PURE__ */ React78.createElement("div", { className: valueClasses.join(" ") }, /* @__PURE__ */ React78.createElement(Text, null, amountString)), canGoDeeper && hasChildren && /* @__PURE__ */ React78.createElement(
6525
+ "div",
6526
+ {
6527
+ className: `Layer__profit-and-loss-row__children ${expanded && "Layer__profit-and-loss-row__children--expanded"}`
6528
+ },
6529
+ /* @__PURE__ */ React78.createElement("div", { className: "Layer__profit-and-loss-row__children--content" }, (line_items || []).map((line_item) => /* @__PURE__ */ React78.createElement(
6530
+ ProfitAndLossRow,
6142
6531
  {
6143
- position: "center",
6144
- value: "Total",
6145
- className: "pie-center-label-title",
6146
- content: (props) => {
6147
- const { cx, cy } = props.viewBox ?? {
6148
- cx: 0,
6149
- cy: 0
6150
- };
6151
- const positioningProps = {
6152
- x: cx,
6153
- y: (cy || 0) + 25,
6154
- height: 20,
6155
- textAnchor: "middle",
6156
- verticalAnchor: "middle"
6157
- };
6158
- if (hoveredItem) {
6159
- return /* @__PURE__ */ React76.createElement(
6160
- ChartText,
6161
- {
6162
- ...positioningProps,
6163
- className: "pie-center-label__share"
6164
- },
6165
- `${formatPercent(
6166
- filteredData.find((x) => x.display_name === hoveredItem)?.share
6167
- )}%`
6168
- );
6169
- }
6170
- return;
6171
- }
6532
+ key: line_item.display_name,
6533
+ lineItem: line_item,
6534
+ depth: depth + 1,
6535
+ maxDepth,
6536
+ direction
6172
6537
  }
6173
- )
6174
- )))));
6538
+ )))
6539
+ ));
6175
6540
  };
6176
6541
 
6177
- // src/components/ProfitAndLossDetailedCharts/DetailedTable.tsx
6178
- import React78 from "react";
6179
-
6180
- // src/icons/SortArrows.tsx
6181
- import * as React77 from "react";
6182
- var SortArrows = ({ size = 13, ...props }) => /* @__PURE__ */ React77.createElement(
6183
- "svg",
6184
- {
6185
- xmlns: "http://www.w3.org/2000/svg",
6186
- viewBox: "0 0 12 13",
6187
- fill: "none",
6188
- ...props,
6189
- width: size,
6190
- height: size
6542
+ // src/components/ProfitAndLossTable/empty_profit_and_loss_report.ts
6543
+ var empty_profit_and_loss_report_default = {
6544
+ type: "Profit_And_Loss",
6545
+ business_id: "",
6546
+ start_date: "",
6547
+ end_date: "",
6548
+ income: {
6549
+ name: "INCOME",
6550
+ display_name: "Income",
6551
+ value: NaN,
6552
+ line_items: null
6191
6553
  },
6192
- /* @__PURE__ */ React77.createElement("g", { "clip-path": "url(#clip0_1758_75388)" }, /* @__PURE__ */ React77.createElement(
6193
- "path",
6194
- {
6195
- d: "M1.33325 8.5L3.99992 11.1667L6.66659 8.5",
6196
- stroke: "currentColor",
6197
- strokeLinecap: "round",
6198
- strokeLinejoin: "round",
6199
- className: "desc-arrow"
6200
- }
6201
- ), /* @__PURE__ */ React77.createElement(
6202
- "path",
6203
- {
6204
- d: "M4 2.5L4 11.1667",
6205
- stroke: "currentColor",
6206
- strokeLinecap: "round",
6207
- strokeLinejoin: "round",
6208
- className: "desc-arrow"
6209
- }
6210
- ), /* @__PURE__ */ React77.createElement(
6211
- "path",
6212
- {
6213
- d: "M5.99988 5.16602L8.66654 2.49935L11.3332 5.16602",
6214
- stroke: "currentColor",
6215
- strokeLinecap: "round",
6216
- strokeLinejoin: "round",
6217
- className: "asc-arrow"
6218
- }
6219
- ), /* @__PURE__ */ React77.createElement(
6220
- "path",
6221
- {
6222
- d: "M8.66663 11.166L8.66663 2.49935",
6223
- stroke: "currentColor",
6224
- strokeLinecap: "round",
6225
- strokeLinejoin: "round",
6226
- className: "asc-arrow"
6227
- }
6228
- )),
6229
- /* @__PURE__ */ React77.createElement("defs", null, /* @__PURE__ */ React77.createElement("clipPath", { id: "clip0_1758_75388" }, /* @__PURE__ */ React77.createElement(
6230
- "rect",
6231
- {
6232
- width: "12",
6233
- height: "12",
6234
- fill: "white",
6235
- transform: "translate(0 0.5)"
6236
- }
6237
- )))
6238
- );
6239
- var SortArrows_default = SortArrows;
6554
+ cost_of_goods_sold: {
6555
+ display_name: "Cost of Goods Sold",
6556
+ name: "COGS",
6557
+ value: NaN,
6558
+ line_items: null
6559
+ },
6560
+ gross_profit: NaN,
6561
+ expenses: {
6562
+ name: "EXPENSES",
6563
+ display_name: "Expenses",
6564
+ value: NaN,
6565
+ line_items: null
6566
+ },
6567
+ profit_before_taxes: NaN,
6568
+ taxes: {
6569
+ name: "TAXES",
6570
+ display_name: "Taxes",
6571
+ value: NaN,
6572
+ line_items: null
6573
+ },
6574
+ net_profit: NaN,
6575
+ other_outflows: {
6576
+ name: "OTHER_OUTFLOWS",
6577
+ display_name: "Other outflows",
6578
+ value: NaN,
6579
+ line_items: null
6580
+ },
6581
+ personal_expenses: {
6582
+ name: "PERSONAL",
6583
+ display_name: "Personal expenses",
6584
+ value: NaN,
6585
+ line_items: null
6586
+ },
6587
+ fully_categorized: false
6588
+ };
6240
6589
 
6241
- // src/components/ProfitAndLossDetailedCharts/DetailedTable.tsx
6242
- import classNames27 from "classnames";
6243
- var DetailedTable = ({
6244
- filteredData,
6245
- sidebarScope,
6246
- filters,
6247
- sortBy,
6248
- hoveredItem,
6249
- setHoveredItem
6250
- }) => {
6251
- const buildColClass = (column) => {
6252
- return classNames27(
6253
- "Layer__sortable-col",
6254
- sidebarScope && filters[sidebarScope]?.sortBy === column ? `sort--${(sidebarScope && filters[sidebarScope]?.sortDirection) ?? "desc"}` : ""
6255
- );
6256
- };
6257
- return /* @__PURE__ */ React78.createElement("div", { className: "details-container" }, /* @__PURE__ */ React78.createElement("div", { className: "table" }, /* @__PURE__ */ React78.createElement("table", null, /* @__PURE__ */ React78.createElement("thead", null, /* @__PURE__ */ React78.createElement("tr", null, /* @__PURE__ */ React78.createElement(
6258
- "th",
6259
- {
6260
- className: buildColClass("category"),
6261
- onClick: () => sortBy(sidebarScope ?? "expenses", "category")
6262
- },
6263
- "Expense/Sale ",
6264
- /* @__PURE__ */ React78.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6265
- ), /* @__PURE__ */ React78.createElement(
6266
- "th",
6267
- {
6268
- className: buildColClass("type"),
6269
- onClick: () => sortBy(sidebarScope ?? "expenses", "type")
6270
- },
6271
- "Type ",
6272
- /* @__PURE__ */ React78.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6273
- ), /* @__PURE__ */ React78.createElement("th", null), /* @__PURE__ */ React78.createElement(
6274
- "th",
6275
- {
6276
- className: buildColClass("value"),
6277
- onClick: () => sortBy(sidebarScope ?? "expenses", "value")
6278
- },
6279
- "Value ",
6280
- /* @__PURE__ */ React78.createElement(SortArrows_default, { className: "Layer__sort-arrows" })
6281
- ))), /* @__PURE__ */ React78.createElement("tbody", null, filteredData.filter((x) => !x.hidden).map((item, idx) => {
6282
- const colorConfig = DEFAULT_CHART_COLORS[idx % DEFAULT_CHART_COLORS.length];
6283
- return /* @__PURE__ */ React78.createElement(
6284
- "tr",
6590
+ // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
6591
+ import classNames28 from "classnames";
6592
+ var ProfitAndLossTable = ({ lockExpanded, asContainer }) => {
6593
+ const {
6594
+ data: actualData,
6595
+ isLoading,
6596
+ setSidebarScope
6597
+ } = useContext6(ProfitAndLoss.Context);
6598
+ const data = !actualData || isLoading ? empty_profit_and_loss_report_default : actualData;
6599
+ if (isLoading || actualData === void 0) {
6600
+ return /* @__PURE__ */ React79.createElement(
6601
+ "div",
6285
6602
  {
6286
- key: `pl-side-table-item-${idx}`,
6287
- className: classNames27(
6288
- "Layer__profit-and-loss-detailed-table__row",
6289
- hoveredItem && hoveredItem === item.display_name ? "active" : ""
6290
- ),
6291
- onMouseEnter: () => setHoveredItem(item.display_name),
6292
- onMouseLeave: () => setHoveredItem(void 0)
6603
+ className: classNames28(
6604
+ "Layer__profit-and-loss-table__loader-container",
6605
+ asContainer && "Layer__component-container"
6606
+ )
6293
6607
  },
6294
- /* @__PURE__ */ React78.createElement("td", { className: "category-col" }, item.display_name),
6295
- /* @__PURE__ */ React78.createElement("td", { className: "type-col" }, item.type),
6296
- /* @__PURE__ */ React78.createElement("td", { className: "value-col" }, "$", centsToDollars(item.value)),
6297
- /* @__PURE__ */ React78.createElement("td", { className: "share-col" }, /* @__PURE__ */ React78.createElement("span", { className: "share-cell-content" }, formatPercent(item.share), "%", /* @__PURE__ */ React78.createElement(
6298
- "div",
6299
- {
6300
- className: "share-icon",
6301
- style: {
6302
- background: colorConfig.color,
6303
- opacity: colorConfig.opacity
6304
- }
6305
- }
6306
- )))
6608
+ /* @__PURE__ */ React79.createElement(Loader2, null)
6307
6609
  );
6308
- })))));
6309
- };
6310
-
6311
- // src/components/ProfitAndLossDetailedCharts/Filters.tsx
6312
- import React79 from "react";
6313
- import Select3, { components as components3 } from "react-select";
6314
- var Filters = ({
6315
- filteredData,
6316
- sidebarScope,
6317
- filters,
6318
- setFilterTypes
6319
- }) => {
6320
- return /* @__PURE__ */ React79.createElement("div", { className: "filters" }, /* @__PURE__ */ React79.createElement(Text, { size: "sm" /* sm */, className: "Layer__label" }, "Filters"), /* @__PURE__ */ React79.createElement(
6321
- Select3,
6610
+ }
6611
+ return /* @__PURE__ */ React79.createElement(React79.Fragment, null, /* @__PURE__ */ React79.createElement(
6612
+ "div",
6322
6613
  {
6323
- className: "Layer__select type-select",
6324
- classNamePrefix: "Layer__select",
6325
- value: sidebarScope && filters[sidebarScope]?.types ? sidebarScope && filters[sidebarScope]?.types?.map((x) => ({
6326
- value: x,
6327
- label: x
6328
- })) : [],
6329
- isMulti: true,
6330
- isClearable: false,
6331
- options: [...new Set(filteredData?.map((x) => x.type))].map((x) => ({
6332
- label: x,
6333
- value: x
6334
- })),
6335
- onChange: (selected) => {
6336
- setFilterTypes(
6337
- sidebarScope ?? "expenses",
6338
- selected.map((x) => x.value)
6339
- );
6340
- },
6341
- components: {
6342
- DropdownIndicator: (props) => /* @__PURE__ */ React79.createElement(components3.DropdownIndicator, { ...props }, /* @__PURE__ */ React79.createElement(ChevronDown_default, null)),
6343
- Placeholder: (props) => /* @__PURE__ */ React79.createElement(components3.Placeholder, { ...props }, /* @__PURE__ */ React79.createElement("div", { className: "Layer__select__multi-all-placeholder-badge" }, "All"))
6614
+ className: classNames28(
6615
+ "Layer__profit-and-loss-table Layer__profit-and-loss-table--main",
6616
+ asContainer && "Layer__component-container"
6617
+ )
6618
+ },
6619
+ /* @__PURE__ */ React79.createElement(
6620
+ ProfitAndLossRow,
6621
+ {
6622
+ lineItem: data.income,
6623
+ direction: "CREDIT" /* CREDIT */,
6624
+ lockExpanded,
6625
+ scope: "revenue",
6626
+ setSidebarScope
6627
+ }
6628
+ ),
6629
+ /* @__PURE__ */ React79.createElement(
6630
+ ProfitAndLossRow,
6631
+ {
6632
+ lineItem: data.cost_of_goods_sold,
6633
+ direction: "DEBIT" /* DEBIT */,
6634
+ lockExpanded,
6635
+ scope: "expenses",
6636
+ setSidebarScope
6637
+ }
6638
+ ),
6639
+ /* @__PURE__ */ React79.createElement(
6640
+ ProfitAndLossRow,
6641
+ {
6642
+ lineItem: {
6643
+ value: data.gross_profit,
6644
+ display_name: "Gross Profit"
6645
+ },
6646
+ variant: "summation",
6647
+ direction: "CREDIT" /* CREDIT */,
6648
+ lockExpanded,
6649
+ scope: "revenue",
6650
+ setSidebarScope
6651
+ }
6652
+ ),
6653
+ /* @__PURE__ */ React79.createElement(
6654
+ ProfitAndLossRow,
6655
+ {
6656
+ lineItem: data.expenses,
6657
+ direction: "DEBIT" /* DEBIT */,
6658
+ lockExpanded,
6659
+ scope: "expenses",
6660
+ setSidebarScope
6661
+ }
6662
+ ),
6663
+ /* @__PURE__ */ React79.createElement(
6664
+ ProfitAndLossRow,
6665
+ {
6666
+ lineItem: {
6667
+ value: data.profit_before_taxes,
6668
+ display_name: "Profit Before Taxes"
6669
+ },
6670
+ variant: "summation",
6671
+ direction: "CREDIT" /* CREDIT */,
6672
+ lockExpanded,
6673
+ scope: "revenue",
6674
+ setSidebarScope
6675
+ }
6676
+ ),
6677
+ /* @__PURE__ */ React79.createElement(
6678
+ ProfitAndLossRow,
6679
+ {
6680
+ lineItem: data.taxes,
6681
+ direction: "DEBIT" /* DEBIT */,
6682
+ lockExpanded,
6683
+ scope: "expenses",
6684
+ setSidebarScope
6685
+ }
6686
+ ),
6687
+ /* @__PURE__ */ React79.createElement(
6688
+ ProfitAndLossRow,
6689
+ {
6690
+ lineItem: {
6691
+ value: data.net_profit,
6692
+ display_name: "Net Profit"
6693
+ },
6694
+ variant: "summation",
6695
+ direction: "CREDIT" /* CREDIT */,
6696
+ lockExpanded
6344
6697
  }
6698
+ )
6699
+ ), data.other_outflows || data.personal_expenses ? /* @__PURE__ */ React79.createElement("div", { className: "Layer__profit-and-loss-table Layer__profit-and-loss-table__outflows" }, /* @__PURE__ */ React79.createElement(
6700
+ ProfitAndLossRow,
6701
+ {
6702
+ lineItem: data.other_outflows,
6703
+ direction: "DEBIT" /* DEBIT */,
6704
+ lockExpanded
6345
6705
  }
6346
- ));
6706
+ ), /* @__PURE__ */ React79.createElement(
6707
+ ProfitAndLossRow,
6708
+ {
6709
+ lineItem: data.personal_expenses,
6710
+ direction: "DEBIT" /* DEBIT */,
6711
+ lockExpanded
6712
+ }
6713
+ )) : null);
6347
6714
  };
6348
6715
 
6349
- // src/components/ProfitAndLossDetailedCharts/ProfitAndLossDetailedCharts.tsx
6350
- import classNames28 from "classnames";
6351
- import { format as format6 } from "date-fns";
6352
- var ProfitAndLossDetailedCharts = () => {
6353
- const {
6354
- filteredData,
6355
- filteredTotal,
6356
- sortBy,
6357
- filters,
6358
- isLoading,
6359
- dateRange,
6360
- sidebarScope,
6361
- setSidebarScope,
6362
- setFilterTypes
6363
- } = useContext6(ProfitAndLoss.Context);
6364
- const [hoveredItem, setHoveredItem] = useState16();
6365
- return /* @__PURE__ */ React80.createElement(
6716
+ // src/components/ProfitAndLoss/ProfitAndLoss.tsx
6717
+ import { endOfMonth as endOfMonth4, startOfMonth as startOfMonth4 } from "date-fns";
6718
+ var PNLContext = createContext2({
6719
+ data: void 0,
6720
+ filteredDataRevenue: [],
6721
+ filteredTotalRevenue: void 0,
6722
+ filteredDataExpenses: [],
6723
+ filteredTotalExpenses: void 0,
6724
+ isLoading: true,
6725
+ isValidating: false,
6726
+ error: void 0,
6727
+ dateRange: {
6728
+ startDate: startOfMonth4(/* @__PURE__ */ new Date()),
6729
+ endDate: endOfMonth4(/* @__PURE__ */ new Date())
6730
+ },
6731
+ changeDateRange: () => {
6732
+ },
6733
+ refetch: () => {
6734
+ },
6735
+ sidebarScope: void 0,
6736
+ setSidebarScope: () => {
6737
+ },
6738
+ sortBy: () => {
6739
+ },
6740
+ setFilterTypes: () => {
6741
+ },
6742
+ filters: {
6743
+ expenses: void 0,
6744
+ revenue: void 0
6745
+ }
6746
+ });
6747
+ var ProfitAndLoss = ({
6748
+ children,
6749
+ tagFilter,
6750
+ reportingBasis,
6751
+ asContainer = true
6752
+ }) => {
6753
+ const contextData = useProfitAndLoss({ tagFilter, reportingBasis });
6754
+ return /* @__PURE__ */ React80.createElement(PNLContext.Provider, { value: contextData }, asContainer ? /* @__PURE__ */ React80.createElement(Container, { name: "profit-and-loss" }, children) : children);
6755
+ };
6756
+ ProfitAndLoss.Chart = ProfitAndLossChart;
6757
+ ProfitAndLoss.Context = PNLContext;
6758
+ ProfitAndLoss.DatePicker = ProfitAndLossDatePicker;
6759
+ ProfitAndLoss.Summaries = ProfitAndLossSummaries;
6760
+ ProfitAndLoss.Table = ProfitAndLossTable;
6761
+ ProfitAndLoss.DetailedCharts = ProfitAndLossDetailedCharts;
6762
+
6763
+ // src/components/ProfitAndLossView/ProfitAndLossView.tsx
6764
+ import React82, { useContext as useContext7, useRef as useRef14 } from "react";
6765
+
6766
+ // src/components/Panel/Panel.tsx
6767
+ import React81, { useEffect as useEffect12, useState as useState18 } from "react";
6768
+ import classNames29 from "classnames";
6769
+ var Panel = ({
6770
+ children,
6771
+ className,
6772
+ sidebar,
6773
+ header,
6774
+ sidebarIsOpen,
6775
+ parentRef
6776
+ }) => {
6777
+ const [sidebarHeight, setSidebarHeight] = useState18(0);
6778
+ useEffect12(() => {
6779
+ if (parentRef?.current?.offsetHeight) {
6780
+ setSidebarHeight(parentRef?.current?.offsetHeight - 1);
6781
+ }
6782
+ }, [parentRef?.current?.offsetHeight, sidebarIsOpen]);
6783
+ return /* @__PURE__ */ React81.createElement(
6366
6784
  "div",
6367
6785
  {
6368
- className: classNames28(
6369
- "Layer__profit-and-loss__side-panel",
6370
- sidebarScope && "open"
6786
+ className: classNames29(
6787
+ "Layer__panel",
6788
+ className,
6789
+ sidebarIsOpen && "Layer__panel--open"
6371
6790
  )
6372
6791
  },
6373
- /* @__PURE__ */ React80.createElement("div", { className: "Layer__profit-and-loss-detailed-charts" }, /* @__PURE__ */ React80.createElement("header", { className: "Layer__profit-and-loss-detailed-charts__header" }, /* @__PURE__ */ React80.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__head" }, /* @__PURE__ */ React80.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, humanizeTitle(sidebarScope)), /* @__PURE__ */ React80.createElement(Text, { size: "sm" /* sm */, className: "date" }, format6(dateRange.startDate, "LLLL, y")), /* @__PURE__ */ React80.createElement(ProfitAndLossDatePicker, null)), /* @__PURE__ */ React80.createElement(
6374
- Button,
6375
- {
6376
- rightIcon: /* @__PURE__ */ React80.createElement(X_default, null),
6377
- iconOnly: true,
6378
- onClick: () => setSidebarScope(void 0),
6379
- variant: "secondary" /* secondary */
6380
- }
6381
- )), /* @__PURE__ */ React80.createElement("header", { className: "Layer__profit-and-loss-detailed-charts__header--tablet" }, /* @__PURE__ */ React80.createElement(BackButton, { onClick: () => setSidebarScope(void 0) })), /* @__PURE__ */ React80.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__content" }, /* @__PURE__ */ React80.createElement(
6382
- DetailedChart,
6383
- {
6384
- filteredData,
6385
- filteredTotal,
6386
- hoveredItem,
6387
- setHoveredItem,
6388
- sidebarScope,
6389
- date: dateRange.startDate
6390
- }
6391
- ), /* @__PURE__ */ React80.createElement("div", { className: "Layer__profit-and-loss-detailed-charts__table-wrapper" }, /* @__PURE__ */ React80.createElement(
6392
- Filters,
6393
- {
6394
- filteredData,
6395
- sidebarScope,
6396
- filters,
6397
- setFilterTypes
6398
- }
6399
- ), /* @__PURE__ */ React80.createElement(
6400
- DetailedTable,
6792
+ /* @__PURE__ */ React81.createElement("div", { className: "Layer__panel__content" }, header, children),
6793
+ sidebar && /* @__PURE__ */ React81.createElement(
6794
+ "div",
6401
6795
  {
6402
- filteredData,
6403
- sidebarScope,
6404
- filters,
6405
- sortBy,
6406
- hoveredItem,
6407
- setHoveredItem
6408
- }
6409
- ))))
6796
+ className: "Layer__panel__sidebar",
6797
+ style: {
6798
+ maxHeight: sidebarHeight > 0 && sidebarIsOpen ? sidebarHeight : 0
6799
+ }
6800
+ },
6801
+ /* @__PURE__ */ React81.createElement("div", { className: "Layer__panel__sidebar-content" }, sidebar)
6802
+ )
6410
6803
  );
6411
6804
  };
6412
6805
 
6413
6806
  // src/components/ProfitAndLossView/ProfitAndLossView.tsx
6414
6807
  var COMPONENT_NAME3 = "profit-and-loss";
6415
6808
  var ProfitAndLossView = (props) => {
6416
- return /* @__PURE__ */ React81.createElement(Container, { name: COMPONENT_NAME3 }, /* @__PURE__ */ React81.createElement(ProfitAndLoss, null, /* @__PURE__ */ React81.createElement("div", { className: `Layer__${COMPONENT_NAME3}__main-panel` }, /* @__PURE__ */ React81.createElement(Header, { className: `Layer__${COMPONENT_NAME3}__header` }, /* @__PURE__ */ React81.createElement(Heading, { className: "Layer__bank-transactions__title" }, "Profit & Loss")), /* @__PURE__ */ React81.createElement(Components, { ...props })), props.showDetailedCharts !== false && /* @__PURE__ */ React81.createElement(ProfitAndLossDetailedCharts, null)));
6809
+ const containerRef = useRef14(null);
6810
+ return /* @__PURE__ */ React82.createElement(Container, { name: COMPONENT_NAME3, ref: containerRef }, /* @__PURE__ */ React82.createElement(ProfitAndLoss, null, /* @__PURE__ */ React82.createElement(ProfitAndLossPanel, { containerRef, ...props })));
6811
+ };
6812
+ var ProfitAndLossPanel = ({
6813
+ containerRef,
6814
+ ...props
6815
+ }) => {
6816
+ const { sidebarScope } = useContext7(ProfitAndLoss.Context);
6817
+ return /* @__PURE__ */ React82.createElement(
6818
+ Panel,
6819
+ {
6820
+ sidebar: /* @__PURE__ */ React82.createElement(ProfitAndLossDetailedCharts, null),
6821
+ sidebarIsOpen: Boolean(sidebarScope),
6822
+ parentRef: containerRef
6823
+ },
6824
+ /* @__PURE__ */ React82.createElement(Header, { className: `Layer__${COMPONENT_NAME3}__header` }, /* @__PURE__ */ React82.createElement(Heading, { className: "Layer__profit-and-loss__title" }, "Profit & Loss")),
6825
+ /* @__PURE__ */ React82.createElement(Components, { ...props })
6826
+ );
6417
6827
  };
6418
6828
  var Components = ({
6419
6829
  hideChart = false,
@@ -6423,7 +6833,7 @@ var Components = ({
6423
6833
  ProfitAndLoss.Context
6424
6834
  );
6425
6835
  if (!isLoading && error) {
6426
- return /* @__PURE__ */ React81.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React81.createElement(
6836
+ return /* @__PURE__ */ React82.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React82.createElement(
6427
6837
  DataState,
6428
6838
  {
6429
6839
  status: "failed" /* failed */,
@@ -6434,27 +6844,27 @@ var Components = ({
6434
6844
  }
6435
6845
  ));
6436
6846
  }
6437
- return /* @__PURE__ */ React81.createElement(React81.Fragment, null, !hideChart && /* @__PURE__ */ React81.createElement("div", { className: `Layer__${COMPONENT_NAME3}__chart_with_summaries` }, /* @__PURE__ */ React81.createElement(
6847
+ return /* @__PURE__ */ React82.createElement(React82.Fragment, null, !hideChart && /* @__PURE__ */ React82.createElement("div", { className: `Layer__${COMPONENT_NAME3}__chart_with_summaries` }, /* @__PURE__ */ React82.createElement(
6438
6848
  "div",
6439
6849
  {
6440
6850
  className: `Layer__${COMPONENT_NAME3}__chart_with_summaries__summary-col`
6441
6851
  },
6442
- /* @__PURE__ */ React81.createElement(ProfitAndLoss.DatePicker, null),
6443
- /* @__PURE__ */ React81.createElement(ProfitAndLoss.Summaries, { vertical: true })
6444
- ), /* @__PURE__ */ React81.createElement(
6852
+ /* @__PURE__ */ React82.createElement(ProfitAndLoss.DatePicker, null),
6853
+ /* @__PURE__ */ React82.createElement(ProfitAndLoss.Summaries, { vertical: true })
6854
+ ), /* @__PURE__ */ React82.createElement(
6445
6855
  "div",
6446
6856
  {
6447
6857
  className: `Layer__${COMPONENT_NAME3}__chart_with_summaries__chart-col`
6448
6858
  },
6449
- /* @__PURE__ */ React81.createElement(ProfitAndLoss.Chart, null)
6450
- )), !hideTable && /* @__PURE__ */ React81.createElement(ProfitAndLoss.Table, null));
6859
+ /* @__PURE__ */ React82.createElement(ProfitAndLoss.Chart, null)
6860
+ )), !hideTable && /* @__PURE__ */ React82.createElement(ProfitAndLoss.Table, null));
6451
6861
  };
6452
6862
 
6453
- // src/components/LedgerAccounts/LedgerAccounts.tsx
6454
- import React88, { createContext as createContext3, useContext as useContext12 } from "react";
6863
+ // src/components/ChartOfAccounts/ChartOfAccounts.tsx
6864
+ import React96, { createContext as createContext3, useContext as useContext14, useState as useState24 } from "react";
6455
6865
 
6456
- // src/hooks/useLedgerAccounts/useLedgerAccounts.tsx
6457
- import { useState as useState17 } from "react";
6866
+ // src/hooks/useChartOfAccounts/useChartOfAccounts.tsx
6867
+ import { useState as useState19 } from "react";
6458
6868
  import useSWR6 from "swr";
6459
6869
  var validate = (formData) => {
6460
6870
  const errors = [];
@@ -6486,15 +6896,14 @@ var validateName = (formData) => {
6486
6896
  return;
6487
6897
  };
6488
6898
  var flattenAccounts = (accounts) => accounts.flatMap((a) => [a, flattenAccounts(a.sub_accounts || [])]).flat().filter((id) => id);
6489
- var useLedgerAccounts = () => {
6899
+ var useChartOfAccounts = () => {
6490
6900
  const { auth, businessId, apiUrl } = useLayerContext();
6491
- const [form, setForm] = useState17();
6492
- const [sendingForm, setSendingForm] = useState17(false);
6493
- const [apiError, setApiError] = useState17(void 0);
6494
- const [showARForAccountId, setShowARForAccountId] = useState17();
6901
+ const [form, setForm] = useState19();
6902
+ const [sendingForm, setSendingForm] = useState19(false);
6903
+ const [apiError, setApiError] = useState19(void 0);
6495
6904
  const { data, isLoading, isValidating, error, mutate } = useSWR6(
6496
- businessId && auth?.access_token && `ledger-accounts-${businessId}`,
6497
- Layer.getLedgerAccounts(apiUrl, auth?.access_token, {
6905
+ businessId && auth?.access_token && `chart-of-accounts-${businessId}`,
6906
+ Layer.getChartOfAccounts(apiUrl, auth?.access_token, {
6498
6907
  params: { businessId }
6499
6908
  })
6500
6909
  );
@@ -6552,13 +6961,13 @@ var useLedgerAccounts = () => {
6552
6961
  return;
6553
6962
  }
6554
6963
  const data2 = {
6555
- name: form.data.name || "Test name",
6964
+ name: form.data.name ?? "",
6556
6965
  normality: form.data.subType?.value,
6557
6966
  parent_id: form.data.parent ? {
6558
6967
  type: "AccountId",
6559
6968
  id: form.data.parent.value
6560
6969
  } : void 0,
6561
- description: form.data.type?.value.toString() || "Test description"
6970
+ description: form.data.type?.value.toString() ?? ""
6562
6971
  };
6563
6972
  if (form.action === "new") {
6564
6973
  create(data2);
@@ -6643,112 +7052,67 @@ var useLedgerAccounts = () => {
6643
7052
  editAccount,
6644
7053
  cancelForm,
6645
7054
  changeFormData,
6646
- submitForm,
6647
- showARForAccountId,
6648
- setShowARForAccountId
7055
+ submitForm
6649
7056
  };
6650
7057
  };
6651
7058
 
6652
- // src/components/AccountsReceivable/AccountsReceivableIndex.tsx
6653
- import React82, { useContext as useContext8, useMemo as useMemo7 } from "react";
6654
- import classNames29 from "classnames";
6655
- import { parseISO as parseISO9, format as formatTime7 } from "date-fns";
6656
- var AccountsReceivable = () => {
6657
- const { data, showARForAccountId, setShowARForAccountId } = useContext8(
6658
- LedgerAccountsContext
7059
+ // src/hooks/useLedgerAccounts/useLedgerAccounts.tsx
7060
+ import { useState as useState20 } from "react";
7061
+ import useSWR7 from "swr";
7062
+ var useLedgerAccounts = () => {
7063
+ const { auth, businessId, apiUrl } = useLayerContext();
7064
+ const [accountId, setAccountId] = useState20();
7065
+ const [selectedEntryId, setSelectedEntryId] = useState20();
7066
+ const { data, isLoading, isValidating, error, mutate } = useSWR7(
7067
+ businessId && accountId && auth?.access_token && `ledger-accounts-lines-${businessId}-${accountId}`,
7068
+ Layer.getLedgerAccountsLines(apiUrl, auth?.access_token, {
7069
+ params: { businessId, accountId }
7070
+ })
6659
7071
  );
6660
- const entry = useMemo7(() => {
6661
- return flattenAccounts(data?.accounts || []).find(
6662
- (x) => x.id === showARForAccountId
6663
- );
6664
- }, [showARForAccountId]);
6665
- const baseClassName = classNames29(
6666
- "Layer__accounts-receivable__index",
6667
- showARForAccountId && "open"
7072
+ const {
7073
+ data: entryData,
7074
+ mutate: mutateEntryData,
7075
+ isLoading: isLoadingEntry,
7076
+ isValidating: isValdiatingEntry,
7077
+ error: errorEntry
7078
+ } = useSWR7(
7079
+ businessId && selectedEntryId && auth?.access_token && `ledger-accounts-entry-${businessId}-${selectedEntryId}}`,
7080
+ Layer.getLedgerAccountsEntry(apiUrl, auth?.access_token, {
7081
+ params: { businessId, entryId: selectedEntryId }
7082
+ })
6668
7083
  );
6669
- const close = () => setShowARForAccountId(void 0);
6670
- return /* @__PURE__ */ React82.createElement("div", { className: baseClassName }, /* @__PURE__ */ React82.createElement("div", { className: "Layer__accounts-receivable__header" }, /* @__PURE__ */ React82.createElement(BackButton, { onClick: close }), /* @__PURE__ */ React82.createElement("div", { className: "Layer__accounts-receivable__title-container" }, /* @__PURE__ */ React82.createElement(
6671
- Text,
6672
- {
6673
- weight: "bold" /* bold */,
6674
- className: "Layer__accounts-receivable__title"
6675
- },
6676
- entry?.name || ""
6677
- ), /* @__PURE__ */ React82.createElement(
6678
- Button,
6679
- {
6680
- variant: "secondary" /* secondary */,
6681
- rightIcon: /* @__PURE__ */ React82.createElement(DownloadCloud_default, { size: 12 })
6682
- },
6683
- "Download"
6684
- )), /* @__PURE__ */ React82.createElement("div", { className: "Layer__accounts-receivable__balance-container" }, /* @__PURE__ */ React82.createElement(
6685
- Text,
6686
- {
6687
- weight: "bold" /* bold */,
6688
- className: "Layer__accounts-receivable__balance-label"
6689
- },
6690
- "Current balance"
6691
- ), /* @__PURE__ */ React82.createElement(
6692
- Text,
6693
- {
6694
- weight: "bold" /* bold */,
6695
- className: "Layer__accounts-receivable__balance-value"
6696
- },
6697
- "$",
6698
- centsToDollars(entry?.balance || 0)
6699
- ))), /* @__PURE__ */ React82.createElement("table", { className: "Layer__table Layer__accounts-receivable-table" }, /* @__PURE__ */ React82.createElement("thead", null, /* @__PURE__ */ React82.createElement("tr", null, /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header" }, "Date"), /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header" }, "Journal id #"), /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header" }, "Source"), /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Debit"), /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Credit"), /* @__PURE__ */ React82.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Running balance"))), /* @__PURE__ */ React82.createElement("tbody", null, entry?.entries?.map((x) => {
6700
- return /* @__PURE__ */ React82.createElement("tr", { key: x.id }, /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, x.createdAt && formatTime7(parseISO9(x.createdAt), DATE_FORMAT))), /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, "#123")), /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, "Invoice")), /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, x.direction, " $X,XXX.XX")), /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, "$X,XXX.XX")), /* @__PURE__ */ React82.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, /* @__PURE__ */ React82.createElement("span", { className: "Layer__table-cell-content" }, "$X,XXX.XX")));
6701
- }))));
7084
+ const refetch = () => mutate();
7085
+ const closeSelectedEntry = () => {
7086
+ setSelectedEntryId(void 0);
7087
+ mutateEntryData();
7088
+ };
7089
+ return {
7090
+ data: data?.data,
7091
+ entryData: entryData?.data,
7092
+ isLoading,
7093
+ isLoadingEntry,
7094
+ isValidating,
7095
+ isValdiatingEntry,
7096
+ error,
7097
+ errorEntry,
7098
+ refetch,
7099
+ accountId,
7100
+ setAccountId,
7101
+ selectedEntryId,
7102
+ setSelectedEntryId,
7103
+ closeSelectedEntry
7104
+ };
6702
7105
  };
6703
7106
 
6704
- // src/components/LedgerAccountsRow/LedgerAccountsRow.tsx
6705
- import React85, { useContext as useContext9, useEffect as useEffect11, useState as useState18 } from "react";
7107
+ // src/components/ChartOfAccountsTable/ChartOfAccountsTable.tsx
7108
+ import React88, { useContext as useContext10 } from "react";
6706
7109
 
6707
- // src/icons/ArrowRightCircle.tsx
6708
- import * as React83 from "react";
6709
- var ArrowRightCircle = ({ size = 18, ...props }) => /* @__PURE__ */ React83.createElement(
6710
- "svg",
6711
- {
6712
- xmlns: "http://www.w3.org/2000/svg",
6713
- viewBox: "0 0 18 18",
6714
- fill: "none",
6715
- ...props,
6716
- width: size,
6717
- height: size
6718
- },
6719
- /* @__PURE__ */ React83.createElement(
6720
- "path",
6721
- {
6722
- d: "M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z",
6723
- stroke: "currentColor",
6724
- strokeLinecap: "round",
6725
- strokeLinejoin: "round"
6726
- }
6727
- ),
6728
- /* @__PURE__ */ React83.createElement(
6729
- "path",
6730
- {
6731
- d: "M9 12L12 9L9 6",
6732
- stroke: "currentColor",
6733
- strokeLinecap: "round",
6734
- strokeLinejoin: "round"
6735
- }
6736
- ),
6737
- /* @__PURE__ */ React83.createElement(
6738
- "path",
6739
- {
6740
- d: "M6 9H12",
6741
- stroke: "currentColor",
6742
- strokeLinecap: "round",
6743
- strokeLinejoin: "round"
6744
- }
6745
- )
6746
- );
6747
- var ArrowRightCircle_default = ArrowRightCircle;
7110
+ // src/components/ChartOfAccountsRow/ChartOfAccountsRow.tsx
7111
+ import React84, { useContext as useContext8, useEffect as useEffect13, useState as useState21 } from "react";
6748
7112
 
6749
7113
  // src/icons/Edit2.tsx
6750
- import * as React84 from "react";
6751
- var Edit2 = ({ size = 18, ...props }) => /* @__PURE__ */ React84.createElement(
7114
+ import * as React83 from "react";
7115
+ var Edit2 = ({ size = 18, ...props }) => /* @__PURE__ */ React83.createElement(
6752
7116
  "svg",
6753
7117
  {
6754
7118
  xmlns: "http://www.w3.org/2000/svg",
@@ -6758,7 +7122,7 @@ var Edit2 = ({ size = 18, ...props }) => /* @__PURE__ */ React84.createElement(
6758
7122
  width: size,
6759
7123
  height: size
6760
7124
  },
6761
- /* @__PURE__ */ React84.createElement(
7125
+ /* @__PURE__ */ React83.createElement(
6762
7126
  "path",
6763
7127
  {
6764
7128
  d: "M12.75 2.25C12.947 2.05301 13.1808 1.89676 13.4382 1.79015C13.6956 1.68355 13.9714 1.62868 14.25 1.62868C14.5286 1.62868 14.8044 1.68355 15.0618 1.79015C15.3192 1.89676 15.553 2.05301 15.75 2.25C15.947 2.44698 16.1032 2.68083 16.2098 2.9382C16.3165 3.19557 16.3713 3.47142 16.3713 3.75C16.3713 4.02857 16.3165 4.30442 16.2098 4.56179C16.1032 4.81916 15.947 5.05302 15.75 5.25L5.625 15.375L1.5 16.5L2.625 12.375L12.75 2.25Z",
@@ -6770,43 +7134,51 @@ var Edit2 = ({ size = 18, ...props }) => /* @__PURE__ */ React84.createElement(
6770
7134
  );
6771
7135
  var Edit2_default = Edit2;
6772
7136
 
6773
- // src/components/LedgerAccountsRow/LedgerAccountsRow.tsx
7137
+ // src/components/ChartOfAccountsRow/ChartOfAccountsRow.tsx
6774
7138
  import classNames30 from "classnames";
6775
- var INDENTATION = 12;
7139
+ var INDENTATION = 24;
7140
+ var MOBILE_INDENTATION = 12;
6776
7141
  var EXPANDED_STYLE = {
6777
7142
  height: 52,
6778
7143
  paddingTop: 12,
6779
7144
  paddingBottom: 12,
6780
7145
  opacity: 1
6781
7146
  };
7147
+ var EXPANDED_MOBILE_STYLE = {
7148
+ height: 76,
7149
+ paddingTop: 12,
7150
+ paddingBottom: 12,
7151
+ opacity: 1
7152
+ };
6782
7153
  var COLLAPSED_STYLE = {
6783
7154
  height: 0,
6784
7155
  paddingTop: 0,
6785
7156
  paddingBottom: 0,
6786
7157
  opacity: 0.5
6787
7158
  };
6788
- var LedgerAccountsRow = ({
7159
+ var ChartOfAccountsRow = ({
6789
7160
  account,
6790
7161
  depth = 0,
6791
7162
  index,
6792
7163
  cumulativeIndex = 0,
6793
7164
  expanded = false,
6794
7165
  defaultOpen = false,
6795
- acountsLength
7166
+ acountsLength,
7167
+ view
6796
7168
  }) => {
6797
- const { form, editAccount, setShowARForAccountId } = useContext9(
6798
- LedgerAccountsContext
6799
- );
6800
- const [isOpen, setIsOpen] = useState18(defaultOpen);
7169
+ const { form, editAccount } = useContext8(ChartOfAccountsContext);
7170
+ const { setAccountId } = useContext8(LedgerAccountsContext);
7171
+ const baseStyle = view === "desktop" ? EXPANDED_STYLE : EXPANDED_MOBILE_STYLE;
7172
+ const [isOpen, setIsOpen] = useState21(defaultOpen);
6801
7173
  const style = expanded ? {
6802
- ...EXPANDED_STYLE,
7174
+ ...baseStyle,
6803
7175
  transitionDelay: `${15 * index}ms`
6804
7176
  } : {
6805
7177
  ...COLLAPSED_STYLE,
6806
7178
  transitionDelay: `${acountsLength - 15 * index}ms`
6807
7179
  };
6808
- const [showComponent, setShowComponent] = useState18(false);
6809
- useEffect11(() => {
7180
+ const [showComponent, setShowComponent] = useState21(false);
7181
+ useEffect13(() => {
6810
7182
  const timeoutId = setTimeout(() => {
6811
7183
  setShowComponent(true);
6812
7184
  }, cumulativeIndex * 50);
@@ -6820,56 +7192,151 @@ var LedgerAccountsRow = ({
6820
7192
  form?.accountId === account.id && "Layer__table-row--active",
6821
7193
  !showComponent && "Layer__table-row--anim-starting-state"
6822
7194
  );
6823
- return /* @__PURE__ */ React85.createElement(React85.Fragment, null, /* @__PURE__ */ React85.createElement("tr", { className: baseClass, onClick: () => setIsOpen(!isOpen) }, /* @__PURE__ */ React85.createElement("td", { className: "Layer__table-cell Layer__coa__name" }, /* @__PURE__ */ React85.createElement("span", { className: "Layer__table-cell-content", style }, /* @__PURE__ */ React85.createElement(
6824
- "span",
6825
- {
6826
- className: "Layer__table-cell-content-indentation",
6827
- style: {
6828
- paddingLeft: INDENTATION * depth + 16
6829
- }
6830
- },
6831
- account.sub_accounts && account.sub_accounts.length > 0 && /* @__PURE__ */ React85.createElement(
6832
- ChevronDownFill_default,
6833
- {
6834
- size: 16,
6835
- className: "Layer__table__expand-icon"
6836
- }
6837
- ),
6838
- /* @__PURE__ */ React85.createElement("span", { className: "Layer__coa__name__text" }, account.name)
6839
- ))), /* @__PURE__ */ React85.createElement("td", { className: "Layer__table-cell Layer__coa__type" }, /* @__PURE__ */ React85.createElement("span", { className: "Layer__table-cell-content", style }, account.normality)), /* @__PURE__ */ React85.createElement("td", { className: "Layer__table-cell Layer__coa__subtype" }, /* @__PURE__ */ React85.createElement("span", { className: "Layer__table-cell-content", style }, "Sub-Type")), /* @__PURE__ */ React85.createElement("td", { className: "Layer__table-cell Layer__coa__balance" }, /* @__PURE__ */ React85.createElement(
6840
- "span",
6841
- {
6842
- className: "Layer__table-cell-content Layer__table-cell--amount",
6843
- style
6844
- },
6845
- "$",
6846
- centsToDollars(Math.abs(account.balance || 0))
6847
- )), /* @__PURE__ */ React85.createElement("td", { className: "Layer__table-cell Layer__coa__actions" }, /* @__PURE__ */ React85.createElement("span", { className: "Layer__table-cell-content", style }, /* @__PURE__ */ React85.createElement(
6848
- Button,
7195
+ const desktopRowClass = classNames30(
7196
+ baseClass,
7197
+ "Layer__chart-of-accounts__row---desktop"
7198
+ );
7199
+ const mobileRowClass = classNames30(
7200
+ baseClass,
7201
+ "Layer__chart-of-accounts__row---mobile"
7202
+ );
7203
+ return /* @__PURE__ */ React84.createElement(React84.Fragment, null, view === "desktop" && /* @__PURE__ */ React84.createElement(
7204
+ "tr",
6849
7205
  {
6850
- variant: "secondary" /* secondary */,
6851
- rightIcon: /* @__PURE__ */ React85.createElement(Edit2_default, { size: 12 }),
7206
+ className: desktopRowClass,
6852
7207
  onClick: (e) => {
6853
7208
  e.preventDefault();
6854
7209
  e.stopPropagation();
6855
- editAccount(account.id);
7210
+ setAccountId(account.id);
6856
7211
  }
6857
7212
  },
6858
- "Edit"
6859
- ), /* @__PURE__ */ React85.createElement(
6860
- Button,
7213
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell Layer__coa__name" }, /* @__PURE__ */ React84.createElement("span", { className: "Layer__table-cell-content", style }, /* @__PURE__ */ React84.createElement(
7214
+ "span",
7215
+ {
7216
+ className: "Layer__table-cell-content-indentation",
7217
+ style: {
7218
+ paddingLeft: INDENTATION * depth + 16
7219
+ }
7220
+ },
7221
+ account.sub_accounts && account.sub_accounts.length > 0 && /* @__PURE__ */ React84.createElement(
7222
+ ChevronDownFill_default,
7223
+ {
7224
+ size: 16,
7225
+ className: "Layer__table__expand-icon",
7226
+ onClick: (e) => {
7227
+ e.stopPropagation();
7228
+ setIsOpen(!isOpen);
7229
+ }
7230
+ }
7231
+ ),
7232
+ /* @__PURE__ */ React84.createElement("span", { className: "Layer__coa__name__text" }, account.name)
7233
+ ))),
7234
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell Layer__coa__type" }, /* @__PURE__ */ React84.createElement(
7235
+ "span",
7236
+ {
7237
+ className: "Layer__table-cell-content Layer__mobile--hidden",
7238
+ style
7239
+ },
7240
+ account.normality
7241
+ ), /* @__PURE__ */ React84.createElement(
7242
+ "span",
7243
+ {
7244
+ className: "Layer__table-cell-content Layer__desktop--hidden",
7245
+ style
7246
+ },
7247
+ /* @__PURE__ */ React84.createElement(
7248
+ Text,
7249
+ {
7250
+ weight: "bold" /* bold */,
7251
+ className: "Layer__coa__type--mobile"
7252
+ },
7253
+ account.normality
7254
+ ),
7255
+ /* @__PURE__ */ React84.createElement(Text, { className: "Layer__coa__subtype--mobile" }, "Sub-Type")
7256
+ )),
7257
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell Layer__coa__subtype Layer__mobile--hidden" }, /* @__PURE__ */ React84.createElement("span", { className: "Layer__table-cell-content", style }, "Sub-Type")),
7258
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell Layer__coa__balance" }, /* @__PURE__ */ React84.createElement(
7259
+ "span",
7260
+ {
7261
+ className: "Layer__table-cell-content Layer__table-cell--amount",
7262
+ style
7263
+ },
7264
+ "$",
7265
+ centsToDollars(Math.abs(account.balance || 0))
7266
+ )),
7267
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell Layer__coa__actions" }, /* @__PURE__ */ React84.createElement("span", { className: "Layer__table-cell-content", style }, /* @__PURE__ */ React84.createElement(
7268
+ Button,
7269
+ {
7270
+ variant: "secondary" /* secondary */,
7271
+ rightIcon: /* @__PURE__ */ React84.createElement(Edit2_default, { size: 12 }),
7272
+ iconOnly: true,
7273
+ onClick: (e) => {
7274
+ e.preventDefault();
7275
+ e.stopPropagation();
7276
+ editAccount(account.id);
7277
+ }
7278
+ },
7279
+ "Edit"
7280
+ )))
7281
+ ), view === "mobile" || view === "tablet" ? /* @__PURE__ */ React84.createElement(
7282
+ "tr",
6861
7283
  {
6862
- variant: "secondary" /* secondary */,
6863
- rightIcon: /* @__PURE__ */ React85.createElement(ArrowRightCircle_default, { size: 12 }),
7284
+ className: mobileRowClass,
6864
7285
  onClick: (e) => {
6865
7286
  e.preventDefault();
6866
7287
  e.stopPropagation();
6867
- setShowARForAccountId(account.id);
7288
+ setAccountId(account.id);
6868
7289
  }
6869
7290
  },
6870
- "Open"
6871
- )))), (account.sub_accounts || []).map((subAccount, idx) => /* @__PURE__ */ React85.createElement(
6872
- LedgerAccountsRow,
7291
+ /* @__PURE__ */ React84.createElement("td", { className: "Layer__table-cell", colSpan: 5 }, /* @__PURE__ */ React84.createElement(
7292
+ "span",
7293
+ {
7294
+ className: "Layer__table-cell-content Layer__table-cell-content-indentation",
7295
+ style: {
7296
+ paddingLeft: MOBILE_INDENTATION * depth + 16,
7297
+ ...style
7298
+ }
7299
+ },
7300
+ account.sub_accounts && account.sub_accounts.length > 0 && /* @__PURE__ */ React84.createElement(
7301
+ ChevronDownFill_default,
7302
+ {
7303
+ size: 16,
7304
+ className: "Layer__table__expand-icon",
7305
+ onClick: (e) => {
7306
+ e.stopPropagation();
7307
+ setIsOpen(!isOpen);
7308
+ }
7309
+ }
7310
+ ),
7311
+ /* @__PURE__ */ React84.createElement("div", { className: "Layer__chart-of-accounts__mobile-row-content" }, /* @__PURE__ */ React84.createElement("div", { className: "Layer__chart-of-accounts__mobile-row-content__top-row" }, /* @__PURE__ */ React84.createElement(
7312
+ Text,
7313
+ {
7314
+ as: "span",
7315
+ className: "Layer__chart-of-accounts__mobile-row-content__name"
7316
+ },
7317
+ account.name
7318
+ ), /* @__PURE__ */ React84.createElement(
7319
+ TextButton,
7320
+ {
7321
+ onClick: (e) => {
7322
+ e.preventDefault();
7323
+ e.stopPropagation();
7324
+ editAccount(account.id);
7325
+ }
7326
+ },
7327
+ "Edit"
7328
+ )), /* @__PURE__ */ React84.createElement("div", { className: "Layer__chart-of-accounts__mobile-row-content__bottom-row" }, /* @__PURE__ */ React84.createElement("div", { className: "Layer__chart-of-accounts__mobile-row-content__types" }, /* @__PURE__ */ React84.createElement(Text, { as: "span" }, account.normality), /* @__PURE__ */ React84.createElement("span", { className: "Layer__chart-of-accounts__mobile-row-content__separator" }), /* @__PURE__ */ React84.createElement(Text, { as: "span" }, "Sub-Type")), /* @__PURE__ */ React84.createElement(
7329
+ Text,
7330
+ {
7331
+ as: "span",
7332
+ className: "Layer__chart-of-accounts__mobile-row-content__balance"
7333
+ },
7334
+ "$",
7335
+ centsToDollars(Math.abs(account.balance || 0))
7336
+ )))
7337
+ ))
7338
+ ) : null, (account.sub_accounts || []).map((subAccount, idx) => /* @__PURE__ */ React84.createElement(
7339
+ ChartOfAccountsRow,
6873
7340
  {
6874
7341
  key: subAccount.id,
6875
7342
  account: subAccount,
@@ -6877,16 +7344,19 @@ var LedgerAccountsRow = ({
6877
7344
  index: idx,
6878
7345
  expanded: isOpen && expanded,
6879
7346
  cumulativeIndex: cumulativeIndex + idx + 1,
6880
- acountsLength: (account.sub_accounts ?? []).length
7347
+ acountsLength: (account.sub_accounts ?? []).length,
7348
+ view
6881
7349
  }
6882
7350
  )));
6883
7351
  };
6884
7352
 
6885
- // src/components/LedgerAccountsSidebar/LedgerAccountsSidebar.tsx
6886
- import React87, { useContext as useContext11 } from "react";
7353
+ // src/components/ChartOfAccountsSidebar/ChartOfAccountsSidebar.tsx
7354
+ import React87 from "react";
6887
7355
 
6888
- // src/components/LedgerAccountsForm/LedgerAccountsForm.tsx
6889
- import React86, { useContext as useContext10, useMemo as useMemo8 } from "react";
7356
+ // src/components/ChartOfAccountsForm/ChartOfAccountsForm.tsx
7357
+ import React86, { useContext as useContext9, useMemo as useMemo8 } from "react";
7358
+
7359
+ // src/components/ChartOfAccountsForm/constants.ts
6890
7360
  var SUB_TYPE_OPTIONS = [
6891
7361
  {
6892
7362
  value: "DEBIT" /* DEBIT */,
@@ -6897,7 +7367,21 @@ var SUB_TYPE_OPTIONS = [
6897
7367
  label: "Credit"
6898
7368
  }
6899
7369
  ];
6900
- var LedgerAccountsForm = () => {
7370
+
7371
+ // src/components/ChartOfAccountsForm/useParentOptions.ts
7372
+ import { useMemo as useMemo7 } from "react";
7373
+ var useParentOptions = (data) => useMemo7(
7374
+ () => flattenAccounts(data?.accounts || []).sort((a, b) => a?.name && b?.name ? a.name.localeCompare(b.name) : 0).map((x) => {
7375
+ return {
7376
+ label: x.name,
7377
+ value: x.id
7378
+ };
7379
+ }),
7380
+ [data?.accounts?.length]
7381
+ );
7382
+
7383
+ // src/components/ChartOfAccountsForm/ChartOfAccountsForm.tsx
7384
+ var ChartOfAccountsForm = () => {
6901
7385
  const {
6902
7386
  form,
6903
7387
  data,
@@ -6906,16 +7390,8 @@ var LedgerAccountsForm = () => {
6906
7390
  submitForm,
6907
7391
  sendingForm,
6908
7392
  apiError
6909
- } = useContext10(LedgerAccountsContext);
6910
- const parentOptions = useMemo8(
6911
- () => flattenAccounts(data?.accounts || []).sort((a, b) => a?.name && b?.name ? a.name.localeCompare(b.name) : 0).map((x) => {
6912
- return {
6913
- label: x.name,
6914
- value: x.id
6915
- };
6916
- }),
6917
- [data?.accounts?.length]
6918
- );
7393
+ } = useContext9(ChartOfAccountsContext);
7394
+ const parentOptions = useParentOptions(data);
6919
7395
  const entry = useMemo8(() => {
6920
7396
  if (form?.action === "edit" && form.accountId) {
6921
7397
  return flattenAccounts(data?.accounts || []).find(
@@ -6936,7 +7412,7 @@ var LedgerAccountsForm = () => {
6936
7412
  submitForm();
6937
7413
  }
6938
7414
  },
6939
- /* @__PURE__ */ React86.createElement("div", { className: "Layer__ledger-accounts__sidebar__header" }, /* @__PURE__ */ React86.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, form?.action === "edit" ? "Edit" : "Add New", " Account"), /* @__PURE__ */ React86.createElement("div", { className: "actions" }, /* @__PURE__ */ React86.createElement(
7415
+ /* @__PURE__ */ React86.createElement("div", { className: "Layer__chart-of-accounts__sidebar__header" }, /* @__PURE__ */ React86.createElement(Text, { size: "lg" /* lg */, weight: "bold" /* bold */, className: "title" }, form?.action === "edit" ? "Edit" : "Add New", " Account"), /* @__PURE__ */ React86.createElement("div", { className: "actions" }, /* @__PURE__ */ React86.createElement(
6940
7416
  Button,
6941
7417
  {
6942
7418
  type: "button",
@@ -6968,12 +7444,12 @@ var LedgerAccountsForm = () => {
6968
7444
  Text,
6969
7445
  {
6970
7446
  size: "sm" /* sm */,
6971
- className: "Layer__ledger-accounts__form__error-message"
7447
+ className: "Layer__chart-of-accounts__form__error-message"
6972
7448
  },
6973
7449
  apiError
6974
7450
  ),
6975
- entry && /* @__PURE__ */ React86.createElement("div", { className: "Layer__ledger-accounts__form-edit-entry" }, /* @__PURE__ */ React86.createElement(Text, { weight: "bold" /* bold */ }, entry.name), /* @__PURE__ */ React86.createElement(Text, { weight: "bold" /* bold */ }, "$", centsToDollars(entry.balance || 0))),
6976
- /* @__PURE__ */ React86.createElement("div", { className: "Layer__ledger-accounts__form" }, /* @__PURE__ */ React86.createElement(InputGroup, { name: "parent", label: "Parent", inline: true }, /* @__PURE__ */ React86.createElement(
7451
+ entry && /* @__PURE__ */ React86.createElement("div", { className: "Layer__chart-of-accounts__form-edit-entry" }, /* @__PURE__ */ React86.createElement(Text, { weight: "bold" /* bold */ }, entry.name), /* @__PURE__ */ React86.createElement(Text, { weight: "bold" /* bold */ }, "$", centsToDollars(entry.balance || 0))),
7452
+ /* @__PURE__ */ React86.createElement("div", { className: "Layer__chart-of-accounts__form" }, /* @__PURE__ */ React86.createElement(InputGroup, { name: "parent", label: "Parent", inline: true }, /* @__PURE__ */ React86.createElement(
6977
7453
  Select2,
6978
7454
  {
6979
7455
  options: parentOptions,
@@ -7020,107 +7496,505 @@ var LedgerAccountsForm = () => {
7020
7496
  );
7021
7497
  };
7022
7498
 
7023
- // src/components/LedgerAccountsSidebar/LedgerAccountsSidebar.tsx
7499
+ // src/components/ChartOfAccountsSidebar/ChartOfAccountsSidebar.tsx
7500
+ var ChartOfAccountsSidebar = ({
7501
+ parentRef: _parentRef
7502
+ }) => {
7503
+ return /* @__PURE__ */ React87.createElement(ChartOfAccountsForm, null);
7504
+ };
7505
+
7506
+ // src/components/ChartOfAccountsTable/ChartOfAccountsTable.tsx
7507
+ var COMPONENT_NAME4 = "chart-of-accounts";
7508
+ var ChartOfAccountsTable = ({
7509
+ view,
7510
+ containerRef
7511
+ }) => {
7512
+ const { data, isLoading, addAccount, error, isValidating, refetch, form } = useContext10(ChartOfAccountsContext);
7513
+ let cumulativeIndex = 0;
7514
+ const accountsLength = data?.accounts.length ?? 0;
7515
+ return /* @__PURE__ */ React88.createElement(
7516
+ Panel,
7517
+ {
7518
+ sidebar: /* @__PURE__ */ React88.createElement(ChartOfAccountsSidebar, { parentRef: containerRef }),
7519
+ sidebarIsOpen: Boolean(form),
7520
+ parentRef: containerRef
7521
+ },
7522
+ /* @__PURE__ */ React88.createElement(Header, { className: `Layer__${COMPONENT_NAME4}__header` }, /* @__PURE__ */ React88.createElement(Heading, { className: `Layer__${COMPONENT_NAME4}__title` }, "Chart of Accounts"), /* @__PURE__ */ React88.createElement("div", { className: `Layer__${COMPONENT_NAME4}__actions` }, /* @__PURE__ */ React88.createElement(
7523
+ Button,
7524
+ {
7525
+ variant: "secondary" /* secondary */,
7526
+ disabled: isLoading,
7527
+ rightIcon: /* @__PURE__ */ React88.createElement(DownloadCloud_default, { size: 12 })
7528
+ },
7529
+ "Download"
7530
+ ), /* @__PURE__ */ React88.createElement(Button, { onClick: () => addAccount(), disabled: isLoading }, "Add Account"))),
7531
+ /* @__PURE__ */ React88.createElement("table", { className: "Layer__chart-of-accounts__table" }, /* @__PURE__ */ React88.createElement("thead", null, /* @__PURE__ */ React88.createElement("tr", { className: "Layer__table-row--header" }, /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__name" }, "Name"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__type" }, "Type"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__subtype Layer__mobile--hidden" }, "Sub-Type"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__balance" }, "Balance"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__actions" }))), /* @__PURE__ */ React88.createElement("tbody", null, !error && data?.accounts.map((account, idx) => {
7532
+ const currentCumulativeIndex = cumulativeIndex;
7533
+ cumulativeIndex = (account.sub_accounts?.length || 0) + cumulativeIndex + 1;
7534
+ return /* @__PURE__ */ React88.createElement(
7535
+ ChartOfAccountsRow,
7536
+ {
7537
+ key: account.id,
7538
+ account,
7539
+ depth: 0,
7540
+ index: idx,
7541
+ cumulativeIndex: currentCumulativeIndex,
7542
+ expanded: true,
7543
+ defaultOpen: true,
7544
+ acountsLength: accountsLength,
7545
+ view
7546
+ }
7547
+ );
7548
+ }))),
7549
+ error ? /* @__PURE__ */ React88.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React88.createElement(
7550
+ DataState,
7551
+ {
7552
+ status: "failed" /* failed */,
7553
+ title: "Something went wrong",
7554
+ description: "We couldn\u2019t load your data.",
7555
+ onRefresh: () => refetch(),
7556
+ isLoading: isValidating || isLoading
7557
+ }
7558
+ )) : null,
7559
+ (!data || isLoading) && !error ? /* @__PURE__ */ React88.createElement("div", { className: `Layer__${COMPONENT_NAME4}__loader-container` }, /* @__PURE__ */ React88.createElement(Loader2, null)) : null,
7560
+ !isLoading && !error && data?.accounts.length === 0 ? /* @__PURE__ */ React88.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React88.createElement(
7561
+ DataState,
7562
+ {
7563
+ status: "info" /* info */,
7564
+ title: "Accounts were not found",
7565
+ description: 'New account can be created with "Add Account".',
7566
+ onRefresh: () => refetch(),
7567
+ isLoading: isValidating
7568
+ }
7569
+ )) : null
7570
+ );
7571
+ };
7572
+
7573
+ // src/components/LedgerAccount/LedgerAccountIndex.tsx
7574
+ import React95, {
7575
+ useContext as useContext13,
7576
+ useEffect as useEffect15,
7577
+ useMemo as useMemo10,
7578
+ useState as useState23
7579
+ } from "react";
7580
+
7581
+ // src/components/LedgerAccountEntryDetails/LedgerAccountEntryDetails.tsx
7582
+ import React93, { useContext as useContext11, useMemo as useMemo9 } from "react";
7583
+
7584
+ // src/components/Card/Card.tsx
7585
+ import React89 from "react";
7024
7586
  import classNames31 from "classnames";
7025
- var LedgerAccountsSidebar = () => {
7026
- const { form } = useContext11(LedgerAccountsContext);
7027
- return /* @__PURE__ */ React87.createElement(
7028
- "div",
7587
+ var Card = ({ children, className }) => {
7588
+ return /* @__PURE__ */ React89.createElement("div", { className: classNames31("Layer__card", className) }, children);
7589
+ };
7590
+
7591
+ // src/components/DateTime/DateTime.tsx
7592
+ import React90 from "react";
7593
+ import { parseISO as parseISO9, format as formatTime7 } from "date-fns";
7594
+ var DateTime = ({
7595
+ value,
7596
+ format: format7,
7597
+ dateFormat,
7598
+ timeFormat,
7599
+ onlyDate,
7600
+ onlyTime
7601
+ }) => {
7602
+ if (format7) {
7603
+ return /* @__PURE__ */ React90.createElement(Text, { className: "Layer__datetime" }, formatTime7(parseISO9(value), format7));
7604
+ }
7605
+ const date = formatTime7(parseISO9(value), dateFormat ?? DATE_FORMAT);
7606
+ const time = formatTime7(parseISO9(value), timeFormat ?? TIME_FORMAT);
7607
+ return /* @__PURE__ */ React90.createElement(Text, { className: "Layer__datetime" }, !onlyTime && /* @__PURE__ */ React90.createElement(
7608
+ Text,
7609
+ {
7610
+ as: "span",
7611
+ weight: "bold" /* bold */,
7612
+ size: "sm" /* sm */,
7613
+ className: "Layer__datetime__date"
7614
+ },
7615
+ date
7616
+ ), !onlyDate && /* @__PURE__ */ React90.createElement(
7617
+ Text,
7029
7618
  {
7030
- className: classNames31(
7031
- "Layer__ledger-accounts__sidebar",
7032
- form ? "open" : ""
7619
+ as: "span",
7620
+ weight: "bold" /* bold */,
7621
+ size: "sm" /* sm */,
7622
+ className: "Layer__datetime__time"
7623
+ },
7624
+ time
7625
+ ));
7626
+ };
7627
+
7628
+ // src/components/DetailsList/DetailsList.tsx
7629
+ import React91 from "react";
7630
+ import classNames32 from "classnames";
7631
+ var DetailsList = ({
7632
+ title,
7633
+ children,
7634
+ className,
7635
+ actions
7636
+ }) => {
7637
+ return /* @__PURE__ */ React91.createElement("div", { className: classNames32("Layer__details-list", className) }, title && /* @__PURE__ */ React91.createElement(Header, null, /* @__PURE__ */ React91.createElement(Heading, { size: "secondary" /* secondary */ }, title), actions && /* @__PURE__ */ React91.createElement("div", { className: "Layer__details-list__actions" }, actions)), /* @__PURE__ */ React91.createElement("ul", { className: "Layer__details-list__list" }, children));
7638
+ };
7639
+
7640
+ // src/components/DetailsList/DetailsListItem.tsx
7641
+ import React92 from "react";
7642
+ var renderValue = (value) => {
7643
+ if (typeof value === "string") {
7644
+ return /* @__PURE__ */ React92.createElement(Text, { weight: "bold" /* bold */, size: "sm" /* sm */ }, value);
7645
+ }
7646
+ return value;
7647
+ };
7648
+ var DetailsListItem = ({
7649
+ label,
7650
+ children,
7651
+ isLoading
7652
+ }) => {
7653
+ return /* @__PURE__ */ React92.createElement("li", { className: "Layer__details-list-item" }, /* @__PURE__ */ React92.createElement("label", { className: "Layer__details-list-item__label" }, label), /* @__PURE__ */ React92.createElement("span", { className: "Layer__details-list-item__value" }, isLoading ? /* @__PURE__ */ React92.createElement(SkeletonLoader, null) : renderValue(children)));
7654
+ };
7655
+
7656
+ // src/components/LedgerAccountEntryDetails/LedgerAccountEntryDetails.tsx
7657
+ var LedgerAccountEntryDetails = () => {
7658
+ const { entryData, isLoadingEntry, closeSelectedEntry, errorEntry } = useContext11(LedgerAccountsContext);
7659
+ const { totalDebit, totalCredit } = useMemo9(() => {
7660
+ let totalDebit2 = 0;
7661
+ let totalCredit2 = 0;
7662
+ entryData?.line_items?.forEach((item) => {
7663
+ if (item.direction === "CREDIT" /* CREDIT */) {
7664
+ totalCredit2 += item.amount || 0;
7665
+ } else if (item.direction === "DEBIT" /* DEBIT */) {
7666
+ totalDebit2 += item.amount || 0;
7667
+ }
7668
+ });
7669
+ return { totalDebit: totalDebit2, totalCredit: totalCredit2 };
7670
+ }, [entryData]);
7671
+ return /* @__PURE__ */ React93.createElement("div", { className: "Layer__ledger-account__entry-details" }, /* @__PURE__ */ React93.createElement("div", { className: "Layer__ledger-account__entry-details__back-btn" }, /* @__PURE__ */ React93.createElement(BackButton, { onClick: () => closeSelectedEntry() })), /* @__PURE__ */ React93.createElement(
7672
+ DetailsList,
7673
+ {
7674
+ title: "Transaction source",
7675
+ actions: /* @__PURE__ */ React93.createElement(
7676
+ IconButton,
7677
+ {
7678
+ icon: /* @__PURE__ */ React93.createElement(X_default, null),
7679
+ onClick: () => closeSelectedEntry(),
7680
+ className: "Layer__hidden-sm Layer__hidden-xs"
7681
+ }
7033
7682
  )
7034
7683
  },
7035
- /* @__PURE__ */ React87.createElement("div", { className: "Layer__ledger-accounts__sidebar-content" }, /* @__PURE__ */ React87.createElement(LedgerAccountsForm, null))
7684
+ /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Source", isLoading: isLoadingEntry }, /* @__PURE__ */ React93.createElement(Badge, null, "Invoice")),
7685
+ /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Number", isLoading: isLoadingEntry }, "1234"),
7686
+ /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Date", isLoading: isLoadingEntry }, "May 5, 2023"),
7687
+ /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Account", isLoading: isLoadingEntry }, "89 8888 7656 6666 0000 6765")
7688
+ ), /* @__PURE__ */ React93.createElement(DetailsList, { title: "Journal Entry #123", className: "Layer__border-top" }, /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Entry type", isLoading: isLoadingEntry }, humanizeEnum(entryData?.entry_type ?? "")), /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Date", isLoading: isLoadingEntry }, entryData?.entry_at && /* @__PURE__ */ React93.createElement(DateTime, { value: entryData?.entry_at })), /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Creation date", isLoading: isLoadingEntry }, entryData?.date && /* @__PURE__ */ React93.createElement(DateTime, { value: entryData?.date })), /* @__PURE__ */ React93.createElement(DetailsListItem, { label: "Reversal", isLoading: isLoadingEntry }, "Journal Entry #79 TBD")), !isLoadingEntry && !errorEntry ? /* @__PURE__ */ React93.createElement("div", { className: "Layer__ledger-account__entry-details__line-items" }, /* @__PURE__ */ React93.createElement(Card, null, /* @__PURE__ */ React93.createElement("table", { className: "Layer__table Layer__ledger-account__entry-details__table" }, /* @__PURE__ */ React93.createElement("thead", null, /* @__PURE__ */ React93.createElement("tr", null, /* @__PURE__ */ React93.createElement("th", { className: "Layer__table-header" }, "Line items"), /* @__PURE__ */ React93.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Debit"), /* @__PURE__ */ React93.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Credit"))), /* @__PURE__ */ React93.createElement("tbody", null, entryData?.line_items?.map((item) => /* @__PURE__ */ React93.createElement("tr", { key: `ledger-line-item-${item.id}` }, /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell" }, item.account?.name || ""), /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, item.direction === "DEBIT" /* DEBIT */ && /* @__PURE__ */ React93.createElement(Badge, { variant: "warning" /* WARNING */ }, "$", centsToDollars(item.amount || 0))), /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, item.direction === "CREDIT" /* CREDIT */ && /* @__PURE__ */ React93.createElement(Badge, { variant: "success" /* SUCCESS */ }, "$", centsToDollars(item.amount || 0))))), /* @__PURE__ */ React93.createElement("tr", { className: "Layer__table Layer__ledger-account__entry-details__table__total-row" }, /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell" }, "Total"), /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, "$", centsToDollars(totalDebit || 0)), /* @__PURE__ */ React93.createElement("td", { className: "Layer__table-cell Layer__table-cell--amount" }, "$", centsToDollars(totalCredit || 0))))))) : null);
7689
+ };
7690
+
7691
+ // src/components/LedgerAccount/LedgerAccountRow.tsx
7692
+ import React94, { useContext as useContext12, useEffect as useEffect14, useState as useState22 } from "react";
7693
+ import classNames33 from "classnames";
7694
+ import { parseISO as parseISO10, format as formatTime8 } from "date-fns";
7695
+ var LedgerAccountRow = ({
7696
+ row,
7697
+ index,
7698
+ initialLoad,
7699
+ view
7700
+ }) => {
7701
+ const { selectedEntryId, setSelectedEntryId, closeSelectedEntry } = useContext12(LedgerAccountsContext);
7702
+ const [showComponent, setShowComponent] = useState22(false);
7703
+ useEffect14(() => {
7704
+ if (initialLoad) {
7705
+ const timeoutId = setTimeout(() => {
7706
+ setShowComponent(true);
7707
+ }, index * 10);
7708
+ return () => clearTimeout(timeoutId);
7709
+ } else {
7710
+ setShowComponent(true);
7711
+ }
7712
+ }, []);
7713
+ if (view === "tablet") {
7714
+ return /* @__PURE__ */ React94.createElement(
7715
+ "tr",
7716
+ {
7717
+ className: classNames33(
7718
+ "Layer__table-row",
7719
+ row.entry_id === selectedEntryId && "Layer__table-row--active",
7720
+ initialLoad && "initial-load",
7721
+ "Layer__table-row--with-show",
7722
+ showComponent ? "show" : "Layer__table-row--anim-starting-state"
7723
+ ),
7724
+ style: { transitionDelay: `${15 * index}ms` },
7725
+ onClick: () => {
7726
+ if (selectedEntryId === row.entry_id) {
7727
+ closeSelectedEntry();
7728
+ } else {
7729
+ setSelectedEntryId(row.entry_id);
7730
+ }
7731
+ }
7732
+ },
7733
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__ledger-account-table__tablet-main-col" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content" }, /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger-account-table__tablet-main-col__date" }, /* @__PURE__ */ React94.createElement(Text, null, row.date && formatTime8(parseISO10(row.date), DATE_FORMAT)), /* @__PURE__ */ React94.createElement(
7734
+ Text,
7735
+ {
7736
+ weight: "bold" /* bold */,
7737
+ className: "Layer__ledger_account-table__journal-id"
7738
+ },
7739
+ "#123"
7740
+ )), /* @__PURE__ */ React94.createElement(Text, null, "Invoice (TBD null)"))),
7741
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, row.direction === "DEBIT" /* DEBIT */ && `$${centsToDollars(row?.amount || 0)}`)),
7742
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, row.direction === "CREDIT" /* CREDIT */ && `$${centsToDollars(row?.amount || 0)}`)),
7743
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, "$X,XXX.XX"))
7744
+ );
7745
+ }
7746
+ if (view === "mobile") {
7747
+ return /* @__PURE__ */ React94.createElement(
7748
+ "tr",
7749
+ {
7750
+ className: classNames33(
7751
+ "Layer__table-row",
7752
+ row.entry_id === selectedEntryId && "Layer__table-row--active",
7753
+ initialLoad && "initial-load",
7754
+ "Layer__table-row--with-show",
7755
+ showComponent ? "show" : "Layer__table-row--anim-starting-state"
7756
+ ),
7757
+ style: { transitionDelay: `${15 * index}ms` },
7758
+ onClick: () => {
7759
+ if (selectedEntryId === row.entry_id) {
7760
+ closeSelectedEntry();
7761
+ } else {
7762
+ setSelectedEntryId(row.entry_id);
7763
+ }
7764
+ }
7765
+ },
7766
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__ledger-account-table__tablet-main-col" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content" }, /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger-account-table__tablet-main-col__date" }, /* @__PURE__ */ React94.createElement(Text, null, row.date && formatTime8(parseISO10(row.date), DATE_FORMAT)), /* @__PURE__ */ React94.createElement(
7767
+ Text,
7768
+ {
7769
+ weight: "bold" /* bold */,
7770
+ className: "Layer__ledger_account-table__journal-id"
7771
+ },
7772
+ "#123"
7773
+ )), /* @__PURE__ */ React94.createElement(Text, null, "Invoice (TBD null)"), /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger_account-table__balances-mobile" }, /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger_account-table__balance-item" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__label" }, "Debit"), /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__value" }, " ", row.direction === "DEBIT" /* DEBIT */ && `$${centsToDollars(row?.amount || 0)}`)), /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger_account-table__balance-item" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__label" }, "Credit"), /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__value" }, row.direction === "CREDIT" /* CREDIT */ && `$${centsToDollars(row?.amount || 0)}`)), /* @__PURE__ */ React94.createElement("div", { className: "Layer__ledger_account-table__balance-item" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__label" }, "Running balance"), /* @__PURE__ */ React94.createElement("span", { className: "Layer__ledger_account-table__balances-mobile__value" }, "$X,XXX.XX")))))
7774
+ );
7775
+ }
7776
+ return /* @__PURE__ */ React94.createElement(
7777
+ "tr",
7778
+ {
7779
+ className: classNames33(
7780
+ "Layer__table-row",
7781
+ row.entry_id === selectedEntryId && "Layer__table-row--active",
7782
+ initialLoad && "initial-load",
7783
+ "Layer__table-row--with-show",
7784
+ showComponent ? "show" : "Layer__table-row--anim-starting-state"
7785
+ ),
7786
+ style: { transitionDelay: `${15 * index}ms` },
7787
+ onClick: () => {
7788
+ if (selectedEntryId === row.entry_id) {
7789
+ closeSelectedEntry();
7790
+ } else {
7791
+ setSelectedEntryId(row.entry_id);
7792
+ }
7793
+ }
7794
+ },
7795
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content" }, row.date && formatTime8(parseISO10(row.date), DATE_FORMAT))),
7796
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content" }, "#123")),
7797
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content" }, "Invoice (TBD null)")),
7798
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, row.direction === "DEBIT" /* DEBIT */ && `$${centsToDollars(row?.amount || 0)}`)),
7799
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, row.direction === "CREDIT" /* CREDIT */ && `$${centsToDollars(row?.amount || 0)}`)),
7800
+ /* @__PURE__ */ React94.createElement("td", { className: "Layer__table-cell Layer__table-cell--primary" }, /* @__PURE__ */ React94.createElement("span", { className: "Layer__table-cell-content Layer__table-cell--amount" }, "$X,XXX.XX"))
7801
+ );
7802
+ };
7803
+
7804
+ // src/components/LedgerAccount/LedgerAccountIndex.tsx
7805
+ import classNames34 from "classnames";
7806
+ var LedgerAccount = ({
7807
+ containerRef,
7808
+ pageSize = 15,
7809
+ view
7810
+ }) => {
7811
+ const [currentPage, setCurrentPage] = useState23(1);
7812
+ const [initialLoad, setInitialLoad] = useState23(true);
7813
+ const { data: accountData } = useContext13(ChartOfAccountsContext);
7814
+ const {
7815
+ data: rawData,
7816
+ error,
7817
+ isLoading,
7818
+ isValidating,
7819
+ accountId,
7820
+ setAccountId,
7821
+ selectedEntryId,
7822
+ closeSelectedEntry,
7823
+ refetch
7824
+ } = useContext13(LedgerAccountsContext);
7825
+ useEffect15(() => {
7826
+ if (!isLoading) {
7827
+ const timeoutLoad = setTimeout(() => {
7828
+ setInitialLoad(false);
7829
+ }, 1e3);
7830
+ return () => clearTimeout(timeoutLoad);
7831
+ }
7832
+ }, [isLoading]);
7833
+ const baseClassName = classNames34(
7834
+ "Layer__ledger-account__index",
7835
+ accountId && "open"
7836
+ );
7837
+ const entry = useMemo10(() => {
7838
+ return flattenAccounts(accountData?.accounts || []).find(
7839
+ (x) => x.id === accountId
7840
+ );
7841
+ }, [accountId]);
7842
+ const data = useMemo10(() => {
7843
+ const firstPageIndex = (currentPage - 1) * pageSize;
7844
+ const lastPageIndex = firstPageIndex + pageSize;
7845
+ return rawData?.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))?.slice(firstPageIndex, lastPageIndex);
7846
+ }, [rawData, currentPage]);
7847
+ const close = () => {
7848
+ setAccountId(void 0);
7849
+ closeSelectedEntry();
7850
+ };
7851
+ return /* @__PURE__ */ React95.createElement(
7852
+ Panel,
7853
+ {
7854
+ sidebar: /* @__PURE__ */ React95.createElement(LedgerAccountEntryDetails, null),
7855
+ sidebarIsOpen: Boolean(selectedEntryId),
7856
+ parentRef: containerRef,
7857
+ className: "Layer__ledger-account__panel"
7858
+ },
7859
+ /* @__PURE__ */ React95.createElement("div", { className: baseClassName }, /* @__PURE__ */ React95.createElement("div", { className: "Layer__ledger-account__header" }, /* @__PURE__ */ React95.createElement(BackButton, { onClick: close }), /* @__PURE__ */ React95.createElement("div", { className: "Layer__ledger-account__title-container" }, /* @__PURE__ */ React95.createElement(
7860
+ Text,
7861
+ {
7862
+ weight: "bold" /* bold */,
7863
+ className: "Layer__ledger-account__title"
7864
+ },
7865
+ entry?.name ?? ""
7866
+ ), /* @__PURE__ */ React95.createElement(
7867
+ Button,
7868
+ {
7869
+ variant: "secondary" /* secondary */,
7870
+ rightIcon: /* @__PURE__ */ React95.createElement(DownloadCloud_default, { size: 12 })
7871
+ },
7872
+ "Download"
7873
+ )), /* @__PURE__ */ React95.createElement("div", { className: "Layer__ledger-account__balance-container" }, /* @__PURE__ */ React95.createElement(
7874
+ Text,
7875
+ {
7876
+ weight: "bold" /* bold */,
7877
+ className: "Layer__ledger-account__balance-label"
7878
+ },
7879
+ "Current balance"
7880
+ ), /* @__PURE__ */ React95.createElement(
7881
+ Text,
7882
+ {
7883
+ weight: "bold" /* bold */,
7884
+ className: "Layer__ledger-account__balance-value"
7885
+ },
7886
+ "$",
7887
+ centsToDollars(entry?.balance || 0)
7888
+ ))), /* @__PURE__ */ React95.createElement("table", { className: "Layer__table Layer__table--hover-effect Layer__ledger-account-table" }, /* @__PURE__ */ React95.createElement("thead", null, /* @__PURE__ */ React95.createElement("tr", null, view !== "desktop" && /* @__PURE__ */ React95.createElement("th", null), view === "desktop" && /* @__PURE__ */ React95.createElement(React95.Fragment, null, /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header" }, "Date"), /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header" }, "Journal id #"), /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header" }, "Source")), view !== "mobile" && /* @__PURE__ */ React95.createElement(React95.Fragment, null, /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Debit"), /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Credit"), /* @__PURE__ */ React95.createElement("th", { className: "Layer__table-header Layer__table-cell--amount" }, "Running balance")))), /* @__PURE__ */ React95.createElement("tbody", null, data?.map((x, index) => /* @__PURE__ */ React95.createElement(
7889
+ LedgerAccountRow,
7890
+ {
7891
+ key: x.id,
7892
+ row: x,
7893
+ index,
7894
+ initialLoad,
7895
+ view
7896
+ }
7897
+ )))), data && /* @__PURE__ */ React95.createElement("div", { className: "Layer__ledger-account__pagination" }, /* @__PURE__ */ React95.createElement(
7898
+ Pagination,
7899
+ {
7900
+ currentPage,
7901
+ totalCount: rawData?.length || 0,
7902
+ pageSize,
7903
+ onPageChange: (page) => setCurrentPage(page)
7904
+ }
7905
+ )), error ? /* @__PURE__ */ React95.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React95.createElement(
7906
+ DataState,
7907
+ {
7908
+ status: "failed" /* failed */,
7909
+ title: "Something went wrong",
7910
+ description: "We couldn\u2019t load your data.",
7911
+ onRefresh: () => refetch(),
7912
+ isLoading: isValidating || isLoading
7913
+ }
7914
+ )) : null, (!data || isLoading) && !error ? /* @__PURE__ */ React95.createElement("div", { className: `Layer__ledger-account__loader-container` }, /* @__PURE__ */ React95.createElement(Loader2, null)) : null, !isLoading && !error && data?.length === 0 ? /* @__PURE__ */ React95.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React95.createElement(
7915
+ DataState,
7916
+ {
7917
+ status: "info" /* info */,
7918
+ title: "No records found",
7919
+ onRefresh: () => refetch(),
7920
+ isLoading: isValidating
7921
+ }
7922
+ )) : null)
7036
7923
  );
7037
7924
  };
7038
7925
 
7039
- // src/components/LedgerAccounts/LedgerAccounts.tsx
7040
- var COMPONENT_NAME4 = "ledger-accounts";
7926
+ // src/components/ChartOfAccounts/ChartOfAccounts.tsx
7927
+ var ChartOfAccountsContext = createContext3(
7928
+ {
7929
+ data: void 0,
7930
+ isLoading: false,
7931
+ isValidating: false,
7932
+ error: void 0,
7933
+ refetch: () => {
7934
+ },
7935
+ create: () => {
7936
+ },
7937
+ form: void 0,
7938
+ sendingForm: false,
7939
+ apiError: void 0,
7940
+ addAccount: () => {
7941
+ },
7942
+ editAccount: () => {
7943
+ },
7944
+ cancelForm: () => {
7945
+ },
7946
+ changeFormData: () => {
7947
+ },
7948
+ submitForm: () => {
7949
+ }
7950
+ }
7951
+ );
7041
7952
  var LedgerAccountsContext = createContext3({
7042
7953
  data: void 0,
7954
+ entryData: void 0,
7043
7955
  isLoading: false,
7956
+ isLoadingEntry: false,
7044
7957
  isValidating: false,
7958
+ isValidatingEntry: false,
7045
7959
  error: void 0,
7960
+ errorEntry: void 0,
7046
7961
  refetch: () => {
7047
7962
  },
7048
- create: () => {
7049
- },
7050
- form: void 0,
7051
- sendingForm: false,
7052
- apiError: void 0,
7053
- addAccount: () => {
7054
- },
7055
- editAccount: () => {
7963
+ accountId: void 0,
7964
+ setAccountId: () => {
7056
7965
  },
7057
- cancelForm: () => {
7966
+ selectedEntryId: void 0,
7967
+ setSelectedEntryId: () => {
7058
7968
  },
7059
- changeFormData: () => {
7060
- },
7061
- submitForm: () => {
7062
- },
7063
- showARForAccountId: void 0,
7064
- setShowARForAccountId: () => {
7969
+ closeSelectedEntry: () => {
7065
7970
  }
7066
7971
  });
7067
- var LedgerAccounts = () => {
7068
- const contextData = useLedgerAccounts();
7069
- return /* @__PURE__ */ React88.createElement(LedgerAccountsContext.Provider, { value: contextData }, /* @__PURE__ */ React88.createElement(LedgerAccountsContent, null));
7972
+ var ChartOfAccounts = (props) => {
7973
+ const chartOfAccountsContextData = useChartOfAccounts();
7974
+ const ledgerAccountsContextData = useLedgerAccounts();
7975
+ return /* @__PURE__ */ React96.createElement(ChartOfAccountsContext.Provider, { value: chartOfAccountsContextData }, /* @__PURE__ */ React96.createElement(LedgerAccountsContext.Provider, { value: ledgerAccountsContextData }, /* @__PURE__ */ React96.createElement(ChartOfAccountsContent, null)));
7070
7976
  };
7071
- var LedgerAccountsContent = () => {
7072
- const { data, isLoading, addAccount, error, isValidating, refetch } = useContext12(LedgerAccountsContext);
7073
- let cumulativeIndex = 0;
7074
- const accountsLength = data?.accounts.length ?? 0;
7075
- return /* @__PURE__ */ React88.createElement(Container, { name: COMPONENT_NAME4 }, /* @__PURE__ */ React88.createElement("div", { className: `Layer__${COMPONENT_NAME4}__main-panel` }, /* @__PURE__ */ React88.createElement(Header, { className: `Layer__${COMPONENT_NAME4}__header` }, /* @__PURE__ */ React88.createElement(Heading, { className: `Layer__${COMPONENT_NAME4}__title` }, "Chart of Accounts"), /* @__PURE__ */ React88.createElement("div", { className: `Layer__${COMPONENT_NAME4}__actions` }, /* @__PURE__ */ React88.createElement(
7076
- Button,
7077
- {
7078
- variant: "secondary" /* secondary */,
7079
- disabled: isLoading,
7080
- rightIcon: /* @__PURE__ */ React88.createElement(DownloadCloud_default, { size: 12 })
7081
- },
7082
- "Download"
7083
- ), /* @__PURE__ */ React88.createElement(Button, { onClick: () => addAccount(), disabled: isLoading }, "Add Account"))), /* @__PURE__ */ React88.createElement("table", { className: `Layer__${COMPONENT_NAME4}__table` }, /* @__PURE__ */ React88.createElement("thead", null, /* @__PURE__ */ React88.createElement("tr", { className: "Layer__table-row--header" }, /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__name" }, "Name"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__type" }, "Type"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__subtype" }, "Sub-Type"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__balance" }, "Balance"), /* @__PURE__ */ React88.createElement("th", { className: "Layer__table-header Layer__coa__actions" }))), /* @__PURE__ */ React88.createElement("tbody", null, !error && data?.accounts.map((account, idx) => {
7084
- const currentCumulativeIndex = cumulativeIndex;
7085
- cumulativeIndex = (account.sub_accounts?.length || 0) + cumulativeIndex + 1;
7086
- return /* @__PURE__ */ React88.createElement(
7087
- LedgerAccountsRow,
7088
- {
7089
- key: account.id,
7090
- account,
7091
- depth: 0,
7092
- index: idx,
7093
- cumulativeIndex: currentCumulativeIndex,
7094
- expanded: true,
7095
- defaultOpen: true,
7096
- acountsLength: accountsLength
7977
+ var ChartOfAccountsContent = ({ asWidget }) => {
7978
+ const { accountId } = useContext14(LedgerAccountsContext);
7979
+ const [view, setView] = useState24("desktop");
7980
+ const containerRef = useElementSize((_a, _b, { width }) => {
7981
+ if (width) {
7982
+ if (width >= BREAKPOINTS.TABLET && view !== "desktop") {
7983
+ setView("desktop");
7984
+ } else if (width <= BREAKPOINTS.TABLET && width > BREAKPOINTS.MOBILE && view !== "tablet") {
7985
+ setView("tablet");
7986
+ } else if (width < BREAKPOINTS.MOBILE && view !== "mobile") {
7987
+ setView("mobile");
7097
7988
  }
7098
- );
7099
- }))), error ? /* @__PURE__ */ React88.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React88.createElement(
7100
- DataState,
7101
- {
7102
- status: "failed" /* failed */,
7103
- title: "Something went wrong",
7104
- description: "We couldn\u2019t load your data.",
7105
- onRefresh: () => refetch(),
7106
- isLoading: isValidating || isLoading
7107
- }
7108
- )) : null, (!data || isLoading) && !error ? /* @__PURE__ */ React88.createElement("div", { className: `Layer__${COMPONENT_NAME4}__loader-container` }, /* @__PURE__ */ React88.createElement(Loader2, null)) : null, !isLoading && !error && data?.accounts.length === 0 ? /* @__PURE__ */ React88.createElement("div", { className: "Layer__table-state-container" }, /* @__PURE__ */ React88.createElement(
7109
- DataState,
7110
- {
7111
- status: "info" /* info */,
7112
- title: "Accounts were not found",
7113
- description: 'New account can be created with "Add Account".',
7114
- onRefresh: () => refetch(),
7115
- isLoading: isValidating
7116
7989
  }
7117
- )) : null), /* @__PURE__ */ React88.createElement(LedgerAccountsSidebar, null), /* @__PURE__ */ React88.createElement(AccountsReceivable, null));
7990
+ });
7991
+ return /* @__PURE__ */ React96.createElement(Container, { name: "chart-of-accounts", ref: containerRef, asWidget }, accountId ? /* @__PURE__ */ React96.createElement(LedgerAccount, { view, containerRef }) : /* @__PURE__ */ React96.createElement(ChartOfAccountsTable, { view, containerRef }));
7118
7992
  };
7119
7993
 
7120
7994
  // src/providers/LayerProvider/LayerProvider.tsx
7121
- import React89, { useReducer, useEffect as useEffect12 } from "react";
7995
+ import React97, { useReducer, useEffect as useEffect16 } from "react";
7122
7996
  import { add as add2, isBefore } from "date-fns";
7123
- import useSWR7, { SWRConfig } from "swr";
7997
+ import useSWR8, { SWRConfig } from "swr";
7124
7998
  var reducer = (state, action) => {
7125
7999
  switch (action.type) {
7126
8000
  case "LayerContext.setAuth" /* setAuth */:
@@ -7173,7 +8047,7 @@ var LayerProvider = ({
7173
8047
  theme,
7174
8048
  colors
7175
8049
  });
7176
- const { data: auth } = appId !== void 0 && appSecret !== void 0 ? useSWR7(
8050
+ const { data: auth } = appId !== void 0 && appSecret !== void 0 ? useSWR8(
7177
8051
  businessAccessToken === void 0 && appId !== void 0 && appSecret !== void 0 && isBefore(state.auth.expires_at, /* @__PURE__ */ new Date()) && "authenticate",
7178
8052
  Layer.authenticate({
7179
8053
  appId,
@@ -7183,7 +8057,7 @@ var LayerProvider = ({
7183
8057
  }),
7184
8058
  defaultSWRConfig
7185
8059
  ) : { data: void 0 };
7186
- useEffect12(() => {
8060
+ useEffect16(() => {
7187
8061
  if (businessAccessToken) {
7188
8062
  dispatch({
7189
8063
  type: "LayerContext.setAuth" /* setAuth */,
@@ -7208,7 +8082,7 @@ var LayerProvider = ({
7208
8082
  });
7209
8083
  }
7210
8084
  }, [businessAccessToken, auth?.access_token]);
7211
- useSWR7(
8085
+ useSWR8(
7212
8086
  businessId && auth?.access_token && `categories-${businessId}`,
7213
8087
  Layer.getCategories(apiUrl, auth?.access_token, { params: { businessId } }),
7214
8088
  {
@@ -7227,22 +8101,136 @@ var LayerProvider = ({
7227
8101
  type: "LayerContext.setTheme" /* setTheme */,
7228
8102
  payload: { theme: theme2 }
7229
8103
  });
8104
+ const setLightColor = (color) => {
8105
+ setTheme({
8106
+ ...state.theme ?? {},
8107
+ colors: {
8108
+ ...state.theme?.colors ?? {},
8109
+ light: color
8110
+ }
8111
+ });
8112
+ };
8113
+ const setDarkColor = (color) => {
8114
+ setTheme({
8115
+ ...state.theme ?? {},
8116
+ colors: {
8117
+ ...state.theme?.colors ?? {},
8118
+ dark: color
8119
+ }
8120
+ });
8121
+ };
8122
+ const setColors = (colors2) => {
8123
+ setTheme({
8124
+ ...state.theme ?? {},
8125
+ colors: colors2
8126
+ });
8127
+ };
7230
8128
  const getColor = (shade) => {
7231
8129
  if (colors && shade in colors) {
7232
8130
  return colors[shade];
7233
8131
  }
7234
8132
  return;
7235
8133
  };
7236
- return /* @__PURE__ */ React89.createElement(SWRConfig, { value: defaultSWRConfig }, /* @__PURE__ */ React89.createElement(LayerContext.Provider, { value: { ...state, setTheme, getColor } }, children));
8134
+ return /* @__PURE__ */ React97.createElement(SWRConfig, { value: defaultSWRConfig }, /* @__PURE__ */ React97.createElement(
8135
+ LayerContext.Provider,
8136
+ {
8137
+ value: { ...state, setTheme, getColor, setLightColor, setDarkColor, setColors }
8138
+ },
8139
+ children
8140
+ ));
8141
+ };
8142
+
8143
+ // src/views/AccountingOverview/AccountingOverview.tsx
8144
+ import React100 from "react";
8145
+
8146
+ // src/components/View/View.tsx
8147
+ import React99 from "react";
8148
+
8149
+ // src/components/ViewHeader/ViewHeader.tsx
8150
+ import React98 from "react";
8151
+ var ViewHeader = ({ title, controls }) => {
8152
+ return /* @__PURE__ */ React98.createElement("div", { className: "Layer__view-header" }, /* @__PURE__ */ React98.createElement("div", { className: "Layer__view-header__content" }, /* @__PURE__ */ React98.createElement(Heading, null, title), controls && /* @__PURE__ */ React98.createElement("div", { className: "Layer__view-header__controls" }, controls)));
8153
+ };
8154
+
8155
+ // src/components/View/View.tsx
8156
+ var View6 = ({ title, children, headerControls }) => {
8157
+ const { theme } = useLayerContext();
8158
+ const styles = parseStylesFromThemeConfig(theme);
8159
+ return /* @__PURE__ */ React99.createElement("div", { className: "Layer__view", style: { ...styles } }, /* @__PURE__ */ React99.createElement(ViewHeader, { title, controls: headerControls }), /* @__PURE__ */ React99.createElement("div", { className: "Layer__view-main" }, children));
8160
+ };
8161
+
8162
+ // src/views/AccountingOverview/AccountingOverview.tsx
8163
+ var AccountingOverview = ({
8164
+ title = "Accounting overview"
8165
+ }) => {
8166
+ return /* @__PURE__ */ React100.createElement(ProfitAndLoss, { asContainer: false }, /* @__PURE__ */ React100.createElement(View6, { title, headerControls: /* @__PURE__ */ React100.createElement(ProfitAndLoss.DatePicker, null) }, /* @__PURE__ */ React100.createElement(ProfitAndLoss.Summaries, { actionable: false }), /* @__PURE__ */ React100.createElement(
8167
+ Container,
8168
+ {
8169
+ name: "accounting-overview-profit-and-loss",
8170
+ asWidget: true,
8171
+ elevated: true
8172
+ },
8173
+ /* @__PURE__ */ React100.createElement(Header, null, /* @__PURE__ */ React100.createElement(Heading, { size: "secondary" /* secondary */ }, "Profit & Loss")),
8174
+ /* @__PURE__ */ React100.createElement(ProfitAndLoss.Chart, null)
8175
+ ), /* @__PURE__ */ React100.createElement("div", { className: "accounting-overview-profit-and-loss-charts" }, /* @__PURE__ */ React100.createElement(Container, { name: "accounting-overview-profit-and-loss-chart" }, /* @__PURE__ */ React100.createElement(ProfitAndLoss.DetailedCharts, { scope: "revenue", hideClose: true })), /* @__PURE__ */ React100.createElement(Container, { name: "accounting-overview-profit-and-loss-chart" }, /* @__PURE__ */ React100.createElement(ProfitAndLoss.DetailedCharts, { scope: "expenses", hideClose: true })))));
8176
+ };
8177
+
8178
+ // src/views/BankTransactionsWithLinkedAccounts/BankTransactionsWithLinkedAccounts.tsx
8179
+ import React101 from "react";
8180
+ var BankTransactionsWithLinkedAccounts = ({
8181
+ title = "Bank transactions"
8182
+ }) => {
8183
+ return /* @__PURE__ */ React101.createElement(View6, { title }, /* @__PURE__ */ React101.createElement(LinkedAccounts, { elevated: true }), /* @__PURE__ */ React101.createElement(BankTransactions, { asWidget: true }));
8184
+ };
8185
+
8186
+ // src/views/Reports/Reports.tsx
8187
+ import React102, { useContext as useContext15, useRef as useRef15 } from "react";
8188
+ var Reports = ({ title = "Reports" }) => {
8189
+ const containerRef = useRef15(null);
8190
+ return /* @__PURE__ */ React102.createElement(ProfitAndLoss, { asContainer: false }, /* @__PURE__ */ React102.createElement(View6, { title, headerControls: /* @__PURE__ */ React102.createElement(ProfitAndLoss.DatePicker, null) }, /* @__PURE__ */ React102.createElement(
8191
+ Toggle,
8192
+ {
8193
+ name: "reports-tabs",
8194
+ options: [
8195
+ {
8196
+ value: "profitAndLoss",
8197
+ label: "Profit & loss"
8198
+ },
8199
+ {
8200
+ value: "balanceSheet",
8201
+ label: "Balance sheet",
8202
+ disabled: true
8203
+ }
8204
+ ],
8205
+ selected: "profitAndLoss",
8206
+ onChange: () => null
8207
+ }
8208
+ ), /* @__PURE__ */ React102.createElement(Container, { name: "reports", ref: containerRef }, /* @__PURE__ */ React102.createElement(ReportsPanel, { containerRef }))));
8209
+ };
8210
+ var ReportsPanel = ({ containerRef }) => {
8211
+ const { sidebarScope } = useContext15(ProfitAndLoss.Context);
8212
+ return /* @__PURE__ */ React102.createElement(
8213
+ Panel,
8214
+ {
8215
+ sidebar: /* @__PURE__ */ React102.createElement(ProfitAndLoss.DetailedCharts, null),
8216
+ sidebarIsOpen: Boolean(sidebarScope),
8217
+ parentRef: containerRef
8218
+ },
8219
+ /* @__PURE__ */ React102.createElement(ProfitAndLoss.Table, { asContainer: false })
8220
+ );
7237
8221
  };
7238
8222
  export {
8223
+ AccountingOverview,
7239
8224
  BalanceSheet,
7240
8225
  BankTransactions,
8226
+ BankTransactionsWithLinkedAccounts,
8227
+ ChartOfAccounts,
7241
8228
  Hello,
7242
8229
  LayerProvider,
7243
- LedgerAccounts,
7244
8230
  LinkedAccounts,
7245
8231
  ProfitAndLoss,
7246
- ProfitAndLossView
8232
+ ProfitAndLossView,
8233
+ Reports,
8234
+ useLayerContext
7247
8235
  };
7248
8236
  //# sourceMappingURL=index.js.map