@accounter/client 0.0.8-alpha-20251028123001-a8ce4e53bbde9f6eeded7bfeea650700f6a63130 → 0.0.8-alpha-20251028124234-328844c99a42b68aa9e2f32fd86da80b4832f631

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.
Files changed (148) hide show
  1. package/CHANGELOG.md +13 -27
  2. package/dist/assets/{Checkbox-sjgv9dlI.js → Checkbox-BR6kGuhg.js} +2 -2
  3. package/dist/assets/MultiSelect-BqcJrWnD.js +1 -0
  4. package/dist/assets/Pagination-6Sv5LXxl.js +1 -0
  5. package/dist/assets/{Progress-DKypjBbn.js → Progress-7xtiFwK3.js} +1 -1
  6. package/dist/assets/Table-C5zxD95i.js +1 -0
  7. package/dist/assets/Typography-CMzSQZKD.js +1 -0
  8. package/dist/assets/YearPickerInput-CllwSjcn.js +1 -0
  9. package/dist/assets/{accordion-Cfc9ae4H.js → accordion-CMR2fANH.js} +1 -1
  10. package/dist/assets/accountant-approvals-BHFXpHHc.js +1 -0
  11. package/dist/assets/accounter-table-CpeQD4PG.js +1 -0
  12. package/dist/assets/addDays-DvwuJbUs.js +1 -0
  13. package/dist/assets/all-charges-At7WJXuW.js +1 -0
  14. package/dist/assets/{arrow-up-down-DapQ791y.js → arrow-up-down-DPG1l9S1.js} +1 -1
  15. package/dist/assets/{building-2-B5JpJWrx.js → building-2-BgvPBt2Z.js} +1 -1
  16. package/dist/assets/business-DKvbSnga.js +32 -0
  17. package/dist/assets/business-extended-info-7CM8px2e.js +13 -0
  18. package/dist/assets/{business-header-BK89Rfvy.js → business-header-u2sfE_d8.js} +1 -1
  19. package/dist/assets/business-transactions-filters-DmpO9Bwo.js +1 -0
  20. package/dist/assets/business-transactions-single-rF6JbAL7.js +1 -0
  21. package/dist/assets/business-trip-BGrp09N7.js +1 -0
  22. package/dist/assets/charge-C-EaA1Xc.js +1 -0
  23. package/dist/assets/charges-filters-Dq-8QHH-.js +1 -0
  24. package/dist/assets/charges-ledger-validation-DlkzVow7.js +1 -0
  25. package/dist/assets/charges-table-Cncs1HLi.js +62 -0
  26. package/dist/assets/{chart-0bAgDGey.js → chart-ByngRufj.js} +6 -6
  27. package/dist/assets/create-event-handler-BiA-1lGu.js +1 -0
  28. package/dist/assets/{data-table-pagination-BgCuddCb.js → data-table-pagination-D4OEFmX_.js} +1 -1
  29. package/dist/assets/download-csv-button-Df5rDeDc.js +1 -0
  30. package/dist/assets/editable-business-trip-Bav24z0u.js +16 -0
  31. package/dist/assets/funnel-BJ71hzoq.js +6 -0
  32. package/dist/assets/index-BRv0JZw4.js +1 -0
  33. package/dist/assets/index-BXlS8oD_.js +1 -0
  34. package/dist/assets/{index-DaSgVGNd.js → index-BetG0HVN.js} +3 -3
  35. package/dist/assets/index-BplSRMAq.css +1 -0
  36. package/dist/assets/{index-Dnafld8G.js → index-Bsl7tJp_.js} +16 -16
  37. package/dist/assets/{index-DLRffFbF.js → index-CLUhAJ3t.js} +7 -7
  38. package/dist/assets/index-Cix5qjA-.js +2 -0
  39. package/dist/assets/index-CizLtiES.js +1 -0
  40. package/dist/assets/index-DKBzv0gc.js +1 -0
  41. package/dist/assets/index-DR_5jpS4.js +6 -0
  42. package/dist/assets/index-DTmtILfq.js +1 -0
  43. package/dist/assets/index-DU0G7FZm.js +1 -0
  44. package/dist/assets/index-DUWRgLfu.js +9 -0
  45. package/dist/assets/index-DYZPWG4k.js +2 -0
  46. package/dist/assets/index-DdUE2_44.js +1 -0
  47. package/dist/assets/index-De5dvO0S.js +1 -0
  48. package/dist/assets/index-Des3eR4f.js +1 -0
  49. package/dist/assets/index-DpYwi5kf.js +6 -0
  50. package/dist/assets/index-GzyQZkbY.js +1 -0
  51. package/dist/assets/index-HzLXi-qB.js +1 -0
  52. package/dist/assets/index-Ji28AZwq.js +1 -0
  53. package/dist/assets/{index-D92U_VYB.js → index-UMFH47hN.js} +2 -2
  54. package/dist/assets/index-fuT9duEO.js +1 -0
  55. package/dist/assets/{index-BBpGo89I.js → index-vChLJwSt.js} +2 -2
  56. package/dist/assets/index-wck8Xuay.js +1 -0
  57. package/dist/assets/index-wyU9I4Kz.js +768 -0
  58. package/dist/assets/{index.es-JpTIgXoh.js → index.es-NphQjU3m.js} +1 -1
  59. package/dist/assets/insert-business-trip-modal-vS1QrUJz.js +6 -0
  60. package/dist/assets/issue-document-pIswc_8i.js +1 -0
  61. package/dist/assets/list-plus-Dy3vzJVy.js +6 -0
  62. package/dist/assets/login-page-YXRfklK1.js +1 -0
  63. package/dist/assets/match-document-modal-BPG_hljb.js +16 -0
  64. package/dist/assets/missing-info-charges-D8dUfChs.js +1 -0
  65. package/dist/assets/modal-D47umnak.js +1 -0
  66. package/dist/assets/page-layout-BG0XvWfD.js +1 -0
  67. package/dist/assets/page-not-found-Cy6oIIb1.js +1 -0
  68. package/dist/assets/panel-top-open-B1rhJYjQ.js +11 -0
  69. package/dist/assets/{pencil-CEfu8zQ4.js → pencil-tV0FsM6V.js} +1 -1
  70. package/dist/assets/report-commentary-row-BL2RkIHq.js +1 -0
  71. package/dist/assets/{save-Drpbh6u3.js → save-Czmh3tvC.js} +1 -1
  72. package/dist/assets/similar-transactions-modal-MQeC2gtu.js +1 -0
  73. package/dist/assets/sub-B4_VmmF9.js +1 -0
  74. package/dist/assets/subMonths-DG7w6bCY.js +1 -0
  75. package/dist/assets/summary-DvHtnArZ.js +1 -0
  76. package/dist/assets/switch-GSloW_Ey.js +1 -0
  77. package/dist/assets/toggle-expansion-button-lwJYTklN.js +1 -0
  78. package/dist/assets/tooltip-BbKSwLCX.js +1 -0
  79. package/dist/assets/use-url-query-CUVSXgm0.js +1 -0
  80. package/dist/index.html +2 -2
  81. package/package.json +1 -1
  82. package/src/components/business/contracts-section.tsx +4 -18
  83. package/src/components/business-transactions/business-extended-info.tsx +5 -5
  84. package/src/components/business-transactions/index.tsx +1 -28
  85. package/src/components/businesses/index.tsx +6 -2
  86. package/src/components/charges/cells/business-trip.tsx +6 -1
  87. package/src/components/charges/cells/counterparty.tsx +4 -28
  88. package/src/components/clients/contracts/modify-contract-dialog.tsx +11 -64
  89. package/src/components/common/business-trip-report/parts/core-expense-row.tsx +2 -2
  90. package/src/components/common/business-trip-report/parts/report-header.tsx +2 -1
  91. package/src/components/common/business-trip-report/parts/uncategorized-transactions.tsx +2 -2
  92. package/src/components/common/buttons/charge-navigate-button.tsx +12 -11
  93. package/src/components/common/modals/edit-charge-modal.tsx +2 -2
  94. package/src/components/common/modals/insert-document-modal.tsx +2 -2
  95. package/src/components/common/modals/match-document-modal.tsx +2 -2
  96. package/src/components/common/new-documents-list.tsx +2 -2
  97. package/src/components/documents-table/cells/creditor.tsx +2 -11
  98. package/src/components/documents-table/cells/debtor.tsx +2 -11
  99. package/src/components/ledger-table/counterparty-cell.tsx +4 -33
  100. package/src/components/reports/conto/index.tsx +1 -18
  101. package/src/components/reports/trial-balance-report/index.tsx +1 -17
  102. package/src/components/screens/businesses/business.tsx +0 -4
  103. package/src/components/screens/charges/all-charges.tsx +1 -17
  104. package/src/components/screens/charges/charge.tsx +0 -4
  105. package/src/components/screens/reports/balance-report/index.tsx +0 -14
  106. package/src/components/screens/reports/depreciation-report/index.tsx +0 -14
  107. package/src/components/transactions-table/cells/counterparty.tsx +2 -23
  108. package/src/components/transactions-table/cells-legacy/counterparty.tsx +3 -26
  109. package/src/gql/gql.ts +6 -6
  110. package/src/gql/graphql.ts +7 -7
  111. package/src/hooks/use-get-all-contracts.ts +1 -1
  112. package/src/providers/urql.tsx +2 -2
  113. package/dist/assets/Typography-CJfovWMc.js +0 -1
  114. package/dist/assets/accountant-approvals-DhCtddzR.js +0 -1
  115. package/dist/assets/all-charges-H_xH1cUe.js +0 -1
  116. package/dist/assets/business-BtKmlUZR.js +0 -32
  117. package/dist/assets/business-transactions-single-Dv6-AKgI.js +0 -1
  118. package/dist/assets/business-trip-DIBdq8Jq.js +0 -1
  119. package/dist/assets/charges-filters-CTMCRKNm.js +0 -1
  120. package/dist/assets/charges-ledger-validation-c6jklgQz.js +0 -1
  121. package/dist/assets/editable-business-trip-Cr87pQT-.js +0 -16
  122. package/dist/assets/index-B8QopG0Z.js +0 -1
  123. package/dist/assets/index-BVZuWqUd.js +0 -1
  124. package/dist/assets/index-Bt7NK9UB.js +0 -1
  125. package/dist/assets/index-CBPTpZHL.css +0 -1
  126. package/dist/assets/index-CKfzp5hU.js +0 -1
  127. package/dist/assets/index-CTzkpoqF.js +0 -2
  128. package/dist/assets/index-CaSs1tPq.js +0 -1
  129. package/dist/assets/index-Cgl63fgb.js +0 -1
  130. package/dist/assets/index-ChwFk-6u.js +0 -1
  131. package/dist/assets/index-CnHbGv9H.js +0 -1
  132. package/dist/assets/index-CnKUadG6.js +0 -886
  133. package/dist/assets/index-CpqDv0tU.js +0 -1
  134. package/dist/assets/index-CtfXFlRt.js +0 -1
  135. package/dist/assets/index-Cyg6_G-8.js +0 -9
  136. package/dist/assets/index-b4v6_EXH.js +0 -6
  137. package/dist/assets/index-f6-rwrBW.js +0 -1
  138. package/dist/assets/index-mXqFMX5P.js +0 -1
  139. package/dist/assets/index-sUDYfUlt.js +0 -1
  140. package/dist/assets/index-tgi4TEs-.js +0 -2
  141. package/dist/assets/issue-document-CejQASYM.js +0 -1
  142. package/dist/assets/login-page-ByDrdoxH.js +0 -1
  143. package/dist/assets/missing-info-charges-DHt03bdz.js +0 -1
  144. package/dist/assets/page-not-found-Bhi5OU5Q.js +0 -1
  145. package/dist/assets/report-commentary-row-CmDH8P-d.js +0 -1
  146. package/dist/assets/sub-DBgZtyi3.js +0 -1
  147. package/dist/assets/subMonths-J6RX2Vo3.js +0 -1
  148. package/src/components/charges/helpers.ts +0 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@accounter/client",
