@accounter/client 0.0.8-alpha-20251021225827-178e480c997a9811913e16f85cb94329041b096e → 0.0.8-alpha-20251022034712-a30a030f5a83f0dff0ee9fa8ccd0ebdaf7986647
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/CHANGELOG.md +1 -25
- package/dist/assets/index-B2UYAO1O.css +1 -0
- package/dist/assets/index-BexxGuN6.js +1224 -0
- package/dist/assets/{index.es-CYeQ4a5s.js → index.es-CWwhWGxX.js} +5 -5
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/components/business-transactions/business-extended-info.tsx +15 -13
- package/src/components/business-transactions/business-transactions-single.tsx +3 -3
- package/src/components/business-transactions/index.tsx +1 -12
- package/src/components/business-trips/business-trip.tsx +3 -3
- package/src/components/charges/cells/business-trip.tsx +8 -6
- package/src/components/charges/cells/counterparty.tsx +5 -7
- package/src/components/common/accounter-table.tsx +5 -6
- package/src/components/common/business-trip-report/parts/core-expense-row.tsx +9 -11
- package/src/components/common/business-trip-report/parts/uncategorized-transactions.tsx +13 -11
- package/src/components/common/buttons/button-with-label.tsx +41 -0
- package/src/components/common/buttons/button.tsx +44 -0
- package/src/components/common/buttons/index.ts +2 -0
- package/src/components/common/buttons/logout-button.tsx +6 -7
- package/src/components/common/documents-to-charge-matcher/selection-handler/index.tsx +2 -4
- package/src/components/common/documents-to-charge-matcher/selection-handler/wide-filtered-selection.tsx +7 -5
- package/src/components/common/forms/edit-document.tsx +10 -23
- package/src/components/common/new-documents-list.tsx +8 -10
- package/src/components/documents-table/cells/creditor.tsx +4 -11
- package/src/components/documents-table/cells/debtor.tsx +4 -11
- package/src/components/layout/dashboard-layout.tsx +0 -4
- package/src/components/layout/sidelinks.tsx +27 -28
- package/src/components/ledger-table/counterparty-cell.tsx +13 -19
- package/src/components/login-page.tsx +1 -2
- package/src/components/reports/corporate-tax-ruling-compliance-report/index.tsx +3 -3
- package/src/components/reports/profit-and-loss-report/index.tsx +3 -3
- package/src/components/reports/tax-report/index.tsx +3 -3
- package/src/components/screens/businesses/business.tsx +9 -21
- package/src/components/screens/charges/charge.tsx +9 -22
- package/src/components/transactions-table/cells/counterparty.tsx +2 -9
- package/src/components/transactions-table/cells-legacy/counterparty.tsx +2 -9
- package/src/index.tsx +22 -4
- package/src/providers/auth-guard.tsx +23 -14
- package/src/providers/index.tsx +2 -7
- package/src/providers/urql.tsx +12 -7
- package/src/providers/user-provider.tsx +2 -3
- package/dist/assets/Checkbox-CxedbJAl.js +0 -6
- package/dist/assets/Progress-D5SuJtCd.js +0 -1
- package/dist/assets/Typography-BQFz-z7L.js +0 -1
- package/dist/assets/accordion-COWOBKuq.js +0 -1
- package/dist/assets/accountant-approvals-Bd2y8us_.js +0 -1
- package/dist/assets/all-charges-SWBnaZu7.js +0 -1
- package/dist/assets/arrow-up-down-dZmrBLse.js +0 -6
- package/dist/assets/business--GVVfDEa.js +0 -37
- package/dist/assets/business-transactions-single-BsbkUf_H.js +0 -1
- package/dist/assets/business-trip-ByXPVXdG.js +0 -1
- package/dist/assets/charges-filters-D43UbXob.js +0 -1
- package/dist/assets/charges-ledger-validation-D0uMH_JE.js +0 -1
- package/dist/assets/chart-ClU1KbWe.js +0 -74
- package/dist/assets/data-table-pagination-D9Y0_Tn8.js +0 -11
- package/dist/assets/editable-business-trip-DhqOQBPa.js +0 -16
- package/dist/assets/graphql-document-dedupe-fragments-ByT8-wlV.js +0 -1
- package/dist/assets/index-1U6rQgQe.js +0 -6
- package/dist/assets/index-3-AKn8tg.js +0 -1
- package/dist/assets/index-91A2PLZ6.js +0 -137
- package/dist/assets/index-BBHuCWRn.js +0 -1
- package/dist/assets/index-BPNuFFtx.js +0 -1
- package/dist/assets/index-BXqHnRVY.js +0 -1
- package/dist/assets/index-BciOH8FS.js +0 -1
- package/dist/assets/index-BjHuUHDO.js +0 -1
- package/dist/assets/index-BxKmoNQd.js +0 -1
- package/dist/assets/index-C3bqiFIv.js +0 -2
- package/dist/assets/index-C5MeepK_.js +0 -11
- package/dist/assets/index-CAwm68Mg.js +0 -1
- package/dist/assets/index-CJ8OGXxv.js +0 -1
- package/dist/assets/index-CJyY-qF6.js +0 -1
- package/dist/assets/index-CMYnx46_.js +0 -6
- package/dist/assets/index-CNrwxUZ7.js +0 -1
- package/dist/assets/index-CvV5z5r9.js +0 -876
- package/dist/assets/index-D08H2GXq.js +0 -17
- package/dist/assets/index-GFsPY1p4.js +0 -2
- package/dist/assets/index-KwNwThNu.js +0 -1
- package/dist/assets/index-YA8IBFyB.js +0 -1
- package/dist/assets/index-ZpyI3qxW.js +0 -24
- package/dist/assets/index-gdTXrWXt.css +0 -1
- package/dist/assets/index-ytnIEraq.js +0 -9
- package/dist/assets/issue-document-CdikNnO2.js +0 -1
- package/dist/assets/login-page-effgZS3V.js +0 -1
- package/dist/assets/missing-info-charges-CnPFTzoZ.js +0 -1
- package/dist/assets/page-not-found-D8YlgDOm.js +0 -1
- package/dist/assets/pencil-mxW0-tGM.js +0 -6
- package/dist/assets/report-commentary-row-DCozKgVE.js +0 -1
- package/dist/assets/save-CHlytUqu.js +0 -11
- package/dist/assets/sequential-CAnleQny.js +0 -1
- package/dist/assets/similar-charges-by-business-modal-Dzbspk_r.js +0 -1
- package/dist/assets/sub-Cp_PhKiD.js +0 -1
- package/dist/assets/subMonths-DCj_iXAn.js +0 -1
- package/src/components/error-boundary.tsx +0 -189
- package/src/components/layout/breadcrumbs.tsx +0 -77
- package/src/components/layout/document-title.tsx +0 -31
- package/src/components/layout/navigation-progress.tsx +0 -52
- package/src/components/layout/page-skeleton.tsx +0 -49
- package/src/providers/urql-client.ts +0 -86
- package/src/router/config.tsx +0 -534
- package/src/router/layouts/dashboard-layout.tsx +0 -20
- package/src/router/layouts/root-layout.tsx +0 -69
- package/src/router/loaders/auth-loader.ts +0 -32
- package/src/router/loaders/business-loader.ts +0 -25
- package/src/router/loaders/charge-loader.ts +0 -25
- package/src/router/loaders/index.ts +0 -17
- package/src/router/routes.ts +0 -88
- 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
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
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:
|
|
52
|
+
href: '/charges',
|
|
54
53
|
icon: <Receipt size={18} />,
|
|
55
54
|
},
|
|
56
55
|
{
|
|
57
56
|
title: 'Missing Info Charges',
|
|
58
57
|
label: '',
|
|
59
|
-
href:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
120
|
+
href: '/reports/shaam6111',
|
|
122
121
|
icon: <HandCoins size={18} />,
|
|
123
122
|
},
|
|
124
123
|
{
|
|
125
124
|
title: 'Accountant Approvals',
|
|
126
125
|
label: '',
|
|
127
|
-
href:
|
|
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:
|
|
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:
|
|
138
|
+
href: '/reports/balance',
|
|
140
139
|
icon: <ChartNoAxesCombined size={18} />,
|
|
141
140
|
},
|
|
142
141
|
{
|
|
143
142
|
title: 'Validate Reports',
|
|
144
143
|
label: '',
|
|
145
|
-
href:
|
|
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:
|
|
163
|
+
href: '/businesses',
|
|
165
164
|
icon: <Factory size={18} />,
|
|
166
165
|
},
|
|
167
166
|
{
|
|
168
167
|
title: 'Business Transactions',
|
|
169
168
|
label: '',
|
|
170
|
-
href:
|
|
169
|
+
href: '/businesses/transactions',
|
|
171
170
|
icon: <ArrowLeftRight size={18} />,
|
|
172
171
|
},
|
|
173
172
|
{
|
|
174
173
|
title: 'Tax Categories',
|
|
175
174
|
label: '',
|
|
176
|
-
href:
|
|
175
|
+
href: '/tax-categories',
|
|
177
176
|
icon: <ArrowDown01 size={18} />,
|
|
178
177
|
},
|
|
179
178
|
{
|
|
180
179
|
title: 'Sort Codes',
|
|
181
180
|
label: '',
|
|
182
|
-
href:
|
|
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:
|
|
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:
|
|
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:
|
|
207
|
+
href: '/documents/issue-document',
|
|
209
208
|
icon: <FilePen size={18} />,
|
|
210
209
|
},
|
|
211
210
|
],
|
|
212
211
|
},
|
|
213
212
|
{
|
|
214
|
-
href:
|
|
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:
|
|
227
|
+
href: '/charts/',
|
|
229
228
|
icon: <BarChartBig size={18} />,
|
|
230
229
|
},
|
|
231
230
|
{
|
|
232
231
|
title: 'Monthly Income/Expense',
|
|
233
232
|
label: '',
|
|
234
|
-
href:
|
|
233
|
+
href: '/charts/monthly-income-expense',
|
|
235
234
|
icon: <BarChartBig size={18} />,
|
|
236
235
|
},
|
|
237
236
|
],
|
|
238
237
|
},
|
|
239
238
|
{
|
|
240
|
-
href:
|
|
239
|
+
href: '/salaries',
|
|
241
240
|
title: 'Salaries',
|
|
242
241
|
label: '',
|
|
243
242
|
icon: <BadgeDollarSign size={18} />,
|
|
244
243
|
},
|
|
245
244
|
{
|
|
246
|
-
href:
|
|
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 {
|
|
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
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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(
|
|
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 {
|
|
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
|
|
112
|
+
const match = useMatch('/reports/corporate-tax-ruling-compliance/:year');
|
|
113
113
|
const { setFiltersContext } = useContext(FiltersContext);
|
|
114
114
|
const [years, setYears] = useState<number[]>(
|
|
115
|
-
|
|
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 {
|
|
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
|
|
138
|
+
const match = useMatch('/reports/profit-and-loss/:year');
|
|
139
139
|
const { setFiltersContext } = useContext(FiltersContext);
|
|
140
140
|
const [year, setYear] = useState<number>(
|
|
141
|
-
|
|
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 {
|
|
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
|
|
143
|
+
const match = useMatch('/reports/tax/:year');
|
|
144
144
|
const { setFiltersContext } = useContext(FiltersContext);
|
|
145
145
|
const [year, setYear] = useState<number>(
|
|
146
|
-
|
|
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 {
|
|
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
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
29
|
+
pause: !businessId,
|
|
38
30
|
variables: {
|
|
39
31
|
businessId: businessId ?? '',
|
|
40
32
|
},
|
|
41
33
|
});
|
|
42
34
|
|
|
43
|
-
|
|
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 || !
|
|
39
|
+
if (!businessId || !data?.business) {
|
|
52
40
|
return <div>Business not found</div>;
|
|
53
41
|
}
|
|
54
42
|
|
|
55
|
-
return <Business data={
|
|
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 {
|
|
2
|
+
import { useMatch } from 'react-router-dom';
|
|
3
3
|
import { useQuery } from 'urql';
|
|
4
|
-
import { ChargeScreenDocument
|
|
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
|
|
33
|
-
const id = chargeId || chargeIdFromUrl;
|
|
32
|
+
const match = useMatch('/charges/:chargeId');
|
|
34
33
|
|
|
35
|
-
|
|
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
|
|
48
|
+
pause: !id,
|
|
58
49
|
variables: {
|
|
59
50
|
chargeId: id ?? '',
|
|
60
51
|
},
|
|
61
52
|
});
|
|
62
53
|
|
|
63
54
|
useEffect(() => {
|
|
64
|
-
if (id
|
|
55
|
+
if (id) {
|
|
65
56
|
fetchCharge();
|
|
66
57
|
}
|
|
67
|
-
}, [id,
|
|
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
|
-
{
|
|
66
|
+
{fetching ? (
|
|
80
67
|
<AccounterLoader />
|
|
81
68
|
) : (
|
|
82
69
|
<ChargesTable
|
|
83
70
|
setEditChargeId={setEditChargeId}
|
|
84
71
|
setInsertDocument={setInsertDocument}
|
|
85
72
|
setMatchDocuments={setMatchDocuments}
|
|
86
|
-
data={
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
-
</
|
|
111
|
+
</a>
|
|
119
112
|
) : (
|
|
120
113
|
<>
|
|
121
114
|
<SelectWithSearch
|
package/src/index.tsx
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
import { StrictMode } from 'react';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
createBrowserRouter,
|
|
5
|
+
createRoutesFromElements,
|
|
6
|
+
Route,
|
|
7
|
+
RouterProvider,
|
|
8
|
+
} from 'react-router-dom';
|
|
9
|
+
import { App } from './app.js';
|
|
10
|
+
import { Providers } from './providers/index.js';
|
|
5
11
|
import './index.css';
|
|
6
12
|
|
|
7
13
|
const rootElement = document.getElementById('root');
|
|
14
|
+
|
|
8
15
|
const root = createRoot(rootElement!);
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
const router = createBrowserRouter(
|
|
18
|
+
createRoutesFromElements(
|
|
19
|
+
<Route
|
|
20
|
+
path="*"
|
|
21
|
+
element={
|
|
22
|
+
<Providers>
|
|
23
|
+
<App />
|
|
24
|
+
</Providers>
|
|
25
|
+
}
|
|
26
|
+
errorElement={<p>error</p>} // TODO: implement
|
|
27
|
+
/>,
|
|
28
|
+
),
|
|
29
|
+
);
|
|
12
30
|
|
|
13
31
|
root.render(
|
|
14
32
|
<StrictMode>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { createContext,
|
|
1
|
+
import { createContext, useEffect, useState, type ReactNode } from 'react';
|
|
2
|
+
import { Route, Routes, useNavigate } from 'react-router-dom';
|
|
3
|
+
import { NetworkError } from '@/components/screens/network-error.js';
|
|
4
|
+
import { LoginPage } from '../components/login-page.js';
|
|
2
5
|
import { UserService } from '../services/user-service.js';
|
|
3
6
|
|
|
4
7
|
type ContextType = {
|
|
@@ -11,19 +14,25 @@ export const AuthContext = createContext<ContextType>({
|
|
|
11
14
|
setAuthService: () => void 0,
|
|
12
15
|
});
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
export const AuthProvider = ({ children }: { children?: ReactNode }): ReactNode => {
|
|
19
|
-
// Use lazy initialization to prevent creating new UserService on every render
|
|
20
|
-
const [authService, setAuthService] = useState<UserService>(() => new UserService());
|
|
17
|
+
export const AuthGuard = ({ children }: { children?: ReactNode }): ReactNode => {
|
|
18
|
+
const [authService, setAuthService] = useState<UserService>(new UserService());
|
|
19
|
+
const navigate = useNavigate();
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
const contextValue = useMemo(() => ({ authService, setAuthService }), [authService]);
|
|
21
|
+
const loggedIn = authService.isLoggedIn();
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!loggedIn) {
|
|
25
|
+
navigate('/login');
|
|
26
|
+
}
|
|
27
|
+
}, [loggedIn, navigate]);
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
return (
|
|
30
|
+
<AuthContext.Provider value={{ authService, setAuthService }}>
|
|
31
|
+
<Routes>
|
|
32
|
+
<Route path="/login" element={<LoginPage />} />
|
|
33
|
+
<Route path="/network-error" element={<NetworkError />} />
|
|
34
|
+
<Route path="*" element={children} />
|
|
35
|
+
</Routes>
|
|
36
|
+
</AuthContext.Provider>
|
|
37
|
+
);
|
|
38
|
+
};
|