@accounter/client 0.0.8-alpha-20251021225827-178e480c997a9811913e16f85cb94329041b096e → 0.0.8-alpha-20251022130946-0923a77d2ee3f22a60a7f5b1e0623bd3bee88868

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 (108) hide show
  1. package/CHANGELOG.md +1 -25
  2. package/dist/assets/index-B2UYAO1O.css +1 -0
  3. package/dist/assets/index-BexxGuN6.js +1224 -0
  4. package/dist/assets/{index.es-CYeQ4a5s.js → index.es-CWwhWGxX.js} +5 -5
  5. package/dist/index.html +2 -2
  6. package/package.json +1 -1
  7. package/src/components/business-transactions/business-extended-info.tsx +15 -13
  8. package/src/components/business-transactions/business-transactions-single.tsx +3 -3
  9. package/src/components/business-transactions/index.tsx +1 -12
  10. package/src/components/business-trips/business-trip.tsx +3 -3
  11. package/src/components/charges/cells/business-trip.tsx +8 -6
  12. package/src/components/charges/cells/counterparty.tsx +5 -7
  13. package/src/components/common/accounter-table.tsx +5 -6
  14. package/src/components/common/business-trip-report/parts/core-expense-row.tsx +9 -11
  15. package/src/components/common/business-trip-report/parts/uncategorized-transactions.tsx +13 -11
  16. package/src/components/common/buttons/button-with-label.tsx +41 -0
  17. package/src/components/common/buttons/button.tsx +44 -0
  18. package/src/components/common/buttons/index.ts +2 -0
  19. package/src/components/common/buttons/logout-button.tsx +6 -7
  20. package/src/components/common/documents-to-charge-matcher/selection-handler/index.tsx +2 -4
  21. package/src/components/common/documents-to-charge-matcher/selection-handler/wide-filtered-selection.tsx +7 -5
  22. package/src/components/common/forms/edit-document.tsx +10 -23
  23. package/src/components/common/new-documents-list.tsx +8 -10
  24. package/src/components/documents-table/cells/creditor.tsx +4 -11
  25. package/src/components/documents-table/cells/debtor.tsx +4 -11
  26. package/src/components/layout/dashboard-layout.tsx +0 -4
  27. package/src/components/layout/sidelinks.tsx +27 -28
  28. package/src/components/ledger-table/counterparty-cell.tsx +13 -19
  29. package/src/components/login-page.tsx +1 -2
  30. package/src/components/reports/corporate-tax-ruling-compliance-report/index.tsx +3 -3
  31. package/src/components/reports/profit-and-loss-report/index.tsx +3 -3
  32. package/src/components/reports/tax-report/index.tsx +3 -3
  33. package/src/components/screens/businesses/business.tsx +9 -21
  34. package/src/components/screens/charges/charge.tsx +9 -22
  35. package/src/components/transactions-table/cells/counterparty.tsx +2 -9
  36. package/src/components/transactions-table/cells-legacy/counterparty.tsx +2 -9
  37. package/src/gql/graphql.ts +4842 -1554
  38. package/src/index.tsx +22 -4
  39. package/src/providers/auth-guard.tsx +23 -14
  40. package/src/providers/index.tsx +2 -7
  41. package/src/providers/urql.tsx +12 -7
  42. package/src/providers/user-provider.tsx +2 -3
  43. package/dist/assets/Checkbox-CxedbJAl.js +0 -6
  44. package/dist/assets/Progress-D5SuJtCd.js +0 -1
  45. package/dist/assets/Typography-BQFz-z7L.js +0 -1
  46. package/dist/assets/accordion-COWOBKuq.js +0 -1
  47. package/dist/assets/accountant-approvals-Bd2y8us_.js +0 -1
  48. package/dist/assets/all-charges-SWBnaZu7.js +0 -1
  49. package/dist/assets/arrow-up-down-dZmrBLse.js +0 -6
  50. package/dist/assets/business--GVVfDEa.js +0 -37
  51. package/dist/assets/business-transactions-single-BsbkUf_H.js +0 -1
  52. package/dist/assets/business-trip-ByXPVXdG.js +0 -1
  53. package/dist/assets/charges-filters-D43UbXob.js +0 -1
  54. package/dist/assets/charges-ledger-validation-D0uMH_JE.js +0 -1
  55. package/dist/assets/chart-ClU1KbWe.js +0 -74
  56. package/dist/assets/data-table-pagination-D9Y0_Tn8.js +0 -11
  57. package/dist/assets/editable-business-trip-DhqOQBPa.js +0 -16
  58. package/dist/assets/graphql-document-dedupe-fragments-ByT8-wlV.js +0 -1
  59. package/dist/assets/index-1U6rQgQe.js +0 -6
  60. package/dist/assets/index-3-AKn8tg.js +0 -1
  61. package/dist/assets/index-91A2PLZ6.js +0 -137
  62. package/dist/assets/index-BBHuCWRn.js +0 -1
  63. package/dist/assets/index-BPNuFFtx.js +0 -1
  64. package/dist/assets/index-BXqHnRVY.js +0 -1
  65. package/dist/assets/index-BciOH8FS.js +0 -1
  66. package/dist/assets/index-BjHuUHDO.js +0 -1
  67. package/dist/assets/index-BxKmoNQd.js +0 -1
  68. package/dist/assets/index-C3bqiFIv.js +0 -2
  69. package/dist/assets/index-C5MeepK_.js +0 -11
  70. package/dist/assets/index-CAwm68Mg.js +0 -1
  71. package/dist/assets/index-CJ8OGXxv.js +0 -1
  72. package/dist/assets/index-CJyY-qF6.js +0 -1
  73. package/dist/assets/index-CMYnx46_.js +0 -6
  74. package/dist/assets/index-CNrwxUZ7.js +0 -1
  75. package/dist/assets/index-CvV5z5r9.js +0 -876
  76. package/dist/assets/index-D08H2GXq.js +0 -17
  77. package/dist/assets/index-GFsPY1p4.js +0 -2
  78. package/dist/assets/index-KwNwThNu.js +0 -1
  79. package/dist/assets/index-YA8IBFyB.js +0 -1
  80. package/dist/assets/index-ZpyI3qxW.js +0 -24
  81. package/dist/assets/index-gdTXrWXt.css +0 -1
  82. package/dist/assets/index-ytnIEraq.js +0 -9
  83. package/dist/assets/issue-document-CdikNnO2.js +0 -1
  84. package/dist/assets/login-page-effgZS3V.js +0 -1
  85. package/dist/assets/missing-info-charges-CnPFTzoZ.js +0 -1
  86. package/dist/assets/page-not-found-D8YlgDOm.js +0 -1
  87. package/dist/assets/pencil-mxW0-tGM.js +0 -6
  88. package/dist/assets/report-commentary-row-DCozKgVE.js +0 -1
  89. package/dist/assets/save-CHlytUqu.js +0 -11
  90. package/dist/assets/sequential-CAnleQny.js +0 -1
  91. package/dist/assets/similar-charges-by-business-modal-Dzbspk_r.js +0 -1
  92. package/dist/assets/sub-Cp_PhKiD.js +0 -1
  93. package/dist/assets/subMonths-DCj_iXAn.js +0 -1
  94. package/src/components/error-boundary.tsx +0 -189
  95. package/src/components/layout/breadcrumbs.tsx +0 -77
  96. package/src/components/layout/document-title.tsx +0 -31
  97. package/src/components/layout/navigation-progress.tsx +0 -52
  98. package/src/components/layout/page-skeleton.tsx +0 -49
  99. package/src/providers/urql-client.ts +0 -86
  100. package/src/router/config.tsx +0 -534
  101. package/src/router/layouts/dashboard-layout.tsx +0 -20
  102. package/src/router/layouts/root-layout.tsx +0 -69
  103. package/src/router/loaders/auth-loader.ts +0 -32
  104. package/src/router/loaders/business-loader.ts +0 -25
  105. package/src/router/loaders/charge-loader.ts +0 -25
  106. package/src/router/loaders/index.ts +0 -17
  107. package/src/router/routes.ts +0 -88
  108. package/src/router/types.ts +0 -62