3
- "version": "0.0.8-alpha-20251028123001-a8ce4e53bbde9f6eeded7bfeea650700f6a63130",
3
+ "version": "0.0.8-alpha-20251028124234-328844c99a42b68aa9e2f32fd86da80b4832f631",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -21,7 +21,7 @@ import {
21
21
  query ClientContractsSection($clientId: UUID!) {
22
22
  contractsByClient(clientId: $clientId) {
23
23
  id
24
- purchaseOrders
24
+ purchaseOrder
25
25
  startDate
26
26
  endDate
27
27
  amount {
@@ -46,7 +46,7 @@ function convertContractDataToFormValues(
46
46
  id: contract.id,
47
47
  // TODO: activate this field later. requires additional backend support
48
48
  // operationsLimit: 0, // Placeholder, as this field is not in the query
49
- pos: contract.purchaseOrders ?? undefined,
49
+ po: contract.purchaseOrder ?? undefined,
50
50
  startDate: contract.startDate,
51
51
  endDate: contract.endDate,
52
52
  paymentAmount: contract.amount.raw,
@@ -130,22 +130,8 @@ export function ContractsSection({ clientId }: Props) {
130
130
  </div>
131
131
 
132
132
  <div className="space-y-0">
133
- <p className="text-sm text-muted-foreground">PO Numbers</p>
134
- <p className="text-sm font-medium font-mono">
135
- {contract.purchaseOrders.toReversed()[0] ?? ''}
136
- </p>
137
- {contract.purchaseOrders.length > 1 && (
138
- <div className="space-x-1">
139
- {contract.purchaseOrders
140
- .toReversed()
141
- .slice(1)
142
- .map(po => (
143
- <span key={po} className="text-xs font-thin font-mono">
144
- {po}
145
- </span>
146
- ))}
147
- </div>
148
- )}
133
+ <p className="text-sm text-muted-foreground">PO Number</p>
134
+ <p className="text-sm font-medium font-mono">{contract.purchaseOrder}</p>
149
135
  </div>
150
136
 
151
137
  {/* TODO: activate this field later. requires additional backend support */}
@@ -3,6 +3,7 @@ import { format } from 'date-fns';
3
3
  import { ChevronsLeftRightEllipsis, ChevronsRightLeft } from 'lucide-react';
4
4
  import { Link } from 'react-router-dom';
5
5
  import { useQuery } from 'urql';
6
+ import { ROUTES } from '@/router/routes.js';
6
7
  import { Mark, Table, Tooltip } from '@mantine/core';
7
8
  import {
8
9
  BusinessTransactionsInfoDocument,
@@ -12,10 +13,8 @@ import {
12
13
  } from '../../gql/graphql.js';
13
14
  import { FIAT_CURRENCIES, formatAmountWithCurrency } from '../../helpers/index.js';
14
15
  import { AccounterLoader } from '../common/index.js';
15
- import { getChargeHref } from '../screens/charges/charge.js';
16
16
  import { Button } from '../ui/button.js';
17
17
  import { DownloadCSV } from './download-csv.js';
18
- import { getBusinessTransactionsHref } from './index.js';
19
18
 
20
19
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
21
20
  /* GraphQL */ `
@@ -229,14 +228,15 @@ export function BusinessExtendedInfo({ businessID, filter }: Props): ReactElemen
229
228
  {extendedTransactions.map((row, index) => (
230
229
  <tr
231
230
  key={index}
231
+ className="cursor-pointer"
232
232
  onClick={event => {
233
233
  event.stopPropagation();
234
- window.open(getChargeHref(row.chargeId), '_blank', 'noreferrer');
234
+ window.open(ROUTES.CHARGES.DETAIL(row.chargeId), '_blank', 'noreferrer');
235
235
  }}
236
236
  >
237
237
  <td>
238
238
  <Link
239
- to={getBusinessTransactionsHref({ businessIDs: [row.business.id] })}
239
+ to={ROUTES.BUSINESSES.DETAIL(row.business.id)}
240
240
  target="_blank"
241
241
  rel="noreferrer"
242
242
  onClick={event => event.stopPropagation()}
@@ -274,7 +274,7 @@ export function BusinessExtendedInfo({ businessID, filter }: Props): ReactElemen
274
274
  <td>
275
275
  {row.counterAccount && (
276
276
  <Link
277
- to={getBusinessTransactionsHref({ businessIDs: [row.counterAccount.id] })}
277
+ to={ROUTES.BUSINESSES.DETAIL(row.counterAccount.id)}
278
278
  target="_blank"
279
279
  rel="noreferrer"
280
280
  onClick={event => event.stopPropagation()}
@@ -21,10 +21,7 @@ import { AccounterTableRow } from '../common/index.js';
21
21
  import { PageLayout } from '../layout/page-layout.js';
22
22
  import { Button } from '../ui/button.js';
23
23
  import { BusinessExtendedInfo } from './business-extended-info.js';
24
- import {
25
- BusinessTransactionsFilters,
26
- encodeTransactionsFilters,
27
- } from './business-transactions-filters.js';
24
+ import { BusinessTransactionsFilters } from './business-transactions-filters.js';
28
25
 
29
26
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
30
27
  /* GraphQL */ `
@@ -69,30 +66,6 @@ import {
69
66
  }
70
67
  `;
71
68
 
72
- export function getBusinessTransactionsHref(filter?: BusinessTransactionsFilter | null): string {
73
- const params = new URLSearchParams();
74
-
75
- let businessId: string | undefined = undefined;
76
- let adjustedFilter = filter;
77
- if (filter?.businessIDs && filter.businessIDs.length === 1) {
78
- const { businessIDs, ...rest } = filter;
79
- businessId = businessIDs[0];
80
- adjustedFilter = rest;
81
- }
82
-
83
- const transactionsFilters = encodeTransactionsFilters(adjustedFilter);
84
- if (transactionsFilters) {
85
- // Add it as a single encoded parameter
86
- params.append('transactionsFilters', transactionsFilters);
87
- }
88
-
89
- const queryParams = params.size > 0 ? `?${params}` : '';
90
- if (businessId) {
91
- return `/businesses/${businessId}/transactions${queryParams}`;
92
- }
93
- return `/businesses/transactions${queryParams}`;
94
- }
95
-
96
69
  type BusinessTransactionsSum = Extract<
97
70
  BusinessTransactionsSummeryQuery['businessTransactionsSumFromLedgerRecords'],
98
71
  { businessTransactionsSum: unknown }
@@ -159,12 +159,16 @@ export const Businesses = (): ReactElement => {
159
159
  tabIndex={0}
160
160
  className="flex-1 cursor-pointer"
161
161
  onClick={(): void => {
162
- navigate(ROUTES.BUSINESSES.DETAIL(business.id));
162
+ navigate(ROUTES.BUSINESSES.DETAIL(business.id), {
163
+ state: { from: ROUTES.BUSINESSES.ALL },
164
+ });
163
165
  }}
164
166
  onKeyDown={(e): void => {
165
167
  if (e.key === 'Enter' || e.key === ' ') {
166
168
  e.preventDefault();
167
- navigate(ROUTES.BUSINESSES.DETAIL(business.id));
169
+ navigate(ROUTES.BUSINESSES.DETAIL(business.id), {
170
+ state: { from: ROUTES.BUSINESSES.ALL },
171
+ });
168
172
  }
169
173
  }}
170
174
  >
@@ -1,5 +1,6 @@
1
1
  import { type ReactElement } from 'react';
2
2
  import { Link } from 'react-router-dom';
3
+ import { ROUTES } from '@/router/routes.js';
3
4
  import { ChargesTableBusinessTripFieldsFragmentDoc } from '../../../gql/graphql.js';
4
5
  import { getFragmentData, type FragmentType } from '../../../gql/index.js';
5
6
 
@@ -30,7 +31,11 @@ export const BusinessTrip = ({ data }: Props): ReactElement => {
30
31
  return (
31
32
  <td>
32
33
  <Link
33
- to={`/business-trips/${charge.businessTrip?.id}`}
34
+ to={
35
+ charge.businessTrip?.id
36
+ ? ROUTES.BUSINESS_TRIPS.DETAIL(charge.businessTrip?.id)
37
+ : ROUTES.BUSINESS_TRIPS.ROOT
38
+ }
34
39
  target="_blank"
35
40
  rel="noreferrer"
36
41
  onClick={event => event.stopPropagation()}
@@ -1,14 +1,9 @@
1
- import { useCallback, useMemo, type ReactElement } from 'react';
1
+ import { useMemo, type ReactElement } from 'react';
2
2
  import { Link } from 'react-router-dom';
3
+ import { ROUTES } from '@/router/routes.js';
3
4
  import { Indicator } from '@mantine/core';
4
- import {
5
- ChargesTableEntityFieldsFragmentDoc,
6
- MissingChargeInfo,
7
- type ChargeFilter,
8
- } from '../../../gql/graphql.js';
5
+ import { ChargesTableEntityFieldsFragmentDoc, MissingChargeInfo } from '../../../gql/graphql.js';
9
6
  import { getFragmentData, type FragmentType } from '../../../gql/index.js';
10
- import { useUrlQuery } from '../../../hooks/use-url-query.js';
11
- import { getBusinessTransactionsHref } from '../../business-transactions/index.js';
12
7
 
13
8
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
14
9
  /* GraphQL */ `
@@ -32,7 +27,6 @@ type Props = {
32
27
  };
33
28
 
34
29
  export const Counterparty = ({ data }: Props): ReactElement => {
35
- const { get } = useUrlQuery();
36
30
  const { counterparty, validationData, __typename } = getFragmentData(
37
31
  ChargesTableEntityFieldsFragmentDoc,
38
32
  data,
@@ -59,31 +53,13 @@ export const Counterparty = ({ data }: Props): ReactElement => {
59
53
  );
60
54
  const { name, id } = counterparty ?? { name: 'Missing', id: undefined };
61
55
 
62
- const encodedFilters = get('chargesFilters');
63
-
64
- const getHref = useCallback(
65
- (businessID: string) => {
66
- const currentFilters = encodedFilters
67
- ? (JSON.parse(decodeURIComponent(encodedFilters as string)) as ChargeFilter)
68
- : {};
69
-
70
- return getBusinessTransactionsHref({
71
- fromDate: currentFilters.fromDate,
72
- toDate: currentFilters.toDate,
73
- ownerIds: currentFilters.byOwners,
74
- businessIDs: [businessID],
75
- });
76
- },
77
- [encodedFilters],
78
- );
79
-
80
56
  return (
81
57
  <td>
82
58
  <div className="flex flex-wrap">
83
59
  <Indicator inline size={12} disabled={!isError} color="red" zIndex="auto">
84
60
  {!isError && id && (
85
61
  <Link
86
- to={getHref(id)}
62
+ to={ROUTES.BUSINESSES.DETAIL(id)}
87
63
  target="_blank"
88
64
  rel="noreferrer"
89
65
  onClick={event => event.stopPropagation()}
@@ -1,9 +1,8 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
2
  import { format } from 'date-fns';
3
- import { Plus, X } from 'lucide-react';
3
+ import { Plus } from 'lucide-react';
4
4
  import { useForm } from 'react-hook-form';
5
5
  import { z } from 'zod';
6
- import { Badge } from '@/components/ui/badge.js';
7
6
  import { Button } from '@/components/ui/button.js';
8
7
  import {
9
8
  Dialog,
@@ -49,7 +48,7 @@ const contractFormSchema = z.object({
49
48
  // operationsLimit: z.number().optional(),
50
49
  startDate: z.iso.date('Start date is required'),
51
50
  endDate: z.iso.date('End date is required'),
52
- pos: z.array(z.string()),
51
+ po: z.string().optional(),
53
52
  paymentAmount: z.number().min(0, 'Payment amount must be non-negative'),
54
53
  paymentCurrency: z.enum(Object.values(Currency), 'Currency is required'),
55
54
  productType: z.enum(Object.values(Product)).optional(),
@@ -68,7 +67,7 @@ const newContractDefaultValues: ContractFormValues = {
68
67
  // operationsLimit: 0,
69
68
  startDate: '',
70
69
  endDate: '',
71
- pos: [],
70
+ po: undefined,
72
71
  paymentAmount: 0,
73
72
  paymentCurrency: Currency.Usd,
74
73
  productType: Product.Hive,
@@ -89,7 +88,6 @@ interface Props {
89
88
  export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
90
89
  const [isDialogOpen, setIsDialogOpen] = useState(false);
91
90
  const [editingContract, setEditingContract] = useState<ContractFormValues | null>(null);
92
- const [newPO, setNewPO] = useState('');
93
91
 
94
92
  const { updateContract, updating } = useUpdateContract();
95
93
  const { createContract, creating } = useCreateContract();
@@ -99,26 +97,6 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
99
97
  defaultValues: contract || newContractDefaultValues,
100
98
  });
101
99
 
102
- const addPO = () => {
103
- const trimmedPO = newPO.trim();
104
- if (trimmedPO) {
105
- const currentLinks = form.getValues('pos');
106
- if (!currentLinks.includes(trimmedPO)) {
107
- form.setValue('pos', [...currentLinks, trimmedPO], { shouldDirty: true });
108
- }
109
- setNewPO('');
110
- }
111
- };
112
-
113
- const removePO = (index: number) => {
114
- const currentLinks = form.getValues('pos');
115
- form.setValue(
116
- 'pos',
117
- currentLinks.filter((_, i) => i !== index),
118
- { shouldDirty: true },
119
- );
120
- };
121
-
122
100
  useEffect(() => {
123
101
  if (contract) {
124
102
  setEditingContract(contract);
@@ -127,7 +105,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
127
105
  // operationsLimit: contract.operationsLimit,
128
106
  startDate: contract.startDate,
129
107
  endDate: contract.endDate,
130
- pos: contract.pos,
108
+ po: contract.po,
131
109
  paymentAmount: contract.paymentAmount,
132
110
  paymentCurrency: contract.paymentCurrency,
133
111
  productType: contract.productType,
@@ -163,7 +141,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
163
141
  msCloud: values.msCloudLink,
164
142
  plan: values.subscriptionPlan,
165
143
  product: values.productType,
166
- purchaseOrders: values.pos,
144
+ purchaseOrder: values.po,
167
145
  remarks: values.defaultRemark,
168
146
  startDate: format(new Date(values.startDate), 'yyyy-MM-dd') as TimelessDateString,
169
147
  },
@@ -185,7 +163,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
185
163
  msCloud: values.msCloudLink,
186
164
  plan: values.subscriptionPlan,
187
165
  product: values.productType,
188
- purchaseOrders: values.pos,
166
+ purchaseOrder: values.po,
189
167
  remarks: values.defaultRemark,
190
168
  startDate: format(new Date(values.startDate), 'yyyy-MM-dd') as TimelessDateString,
191
169
  },
@@ -233,46 +211,15 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
233
211
  </FormItem>
234
212
  )}
235
213
  /> */}
236
-
237
214
  <FormField
238
215
  control={form.control}
239
- name="pos"
216
+ name="po"
240
217
  render={({ field }) => (
241
218
  <FormItem>
242
- <FormLabel>Purchase Orders</FormLabel>
243
- <div className="flex gap-2">
244
- <Input
245
- placeholder="Add PO..."
246
- value={newPO}
247
- onChange={e => setNewPO(e.target.value)}
248
- onKeyDown={e => {
249
- if (e.key === 'Enter') {
250
- e.preventDefault();
251
- addPO();
252
- }
253
- }}
254
- />
255
- <Button type="button" size="sm" onClick={addPO}>
256
- <Plus className="h-4 w-4" />
257
- </Button>
258
- </div>
259
- <div className="flex flex-wrap gap-2 mt-2">
260
- {field.value?.map((link, index) => (
261
- <Badge key={link} variant="secondary" className="gap-1 max-w-xs truncate">
262
- {link}
263
- {index === field.value.length - 1 && (
264
- <Button
265
- variant="ghost"
266
- size="icon"
267
- className="p-0 size-3"
268
- onClick={() => removePO(index)}
269
- >
270
- <X className="size-3 cursor-pointer flex-shrink-0" />
271
- </Button>
272
- )}
273
- </Badge>
274
- ))}
275
- </div>
219
+ <FormLabel>PO Number</FormLabel>
220
+ <FormControl>
221
+ <Input placeholder="PO-2024-001" {...field} />
222
+ </FormControl>
276
223
  <FormMessage />
277
224
  </FormItem>
278
225
  )}
@@ -4,6 +4,7 @@ import { Controller, type Control } from 'react-hook-form';
4
4
  import { Link } from 'react-router-dom';
5
5
  import { toast } from 'sonner';
6
6
  import { useQuery } from 'urql';
7
+ import { ROUTES } from '@/router/routes.js';
7
8
  import { Select, Text } from '@mantine/core';
8
9
  import { DatePickerInput } from '@mantine/dates';
9
10
  import {
@@ -14,7 +15,6 @@ import {
14
15
  } from '../../../../gql/graphql.js';
15
16
  import { getFragmentData, type FragmentType } from '../../../../gql/index.js';
16
17
  import { TIMELESS_DATE_REGEX } from '../../../../helpers/consts.js';
17
- import { getChargeHref } from '../../../screens/charges/charge.js';
18
18
  import { CurrencyInput } from '../../index.js';
19
19
 
20
20
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
@@ -239,7 +239,7 @@ export const CoreExpenseRow = ({
239
239
  {linkedChargeIds.map(id => (
240
240
  <Link
241
241
  key={id}
242
- to={getChargeHref(id)}
242
+ to={ROUTES.CHARGES.DETAIL(id)}
243
243
  target="_blank"
244
244
  rel="noreferrer"
245
245
  onClick={event => event.stopPropagation()}
@@ -1,5 +1,6 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import { differenceInDays, format, setHours } from 'date-fns';
3
+ import { ROUTES } from '@/router/routes.js';
3
4
  import { Grid, Text } from '@mantine/core';
4
5
  import { BusinessTripReportHeaderFieldsFragmentDoc } from '../../../../gql/graphql.js';
5
6
  import { getFragmentData, type FragmentType } from '../../../../gql/index.js';
@@ -43,7 +44,7 @@ export const ReportHeader = ({ data, onChange }: Props): ReactElement => {
43
44
  <AccountantApproval data={businessTrip} onChange={onChange} />
44
45
  <CopyToClipboardButton
45
46
  isLink
46
- content={`${window.location.origin}/business-trips/${businessTrip.id}`}
47
+ content={`${window.location.origin}${ROUTES.BUSINESS_TRIPS.DETAIL(businessTrip.id)}`}
47
48
  />
48
49
  <BusinessTripToggleMenu businessTripId={businessTrip.id} />
49
50
  </div>
@@ -1,6 +1,7 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import { AlertCircle } from 'lucide-react';
3
3
  import { Link } from 'react-router-dom';
4
+ import { ROUTES } from '@/router/routes.js';
4
5
  import { Popover, Table, Text } from '@mantine/core';
5
6
  import { useDisclosure } from '@mantine/hooks';
6
7
  import {
@@ -10,7 +11,6 @@ import {
10
11
  } from '../../../../gql/graphql.js';
11
12
  import { getFragmentData, type FragmentType } from '../../../../gql/index.js';
12
13
  import { formatStringifyAmount } from '../../../../helpers/index.js';
13
- import { getChargeHref } from '../../../screens/charges/charge.js';
14
14
  import {
15
15
  Account,
16
16
  Counterparty,
@@ -94,7 +94,7 @@ export const UncategorizedTransactions = ({ data, onChange }: Props): ReactEleme
94
94
  <Amount data={uncategorizedTransaction} />
95
95
  <td>
96
96
  <Link
97
- to={getChargeHref(uncategorizedTransaction.transaction.chargeId)}
97
+ to={ROUTES.CHARGES.DETAIL(uncategorizedTransaction.transaction.chargeId)}
98
98
  target="_blank"
99
99
  rel="noreferrer"
100
100
  onClick={event => event.stopPropagation()}
@@ -1,8 +1,9 @@
1
1
  import type { ComponentProps, ReactElement } from 'react';
2
2
  import { ExternalLink } from 'lucide-react';
3
+ import { Link } from 'react-router-dom';
3
4
  import { Tooltip } from '@mantine/core';
4
5
  import { cn } from '../../../lib/utils.js';
5
- import { getChargeHref } from '../../screens/charges/charge.js';
6
+ import { ROUTES } from '../../../router/routes.js';
6
7
  import { Button } from '../../ui/button.js';
7
8
 
8
9
  export function ChargeNavigateButton(
@@ -10,17 +11,17 @@ export function ChargeNavigateButton(
10
11
  ): ReactElement {
11
12
  return (
12
13
  <Tooltip label="To Charge">
13
- <Button
14
- onClick={event => {
15
- event.stopPropagation();
16
- window.open(getChargeHref(props.chargeId), '_blank', 'noreferrer');
17
- }}
18
- {...props}
19
- className={cn('size-7.5', props.className)}
20
- variant="ghost"
14
+ <Link
15
+ to={ROUTES.CHARGES.DETAIL(props.chargeId)}
16
+ target="_blank"
17
+ rel="noreferrer"
18
+ onClick={event => event.stopPropagation()}
19
+ className="inline-block"
21
20
  >
22
- <ExternalLink className="size-5" />
23
- </Button>
21
+ <Button {...props} className={cn('size-7.5', props.className)} variant="ghost">
22
+ <ExternalLink className="size-5" />
23
+ </Button>
24
+ </Link>
24
25
  </Tooltip>
25
26
  );
26
27
  }
@@ -1,8 +1,8 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import { useQuery } from 'urql';
3
+ import { ROUTES } from '@/router/routes.js';
3
4
  import { Loader } from '@mantine/core';
4
5
  import { EditChargeDocument } from '../../../gql/graphql.js';
5
- import { getChargeHref } from '../../screens/charges/charge.js';
6
6
  import { CopyToClipboardButton, EditCharge, PopUpDrawer } from '../index.js';
7
7
 
8
8
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
@@ -89,7 +89,7 @@ export const EditChargeModalContent = ({
89
89
  ID: {chargeId}
90
90
  <CopyToClipboardButton
91
91
  isLink
92
- content={`${window.location.origin}${getChargeHref(chargeId)}`}
92
+ content={`${window.location.origin}${ROUTES.CHARGES.DETAIL(chargeId)}`}
93
93
  />
94
94
  </div>
95
95
  </div>
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from 'react';
2
- import { getChargeHref } from '../../screens/charges/charge.js';
2
+ import { ROUTES } from '@/router/routes.js';
3
3
  import { CopyToClipboardButton, InsertDocument, PopUpDrawer } from '../index.js';
4
4
 
5
5
  interface Props {
@@ -24,7 +24,7 @@ export const InsertDocumentModal = ({
24
24
  Charge ID: {chargeId}
25
25
  <CopyToClipboardButton
26
26
  isLink
27
- content={`${window.location.origin}${getChargeHref(chargeId)}`}
27
+ content={`${window.location.origin}${ROUTES.CHARGES.DETAIL(chargeId)}`}
28
28
  />
29
29
  </div>
30
30
  </div>
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from 'react';
2
- import { getChargeHref } from '../../screens/charges/charge.js';
2
+ import { ROUTES } from '@/router/routes.js';
3
3
  import { DocumentsToChargeMatcher } from '../documents-to-charge-matcher/index.js';
4
4
  import { CopyToClipboardButton, PopUpDrawer } from '../index.js';
5
5
 
@@ -25,7 +25,7 @@ export const MatchDocumentModal = ({
25
25
  Charge ID: {chargeId}
26
26
  <CopyToClipboardButton
27
27
  isLink
28
- content={`${window.location.origin}${getChargeHref(chargeId)}`}
28
+ content={`${window.location.origin}${ROUTES.CHARGES.DETAIL(chargeId)}`}
29
29
  />
30
30
  </div>
31
31
  </div>
@@ -1,8 +1,8 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import { Link } from 'react-router-dom';
3
+ import { ROUTES } from '@/router/routes.js';
3
4
  import { NewFetchedDocumentFieldsFragmentDoc } from '../../gql/graphql.js';
4
5
  import { getFragmentData, type FragmentType } from '../../gql/index.js';
5
- import { getChargeHref } from '../screens/charges/charge.js';
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
8
8
  /* GraphQL */ `
@@ -34,7 +34,7 @@ export const NewDocumentsList = ({ data }: Props): ReactElement => {
34
34
  .map(doc => (
35
35
  <Link
36
36
  key={doc.id}
37
- to={getChargeHref(doc.charge!.id)}
37
+ to={ROUTES.CHARGES.DETAIL(doc.charge!.id)}
38
38
  target="_blank"
39
39
  rel="noreferrer"
40
40
  onClick={event => event.stopPropagation()}
@@ -3,9 +3,8 @@ import { Link } from 'react-router-dom';
3
3
  import { DocumentType } from '@/gql/graphql.js';
4
4
  import { useGetBusinesses } from '@/hooks/use-get-businesses.js';
5
5
  import { useUpdateDocument } from '@/hooks/use-update-document.js';
6
- import { useUrlQuery } from '@/hooks/use-url-query.js';
6
+ import { ROUTES } from '@/router/routes.js';
7
7
  import { Indicator } from '@mantine/core';
8
- import { getBusinessHref } from '../../charges/helpers.js';
9
8
  import { ConfirmMiniButton, InsertBusiness, SelectWithSearch } from '../../common/index.js';
10
9
  import type { DocumentsTableRowType } from '../columns.js';
11
10
 
@@ -20,7 +19,6 @@ type Props = {
20
19
  };
21
20
 
22
21
  export const Creditor = ({ document, onChange }: Props): ReactElement => {
23
- const { get } = useUrlQuery();
24
22
  const dbCreditor = 'creditor' in document ? document.creditor : undefined;
25
23
 
26
24
  const shouldHaveCreditor =
@@ -30,13 +28,6 @@ export const Creditor = ({ document, onChange }: Props): ReactElement => {
30
28
 
31
29
  const { selectableBusinesses, refresh: refreshBusinesses } = useGetBusinesses();
32
30
 
33
- const encodedFilters = get('chargesFilters');
34
-
35
- const getHref = useCallback(
36
- (businessId: string) => getBusinessHref(businessId, encodedFilters as string),
37
- [encodedFilters],
38
- );
39
-
40
31
  const suggestedCreditor = useMemo(() => {
41
32
  if (dbCreditor || !('missingInfoSuggestions' in document) || !document.missingInfoSuggestions) {
42
33
  // case when creditor is already set or no suggestions
@@ -106,7 +97,7 @@ export const Creditor = ({ document, onChange }: Props): ReactElement => {
106
97
  {shouldHaveCreditor &&
107
98
  (id ? (
108
99
  <Link
109
- to={getHref(id)}
100
+ to={ROUTES.BUSINESSES.DETAIL(id)}
110
101
  target="_blank"
111
102
  rel="noreferrer"
112
103
  onClick={event => event.stopPropagation()}
@@ -1,11 +1,10 @@
1
1
  import { useCallback, useMemo, useState, type ReactElement } from 'react';
2
2
  import { Link } from 'react-router-dom';
3
3
  import { useGetBusinesses } from '@/hooks/use-get-businesses.js';
4
+ import { ROUTES } from '@/router/routes.js';
4
5
  import { Indicator } from '@mantine/core';
5
6
  import { DocumentType } from '../../../gql/graphql.js';
6
7
  import { useUpdateDocument } from '../../../hooks/use-update-document.js';
7
- import { useUrlQuery } from '../../../hooks/use-url-query.js';
8
- import { getBusinessHref } from '../../charges/helpers.js';
9
8
  import { ConfirmMiniButton, InsertBusiness, SelectWithSearch } from '../../common/index.js';
10
9
  import type { DocumentsTableRowType } from '../columns.js';
11
10
  import { COUNTERPARTIES_LESS_DOCUMENT_TYPES } from './index.js';
@@ -16,7 +15,6 @@ type Props = {
16
15
  };
17
16
 
18
17
  export const Debtor = ({ document, onChange }: Props): ReactElement => {
19
- const { get } = useUrlQuery();
20
18
  const dbDebtor = 'debtor' in document ? document.debtor : undefined;
21
19
 
22
20
  const shouldHaveDebtor =
@@ -26,13 +24,6 @@ export const Debtor = ({ document, onChange }: Props): ReactElement => {
26
24
 
27
25
  const { selectableBusinesses, refresh: refreshBusinesses } = useGetBusinesses();
28
26
 
29
- const encodedFilters = get('chargesFilters');
30
-
31
- const getHref = useCallback(
32
- (businessId: string) => getBusinessHref(businessId, encodedFilters as string),
33
- [encodedFilters],
34
- );
35
-
36
27
  const suggestedDebtor = useMemo(() => {
37
28
  if (dbDebtor || !('missingInfoSuggestions' in document) || !document.missingInfoSuggestions) {
38
29
  // case when creditor is already set or no suggestions
@@ -102,7 +93,7 @@ export const Debtor = ({ document, onChange }: Props): ReactElement => {
102
93
  {shouldHaveDebtor &&
103
94
  (id ? (
104
95
  <Link
105
- to={getHref(id)}
96
+ to={ROUTES.BUSINESSES.DETAIL(id)}
106
97
  target="_blank"
107
98
  rel="noreferrer"
108
99
  onClick={event => event.stopPropagation()}