@accounter/client 0.0.7-alpha-20250824105500-3626afe3dcdebcf10a7c77e76f0f4f5e4055867d → 0.0.7-alpha-20250824105539-11d89409a8942fb030a7abff740450f8a906266d
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 +8 -1
- package/dist/assets/index-MZlvICfp.css +1 -0
- package/dist/assets/{index-B48VtrKS.js → index-l02ac6P4.js} +383 -343
- package/dist/assets/{index.es-DCjhV4bb.js → index.es-Cn_bInoc.js} +6 -6
- package/dist/index.html +2 -2
- package/package.json +5 -4
- package/src/app.tsx +4 -0
- package/src/components/charges-ledger-validation.tsx +17 -1
- package/src/components/layout/sidelinks.tsx +15 -0
- package/src/components/screens/operations/annual-audit/annual-audit-filters.tsx +158 -0
- package/src/components/screens/operations/annual-audit/index.tsx +370 -0
- package/src/components/screens/operations/annual-audit/step-01-validate-charges/index.tsx +266 -0
- package/src/components/screens/operations/annual-audit/step-02-ledger-changes/index.tsx +132 -0
- package/src/components/screens/operations/annual-audit/step-03-opening-balance/index.tsx +171 -0
- package/src/components/screens/operations/annual-audit/step-base.tsx +149 -0
- package/src/components/screens/operations/annual-audit/step-simple.tsx +43 -0
- package/src/components/ui/progress.tsx +28 -0
- package/src/gql/gql.ts +18 -0
- package/src/gql/graphql.ts +61 -0
- package/src/hooks/use-get-admin-businesses.ts +57 -0
- package/dist/assets/index-BERPxH5K.css +0 -1
package/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" href="/icons/accounter-logo.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Accounter</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-l02ac6P4.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-MZlvICfp.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accounter/client",
|
|
3
|
-
"version": "0.0.7-alpha-
|
|
3
|
+
"version": "0.0.7-alpha-20250824105539-11d89409a8942fb030a7abff740450f8a906266d",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@radix-ui/react-icons": "1.3.2",
|
|
31
31
|
"@radix-ui/react-label": "2.1.7",
|
|
32
32
|
"@radix-ui/react-popover": "1.1.15",
|
|
33
|
+
"@radix-ui/react-progress": "1.1.7",
|
|
33
34
|
"@radix-ui/react-scroll-area": "1.2.10",
|
|
34
35
|
"@radix-ui/react-select": "2.2.6",
|
|
35
36
|
"@radix-ui/react-separator": "1.1.7",
|
|
@@ -66,21 +67,21 @@
|
|
|
66
67
|
"react-error-boundary": "6.0.0",
|
|
67
68
|
"react-hook-form": "7.62.0",
|
|
68
69
|
"react-number-format": "5.4.4",
|
|
69
|
-
"react-router-dom": "7.8.
|
|
70
|
+
"react-router-dom": "7.8.1",
|
|
70
71
|
"react-to-pdf": "2.0.1",
|
|
71
72
|
"recharts": "2.15.4",
|
|
72
73
|
"sonner": "2.0.7",
|
|
73
74
|
"tailwind-merge": "3.3.1",
|
|
74
75
|
"urql": "5.0.0",
|
|
75
76
|
"vaul": "1.1.2",
|
|
76
|
-
"zod": "4.1.
|
|
77
|
+
"zod": "4.1.0",
|
|
77
78
|
"zustand": "5.0.8"
|
|
78
79
|
},
|
|
79
80
|
"devDependencies": {
|
|
80
81
|
"@tailwindcss/vite": "4.1.12",
|
|
81
82
|
"@types/chart.js": "4.0.1",
|
|
82
83
|
"@types/deep-equal": "1.0.4",
|
|
83
|
-
"@types/react": "19.1.
|
|
84
|
+
"@types/react": "19.1.10",
|
|
84
85
|
"@types/react-dom": "19.1.7",
|
|
85
86
|
"@vitejs/plugin-react": "5.0.1",
|
|
86
87
|
"autoprefixer": "10.4.21",
|
package/src/app.tsx
CHANGED
|
@@ -25,6 +25,7 @@ import { MissingInfoCharges } from './components/screens/charges/missing-info-ch
|
|
|
25
25
|
import { DocumentsReport } from './components/screens/documents/all-documents/index.jsx';
|
|
26
26
|
import { IssueDocumentScreen } from './components/screens/documents/issue-document.js';
|
|
27
27
|
import { IssueDocuments } from './components/screens/documents/issue-documents/index.js';
|
|
28
|
+
import { AnnualAuditFlow } from './components/screens/operations/annual-audit/index.jsx';
|
|
28
29
|
import { BalanceReport } from './components/screens/reports/balance-report/index.js';
|
|
29
30
|
import { DepreciationReport } from './components/screens/reports/depreciation-report/index.js';
|
|
30
31
|
import { Shaam6111Report } from './components/screens/reports/shaam6111-report/index.js';
|
|
@@ -85,6 +86,9 @@ export function App(): ReactElement {
|
|
|
85
86
|
<Route path="balance" element={<BalanceReport />} />
|
|
86
87
|
<Route path="validate-reports" element={<ValidateReportsScreen />} />
|
|
87
88
|
</Route>
|
|
89
|
+
<Route path="workflows">
|
|
90
|
+
<Route path="annual-audit" element={<AnnualAuditFlow />} />
|
|
91
|
+
</Route>
|
|
88
92
|
<Route path="salaries" element={<Salaries />} />
|
|
89
93
|
<Route path="tags" element={<TagsManager />} />
|
|
90
94
|
<Route path="tax-categories" element={<TaxCategories />} />
|
|
@@ -5,7 +5,7 @@ import { Loader, Progress, ThemeIcon, Tooltip } from '@mantine/core';
|
|
|
5
5
|
import { ChargesLedgerValidationDocument, type ChargeFilter } from '../gql/graphql.js';
|
|
6
6
|
import { useUrlQuery } from '../hooks/use-url-query.js';
|
|
7
7
|
import { FiltersContext } from '../providers/filters-context.js';
|
|
8
|
-
import { ChargesFilters } from './charges/charges-filters.js';
|
|
8
|
+
import { ChargesFilters, encodeChargesFilters } from './charges/charges-filters.js';
|
|
9
9
|
import { ChargesTable } from './charges/charges-table.js';
|
|
10
10
|
import {
|
|
11
11
|
EditChargeModal,
|
|
@@ -29,6 +29,22 @@ import { Button } from './ui/button.js';
|
|
|
29
29
|
}
|
|
30
30
|
`;
|
|
31
31
|
|
|
32
|
+
export function getLedgerValidationHref(filter?: ChargeFilter | null, page?: number): string {
|
|
33
|
+
const params = new URLSearchParams();
|
|
34
|
+
if (page) {
|
|
35
|
+
params.append('page', String(page));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const chargesFilters = encodeChargesFilters(filter);
|
|
39
|
+
if (chargesFilters) {
|
|
40
|
+
// Add it as a single encoded parameter
|
|
41
|
+
params.append('chargesFilters', chargesFilters);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const queryParams = params.size > 0 ? `?${params}` : '';
|
|
45
|
+
return `/charges-ledger-validation${queryParams}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
export const ChargesLedgerValidation = (): ReactElement => {
|
|
33
49
|
const { setFiltersContext } = useContext(FiltersContext);
|
|
34
50
|
const [editChargeId, setEditChargeId] = useState<
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
Files,
|
|
17
17
|
HandCoins,
|
|
18
18
|
IdCard,
|
|
19
|
+
ListChecks,
|
|
19
20
|
ParkingMeter,
|
|
20
21
|
PlaneTakeoff,
|
|
21
22
|
Puzzle,
|
|
@@ -235,6 +236,20 @@ export const sidelinks: SideLink[] = [
|
|
|
235
236
|
},
|
|
236
237
|
],
|
|
237
238
|
},
|
|
239
|
+
{
|
|
240
|
+
title: 'Workflows',
|
|
241
|
+
label: '',
|
|
242
|
+
href: '',
|
|
243
|
+
icon: <ListChecks size={18} />,
|
|
244
|
+
sub: [
|
|
245
|
+
{
|
|
246
|
+
title: 'Year-end audit',
|
|
247
|
+
label: '',
|
|
248
|
+
href: '/workflows/annual-audit',
|
|
249
|
+
icon: <ListChecks size={18} />,
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
},
|
|
238
253
|
{
|
|
239
254
|
href: '/salaries',
|
|
240
255
|
title: 'Salaries',
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useCallback, useState, type ReactElement } from 'react';
|
|
2
|
+
import equal from 'deep-equal';
|
|
3
|
+
import { Filter, Loader2 } from 'lucide-react';
|
|
4
|
+
import { useForm, type SubmitHandler } from 'react-hook-form';
|
|
5
|
+
import { Indicator } from '@mantine/core';
|
|
6
|
+
import { isObjectEmpty } from '../../../../helpers/index.js';
|
|
7
|
+
import { useGetAdminBusinesses } from '../../../../hooks/use-get-admin-businesses.js';
|
|
8
|
+
import { ComboBox, NumberInput } from '../../../common/index.js';
|
|
9
|
+
import { Button } from '../../../ui/button.js';
|
|
10
|
+
import { Dialog, DialogContent, DialogFooter, DialogTrigger } from '../../../ui/dialog.js';
|
|
11
|
+
import {
|
|
12
|
+
Form,
|
|
13
|
+
FormControl,
|
|
14
|
+
FormField,
|
|
15
|
+
FormItem,
|
|
16
|
+
FormLabel,
|
|
17
|
+
FormMessage,
|
|
18
|
+
} from '../../../ui/form.js';
|
|
19
|
+
|
|
20
|
+
export type AnnualAuditFlowFilter = {
|
|
21
|
+
year: number;
|
|
22
|
+
adminBusinessId?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function encodeAnnualAuditFlowFilters(filter?: AnnualAuditFlowFilter | null): string | null {
|
|
26
|
+
return !filter || isObjectEmpty(filter) ? null : encodeURIComponent(JSON.stringify(filter));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const ANNUAL_AUDIT_FLOW_FILTERS_QUERY_PARAM = 'annualAuditFlowFilters';
|
|
30
|
+
|
|
31
|
+
interface AnnualAuditFlowFiltersFormProps {
|
|
32
|
+
filter: AnnualAuditFlowFilter;
|
|
33
|
+
setFilter: (filter: AnnualAuditFlowFilter) => void;
|
|
34
|
+
closeModal: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AnnualAuditFlowFiltersForm({
|
|
38
|
+
filter,
|
|
39
|
+
setFilter,
|
|
40
|
+
closeModal,
|
|
41
|
+
}: AnnualAuditFlowFiltersFormProps): ReactElement {
|
|
42
|
+
const form = useForm<AnnualAuditFlowFilter>({
|
|
43
|
+
defaultValues: filter,
|
|
44
|
+
});
|
|
45
|
+
const { control, handleSubmit } = form;
|
|
46
|
+
const { selectableAdminBusinesses: adminBusinesses, fetching: adminBusinessesFetching } =
|
|
47
|
+
useGetAdminBusinesses();
|
|
48
|
+
|
|
49
|
+
const onSubmit: SubmitHandler<AnnualAuditFlowFilter> = data => {
|
|
50
|
+
setFilter(data);
|
|
51
|
+
closeModal();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
{adminBusinessesFetching ? (
|
|
57
|
+
<div className="flex justify-center">
|
|
58
|
+
<Loader2 className="h-6 w-6 animate-spin" />
|
|
59
|
+
</div>
|
|
60
|
+
) : (
|
|
61
|
+
<div />
|
|
62
|
+
)}
|
|
63
|
+
<Form {...form}>
|
|
64
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
65
|
+
<FormField
|
|
66
|
+
name="year"
|
|
67
|
+
control={control}
|
|
68
|
+
rules={{
|
|
69
|
+
required: 'Year is required',
|
|
70
|
+
validate: (value): boolean | string => {
|
|
71
|
+
const year = Number(value);
|
|
72
|
+
return Number.isNaN(year) || year < 2000 || year > 2100 ? 'Invalid year' : true;
|
|
73
|
+
},
|
|
74
|
+
}}
|
|
75
|
+
render={({ field }): ReactElement => (
|
|
76
|
+
<FormItem>
|
|
77
|
+
<FormLabel>Year</FormLabel>
|
|
78
|
+
<FormControl>
|
|
79
|
+
<NumberInput {...field} hideControls decimalScale={0} />
|
|
80
|
+
</FormControl>
|
|
81
|
+
<FormMessage />
|
|
82
|
+
</FormItem>
|
|
83
|
+
)}
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<FormField
|
|
87
|
+
name="adminBusinessId"
|
|
88
|
+
defaultValue={filter?.adminBusinessId}
|
|
89
|
+
control={control}
|
|
90
|
+
render={({ field }) => (
|
|
91
|
+
<FormItem>
|
|
92
|
+
<FormLabel>Owner</FormLabel>
|
|
93
|
+
<ComboBox
|
|
94
|
+
{...field}
|
|
95
|
+
data={adminBusinesses}
|
|
96
|
+
value={field.value ?? undefined}
|
|
97
|
+
disabled={adminBusinessesFetching}
|
|
98
|
+
placeholder="Select a financial entity"
|
|
99
|
+
formPart
|
|
100
|
+
/>
|
|
101
|
+
<FormMessage />
|
|
102
|
+
</FormItem>
|
|
103
|
+
)}
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<DialogFooter>
|
|
107
|
+
<Button type="submit" disabled={adminBusinessesFetching}>
|
|
108
|
+
Filter
|
|
109
|
+
</Button>
|
|
110
|
+
</DialogFooter>
|
|
111
|
+
</form>
|
|
112
|
+
</Form>
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface AnnualAuditFlowFiltersProps {
|
|
118
|
+
filter: AnnualAuditFlowFilter;
|
|
119
|
+
setFilter: (filter: AnnualAuditFlowFilter) => void;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function AnnualAuditFlowFilters({
|
|
123
|
+
filter,
|
|
124
|
+
setFilter,
|
|
125
|
+
}: AnnualAuditFlowFiltersProps): ReactElement {
|
|
126
|
+
const [opened, setOpened] = useState(false);
|
|
127
|
+
const [isFiltered, setIsFiltered] = useState(!isObjectEmpty(filter));
|
|
128
|
+
|
|
129
|
+
const onSetFilter = useCallback(
|
|
130
|
+
(newFilter: AnnualAuditFlowFilter) => {
|
|
131
|
+
// looks for actual changes before triggering update
|
|
132
|
+
if (!equal(newFilter, filter)) {
|
|
133
|
+
setFilter(newFilter);
|
|
134
|
+
setIsFiltered(!isObjectEmpty(newFilter));
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
[filter, setFilter],
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Dialog open={opened} onOpenChange={setOpened}>
|
|
142
|
+
<DialogTrigger asChild>
|
|
143
|
+
<Indicator inline size={16} disabled={!isFiltered}>
|
|
144
|
+
<Button variant="outline" size="icon">
|
|
145
|
+
<Filter size={20} />
|
|
146
|
+
</Button>
|
|
147
|
+
</Indicator>
|
|
148
|
+
</DialogTrigger>
|
|
149
|
+
<DialogContent className="sm:max-w-[425px]">
|
|
150
|
+
<AnnualAuditFlowFiltersForm
|
|
151
|
+
filter={filter}
|
|
152
|
+
setFilter={onSetFilter}
|
|
153
|
+
closeModal={(): void => setOpened(false)}
|
|
154
|
+
/>
|
|
155
|
+
</DialogContent>
|
|
156
|
+
</Dialog>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type ReactElement,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import { Calculator, Download, Eye, FileText, Lock, Settings, Upload, Users } from 'lucide-react';
|
|
11
|
+
import { useUrlQuery } from '../../../../hooks/use-url-query.js';
|
|
12
|
+
import { FiltersContext } from '../../../../providers/filters-context.js';
|
|
13
|
+
import { UserContext } from '../../../../providers/user-provider.js';
|
|
14
|
+
import { PageLayout } from '../../../layout/page-layout.js';
|
|
15
|
+
import { Button } from '../../../ui/button.js';
|
|
16
|
+
import { Card, CardContent, CardHeader, CardTitle } from '../../../ui/card.js';
|
|
17
|
+
import { Progress } from '../../../ui/progress.js';
|
|
18
|
+
import {
|
|
19
|
+
ANNUAL_AUDIT_FLOW_FILTERS_QUERY_PARAM,
|
|
20
|
+
AnnualAuditFlowFilters,
|
|
21
|
+
encodeAnnualAuditFlowFilters,
|
|
22
|
+
type AnnualAuditFlowFilter,
|
|
23
|
+
} from './annual-audit-filters.js';
|
|
24
|
+
// Import step components
|
|
25
|
+
import { Step01ValidateCharges } from './step-01-validate-charges/index.js';
|
|
26
|
+
import { Step02LedgerChanges } from './step-02-ledger-changes/index.js';
|
|
27
|
+
import Step03OpeningBalance from './step-03-opening-balance/index.js';
|
|
28
|
+
import type { StepStatus } from './step-base.js';
|
|
29
|
+
import SimpleStep from './step-simple.js';
|
|
30
|
+
|
|
31
|
+
export function getAnnualAuditFlowHref(filter?: AnnualAuditFlowFilter | null): string {
|
|
32
|
+
const params = new URLSearchParams();
|
|
33
|
+
|
|
34
|
+
const annualAuditFlowFilters = encodeAnnualAuditFlowFilters(filter);
|
|
35
|
+
if (annualAuditFlowFilters) {
|
|
36
|
+
// Add it as a single encoded parameter
|
|
37
|
+
params.append(ANNUAL_AUDIT_FLOW_FILTERS_QUERY_PARAM, annualAuditFlowFilters);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const queryParams = params.size > 0 ? `?${params}` : '';
|
|
41
|
+
return `/workflows/annual-audit${queryParams}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const AnnualAuditFlow = (): ReactElement => {
|
|
45
|
+
const { setFiltersContext } = useContext(FiltersContext);
|
|
46
|
+
const { userContext } = useContext(UserContext);
|
|
47
|
+
const { get } = useUrlQuery();
|
|
48
|
+
const initialFilters = useMemo(() => {
|
|
49
|
+
const defaultFilters: AnnualAuditFlowFilter = {
|
|
50
|
+
year: new Date().getFullYear() - 1,
|
|
51
|
+
adminBusinessId: userContext?.context.adminBusinessId,
|
|
52
|
+
};
|
|
53
|
+
const uriFilters = get(ANNUAL_AUDIT_FLOW_FILTERS_QUERY_PARAM);
|
|
54
|
+
if (uriFilters) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(decodeURIComponent(uriFilters)) as AnnualAuditFlowFilter;
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('Failed to parse filters from URI:', error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return defaultFilters;
|
|
63
|
+
}, [userContext?.context.adminBusinessId]);
|
|
64
|
+
const [filter, setFilter] = useState<AnnualAuditFlowFilter>(initialFilters);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
setFiltersContext(
|
|
68
|
+
<div className="flex flex-row gap-x-5">
|
|
69
|
+
<AnnualAuditFlowFilters filter={filter} setFilter={setFilter} />
|
|
70
|
+
</div>,
|
|
71
|
+
);
|
|
72
|
+
}, [filter, setFiltersContext, setFilter]);
|
|
73
|
+
|
|
74
|
+
const totalSteps = 21;
|
|
75
|
+
const YEAR = 2024; // TODO: Example year, should be dynamic
|
|
76
|
+
|
|
77
|
+
// Track step statuses to avoid double counting
|
|
78
|
+
const stepStatusesRef = useRef<Map<string, StepStatus>>(new Map());
|
|
79
|
+
const [completedSteps, setCompletedSteps] = useState(0);
|
|
80
|
+
|
|
81
|
+
const handleStatusChange = useCallback((stepId: string, status: StepStatus) => {
|
|
82
|
+
const previousStatus = stepStatusesRef.current.get(stepId);
|
|
83
|
+
|
|
84
|
+
// Only update if status actually changed
|
|
85
|
+
if (previousStatus !== status) {
|
|
86
|
+
stepStatusesRef.current.set(stepId, status);
|
|
87
|
+
|
|
88
|
+
// Recalculate completed steps count
|
|
89
|
+
const completedCount = Array.from(stepStatusesRef.current.values()).filter(
|
|
90
|
+
s => s === 'completed',
|
|
91
|
+
).length;
|
|
92
|
+
|
|
93
|
+
setCompletedSteps(completedCount);
|
|
94
|
+
}
|
|
95
|
+
}, []);
|
|
96
|
+
|
|
97
|
+
const progressPercentage = (completedSteps / totalSteps) * 100;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<PageLayout
|
|
101
|
+
title="Annual Audit Flow"
|
|
102
|
+
description="Complete audit process for annual financial reporting and compliance"
|
|
103
|
+
>
|
|
104
|
+
<div className="container mx-auto p-6 max-w-6xl">
|
|
105
|
+
<div className="mb-8">
|
|
106
|
+
<Card className="mb-6">
|
|
107
|
+
<CardHeader>
|
|
108
|
+
<CardTitle className="text-lg">Progress Overview</CardTitle>
|
|
109
|
+
</CardHeader>
|
|
110
|
+
<CardContent>
|
|
111
|
+
<div className="space-y-2">
|
|
112
|
+
<div className="flex justify-between text-sm">
|
|
113
|
+
<span>Completed Steps</span>
|
|
114
|
+
<span>
|
|
115
|
+
{completedSteps} of {totalSteps}
|
|
116
|
+
</span>
|
|
117
|
+
</div>
|
|
118
|
+
<Progress value={progressPercentage} className="h-2" />
|
|
119
|
+
<div className="text-xs text-muted-foreground">
|
|
120
|
+
{progressPercentage.toFixed(1)}% Complete
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div className="space-y-4">
|
|
128
|
+
{/* Step 1 - Custom component with server data */}
|
|
129
|
+
<Step01ValidateCharges
|
|
130
|
+
id="1"
|
|
131
|
+
year={YEAR}
|
|
132
|
+
adminBusinessId={userContext?.context.adminBusinessId}
|
|
133
|
+
title="Validate All Charges"
|
|
134
|
+
description="Ensure all charges of the year were reviewed, handle pending charges"
|
|
135
|
+
onStatusChange={handleStatusChange}
|
|
136
|
+
/>
|
|
137
|
+
|
|
138
|
+
{/* Step 2 - Custom component with server data */}
|
|
139
|
+
<Step02LedgerChanges
|
|
140
|
+
id="2"
|
|
141
|
+
year={YEAR}
|
|
142
|
+
adminBusinessId={userContext?.context.adminBusinessId}
|
|
143
|
+
title="Check Pending Ledger Changes"
|
|
144
|
+
description="Ensure no pending ledger changes exist"
|
|
145
|
+
onStatusChange={handleStatusChange}
|
|
146
|
+
/>
|
|
147
|
+
|
|
148
|
+
{/* Step 3 - Custom component with substeps */}
|
|
149
|
+
<Step03OpeningBalance
|
|
150
|
+
id="3"
|
|
151
|
+
year={YEAR}
|
|
152
|
+
adminBusinessId={userContext?.context.adminBusinessId}
|
|
153
|
+
title="Verify Opening Balance"
|
|
154
|
+
description="Handle opening balance verification based on user type"
|
|
155
|
+
onStatusChange={handleStatusChange}
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
{/* Step 4 - Simple step with static data */}
|
|
159
|
+
<SimpleStep
|
|
160
|
+
id="4"
|
|
161
|
+
title="Generate Financial Charges"
|
|
162
|
+
description="Create various financial charges and reserves"
|
|
163
|
+
icon={<Calculator className="h-4 w-4" />}
|
|
164
|
+
onStatusChange={handleStatusChange}
|
|
165
|
+
actions={[
|
|
166
|
+
{ label: 'Calculate Vacation Reserves', href: '/reserves/vacation' },
|
|
167
|
+
{ label: 'Calculate Recovery Reserves', href: '/reserves/recovery' },
|
|
168
|
+
{ label: 'Process Bank Deposits', href: '/deposits/bank' },
|
|
169
|
+
{ label: 'Perform Revaluation', href: '/revaluation' },
|
|
170
|
+
{ label: 'Calculate Tax Expenses', href: '/tax/expenses' },
|
|
171
|
+
{ label: 'Calculate Depreciation', href: '/depreciation/calculate' },
|
|
172
|
+
]}
|
|
173
|
+
/>
|
|
174
|
+
|
|
175
|
+
{/* Step 5 - Simple step */}
|
|
176
|
+
<SimpleStep
|
|
177
|
+
id="5"
|
|
178
|
+
title="Audit Main Process"
|
|
179
|
+
description="Task management system for comprehensive audit checks"
|
|
180
|
+
icon={<FileText className="h-4 w-4" />}
|
|
181
|
+
onStatusChange={handleStatusChange}
|
|
182
|
+
actions={[
|
|
183
|
+
{ label: 'Manage Conto Tree', href: '/conto/tree' },
|
|
184
|
+
{ label: 'Open Checklist', href: '/validations/checklist' },
|
|
185
|
+
{ label: 'Compare VAT', href: '/vat/comparison' },
|
|
186
|
+
{ label: 'Generate Draft', href: '/depreciation/draft' },
|
|
187
|
+
{ label: 'Manage Audit Checks', href: '/audit/checks' },
|
|
188
|
+
{ label: 'Review Tax Report', href: '/tax/review' },
|
|
189
|
+
{ label: 'Cash Flow Analysis', href: '/cashflow/analysis' },
|
|
190
|
+
]}
|
|
191
|
+
/>
|
|
192
|
+
|
|
193
|
+
{/* Steps 6-21 - Simple steps with basic configuration */}
|
|
194
|
+
<SimpleStep
|
|
195
|
+
id="6"
|
|
196
|
+
title="Add Shareholders Data (1214)"
|
|
197
|
+
description="For 1214 report preparation"
|
|
198
|
+
icon={<Users className="h-4 w-4" />}
|
|
199
|
+
onStatusChange={handleStatusChange}
|
|
200
|
+
actions={[
|
|
201
|
+
{ label: 'Manage Shareholders', href: '/shareholders/manage' },
|
|
202
|
+
{ label: 'Import Data', href: '/shareholders/import' },
|
|
203
|
+
]}
|
|
204
|
+
/>
|
|
205
|
+
|
|
206
|
+
<SimpleStep
|
|
207
|
+
id="7"
|
|
208
|
+
title="Revalidate Pending Items"
|
|
209
|
+
description="Ensure no charges approval or ledger regeneration pending"
|
|
210
|
+
icon={<Eye className="h-4 w-4" />}
|
|
211
|
+
onStatusChange={handleStatusChange}
|
|
212
|
+
actions={[
|
|
213
|
+
{ label: 'Check Pending Approvals', href: '/approvals/pending' },
|
|
214
|
+
{ label: 'Ledger Status', href: '/ledger/status' },
|
|
215
|
+
]}
|
|
216
|
+
/>
|
|
217
|
+
|
|
218
|
+
<SimpleStep
|
|
219
|
+
id="8"
|
|
220
|
+
title="Lock Ledger"
|
|
221
|
+
description="Lock ledger by records and by date"
|
|
222
|
+
icon={<Lock className="h-4 w-4" />}
|
|
223
|
+
onStatusChange={handleStatusChange}
|
|
224
|
+
actions={[
|
|
225
|
+
{ label: 'Lock by Records', href: '/ledger/lock-records' },
|
|
226
|
+
{ label: 'Lock by Date', href: '/ledger/lock-date' },
|
|
227
|
+
]}
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
<SimpleStep
|
|
231
|
+
id="9"
|
|
232
|
+
title="Save Final Dynamic Report Template"
|
|
233
|
+
icon={<FileText className="h-4 w-4" />}
|
|
234
|
+
onStatusChange={handleStatusChange}
|
|
235
|
+
actions={[{ label: 'Save Template', href: '/reports/save-template' }]}
|
|
236
|
+
/>
|
|
237
|
+
|
|
238
|
+
<SimpleStep
|
|
239
|
+
id="10"
|
|
240
|
+
title="Export Year-end Trial Balance"
|
|
241
|
+
description="For future validations"
|
|
242
|
+
icon={<Download className="h-4 w-4" />}
|
|
243
|
+
onStatusChange={handleStatusChange}
|
|
244
|
+
actions={[{ label: 'Export Trial Balance', href: '/export/trial-balance' }]}
|
|
245
|
+
/>
|
|
246
|
+
|
|
247
|
+
<SimpleStep
|
|
248
|
+
id="11"
|
|
249
|
+
title="Generate Final Depreciation Report"
|
|
250
|
+
icon={<FileText className="h-4 w-4" />}
|
|
251
|
+
onStatusChange={handleStatusChange}
|
|
252
|
+
actions={[{ label: 'Generate Report', href: '/depreciation/final' }]}
|
|
253
|
+
/>
|
|
254
|
+
|
|
255
|
+
<SimpleStep
|
|
256
|
+
id="12"
|
|
257
|
+
title="Generate Financial Reports"
|
|
258
|
+
description="With comparison numbers from last year"
|
|
259
|
+
icon={<FileText className="h-4 w-4" />}
|
|
260
|
+
onStatusChange={handleStatusChange}
|
|
261
|
+
actions={[{ label: 'Generate Reports', href: '/reports/financial' }]}
|
|
262
|
+
/>
|
|
263
|
+
|
|
264
|
+
<SimpleStep
|
|
265
|
+
id="13"
|
|
266
|
+
title="Generate Tax Report"
|
|
267
|
+
icon={<FileText className="h-4 w-4" />}
|
|
268
|
+
onStatusChange={handleStatusChange}
|
|
269
|
+
actions={[{ label: 'Generate Tax Report', href: '/tax/generate' }]}
|
|
270
|
+
/>
|
|
271
|
+
|
|
272
|
+
<SimpleStep
|
|
273
|
+
id="14"
|
|
274
|
+
title="Generate Tax Compliance Reports"
|
|
275
|
+
description="For Yossi's review"
|
|
276
|
+
icon={<FileText className="h-4 w-4" />}
|
|
277
|
+
onStatusChange={handleStatusChange}
|
|
278
|
+
actions={[{ label: 'Generate Report', href: '/compliance/clients-country' }]}
|
|
279
|
+
/>
|
|
280
|
+
|
|
281
|
+
<SimpleStep
|
|
282
|
+
id="15"
|
|
283
|
+
title="Generate Tax Compliance Report"
|
|
284
|
+
icon={<FileText className="h-4 w-4" />}
|
|
285
|
+
onStatusChange={handleStatusChange}
|
|
286
|
+
actions={[
|
|
287
|
+
{ label: 'Generate 973', href: '/reports/973' },
|
|
288
|
+
{ label: 'Generate 901א', href: '/reports/901a' },
|
|
289
|
+
]}
|
|
290
|
+
/>
|
|
291
|
+
|
|
292
|
+
<SimpleStep
|
|
293
|
+
id="16"
|
|
294
|
+
title="Generate 6111 Report"
|
|
295
|
+
icon={<FileText className="h-4 w-4" />}
|
|
296
|
+
onStatusChange={handleStatusChange}
|
|
297
|
+
actions={[{ label: 'Generate 6111', href: '/reports/6111' }]}
|
|
298
|
+
/>
|
|
299
|
+
|
|
300
|
+
<SimpleStep
|
|
301
|
+
id="17"
|
|
302
|
+
title="Generate Dividend Report 1214ב"
|
|
303
|
+
icon={<FileText className="h-4 w-4" />}
|
|
304
|
+
onStatusChange={handleStatusChange}
|
|
305
|
+
actions={[{ label: 'Generate Dividend Report', href: '/reports/dividend-1214b' }]}
|
|
306
|
+
/>
|
|
307
|
+
|
|
308
|
+
<SimpleStep
|
|
309
|
+
id="18"
|
|
310
|
+
title="Generate 1214 Report"
|
|
311
|
+
icon={<FileText className="h-4 w-4" />}
|
|
312
|
+
onStatusChange={handleStatusChange}
|
|
313
|
+
actions={[{ label: 'Generate 1214', href: '/reports/1214' }]}
|
|
314
|
+
/>
|
|
315
|
+
|
|
316
|
+
<SimpleStep
|
|
317
|
+
id="19"
|
|
318
|
+
title="Compare Tax Expenses"
|
|
319
|
+
description="Compare 1214 tax expenses with ledger tax expenses"
|
|
320
|
+
icon={<Calculator className="h-4 w-4" />}
|
|
321
|
+
onStatusChange={handleStatusChange}
|
|
322
|
+
actions={[{ label: 'Compare Expenses', href: '/tax/compare-expenses' }]}
|
|
323
|
+
/>
|
|
324
|
+
|
|
325
|
+
<SimpleStep
|
|
326
|
+
id="20"
|
|
327
|
+
title="Signing Process"
|
|
328
|
+
description="Handle signing process and accompanying documents"
|
|
329
|
+
icon={<FileText className="h-4 w-4" />}
|
|
330
|
+
onStatusChange={handleStatusChange}
|
|
331
|
+
actions={[
|
|
332
|
+
{ label: 'Prepare Documents', href: '/signing/prepare' },
|
|
333
|
+
{ label: 'Digital Signing', href: '/signing/digital' },
|
|
334
|
+
]}
|
|
335
|
+
/>
|
|
336
|
+
|
|
337
|
+
<SimpleStep
|
|
338
|
+
id="21"
|
|
339
|
+
title="File Annual Report"
|
|
340
|
+
description="Submit annual report to companies government office"
|
|
341
|
+
icon={<Upload className="h-4 w-4" />}
|
|
342
|
+
onStatusChange={handleStatusChange}
|
|
343
|
+
actions={[
|
|
344
|
+
{ label: 'Prepare Filing', href: '/filing/prepare' },
|
|
345
|
+
{ label: 'Submit Report', href: '/filing/submit' },
|
|
346
|
+
]}
|
|
347
|
+
/>
|
|
348
|
+
</div>
|
|
349
|
+
|
|
350
|
+
<div className="mt-8 p-4 bg-muted rounded-lg">
|
|
351
|
+
<h3 className="font-semibold mb-2">Quick Actions</h3>
|
|
352
|
+
<div className="flex flex-wrap gap-2">
|
|
353
|
+
<Button variant="outline" size="sm">
|
|
354
|
+
<Download className="h-4 w-4 mr-2" />
|
|
355
|
+
Export Progress Report
|
|
356
|
+
</Button>
|
|
357
|
+
<Button variant="outline" size="sm">
|
|
358
|
+
<Settings className="h-4 w-4 mr-2" />
|
|
359
|
+
Configure Workflow
|
|
360
|
+
</Button>
|
|
361
|
+
<Button variant="outline" size="sm">
|
|
362
|
+
<Eye className="h-4 w-4 mr-2" />
|
|
363
|
+
View All Reports
|
|
364
|
+
</Button>
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</PageLayout>
|
|
369
|
+
);
|
|
370
|
+
};
|