@@ -1,7 +1,6 @@
1
1
  import { useCallback, useMemo, useState, type ReactElement } from 'react';
2
- import { Link } from 'react-router-dom';
3
2
  import { useGetBusinesses } from '@/hooks/use-get-businesses.js';
4
- import { Indicator } from '@mantine/core';
3
+ import { Indicator, NavLink } from '@mantine/core';
5
4
  import { DocumentType } from '../../../gql/graphql.js';
6
5
  import { useUpdateDocument } from '../../../hooks/use-update-document.js';
7
6
  import { useUrlQuery } from '../../../hooks/use-url-query.js';
@@ -101,15 +100,9 @@ export const Debtor = ({ document, onChange }: Props): ReactElement => {
101
100
  <Indicator inline size={12} disabled={!isError} color="red" zIndex="auto">
102
101
  {shouldHaveDebtor &&
103
102
  (id ? (
104
- <Link
105
- to={getHref(id)}
106
- target="_blank"
107
- rel="noreferrer"
108
- onClick={event => event.stopPropagation()}
109
- className="inline-flex items-center font-semibold"
110
- >
111
- {name}
112
- </Link>
103
+ <a href={getHref(id)} target="_blank" rel="noreferrer">
104
+ <NavLink label={name} className="[&>*>.mantine-NavLink-label]:font-semibold" />
105
+ </a>
113
106
  ) : (
114
107
  <SelectWithSearch
115
108
  options={selectableBusinesses}
@@ -1,9 +1,7 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import { useSidebar } from '../../hooks/use-sidebar.js';
3
- import { Breadcrumbs } from './breadcrumbs.js';
4
3
  import { Footer } from './footer.js';
5
4
  import { Header } from './header.js';
6
- import { NavigationProgress } from './navigation-progress.js';
7
5
  import { Sidebar } from './sidebar.js';
8
6
 
9
7
  type DashboardLayoutProps = {
@@ -16,14 +14,12 @@ export function DashboardLayout({ children, filtersContext }: DashboardLayoutPro
16
14
 
17
15
  return (
18
16
  <main>
19
- <NavigationProgress />
20
17
  <Header />
21
18
  <div className="flex h-screen overflow-hidden bg-gray-100">
22
19
  <Sidebar />
23
20
  <div
24
21
  className={`overflow-scroll flex flex-col justify-start gap-10 z-0 my-20 pl-10 flex-1 ${isMinimized ? 'pr-10' : 'pr-5'} transition-all`}
25
22
  >
26
- <Breadcrumbs />
27
23
  {children}
28
24
  </div>
29
25
  </div>
@@ -26,7 +26,6 @@ import {
26
26
  Scale,
27
27
  Tags,
28
28
  } from 'lucide-react';
29
- import { ROUTES } from '../../router/routes.js';
30
29
 
31
30
  export interface NavLink {
32
31
  title: string;
@@ -50,19 +49,19 @@ export const sidelinks: SideLink[] = [
50
49
  {
51
50
  title: 'All Charges',
52
51
  label: '',
53
- href: ROUTES.CHARGES.ALL,
52
+ href: '/charges',
54
53
  icon: <Receipt size={18} />,
55
54
  },
56
55
  {
57
56
  title: 'Missing Info Charges',
58
57
  label: '',
59
- href: ROUTES.CHARGES.MISSING_INFO,
58
+ href: '/charges/missing-info',
60
59
  icon: <RectangleEllipsis size={18} />,
61
60
  },
62
61
  {
63
62
  title: 'Ledger Validation',
64
63
  label: '',
65
- href: ROUTES.CHARGES.LEDGER_VALIDATION,
64
+ href: '/charges/ledger-validation',
66
65
  icon: <BookOpenCheck size={18} />,
67
66
  },
68
67
  ],
@@ -76,73 +75,73 @@ export const sidelinks: SideLink[] = [
76
75
  {
77
76
  title: 'VAT Monthly Report',
78
77
  label: '',
79
- href: ROUTES.REPORTS.VAT_MONTHLY,
78
+ href: '/reports/vat-monthly',
80
79
  icon: <Receipt size={18} />,
81
80
  },
82
81
  {
83
82
  title: 'Trial Balance Report',
84
83
  label: '',
85
- href: ROUTES.REPORTS.TRIAL_BALANCE,
84
+ href: '/reports/trial-balance',
86
85
  icon: <Scale size={18} />,
87
86
  },
88
87
  {
89
88
  title: 'Conto Report',
90
89
  label: '',
91
- href: ROUTES.REPORTS.CONTO,
90
+ href: '/reports/conto',
92
91
  icon: <Puzzle size={18} />,
93
92
  },
94
93
  {
95
94
  title: 'Profit and Loss Report',
96
95
  label: '',
97
- href: ROUTES.REPORTS.PROFIT_AND_LOSS(),
96
+ href: '/reports/profit-and-loss',
98
97
  icon: <HandCoins size={18} />,
99
98
  },
100
99
  {
101
100
  title: 'Tax Report',
102
101
  label: '',
103
- href: ROUTES.REPORTS.TAX(),
102
+ href: '/reports/tax',
104
103
  icon: <ParkingMeter size={18} />,
105
104
  },
106
105
  {
107
106
  title: 'Corporate Tax Ruling Compliance Report',
108
107
  label: '',
109
- href: ROUTES.REPORTS.CORPORATE_TAX_RULING_COMPLIANCE(),
108
+ href: '/reports/corporate-tax-ruling-compliance',
110
109
  icon: <ParkingMeter size={18} />,
111
110
  },
112
111
  {
113
112
  title: 'Depreciation Report',
114
113
  label: '',
115
- href: ROUTES.REPORTS.DEPRECIATION,
114
+ href: '/reports/depreciation',
116
115
  icon: <ChartColumnDecreasing size={18} />,
117
116
  },
118
117
  {
119
118
  title: 'Shaam 6111 Report',
120
119
  label: '',
121
- href: ROUTES.REPORTS.SHAAM_6111,
120
+ href: '/reports/shaam6111',
122
121
  icon: <HandCoins size={18} />,
123
122
  },
124
123
  {
125
124
  title: 'Accountant Approvals',
126
125
  label: '',
127
- href: ROUTES.ACCOUNTANT_APPROVALS,
126
+ href: '/accountant-approvals',
128
127
  icon: <Calculator size={18} />,
129
128
  },
130
129
  {
131
130
  title: 'Yearly Ledger Report',
132
131
  label: '',
133
- href: ROUTES.REPORTS.YEARLY_LEDGER,
132
+ href: '/reports/yearly-ledger',
134
133
  icon: <Rows4 size={18} />,
135
134
  },
136
135
  {
137
136
  title: 'Transactions Balance',
138
137
  label: '',
139
- href: ROUTES.REPORTS.BALANCE,
138
+ href: '/reports/balance',
140
139
  icon: <ChartNoAxesCombined size={18} />,
141
140
  },
142
141
  {
143
142
  title: 'Validate Reports',
144
143
  label: '',
145
- href: ROUTES.REPORTS.VALIDATE_REPORTS,
144
+ href: '/reports/validate-reports',
146
145
  icon: <CheckCheck size={18} />,
147
146
  },
148
147
  {
@@ -161,25 +160,25 @@ export const sidelinks: SideLink[] = [
161
160
  {
162
161
  title: 'Businesses',
163
162
  label: '',
164
- href: ROUTES.BUSINESSES.ALL,
163
+ href: '/businesses',
165
164
  icon: <Factory size={18} />,
166
165
  },
167
166
  {
168
167
  title: 'Business Transactions',
169
168
  label: '',
170
- href: ROUTES.BUSINESSES.TRANSACTIONS,
169
+ href: '/businesses/transactions',
171
170
  icon: <ArrowLeftRight size={18} />,
172
171
  },
173
172
  {
174
173
  title: 'Tax Categories',
175
174
  label: '',
176
- href: ROUTES.TAX_CATEGORIES,
175
+ href: '/tax-categories',
177
176
  icon: <ArrowDown01 size={18} />,
178
177
  },
179
178
  {
180
179
  title: 'Sort Codes',
181
180
  label: '',
182
- href: ROUTES.SORT_CODES,
181
+ href: '/sort-codes',
183
182
  icon: <Book size={18} />,
184
183
  },
185
184
  ],
@@ -191,7 +190,7 @@ export const sidelinks: SideLink[] = [
191
190
  icon: <Files size={18} />,
192
191
  sub: [
193
192
  {
194
- href: ROUTES.DOCUMENTS.ALL,
193
+ href: '/documents',
195
194
  title: 'All Documents',
196
195
  label: '',
197
196
  icon: <Files size={18} />,
@@ -199,19 +198,19 @@ export const sidelinks: SideLink[] = [
199
198
  {
200
199
  title: 'Issue Documents',
201
200
  label: '',
202
- href: ROUTES.DOCUMENTS.ISSUE_DOCUMENTS,
201
+ href: '/documents/issue-documents',
203
202
  icon: <FilePen size={18} />,
204
203
  },
205
204
  {
206
205
  title: 'Issue Document',
207
206
  label: '',
208
- href: ROUTES.DOCUMENTS.ISSUE_DOCUMENT,
207
+ href: '/documents/issue-document',
209
208
  icon: <FilePen size={18} />,
210
209
  },
211
210
  ],
212
211
  },
213
212
  {
214
- href: ROUTES.BUSINESS_TRIPS.ALL,
213
+ href: '/business-trips',
215
214
  title: 'Business Trips',
216
215
  label: '',
217
216
  icon: <PlaneTakeoff size={18} />,
@@ -225,25 +224,25 @@ export const sidelinks: SideLink[] = [
225
224
  {
226
225
  title: 'Main',
227
226
  label: '',
228
- href: ROUTES.CHARTS.MAIN,
227
+ href: '/charts/',
229
228
  icon: <BarChartBig size={18} />,
230
229
  },
231
230
  {
232
231
  title: 'Monthly Income/Expense',
233
232
  label: '',
234
- href: ROUTES.CHARTS.MONTHLY_INCOME_EXPENSE,
233
+ href: '/charts/monthly-income-expense',
235
234
  icon: <BarChartBig size={18} />,
236
235
  },
237
236
  ],
238
237
  },
239
238
  {
240
- href: ROUTES.SALARIES,
239
+ href: '/salaries',
241
240
  title: 'Salaries',
242
241
  label: '',
243
242
  icon: <BadgeDollarSign size={18} />,
244
243
  },
245
244
  {
246
- href: ROUTES.TAGS,
245
+ href: '/tags',
247
246
  title: 'Tags',
248
247
  label: '',
249
248
  icon: <Tags size={18} />,
@@ -1,5 +1,5 @@
1
1
  import { useCallback, type ReactElement } from 'react';
2
- import { Link } from 'react-router-dom';
2
+ import { NavLink } from '@mantine/core';
3
3
  import type { ChargeFilter } from '../../gql/graphql.js';
4
4
  import { useUrlQuery } from '../../hooks/use-url-query.js';
5
5
  import { getBusinessTransactionsHref } from '../business-transactions/index.js';
@@ -50,27 +50,21 @@ export const CounterpartyCell = ({ account, diffAccount }: Props): ReactElement
50
50
  {(account || isAccountDiff) && (
51
51
  <>
52
52
  {account && (
53
- <Link
54
- to={getHref(account.id)}
55
- target="_blank"
56
- rel="noreferrer"
57
- onClick={event => event.stopPropagation()}
58
- className="inline-flex items-center font-semibold"
59
- >
60
- {account.name}
61
- </Link>
53
+ <a href={getHref(account.id)} target="_blank" rel="noreferrer">
54
+ <NavLink
55
+ label={account.name}
56
+ className={`[&>*>.mantine-NavLink-label]:font-semibold ${isAccountDiff ? 'line-through' : ''}`}
57
+ />
58
+ </a>
62
59
  )}
63
60
  {isAccountDiff && diffAccount && (
64
61
  <div className="border-2 border-yellow-500 rounded-md">
65
- <Link
66
- to={getHref(diffAccount.id)}
67
- target="_blank"
68
- rel="noreferrer"
69
- onClick={event => event.stopPropagation()}
70
- className="inline-flex items-center font-semibold"
71
- >
72
- {diffAccount.name}
73
- </Link>
62
+ <a href={getHref(diffAccount.id)} target="_blank" rel="noreferrer">
63
+ <NavLink
64
+ label={diffAccount.name}
65
+ className="[&>*>.mantine-NavLink-label]:font-semibold"
66
+ />
67
+ </a>
74
68
  </div>
75
69
  )}
76
70
  </>
@@ -5,7 +5,6 @@ import { toast } from 'sonner';
5
5
  import { z } from 'zod';
6
6
  import { zodResolver } from '@hookform/resolvers/zod';
7
7
  import { AuthContext } from '../providers/auth-guard.js';
8
- import { ROUTES } from '../router/routes.js';
9
8
  import { Button } from './ui/button.js';
10
9
  import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from './ui/form.js';
11
10
  import { Input } from './ui/input.js';
@@ -33,7 +32,7 @@ export function LoginPage(): ReactElement {
33
32
  function onSubmit(values: z.infer<typeof formSchema>) {
34
33
  try {
35
34
  authService.login(values.username, values.password).then(_user => {
36
- navigate(ROUTES.HOME);
35
+ navigate('/');
37
36
  });
38
37
  toast.success('Success', {
39
38
  description: 'You have successfully logged in.',
@@ -1,6 +1,6 @@
1
1
  import { useContext, useEffect, useState, type ReactElement } from 'react';
2
2
  import { Loader2 } from 'lucide-react';
3
- import { useParams } from 'react-router-dom';
3
+ import { useMatch } from 'react-router-dom';
4
4
  import { useQuery } from 'urql';
5
5
  import { Indicator, Table, Tooltip } from '@mantine/core';
6
6
  import { CorporateTaxRulingComplianceReportDocument, Currency } from '../../../gql/graphql.js';
@@ -109,10 +109,10 @@ function multipleOptionalFormatter(amounts: number[], currency: Currency) {
109
109
  }
110
110
 
111
111
  export const CorporateTaxRulingComplianceReport = (): ReactElement => {
112
- const { year: yearFromUrl } = useParams<{ year: string }>();
112
+ const match = useMatch('/reports/corporate-tax-ruling-compliance/:year');
113
113
  const { setFiltersContext } = useContext(FiltersContext);
114
114
  const [years, setYears] = useState<number[]>(
115
- yearFromUrl ? [Number(yearFromUrl)] : [new Date().getFullYear()],
115
+ (match ? [Number(match.params.year)] : undefined) ?? [new Date().getFullYear()],
116
116
  );
117
117
 
118
118
  // fetch data
@@ -1,6 +1,6 @@
1
1
  import { useContext, useEffect, useState, type ReactElement } from 'react';
2
2
  import { Loader2 } from 'lucide-react';
3
- import { useParams } from 'react-router-dom';
3
+ import { useMatch } from 'react-router-dom';
4
4
  import { useQuery } from 'urql';
5
5
  import { Table } from '@mantine/core';
6
6
  import { ProfitAndLossReportDocument } from '../../../gql/graphql.js';
@@ -135,10 +135,10 @@ import { ProfitAndLossReportFilter } from './profit-and-loss-report-filters.js';
135
135
  `;
136
136
 
137
137
  export const ProfitAndLossReport = (): ReactElement => {
138
- const { year: yearFromUrl } = useParams<{ year: string }>();
138
+ const match = useMatch('/reports/profit-and-loss/:year');
139
139
  const { setFiltersContext } = useContext(FiltersContext);
140
140
  const [year, setYear] = useState<number>(
141
- yearFromUrl ? Number(yearFromUrl) : new Date().getFullYear(),
141
+ (match ? Number(match.params.year) : undefined) ?? new Date().getFullYear(),
142
142
  );
143
143
  const [referenceYears, setReferenceYears] = useState<number[]>([]);
144
144
 
@@ -1,6 +1,6 @@
1
1
  import { useContext, useEffect, useState, type ReactElement } from 'react';
2
2
  import { Loader2 } from 'lucide-react';
3
- import { useParams } from 'react-router-dom';
3
+ import { useMatch } from 'react-router-dom';
4
4
  import { useQuery } from 'urql';
5
5
  import { Table } from '@mantine/core';
6
6
  import { TaxReportDocument } from '../../../gql/graphql.js';
@@ -140,10 +140,10 @@ import { TaxReportFilter } from './tax-report-filters.js';
140
140
  `;
141
141
 
142
142
  export const TaxReport = (): ReactElement => {
143
- const { year: yearFromUrl } = useParams<{ year: string }>();
143
+ const match = useMatch('/reports/tax/:year');
144
144
  const { setFiltersContext } = useContext(FiltersContext);
145
145
  const [year, setYear] = useState<number>(
146
- yearFromUrl ? Number(yearFromUrl) : new Date().getFullYear(),
146
+ (match ? Number(match.params.year) : undefined) ?? new Date().getFullYear(),
147
147
  );
148
148
  const [referenceYears, setReferenceYears] = useState<number[]>([]);
149
149
 
@@ -1,8 +1,8 @@
1
1
  import { type ReactElement } from 'react';
2
- import { useLoaderData, useParams } from 'react-router-dom';
2
+ import { useMatch } from 'react-router-dom';
3
3
  import { useQuery } from 'urql';
4
4
  import Business from '@/components/business/index.js';
5
- import { BusinessScreenDocument, type BusinessScreenQuery } from '../../../gql/graphql.js';
5
+ import { BusinessScreenDocument } from '../../../gql/graphql.js';
6
6
  import { AccounterLoader } from '../../common/index.js';
7
7
 
8
8
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
@@ -20,37 +20,25 @@ export function getBusinessHref(businessId: string): string {
20
20
  }
21
21
 
22
22
  export const BusinessScreen = (): ReactElement => {
23
- const { businessId } = useParams<{ businessId: string }>();
24
-
25
- // Try to get loader data (will be available when navigating via router)
26
- let loaderData: BusinessScreenQuery | undefined;
27
- try {
28
- // eslint-disable-next-line react-hooks/rules-of-hooks
29
- loaderData = useLoaderData() as BusinessScreenQuery;
30
- } catch {
31
- // No loader data - fallback to query
32
- }
23
+ const match = useMatch('/businesses/:businessId');
24
+
25
+ const businessId = match?.params.businessId;
33
26
 
34
- // Only fetch if we don't have loader data
35
27
  const [{ data, fetching }, fetchBusiness] = useQuery({
36
28
  query: BusinessScreenDocument,
37
- pause: !businessId || !!loaderData,
29
+ pause: !businessId,
38
30
  variables: {
39
31
  businessId: businessId ?? '',
40
32
  },
41
33
  });
42
34
 
43
- // Use loader data if available, otherwise use query data
44
- const businessData = loaderData || data;
45
- const isLoading = !loaderData && fetching;
46
-
47
- if (isLoading && !businessData?.business) {
35
+ if (fetching && !data?.business) {
48
36
  return <AccounterLoader />;
49
37
  }
50
38
 
51
- if (!businessId || !businessData?.business) {
39
+ if (!businessId || !data?.business) {
52
40
  return <div>Business not found</div>;
53
41
  }
54
42
 
55
- return <Business data={businessData.business} refetchBusiness={async () => fetchBusiness()} />;
43
+ return <Business data={data.business} refetchBusiness={async () => fetchBusiness()} />;
56
44
  };
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useState, type ReactElement } from 'react';
2
- import { useLoaderData, useParams } from 'react-router-dom';
2
+ import { useMatch } from 'react-router-dom';
3
3
  import { useQuery } from 'urql';
4
- import { ChargeScreenDocument, type ChargeScreenQuery } from '../../../gql/graphql.js';
4
+ import { ChargeScreenDocument } from '../../../gql/graphql.js';
5
5
  import { ChargesTable } from '../../charges/charges-table.js';
6
6
  import {
7
7
  AccounterLoader,
@@ -29,17 +29,9 @@ type Props = {
29
29
  };
30
30
 
31
31
  export const Charge = ({ chargeId }: Props): ReactElement => {
32
- const { chargeId: chargeIdFromUrl } = useParams<{ chargeId: string }>();
33
- const id = chargeId || chargeIdFromUrl;
32
+ const match = useMatch('/charges/:chargeId');
34
33
 
35
- // Try to get loader data (will be available when navigating via router)
36
- let loaderData: ChargeScreenQuery | undefined;
37
- try {
38
- // eslint-disable-next-line react-hooks/rules-of-hooks
39
- loaderData = useLoaderData() as ChargeScreenQuery;
40
- } catch {
41
- // No loader data - component used outside router context (e.g., as child component)
42
- }
34
+ const id = chargeId || match?.params.chargeId;
43
35
 
44
36
  const [editChargeId, setEditChargeId] = useState<
45
37
  { id: string; onChange: () => void } | undefined
@@ -51,24 +43,19 @@ export const Charge = ({ chargeId }: Props): ReactElement => {
51
43
  undefined,
52
44
  );
53
45
 
54
- // Only fetch if we don't have loader data and need to fetch (prop-based usage)
55
46
  const [{ data, fetching }, fetchCharge] = useQuery({
56
47
  query: ChargeScreenDocument,
57
- pause: !id || !!loaderData,
48
+ pause: !id,
58
49
  variables: {
59
50
  chargeId: id ?? '',
60
51
  },
61
52
  });
62
53
 
63
54
  useEffect(() => {
64
- if (id && !loaderData) {
55
+ if (id) {
65
56
  fetchCharge();
66
57
  }
67
- }, [id, loaderData, fetchCharge]);
68
-
69
- // Use loader data if available, otherwise use query data
70
- const chargeData = loaderData || data;
71
- const isLoading = !loaderData && fetching;
58
+ }, [id, fetchCharge]);
72
59
 
73
60
  if (!id) {
74
61
  return <div>Charge not found</div>;
@@ -76,14 +63,14 @@ export const Charge = ({ chargeId }: Props): ReactElement => {
76
63
 
77
64
  return (
78
65
  <>
79
- {isLoading ? (
66
+ {fetching ? (
80
67
  <AccounterLoader />
81
68
  ) : (
82
69
  <ChargesTable
83
70
  setEditChargeId={setEditChargeId}
84
71
  setInsertDocument={setInsertDocument}
85
72
  setMatchDocuments={setMatchDocuments}
86
- data={chargeData?.charge ? [chargeData.charge] : []}
73
+ data={data?.charge ? [data.charge] : []}
87
74
  isAllOpened
88
75
  />
89
76
  )}
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useState, type ReactElement } from 'react';
2
2
  import { CheckIcon } from 'lucide-react';
3
- import { Link } from 'react-router-dom';
4
3
  import type { ChargeFilter } from '../../../gql/graphql.js';
5
4
  import { useGetBusinesses } from '../../../hooks/use-get-businesses.js';
6
5
  import { useUpdateTransaction } from '../../../hooks/use-update-transaction.js';
@@ -86,15 +85,9 @@ export function Counterparty({ transaction, onChange }: Props): ReactElement {
86
85
  <>
87
86
  <div className="flex flex-wrap flex-col justify-center">
88
87
  {counterparty?.id ? (
89
- <Link
90
- to={getHref(counterparty.id)}
91
- target="_blank"
92
- rel="noreferrer"
93
- onClick={event => event.stopPropagation()}
94
- className="inline-flex items-center font-semibold"
95
- >
88
+ <a href={getHref(counterparty.id)} target="_blank" rel="noreferrer">
96
89
  {name}
97
- </Link>
90
+ </a>
98
91
  ) : (
99
92
  <>
100
93
  <SelectWithSearch
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useState, type ReactElement } from 'react';
2
2
  import { CheckIcon } from 'lucide-react';
3
- import { Link } from 'react-router-dom';
4
3
  import {
5
4
  TransactionsTableEntityFieldsFragmentDoc,
6
5
  type ChargeFilter,
@@ -107,15 +106,9 @@ export function Counterparty({ data, onChange, enableEdit }: Props): ReactElemen
107
106
  <td>
108
107
  <div className="flex flex-wrap gap-1 items-center justify-center">
109
108
  {counterparty?.id ? (
110
- <Link
111
- to={getHref(counterparty.id)}
112
- target="_blank"
113
- rel="noreferrer"
114
- onClick={event => event.stopPropagation()}
115
- className="inline-flex items-center font-semibold"
116
- >
109
+ <a href={getHref(counterparty.id)} target="_blank" rel="noreferrer">
117
110
  {name}
118
- </Link>
111
+ </a>
119
112
  ) : (
120
113
  <>
121
114
  <SelectWithSearch