@accounter/client 0.0.8-alpha-20251030162303-87017b2c2addf0e61478260aac336b9343f15c98 → 0.0.8-alpha-20251031025517-bd142395bc1d7267ab00d6b53b116062b581b7d8
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 +49 -1
- package/dist/assets/{Checkbox-CLE7WylX.js → Checkbox-CMTNcrRo.js} +1 -1
- package/dist/assets/{MultiSelect-SsgUtHuW.js → MultiSelect-DP26KzMa.js} +1 -1
- package/dist/assets/{Progress-D7j8SJRp.js → Progress-C3jVWDXK.js} +1 -1
- package/dist/assets/{Table-DpZKU9e6.js → Table-c1ug6Rpw.js} +1 -1
- package/dist/assets/{Typography-DOCvIzjw.js → Typography-BC-9NaKB.js} +1 -1
- package/dist/assets/{YearPickerInput-BbyQMsmW.js → YearPickerInput-CNSe9Fno.js} +1 -1
- package/dist/assets/{accordion-KRd9M_7N.js → accordion-CLvZdMsA.js} +1 -1
- package/dist/assets/{accountant-approvals-BWkXiUJx.js → accountant-approvals-BbNBYszL.js} +1 -1
- package/dist/assets/{accounter-table-BvOYdMv2.js → accounter-table-C7UgjlTA.js} +1 -1
- package/dist/assets/{addDays-HTdY9JyJ.js → addDays-CB-j-d4t.js} +1 -1
- package/dist/assets/{all-charges-uOrXkSoe.js → all-charges-vuUUzmwW.js} +1 -1
- package/dist/assets/{arrow-up-down-D0e6luFS.js → arrow-up-down-DWlT-GED.js} +1 -1
- package/dist/assets/{building-2-BScQAy2y.js → building-2-Dkd3B-3N.js} +1 -1
- package/dist/assets/business-BuVKb8Oy.js +37 -0
- package/dist/assets/{business-extended-info-BPdDug4k.js → business-extended-info-B4Wt-Sq3.js} +1 -1
- package/dist/assets/{business-header-ScM944FH.js → business-header-BpYfBk40.js} +1 -1
- package/dist/assets/{business-ledger-filters-C6zdPVNQ.js → business-ledger-filters-ByAYFfgh.js} +1 -1
- package/dist/assets/{business-ledger-single-D_gxQY7c.js → business-ledger-single-cLd56KYs.js} +1 -1
- package/dist/assets/{business-trip-BD6qMULS.js → business-trip-BWUbbHEK.js} +1 -1
- package/dist/assets/{charge-CXgCTI2e.js → charge-DyLqPZn0.js} +1 -1
- package/dist/assets/{charges-filters-DhYogrgu.js → charges-filters-CUyYbpwk.js} +1 -1
- package/dist/assets/{charges-ledger-validation-K96Gpr99.js → charges-ledger-validation-Br2BBUCN.js} +1 -1
- package/dist/assets/{charges-table-Cff0tibm.js → charges-table-Cw-X1ZkK.js} +6 -6
- package/dist/assets/{chart-Rag7RVt5.js → chart-TrN24kVd.js} +1 -1
- package/dist/assets/contracts-CbwbCzFG.js +16 -0
- package/dist/assets/{data-table-pagination-BenxjRXY.js → data-table-pagination-BZmytrQe.js} +2 -2
- package/dist/assets/{download-csv-button-8ow10rSS.js → download-csv-button-r9hq7Mun.js} +1 -1
- package/dist/assets/{edit-issue-document-modal-2d_PTbvO.js → edit-issue-document-modal-aZgmep8e.js} +1 -1
- package/dist/assets/{editable-business-trip-BFJ_Mqji.js → editable-business-trip-BCj8haJN.js} +2 -2
- package/dist/assets/{eye-off-BNMLF-BO.js → eye-off-Cd4HW5Ki.js} +1 -1
- package/dist/assets/{funnel-DW3_rS_8.js → funnel-DlU6IKDd.js} +1 -1
- package/dist/assets/{index-4ufIi3AX.js → index-4Zj8Hp3W.js} +2 -2
- package/dist/assets/{index-2unHvdGT.js → index-BGcp3XaM.js} +1 -1
- package/dist/assets/{index-B0Je179L.js → index-BM_DgFX-.js} +1 -1
- package/dist/assets/{index-Bo2SK7RM.js → index-BnDJ3EgW.js} +1 -1
- package/dist/assets/{index-DyLWk3js.js → index-Bo91VSNv.js} +1 -1
- package/dist/assets/{index-BHA96r33.js → index-BovGiTUZ.js} +1 -1
- package/dist/assets/{index-1iKxq5ag.js → index-Bt94reMP.js} +2 -2
- package/dist/assets/index-BwqfmUGW.js +1 -0
- package/dist/assets/index-C4ozKIHg.js +1 -0
- package/dist/assets/{index-BPS5RB7_.js → index-CLyrvG5S.js} +1 -1
- package/dist/assets/{index-CKNxDyu9.js → index-CS2mkstk.js} +1 -1
- package/dist/assets/index-CsxUWF65.js +1 -0
- package/dist/assets/index-Cuu0j4Ul.js +1 -0
- package/dist/assets/{index-BDUyPP2c.js → index-DOzNNsNU.js} +1 -1
- package/dist/assets/{index-Bp6IHcih.js → index-DPLJ9sZn.js} +1 -1
- package/dist/assets/index-Dl3yi4zQ.js +1 -0
- package/dist/assets/{index-VD71ra9C.js → index-DmC4088R.js} +2 -2
- package/dist/assets/{index-B2VI47XT.js → index-DnkSW9Wf.js} +1 -1
- package/dist/assets/{index-lMXNkFuw.js → index-Dzi5mI80.js} +2 -2
- package/dist/assets/{index-Bd-SKdyy.js → index-UOt3vExk.js} +196 -196
- package/dist/assets/{index-BQyZXdTq.js → index-VYPC3lji.js} +2 -2
- package/dist/assets/index-Wu-q9oyp.js +1 -0
- package/dist/assets/{index-DvvRs9Ha.js → index-as7vp0Ty.js} +1 -1
- package/dist/assets/{index-BCiHeRl-.js → index-jFDc_D4d.js} +1 -1
- package/dist/assets/{index-CEiIgRJ2.js → index-jpqj1MvA.js} +7 -7
- package/dist/assets/{index.es-C9I2aTP4.js → index.es-CuvVRlqN.js} +1 -1
- package/dist/assets/{insert-business-trip-modal-DVcWpJHr.js → insert-business-trip-modal-DyHAvuG6.js} +2 -2
- package/dist/assets/issue-document-BvIvdS89.js +1 -0
- package/dist/assets/{list-plus-B7wBrICK.js → list-plus-CYtq--On.js} +1 -1
- package/dist/assets/login-page-DcZw6k7i.js +1 -0
- package/dist/assets/{match-document-modal-CqP2SE2c.js → match-document-modal-Bs-5Zbj9.js} +4 -4
- package/dist/assets/{missing-info-charges-CIs_kE3P.js → missing-info-charges-e6O9it1V.js} +1 -1
- package/dist/assets/{modal-CwuHXtxz.js → modal-CqL_DX_G.js} +1 -1
- package/dist/assets/modify-contract-dialog-C8WuljxW.js +1 -0
- package/dist/assets/{page-layout-XgNPsCmr.js → page-layout-DfZJtWW1.js} +1 -1
- package/dist/assets/{page-not-found-CrFJMQNO.js → page-not-found-DnA0E-xR.js} +1 -1
- package/dist/assets/{panel-top-open-DU7alj-S.js → panel-top-open-D0lkFvhk.js} +1 -1
- package/dist/assets/{pencil-9DTTP5vx.js → pencil-DhN5v-Lb.js} +1 -1
- package/dist/assets/{report-commentary-row-BdS3qqMS.js → report-commentary-row-DvvXelmb.js} +1 -1
- package/dist/assets/{save-i8sPy_OW.js → save-CCZ-i4rw.js} +1 -1
- package/dist/assets/{similar-transactions-modal-CZAOYt-d.js → similar-transactions-modal-kFlTMg9C.js} +1 -1
- package/dist/assets/{sub-BL9nfaPD.js → sub-BKVGhLrr.js} +1 -1
- package/dist/assets/subMonths-Cbkj4M6-.js +1 -0
- package/dist/assets/{summary-Dfiju7xJ.js → summary-BuSv6nwb.js} +1 -1
- package/dist/assets/{toggle-expansion-button-BbVh8z6s.js → toggle-expansion-button-CojtDNtC.js} +1 -1
- package/dist/assets/tooltip-CoQF2skM.js +1 -0
- package/dist/assets/{use-url-query-5TFyEk1x.js → use-url-query-90MrwS1C.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +2 -2
- package/src/components/business/admin-business-section.tsx +282 -103
- package/src/components/clients/contracts/modify-contract-dialog.tsx +1 -7
- package/src/components/contracts/cells/date.tsx +5 -1
- package/src/components/contracts/columns.tsx +1 -1
- package/src/components/contracts/contracts-filter.tsx +8 -9
- package/src/components/contracts/index.tsx +0 -1
- package/src/components/contracts/issue-documents-modal.tsx +5 -3
- package/src/components/screens/businesses/clients/contracts/contracts.tsx +2 -4
- package/src/gql/gql.ts +3 -3
- package/src/gql/graphql.ts +52 -17
- package/dist/assets/business-qHY5sNtm.js +0 -37
- package/dist/assets/contracts-C26gq1yS.js +0 -16
- package/dist/assets/index-B86FoQmY.js +0 -1
- package/dist/assets/index-BZLSFBEt.js +0 -1
- package/dist/assets/index-CqIav7Xr.js +0 -1
- package/dist/assets/index-Dp9F68vS.js +0 -1
- package/dist/assets/index-NdA_oCxx.js +0 -1
- package/dist/assets/index-q3ev6JER.js +0 -1
- package/dist/assets/issue-document-BxTTlJ1T.js +0 -1
- package/dist/assets/login-page-BpgscuKm.js +0 -1
- package/dist/assets/modify-contract-dialog-BoeamC68.js +0 -1
- package/dist/assets/subMonths-DHPWOZP6.js +0 -1
- package/dist/assets/tooltip-C-fd9L1l.js +0 -1
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import type React from 'react';
|
|
4
4
|
import { useEffect, useState } from 'react';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { format } from 'date-fns';
|
|
6
|
+
import { Plus, Save, Shield, X } from 'lucide-react';
|
|
7
|
+
import { useFieldArray, useForm } from 'react-hook-form';
|
|
7
8
|
import { z } from 'zod';
|
|
8
9
|
import { Button } from '@/components/ui/button.js';
|
|
9
10
|
import {
|
|
@@ -38,6 +39,7 @@ import {
|
|
|
38
39
|
} from '@/helpers/index.js';
|
|
39
40
|
import { useUpdateAdminBusiness } from '@/hooks/use-update-admin-business.js';
|
|
40
41
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
42
|
+
import { Label } from '../ui/label';
|
|
41
43
|
import { Separator } from '../ui/separator';
|
|
42
44
|
|
|
43
45
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
@@ -47,59 +49,81 @@ import { Separator } from '../ui/separator';
|
|
|
47
49
|
... on LtdFinancialEntity {
|
|
48
50
|
adminInfo {
|
|
49
51
|
id
|
|
50
|
-
withholdingTaxBookNumber
|
|
51
|
-
withholdingTaxFileNumber
|
|
52
|
-
socialSecurityEmployerId
|
|
53
|
-
taxAdvancesRate
|
|
54
|
-
taxAdvancesId
|
|
55
52
|
registrationDate
|
|
53
|
+
withholdingTaxAnnualIds {
|
|
54
|
+
id
|
|
55
|
+
year
|
|
56
|
+
}
|
|
57
|
+
withholdingTaxCompanyId
|
|
58
|
+
socialSecurityEmployerIds {
|
|
59
|
+
id
|
|
60
|
+
year
|
|
61
|
+
}
|
|
62
|
+
socialSecurityDeductionsId
|
|
63
|
+
taxAdvancesAnnualIds {
|
|
64
|
+
id
|
|
65
|
+
year
|
|
66
|
+
}
|
|
67
|
+
taxAdvancesRates {
|
|
68
|
+
date
|
|
69
|
+
rate
|
|
70
|
+
}
|
|
56
71
|
}
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
`;
|
|
60
75
|
|
|
76
|
+
const annualIdSchema = z.object({
|
|
77
|
+
year: z.number().min(2000).max(2100),
|
|
78
|
+
id: z.string().min(1, { message: 'ID is required' }),
|
|
79
|
+
});
|
|
80
|
+
|
|
61
81
|
const adminBusinessFormSchema = z.object({
|
|
62
|
-
withholdingTaxBookNumber: z.string().min(1, {
|
|
63
|
-
message: 'Withholding Tax Book Number is required',
|
|
64
|
-
}),
|
|
65
|
-
withholdingTaxFileNumber: z.string().min(1, {
|
|
66
|
-
message: 'Withholding Tax File Number is required',
|
|
67
|
-
}),
|
|
68
|
-
socialSecurityEmployerId: z.string().min(1, {
|
|
69
|
-
message: 'National Insurance Employer ID is required',
|
|
70
|
-
}),
|
|
71
|
-
taxAdvancesRate: z
|
|
72
|
-
.number()
|
|
73
|
-
.min(0, {
|
|
74
|
-
message: 'Advance Tax Rate must be at least 0',
|
|
75
|
-
})
|
|
76
|
-
.max(100, {
|
|
77
|
-
message: 'Advance Tax Rate must be at most 100',
|
|
78
|
-
}),
|
|
79
|
-
taxAdvancesId: z.string().min(1, {
|
|
80
|
-
message: 'Tax Advances ID is required',
|
|
81
|
-
}),
|
|
82
82
|
registrationDate: z.string().min(1, {
|
|
83
83
|
message: 'Business Registration Start Date is required',
|
|
84
84
|
}),
|
|
85
|
+
withholdingTaxAnnualIds: z.array(annualIdSchema),
|
|
86
|
+
withholdingTaxCompanyId: z.string().min(1, { message: 'Withholding Tax Company ID is required' }),
|
|
87
|
+
socialSecurityEmployerIds: z.array(annualIdSchema),
|
|
88
|
+
socialSecurityDeductionsId: z
|
|
89
|
+
.string()
|
|
90
|
+
.min(1, { message: 'Social Security Deductions ID is required' }),
|
|
91
|
+
taxAdvancesAnnualIds: z.array(annualIdSchema),
|
|
92
|
+
taxAdvancesRates: z.array(
|
|
93
|
+
z.object({
|
|
94
|
+
date: z.iso.date(),
|
|
95
|
+
rate: z
|
|
96
|
+
.number()
|
|
97
|
+
.min(0, { message: 'Rate must be at least 0' })
|
|
98
|
+
.max(100, { message: 'Rate must be at most 100' }),
|
|
99
|
+
}),
|
|
100
|
+
),
|
|
85
101
|
});
|
|
86
102
|
|
|
87
103
|
type AdminBusinessFormValues = z.infer<typeof adminBusinessFormSchema>;
|
|
88
104
|
|
|
89
105
|
function BusinessAdminSectionFragmentToFormValues(
|
|
90
106
|
admin?: BusinessAdminSectionFragment,
|
|
91
|
-
): AdminBusinessFormValues {
|
|
107
|
+
): Partial<AdminBusinessFormValues> {
|
|
92
108
|
if (!admin || admin.__typename !== 'LtdFinancialEntity' || !admin.adminInfo) {
|
|
93
|
-
return {}
|
|
109
|
+
return {};
|
|
94
110
|
}
|
|
95
111
|
|
|
96
112
|
return {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
registrationDate: admin.adminInfo.registrationDate,
|
|
114
|
+
withholdingTaxAnnualIds: admin.adminInfo.withholdingTaxAnnualIds.sort(
|
|
115
|
+
(a, b) => b.year - a.year,
|
|
116
|
+
),
|
|
117
|
+
withholdingTaxCompanyId: admin.adminInfo.withholdingTaxCompanyId ?? undefined,
|
|
118
|
+
socialSecurityEmployerIds: admin.adminInfo.socialSecurityEmployerIds.sort(
|
|
119
|
+
(a, b) => b.year - a.year,
|
|
120
|
+
),
|
|
121
|
+
socialSecurityDeductionsId: admin.adminInfo.socialSecurityDeductionsId ?? undefined,
|
|
122
|
+
taxAdvancesAnnualIds: admin.adminInfo.taxAdvancesAnnualIds.sort((a, b) => b.year - a.year),
|
|
123
|
+
taxAdvancesRates: admin.adminInfo.taxAdvancesRates?.map(rate => ({
|
|
124
|
+
date: rate.date,
|
|
125
|
+
rate: rate.rate * 100,
|
|
126
|
+
})),
|
|
103
127
|
};
|
|
104
128
|
}
|
|
105
129
|
|
|
@@ -107,14 +131,17 @@ function convertFormDataToUpdateAdminBusinessInput(
|
|
|
107
131
|
formData: Partial<AdminBusinessFormValues>,
|
|
108
132
|
): UpdateAdminBusinessInput {
|
|
109
133
|
return {
|
|
110
|
-
withholdingTaxBookNumber: formData.withholdingTaxBookNumber,
|
|
111
|
-
withholdingTaxFileNumber: formData.withholdingTaxFileNumber,
|
|
112
|
-
socialSecurityEmployerId: formData.socialSecurityEmployerId,
|
|
113
|
-
taxAdvancesRate: formData.taxAdvancesRate,
|
|
114
|
-
taxAdvancesId: formData.taxAdvancesId,
|
|
115
134
|
registrationDate: formData.registrationDate
|
|
116
|
-
?
|
|
135
|
+
? formatTimelessDateString(new Date(formData.registrationDate))
|
|
117
136
|
: undefined,
|
|
137
|
+
withholdingTaxAnnualIds: formData.withholdingTaxAnnualIds,
|
|
138
|
+
withholdingTaxCompanyId: formData.withholdingTaxCompanyId,
|
|
139
|
+
socialSecurityEmployerIds: formData.socialSecurityEmployerIds,
|
|
140
|
+
taxAdvancesRates: formData.taxAdvancesRates?.map(rate => ({
|
|
141
|
+
date: rate.date,
|
|
142
|
+
rate: rate.rate / 100,
|
|
143
|
+
})) as { date: TimelessDateString; rate: number }[] | undefined,
|
|
144
|
+
taxAdvancesAnnualIds: formData.taxAdvancesAnnualIds,
|
|
118
145
|
};
|
|
119
146
|
}
|
|
120
147
|
|
|
@@ -166,6 +193,58 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
166
193
|
}
|
|
167
194
|
}, [admin, form]);
|
|
168
195
|
|
|
196
|
+
// Make taxAdvancesAnnualIds a controlled field array using RHF's useFieldArray
|
|
197
|
+
const {
|
|
198
|
+
fields: taxAdvancesFields,
|
|
199
|
+
append: appendTaxAdvances,
|
|
200
|
+
remove: removeTaxAdvances,
|
|
201
|
+
} = useFieldArray({ control: form.control, name: 'taxAdvancesAnnualIds' as const });
|
|
202
|
+
|
|
203
|
+
// Make withholdingTaxAnnualIds a controlled field array using RHF's useFieldArray
|
|
204
|
+
const {
|
|
205
|
+
fields: withholdingTaxFields,
|
|
206
|
+
append: appendWithholdingTax,
|
|
207
|
+
remove: removeWithholdingTax,
|
|
208
|
+
} = useFieldArray({ control: form.control, name: 'withholdingTaxAnnualIds' as const });
|
|
209
|
+
|
|
210
|
+
// Make socialSecurityEmployerIds a controlled field array using RHF's useFieldArray
|
|
211
|
+
const {
|
|
212
|
+
fields: socialSecurityFields,
|
|
213
|
+
append: appendSocialSecurity,
|
|
214
|
+
remove: removeSocialSecurity,
|
|
215
|
+
} = useFieldArray({ control: form.control, name: 'socialSecurityEmployerIds' as const });
|
|
216
|
+
|
|
217
|
+
const annualIdActions = {
|
|
218
|
+
withholdingTaxAnnualIds: { append: appendWithholdingTax, remove: removeWithholdingTax },
|
|
219
|
+
taxAdvancesAnnualIds: { append: appendTaxAdvances, remove: removeTaxAdvances },
|
|
220
|
+
socialSecurityEmployerIds: { append: appendSocialSecurity, remove: removeSocialSecurity },
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
type AnnualIdField = keyof typeof annualIdActions;
|
|
224
|
+
|
|
225
|
+
const addAnnualId = (field: AnnualIdField) => {
|
|
226
|
+
annualIdActions[field].append({ year: new Date().getFullYear(), id: '' });
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const removeAnnualId = (field: AnnualIdField, index: number): void => {
|
|
230
|
+
annualIdActions[field].remove(index);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Make taxAdvancesRates a controlled field array using RHF's useFieldArray
|
|
234
|
+
const {
|
|
235
|
+
fields: taxAdvancesRateFields,
|
|
236
|
+
append: appendTaxAdvancesRate,
|
|
237
|
+
remove: removeTaxAdvancesRate,
|
|
238
|
+
} = useFieldArray({ control: form.control, name: 'taxAdvancesRates' as const });
|
|
239
|
+
|
|
240
|
+
const addRate = () => {
|
|
241
|
+
appendTaxAdvancesRate({ date: format(new Date(), 'yyyy-MM-dd'), rate: 0 });
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const removeRate = (index: number): void => {
|
|
245
|
+
removeTaxAdvancesRate(index);
|
|
246
|
+
};
|
|
247
|
+
|
|
169
248
|
return (
|
|
170
249
|
<Card>
|
|
171
250
|
<CardHeader>
|
|
@@ -187,13 +266,13 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
187
266
|
|
|
188
267
|
<FormField
|
|
189
268
|
control={form.control}
|
|
190
|
-
name="
|
|
269
|
+
name="withholdingTaxCompanyId"
|
|
191
270
|
render={({ field, fieldState }) => (
|
|
192
271
|
<FormItem>
|
|
193
|
-
<FormLabel>
|
|
272
|
+
<FormLabel>Company Tax ID</FormLabel>
|
|
194
273
|
<FormControl>
|
|
195
274
|
<Input
|
|
196
|
-
placeholder="Enter
|
|
275
|
+
placeholder="Enter company ID"
|
|
197
276
|
{...field}
|
|
198
277
|
className={dirtyFieldMarker(fieldState)}
|
|
199
278
|
/>
|
|
@@ -203,67 +282,127 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
203
282
|
)}
|
|
204
283
|
/>
|
|
205
284
|
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
285
|
+
<div className="space-y-4">
|
|
286
|
+
<div className="flex items-center justify-between">
|
|
287
|
+
<Label>Annual IDs</Label>
|
|
288
|
+
<Button
|
|
289
|
+
type="button"
|
|
290
|
+
variant="outline"
|
|
291
|
+
size="sm"
|
|
292
|
+
onClick={() => addAnnualId('withholdingTaxAnnualIds')}
|
|
293
|
+
>
|
|
294
|
+
<Plus className="size-4" />
|
|
295
|
+
</Button>
|
|
296
|
+
</div>
|
|
297
|
+
<div className="space-y-3">
|
|
298
|
+
{withholdingTaxFields.map((field, index) => (
|
|
299
|
+
<div key={field.id} className="flex gap-2 items-start">
|
|
300
|
+
<div className="flex-1 grid grid-cols-2 gap-2">
|
|
301
|
+
<Input
|
|
302
|
+
placeholder="Year"
|
|
303
|
+
type="number"
|
|
304
|
+
{...form.register(`withholdingTaxAnnualIds.${index}.year`, {
|
|
305
|
+
valueAsNumber: true,
|
|
306
|
+
})}
|
|
307
|
+
/>
|
|
308
|
+
<Input
|
|
309
|
+
placeholder="ID"
|
|
310
|
+
{...form.register(`withholdingTaxAnnualIds.${index}.id`)}
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
<Button
|
|
314
|
+
type="button"
|
|
315
|
+
variant="ghost"
|
|
316
|
+
size="icon"
|
|
317
|
+
onClick={() => removeAnnualId('withholdingTaxAnnualIds', index)}
|
|
318
|
+
>
|
|
319
|
+
<X className="size-4" />
|
|
320
|
+
</Button>
|
|
321
|
+
</div>
|
|
322
|
+
))}
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
223
325
|
|
|
224
326
|
<Separator className="md:col-span-2" />
|
|
225
327
|
|
|
226
328
|
<h3 className="text-sm font-semibold text-foreground md:col-span-2">Tax Advances</h3>
|
|
227
329
|
|
|
228
|
-
<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
330
|
+
<div className="space-y-4">
|
|
331
|
+
<div className="flex items-center justify-between">
|
|
332
|
+
<Label>Annual IDs</Label>
|
|
333
|
+
<Button
|
|
334
|
+
type="button"
|
|
335
|
+
variant="outline"
|
|
336
|
+
size="sm"
|
|
337
|
+
onClick={() => addAnnualId('taxAdvancesAnnualIds')}
|
|
338
|
+
>
|
|
339
|
+
<Plus className="size-4" />
|
|
340
|
+
</Button>
|
|
341
|
+
</div>
|
|
342
|
+
<div className="space-y-3">
|
|
343
|
+
{taxAdvancesFields.map((field, index) => (
|
|
344
|
+
<div key={field.id} className="flex gap-2 items-start">
|
|
345
|
+
<div className="flex-1 grid grid-cols-2 gap-2">
|
|
346
|
+
<Input
|
|
347
|
+
placeholder="Year"
|
|
348
|
+
type="number"
|
|
349
|
+
{...form.register(`taxAdvancesAnnualIds.${index}.year`, {
|
|
350
|
+
valueAsNumber: true,
|
|
351
|
+
})}
|
|
352
|
+
/>
|
|
353
|
+
<Input
|
|
354
|
+
placeholder="ID"
|
|
355
|
+
{...form.register(`taxAdvancesAnnualIds.${index}.id`)}
|
|
356
|
+
/>
|
|
357
|
+
</div>
|
|
358
|
+
<Button
|
|
359
|
+
type="button"
|
|
360
|
+
variant="ghost"
|
|
361
|
+
size="icon"
|
|
362
|
+
onClick={() => removeAnnualId('taxAdvancesAnnualIds', index)}
|
|
363
|
+
>
|
|
364
|
+
<X className="size-4" />
|
|
365
|
+
</Button>
|
|
366
|
+
</div>
|
|
367
|
+
))}
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
245
370
|
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
371
|
+
<div className="space-y-4">
|
|
372
|
+
<div className="flex items-center justify-between">
|
|
373
|
+
<Label>Rates (%)</Label>
|
|
374
|
+
<Button type="button" variant="outline" size="sm" onClick={addRate}>
|
|
375
|
+
<Plus className="size-4" />
|
|
376
|
+
</Button>
|
|
377
|
+
</div>
|
|
378
|
+
<div className="space-y-3">
|
|
379
|
+
{taxAdvancesRateFields.map((field, index) => (
|
|
380
|
+
<div key={field.id} className="flex gap-2 items-start">
|
|
381
|
+
<div className="flex-1 grid grid-cols-2 gap-2">
|
|
382
|
+
<Input
|
|
383
|
+
placeholder="Date"
|
|
384
|
+
type="date"
|
|
385
|
+
{...form.register(`taxAdvancesRates.${index}.date`)}
|
|
386
|
+
/>
|
|
387
|
+
<Input
|
|
388
|
+
placeholder="Rate"
|
|
389
|
+
{...form.register(`taxAdvancesRates.${index}.rate`, {
|
|
390
|
+
valueAsNumber: true,
|
|
391
|
+
})}
|
|
392
|
+
/>
|
|
393
|
+
</div>
|
|
394
|
+
<Button
|
|
395
|
+
type="button"
|
|
396
|
+
variant="ghost"
|
|
397
|
+
size="icon"
|
|
398
|
+
onClick={() => removeRate(index)}
|
|
399
|
+
>
|
|
400
|
+
<X className="size-4" />
|
|
401
|
+
</Button>
|
|
402
|
+
</div>
|
|
403
|
+
))}
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
267
406
|
|
|
268
407
|
<Separator className="md:col-span-2" />
|
|
269
408
|
|
|
@@ -271,16 +410,15 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
271
410
|
Social Security
|
|
272
411
|
</h3>
|
|
273
412
|
|
|
274
|
-
{/* Social Security Employer ID */}
|
|
275
413
|
<FormField
|
|
276
414
|
control={form.control}
|
|
277
|
-
name="
|
|
415
|
+
name="socialSecurityDeductionsId"
|
|
278
416
|
render={({ field, fieldState }) => (
|
|
279
417
|
<FormItem>
|
|
280
|
-
<FormLabel>
|
|
418
|
+
<FormLabel>Deductions ID</FormLabel>
|
|
281
419
|
<FormControl>
|
|
282
420
|
<Input
|
|
283
|
-
placeholder="Enter
|
|
421
|
+
placeholder="Enter deductions ID"
|
|
284
422
|
{...field}
|
|
285
423
|
className={dirtyFieldMarker(fieldState)}
|
|
286
424
|
/>
|
|
@@ -290,6 +428,47 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
290
428
|
)}
|
|
291
429
|
/>
|
|
292
430
|
|
|
431
|
+
<div className="space-y-4">
|
|
432
|
+
<div className="flex items-center justify-between">
|
|
433
|
+
<Label>Annual Employer IDs</Label>
|
|
434
|
+
<Button
|
|
435
|
+
type="button"
|
|
436
|
+
variant="outline"
|
|
437
|
+
size="sm"
|
|
438
|
+
onClick={() => addAnnualId('socialSecurityEmployerIds')}
|
|
439
|
+
>
|
|
440
|
+
<Plus className="size-4" />
|
|
441
|
+
</Button>
|
|
442
|
+
</div>
|
|
443
|
+
<div className="space-y-3">
|
|
444
|
+
{socialSecurityFields.map((field, index) => (
|
|
445
|
+
<div key={field.id} className="flex gap-2 items-start">
|
|
446
|
+
<div className="flex-1 grid grid-cols-2 gap-2">
|
|
447
|
+
<Input
|
|
448
|
+
placeholder="Year"
|
|
449
|
+
type="number"
|
|
450
|
+
{...form.register(`socialSecurityEmployerIds.${index}.year`, {
|
|
451
|
+
valueAsNumber: true,
|
|
452
|
+
})}
|
|
453
|
+
/>
|
|
454
|
+
<Input
|
|
455
|
+
placeholder="ID"
|
|
456
|
+
{...form.register(`socialSecurityEmployerIds.${index}.id`)}
|
|
457
|
+
/>
|
|
458
|
+
</div>
|
|
459
|
+
<Button
|
|
460
|
+
type="button"
|
|
461
|
+
variant="ghost"
|
|
462
|
+
size="icon"
|
|
463
|
+
onClick={() => removeAnnualId('socialSecurityEmployerIds', index)}
|
|
464
|
+
>
|
|
465
|
+
<X className="size-4" />
|
|
466
|
+
</Button>
|
|
467
|
+
</div>
|
|
468
|
+
))}
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
|
|
293
472
|
<Separator className="md:col-span-2" />
|
|
294
473
|
|
|
295
474
|
{/* Business Registration Start Date */}
|
|
@@ -130,7 +130,7 @@ export function ModifyContractDialog({ clientId, contract, contractId, onDone }:
|
|
|
130
130
|
const { createContract, creating } = useCreateContract();
|
|
131
131
|
|
|
132
132
|
// Only fetch if we don't have loader data
|
|
133
|
-
const [{ data: fetchedContractData, fetching }
|
|
133
|
+
const [{ data: fetchedContractData, fetching }] = useQuery({
|
|
134
134
|
query: ContractsEditModalDocument,
|
|
135
135
|
pause: !contractId || !isDialogOpen,
|
|
136
136
|
variables: {
|
|
@@ -138,12 +138,6 @@ export function ModifyContractDialog({ clientId, contract, contractId, onDone }:
|
|
|
138
138
|
},
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
if (isDialogOpen && contractId) {
|
|
143
|
-
fetchContract();
|
|
144
|
-
}
|
|
145
|
-
}, [isDialogOpen, contractId, fetchContract]);
|
|
146
|
-
|
|
147
141
|
const form = useForm<ContractFormValues>({
|
|
148
142
|
resolver: zodResolver(contractFormSchema),
|
|
149
143
|
defaultValues: contract || newContractDefaultValues,
|
|
@@ -6,5 +6,9 @@ type Props = {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export const DateCell = ({ timelessDate }: Props): ReactElement => {
|
|
9
|
-
return
|
|
9
|
+
return (
|
|
10
|
+
<p className="text-sm font-medium">
|
|
11
|
+
{new Date(timelessDate).toLocaleDateString(undefined, { timeZone: 'UTC' })}
|
|
12
|
+
</p>
|
|
13
|
+
);
|
|
10
14
|
};
|
|
@@ -123,7 +123,7 @@ export const columns: ColumnDef<ContractRow>[] = [
|
|
|
123
123
|
<div className="flex flex-row gap-1 items-center">
|
|
124
124
|
{row.original.msCloud && (
|
|
125
125
|
<Link to={row.original.msCloud} target="_blank" rel="noreferrer" className="size-8">
|
|
126
|
-
<Button variant="link" size="sm"
|
|
126
|
+
<Button variant="link" size="sm">
|
|
127
127
|
<LinkIcon className="size-4" />
|
|
128
128
|
</Button>
|
|
129
129
|
</Link>
|
|
@@ -47,7 +47,7 @@ export function ContractsFilter({ table }: Props) {
|
|
|
47
47
|
<Label>Product Type</Label>
|
|
48
48
|
<Select
|
|
49
49
|
onValueChange={value =>
|
|
50
|
-
table.getColumn('product')?.setFilterValue(value === 'NULL' ?
|
|
50
|
+
table.getColumn('product')?.setFilterValue(value === 'NULL' ? undefined : value)
|
|
51
51
|
}
|
|
52
52
|
value={table.getColumn('product')?.getFilterValue() as Product | ''}
|
|
53
53
|
>
|
|
@@ -70,7 +70,9 @@ export function ContractsFilter({ table }: Props) {
|
|
|
70
70
|
<Label>Billing Cycle</Label>
|
|
71
71
|
<Select
|
|
72
72
|
onValueChange={value =>
|
|
73
|
-
table
|
|
73
|
+
table
|
|
74
|
+
.getColumn('billingCycle')
|
|
75
|
+
?.setFilterValue(value === 'NULL' ? undefined : value)
|
|
74
76
|
}
|
|
75
77
|
value={table.getColumn('billingCycle')?.getFilterValue() as BillingCycle | ''}
|
|
76
78
|
>
|
|
@@ -96,7 +98,7 @@ export function ContractsFilter({ table }: Props) {
|
|
|
96
98
|
<Label>Subscription Plan</Label>
|
|
97
99
|
<Select
|
|
98
100
|
onValueChange={value =>
|
|
99
|
-
table.getColumn('plan')?.setFilterValue(value === 'NULL' ?
|
|
101
|
+
table.getColumn('plan')?.setFilterValue(value === 'NULL' ? undefined : value)
|
|
100
102
|
}
|
|
101
103
|
value={table.getColumn('plan')?.getFilterValue() as SubscriptionPlan | ''}
|
|
102
104
|
>
|
|
@@ -122,7 +124,9 @@ export function ContractsFilter({ table }: Props) {
|
|
|
122
124
|
onValueChange={value =>
|
|
123
125
|
table
|
|
124
126
|
.getColumn('isActive')
|
|
125
|
-
?.setFilterValue(
|
|
127
|
+
?.setFilterValue(
|
|
128
|
+
value === 'NULL' ? undefined : value === 'active' ? true : false,
|
|
129
|
+
)
|
|
126
130
|
}
|
|
127
131
|
value={convertBooleanToString(
|
|
128
132
|
table.getColumn('isActive')?.getFilterValue() as boolean | undefined,
|
|
@@ -140,11 +144,6 @@ export function ContractsFilter({ table }: Props) {
|
|
|
140
144
|
</SelectContent>
|
|
141
145
|
</Select>
|
|
142
146
|
</div>
|
|
143
|
-
|
|
144
|
-
{/* <div>
|
|
145
|
-
<FormLabel className="text-base">Active Status</FormLabel>
|
|
146
|
-
<Switch checked={field.value} onCheckedChange={field.onChange} />
|
|
147
|
-
</div> */}
|
|
148
147
|
</div>
|
|
149
148
|
</div>
|
|
150
149
|
</DialogContent>
|
|
@@ -163,7 +163,6 @@ export const ContractsTable = ({ data }: Props): ReactElement => {
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
useEffect(() => {
|
|
166
|
-
console.log('Row selection changed:', rowSelection);
|
|
167
166
|
const selectedIndexes = Object.entries(rowSelection)
|
|
168
167
|
.filter(([, value]) => !!value)
|
|
169
168
|
.map(([key]) => Number(key));
|
|
@@ -113,7 +113,7 @@ export const IssueDocumentsModal = ({ contractIds }: Props): ReactElement => {
|
|
|
113
113
|
return {
|
|
114
114
|
...field,
|
|
115
115
|
...watchFieldArray[index],
|
|
116
|
-
id: field.
|
|
116
|
+
id: field.id,
|
|
117
117
|
};
|
|
118
118
|
});
|
|
119
119
|
}, [fields, watchFieldArray]);
|
|
@@ -127,8 +127,10 @@ export const IssueDocumentsModal = ({ contractIds }: Props): ReactElement => {
|
|
|
127
127
|
</DialogTrigger>
|
|
128
128
|
<DialogContent className="min-w-[90vw] w-full max-h-[90vh] overflow-y-auto">
|
|
129
129
|
<DialogHeader>
|
|
130
|
-
<DialogTitle>
|
|
131
|
-
<DialogDescription>
|
|
130
|
+
<DialogTitle>Issue Documents for Contracts</DialogTitle>
|
|
131
|
+
<DialogDescription>
|
|
132
|
+
Review and issue monthly documents for the selected contracts
|
|
133
|
+
</DialogDescription>
|
|
132
134
|
</DialogHeader>
|
|
133
135
|
{fetching ? (
|
|
134
136
|
<AccounterLoader />
|
|
@@ -30,7 +30,7 @@ export const ContractsScreen = (): ReactElement => {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Only fetch if we don't have loader data
|
|
33
|
-
const [{ data, fetching }
|
|
33
|
+
const [{ data, fetching }] = useQuery({
|
|
34
34
|
query: ContractsScreenDocument,
|
|
35
35
|
pause: !adminId || !!loaderData,
|
|
36
36
|
variables: {
|
|
@@ -50,7 +50,5 @@ export const ContractsScreen = (): ReactElement => {
|
|
|
50
50
|
return <div>Contracts not found</div>;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
return
|
|
54
|
-
<ContractsTable data={contractsData.contractsByAdmin} onChange={async () => fetchContracts()} />
|
|
55
|
-
);
|
|
53
|
+
return <ContractsTable data={contractsData.contractsByAdmin} />;
|
|
56
54
|
};
|