@accounter/client 0.0.8-alpha-20251029152834-4e95d9a4cd7f292ec1789163f46763388b63a377 → 0.0.8-alpha-20251029232510-4bc0c8b8c08a26f0c27788725ae584e515236d20

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 (94) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/assets/{Checkbox-qIwbw1Vm.js → Checkbox-Cmx4P-eR.js} +2 -2
  3. package/dist/assets/{MultiSelect-Uj0K1auE.js → MultiSelect-tfWMeMsf.js} +1 -1
  4. package/dist/assets/{Pagination-D9TkQfLt.js → Pagination-p2BVFuhf.js} +1 -1
  5. package/dist/assets/{Progress-lLgzD5SX.js → Progress-BwoJerOb.js} +1 -1
  6. package/dist/assets/{Table-Cr3nIx5M.js → Table-Cve82Lq5.js} +1 -1
  7. package/dist/assets/{Typography-D8eUZCfX.js → Typography-CAgQOS4U.js} +1 -1
  8. package/dist/assets/{YearPickerInput-BdNLRDw_.js → YearPickerInput-BPVLgEAY.js} +1 -1
  9. package/dist/assets/{accordion-DwkOqBRF.js → accordion-Ca5XgpUz.js} +1 -1
  10. package/dist/assets/accountant-approvals-BXTzXE96.js +1 -0
  11. package/dist/assets/{accounter-table-R92v4QWf.js → accounter-table-CBlUbpQl.js} +1 -1
  12. package/dist/assets/{addDays-CHr5nY3e.js → addDays-ClGDfhvI.js} +1 -1
  13. package/dist/assets/{all-charges-DVKRQLII.js → all-charges-DV7V8QJ6.js} +1 -1
  14. package/dist/assets/{arrow-up-down-CTxePA5K.js → arrow-up-down-DMdWvrmz.js} +1 -1
  15. package/dist/assets/{building-2-B6TvGHom.js → building-2-Y3dys8Pf.js} +1 -1
  16. package/dist/assets/business-CRd0ns94.js +37 -0
  17. package/dist/assets/{business-extended-info-tkrkodR7.js → business-extended-info-BKVk3weU.js} +2 -2
  18. package/dist/assets/{business-header-Dx4N1uVn.js → business-header-S5R7Fq8P.js} +1 -1
  19. package/dist/assets/{business-ledger-filters-GmMxns0y.js → business-ledger-filters-C_x4y5uJ.js} +1 -1
  20. package/dist/assets/{business-ledger-single-BeO0VVgy.js → business-ledger-single-Dku8gbU9.js} +1 -1
  21. package/dist/assets/business-trip-CB51p6xt.js +1 -0
  22. package/dist/assets/{charge-DPnVzmY7.js → charge-C79C95t6.js} +1 -1
  23. package/dist/assets/{charges-filters-BSbPgdun.js → charges-filters-RFRXF1Oa.js} +1 -1
  24. package/dist/assets/{charges-ledger-validation-zkS0soMY.js → charges-ledger-validation-DTglElRA.js} +1 -1
  25. package/dist/assets/{charges-table-BIpECr1x.js → charges-table-D3WwcB50.js} +7 -7
  26. package/dist/assets/{chart-Caa1VlDy.js → chart-2MG3qLL8.js} +1 -1
  27. package/dist/assets/{data-table-pagination-psKhAMGL.js → data-table-pagination-Dhmbf7BR.js} +1 -1
  28. package/dist/assets/{download-csv-button-B1TMXv92.js → download-csv-button-BQSz29rY.js} +1 -1
  29. package/dist/assets/{editable-business-trip-CCy91YvH.js → editable-business-trip-BlqinsvU.js} +2 -2
  30. package/dist/assets/{funnel-DP2XBopJ.js → funnel-B2plvroD.js} +1 -1
  31. package/dist/assets/{index-BsxEk8Re.js → index--xgmdJzW.js} +1 -1
  32. package/dist/assets/{index-CvxMeW9Y.js → index-5R7-0kTp.js} +1 -1
  33. package/dist/assets/{index-lk_kdDxO.js → index-BRNnfzgV.js} +2 -2
  34. package/dist/assets/{index-D9OJexEV.js → index-BdRubi2c.js} +1 -1
  35. package/dist/assets/{index-CY-XVbUJ.js → index-BgLtHIxa.js} +1 -1
  36. package/dist/assets/{index-CV2QxRmK.js → index-Bs4RBq4h.js} +1 -1
  37. package/dist/assets/{index-PfXGaCrc.js → index-C0ZATVhv.js} +1 -1
  38. package/dist/assets/{index-xJNjwngg.js → index-C4gCwrJJ.js} +1 -1
  39. package/dist/assets/{index-fZcP3X7C.js → index-C6OmHOHr.js} +191 -191
  40. package/dist/assets/index-CIdZZL-X.js +1 -0
  41. package/dist/assets/{index-BfV_NJXM.js → index-CSEktEoZ.js} +7 -7
  42. package/dist/assets/{index-CDhroLKu.js → index-Cn4t95Q9.js} +1 -1
  43. package/dist/assets/{index-dsDfIa4Y.js → index-Csdsjvrl.js} +2 -2
  44. package/dist/assets/{index-4ge3Am6D.js → index-DA3Ccstm.js} +1 -1
  45. package/dist/assets/{index-CdGH-wdf.js → index-DKZGNBg3.js} +2 -2
  46. package/dist/assets/{index-BiaDwWnW.js → index-DZ6Bqs7R.js} +1 -1
  47. package/dist/assets/{index-CFIvwwkB.js → index-DemO-kJJ.js} +2 -2
  48. package/dist/assets/index-DhRIY5eN.js +1 -0
  49. package/dist/assets/{index-DtwTITCT.js → index-HG5RXBPG.js} +1 -1
  50. package/dist/assets/{index-CRuhKIVD.js → index-P9_YuS6e.js} +1 -1
  51. package/dist/assets/index-aEEtRfbo.js +1 -0
  52. package/dist/assets/{index-DjTdlXK_.js → index-arYAg9nt.js} +1 -1
  53. package/dist/assets/{index-PaMjwOfa.js → index-eIVAASqp.js} +1 -1
  54. package/dist/assets/index-nshyF-PE.js +6 -0
  55. package/dist/assets/{index-CeSVmmFv.js → index-qMYyjtmt.js} +1 -1
  56. package/dist/assets/{index.es-tIpBPUgx.js → index.es-BrfHJ6Yj.js} +1 -1
  57. package/dist/assets/{insert-business-trip-modal-qIM7A1Dw.js → insert-business-trip-modal-COXHjjIY.js} +2 -2
  58. package/dist/assets/issue-document-CBKTg1VC.js +1 -0
  59. package/dist/assets/{list-plus-ZIHrrCaO.js → list-plus-DbuCDPM8.js} +1 -1
  60. package/dist/assets/{login-page-z7UM7kNz.js → login-page-ChNFTZLU.js} +1 -1
  61. package/dist/assets/{match-document-modal-CpUhpMJc.js → match-document-modal-Cp2DKG3j.js} +4 -4
  62. package/dist/assets/{missing-info-charges-C1tPzMqU.js → missing-info-charges-IUzXIDY1.js} +1 -1
  63. package/dist/assets/{modal-B_jJz-4Z.js → modal-CCAYjiOC.js} +1 -1
  64. package/dist/assets/{page-layout-DUgx8eXl.js → page-layout-DpwpZHY3.js} +1 -1
  65. package/dist/assets/{page-not-found-D8UJ6_C9.js → page-not-found-NbOMK1Jv.js} +1 -1
  66. package/dist/assets/{panel-top-open-CcWXXds7.js → panel-top-open-CNX1-h4c.js} +1 -1
  67. package/dist/assets/{pencil-zApPUfTb.js → pencil-Z4i9z0vF.js} +1 -1
  68. package/dist/assets/{report-commentary-row-BonuPEAK.js → report-commentary-row-C4I-ATEX.js} +1 -1
  69. package/dist/assets/{save-tZoVFUtG.js → save-D0kOxdMh.js} +1 -1
  70. package/dist/assets/similar-transactions-modal-DgD48GZ2.js +1 -0
  71. package/dist/assets/{sub-zRppNrG0.js → sub-BAZr7Qdd.js} +1 -1
  72. package/dist/assets/subMonths-Df-03cZk.js +1 -0
  73. package/dist/assets/{summary-yiqSbK4V.js → summary-CkpRtdVA.js} +1 -1
  74. package/dist/assets/{toggle-expansion-button-pWLCCDmM.js → toggle-expansion-button-Babot8nj.js} +1 -1
  75. package/dist/assets/tooltip-DStdzzhK.js +1 -0
  76. package/dist/assets/{use-url-query-DyJg_rMw.js → use-url-query-BSUiacze.js} +1 -1
  77. package/dist/index.html +1 -1
  78. package/package.json +1 -1
  79. package/src/components/business/admin-business-section.tsx +299 -103
  80. package/src/gql/gql.ts +3 -3
  81. package/src/gql/graphql.ts +53 -17
  82. package/src/providers/index.ts +4 -0
  83. package/dist/assets/accountant-approvals-DX9vcA7l.js +0 -1
  84. package/dist/assets/business-CCLPxEIP.js +0 -37
  85. package/dist/assets/business-trip-D3REiwV6.js +0 -1
  86. package/dist/assets/index-8gQaTQhF.js +0 -6
  87. package/dist/assets/index-CLvGPwjT.js +0 -1
  88. package/dist/assets/index-CmRnzPuP.js +0 -1
  89. package/dist/assets/index-DkgLEg6I.js +0 -1
  90. package/dist/assets/issue-document-CAewRj6P.js +0 -1
  91. package/dist/assets/similar-transactions-modal-Cdv2FmQ8.js +0 -1
  92. package/dist/assets/subMonths-CLe-U48r.js +0 -1
  93. package/dist/assets/tooltip-r34BEIrK.js +0 -1
  94. package/src/providers/index.tsx +0 -56
@@ -2,8 +2,9 @@
2
2
 
3
3
  import type React from 'react';
4
4
  import { useEffect, useState } from 'react';
5
- import { Save, Shield } from 'lucide-react';
6
- import { useForm } from 'react-hook-form';
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 {} as AdminBusinessFormValues;
109
+ return {};
94
110
  }
95
111
 
96
112
  return {
97
- withholdingTaxBookNumber: admin.adminInfo.withholdingTaxBookNumber ?? '',
98
- withholdingTaxFileNumber: admin.adminInfo.withholdingTaxFileNumber ?? '',
99
- socialSecurityEmployerId: admin.adminInfo.socialSecurityEmployerId ?? '',
100
- taxAdvancesRate: admin.adminInfo.taxAdvancesRate ?? 0,
101
- taxAdvancesId: admin.adminInfo.taxAdvancesId ?? '',
102
- registrationDate: admin.adminInfo.registrationDate ?? '',
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
- ? (formatTimelessDateString(new Date(formData.registrationDate)) as TimelessDateString)
135
+ ? formatTimelessDateString(new Date(formData.registrationDate))
117
136
  : undefined,
137
+ withholdingTaxAnnualIds: formData.withholdingTaxAnnualIds,
138
+ withholdingTaxCompanyId: formData.withholdingTaxCompanyId,
139
+ socialSecurityEmployerIds: formData.socialSecurityEmployerIds,
140
+ socialSecurityDeductionsId: formData.socialSecurityDeductionsId,
141
+ taxAdvancesRates: formData.taxAdvancesRates as
142
+ | { date: TimelessDateString; rate: number }[]
143
+ | undefined,
144
+ taxAdvancesAnnualIds: formData.taxAdvancesAnnualIds,
118
145
  };
119
146
  }
120
147
 
@@ -166,6 +193,75 @@ 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 addAnnualId = (
218
+ field: 'withholdingTaxAnnualIds' | 'taxAdvancesAnnualIds' | 'socialSecurityEmployerIds',
219
+ ) => {
220
+ switch (field) {
221
+ case 'withholdingTaxAnnualIds':
222
+ appendWithholdingTax({ year: new Date().getFullYear(), id: '' });
223
+ break;
224
+ case 'taxAdvancesAnnualIds':
225
+ appendTaxAdvances({ year: new Date().getFullYear(), id: '' });
226
+ break;
227
+ case 'socialSecurityEmployerIds':
228
+ appendSocialSecurity({ year: new Date().getFullYear(), id: '' });
229
+ break;
230
+ }
231
+ };
232
+
233
+ const removeAnnualId = (
234
+ field: 'withholdingTaxAnnualIds' | 'taxAdvancesAnnualIds' | 'socialSecurityEmployerIds',
235
+ index: number,
236
+ ): void => {
237
+ switch (field) {
238
+ case 'withholdingTaxAnnualIds':
239
+ removeWithholdingTax(index);
240
+ break;
241
+ case 'taxAdvancesAnnualIds':
242
+ removeTaxAdvances(index);
243
+ break;
244
+ case 'socialSecurityEmployerIds':
245
+ removeSocialSecurity(index);
246
+ break;
247
+ }
248
+ };
249
+
250
+ // Make taxAdvancesRates a controlled field array using RHF's useFieldArray
251
+ const {
252
+ fields: taxAdvancesRateFields,
253
+ append: appendTaxAdvancesRate,
254
+ remove: removeTaxAdvancesRate,
255
+ } = useFieldArray({ control: form.control, name: 'taxAdvancesRates' as const });
256
+
257
+ const addRate = () => {
258
+ appendTaxAdvancesRate({ date: format(new Date(), 'yyyy-MM-dd'), rate: 0 });
259
+ };
260
+
261
+ const removeRate = (index: number): void => {
262
+ removeTaxAdvancesRate(index);
263
+ };
264
+
169
265
  return (
170
266
  <Card>
171
267
  <CardHeader>
@@ -187,13 +283,13 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
187
283
 
188
284
  <FormField
189
285
  control={form.control}
190
- name="withholdingTaxBookNumber"
286
+ name="withholdingTaxCompanyId"
191
287
  render={({ field, fieldState }) => (
192
288
  <FormItem>
193
- <FormLabel>Book Number</FormLabel>
289
+ <FormLabel>Company Tax ID</FormLabel>
194
290
  <FormControl>
195
291
  <Input
196
- placeholder="Enter book number"
292
+ placeholder="Enter company ID"
197
293
  {...field}
198
294
  className={dirtyFieldMarker(fieldState)}
199
295
  />
@@ -203,67 +299,127 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
203
299
  )}
204
300
  />
205
301
 
206
- <FormField
207
- control={form.control}
208
- name="withholdingTaxFileNumber"
209
- render={({ field, fieldState }) => (
210
- <FormItem>
211
- <FormLabel>File Number</FormLabel>
212
- <FormControl>
213
- <Input
214
- placeholder="Enter file number"
215
- {...field}
216
- className={dirtyFieldMarker(fieldState)}
217
- />
218
- </FormControl>
219
- <FormMessage />
220
- </FormItem>
221
- )}
222
- />
302
+ <div className="space-y-4">
303
+ <div className="flex items-center justify-between">
304
+ <Label>Annual IDs</Label>
305
+ <Button
306
+ type="button"
307
+ variant="outline"
308
+ size="sm"
309
+ onClick={() => addAnnualId('withholdingTaxAnnualIds')}
310
+ >
311
+ <Plus className="size-4" />
312
+ </Button>
313
+ </div>
314
+ <div className="space-y-3">
315
+ {withholdingTaxFields.map((field, index) => (
316
+ <div key={field.id} className="flex gap-2 items-start">
317
+ <div className="flex-1 grid grid-cols-2 gap-2">
318
+ <Input
319
+ placeholder="Year"
320
+ type="number"
321
+ {...form.register(`withholdingTaxAnnualIds.${index}.year`, {
322
+ valueAsNumber: true,
323
+ })}
324
+ />
325
+ <Input
326
+ placeholder="ID"
327
+ {...form.register(`withholdingTaxAnnualIds.${index}.id`)}
328
+ />
329
+ </div>
330
+ <Button
331
+ type="button"
332
+ variant="ghost"
333
+ size="icon"
334
+ onClick={() => removeAnnualId('withholdingTaxAnnualIds', index)}
335
+ >
336
+ <X className="size-4" />
337
+ </Button>
338
+ </div>
339
+ ))}
340
+ </div>
341
+ </div>
223
342
 
224
343
  <Separator className="md:col-span-2" />
225
344
 
226
345
  <h3 className="text-sm font-semibold text-foreground md:col-span-2">Tax Advances</h3>
227
346
 
228
- <FormField
229
- control={form.control}
230
- name="taxAdvancesId"
231
- render={({ field, fieldState }) => (
232
- <FormItem>
233
- <FormLabel>Identification number</FormLabel>
234
- <FormControl>
235
- <Input
236
- placeholder="Enter tax advances ID"
237
- {...field}
238
- className={dirtyFieldMarker(fieldState)}
239
- />
240
- </FormControl>
241
- <FormMessage />
242
- </FormItem>
243
- )}
244
- />
347
+ <div className="space-y-4">
348
+ <div className="flex items-center justify-between">
349
+ <Label>Annual IDs</Label>
350
+ <Button
351
+ type="button"
352
+ variant="outline"
353
+ size="sm"
354
+ onClick={() => addAnnualId('taxAdvancesAnnualIds')}
355
+ >
356
+ <Plus className="size-4" />
357
+ </Button>
358
+ </div>
359
+ <div className="space-y-3">
360
+ {taxAdvancesFields.map((field, index) => (
361
+ <div key={field.id} className="flex gap-2 items-start">
362
+ <div className="flex-1 grid grid-cols-2 gap-2">
363
+ <Input
364
+ placeholder="Year"
365
+ type="number"
366
+ {...form.register(`taxAdvancesAnnualIds.${index}.year`, {
367
+ valueAsNumber: true,
368
+ })}
369
+ />
370
+ <Input
371
+ placeholder="ID"
372
+ {...form.register(`taxAdvancesAnnualIds.${index}.id`)}
373
+ />
374
+ </div>
375
+ <Button
376
+ type="button"
377
+ variant="ghost"
378
+ size="icon"
379
+ onClick={() => removeAnnualId('taxAdvancesAnnualIds', index)}
380
+ >
381
+ <X className="size-4" />
382
+ </Button>
383
+ </div>
384
+ ))}
385
+ </div>
386
+ </div>
245
387
 
246
- <FormField
247
- control={form.control}
248
- name="taxAdvancesRate"
249
- render={({ field, fieldState }) => (
250
- <FormItem>
251
- <FormLabel>Tax Rate (%)</FormLabel>
252
- <FormControl>
253
- <Input
254
- type="number"
255
- step="0.01"
256
- min="0"
257
- max="100"
258
- placeholder="Enter tax rate"
259
- {...field}
260
- className={dirtyFieldMarker(fieldState)}
261
- />
262
- </FormControl>
263
- <FormMessage />
264
- </FormItem>
265
- )}
266
- />
388
+ <div className="space-y-4">
389
+ <div className="flex items-center justify-between">
390
+ <Label>Rates</Label>
391
+ <Button type="button" variant="outline" size="sm" onClick={addRate}>
392
+ <Plus className="size-4" />
393
+ </Button>
394
+ </div>
395
+ <div className="space-y-3">
396
+ {taxAdvancesRateFields.map((field, index) => (
397
+ <div key={field.id} className="flex gap-2 items-start">
398
+ <div className="flex-1 grid grid-cols-2 gap-2">
399
+ <Input
400
+ placeholder="Date"
401
+ type="date"
402
+ {...form.register(`taxAdvancesRates.${index}.date`)}
403
+ />
404
+ <Input
405
+ placeholder="Rate"
406
+ {...form.register(`taxAdvancesRates.${index}.rate`, {
407
+ valueAsNumber: true,
408
+ })}
409
+ />
410
+ </div>
411
+ <Button
412
+ type="button"
413
+ variant="ghost"
414
+ size="icon"
415
+ onClick={() => removeRate(index)}
416
+ >
417
+ <X className="size-4" />
418
+ </Button>
419
+ </div>
420
+ ))}
421
+ </div>
422
+ </div>
267
423
 
268
424
  <Separator className="md:col-span-2" />
269
425
 
@@ -271,16 +427,15 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
271
427
  Social Security
272
428
  </h3>
273
429
 
274
- {/* Social Security Employer ID */}
275
430
  <FormField
276
431
  control={form.control}
277
- name="socialSecurityEmployerId"
432
+ name="socialSecurityDeductionsId"
278
433
  render={({ field, fieldState }) => (
279
434
  <FormItem>
280
- <FormLabel>Employer Identifier</FormLabel>
435
+ <FormLabel>Deductions ID</FormLabel>
281
436
  <FormControl>
282
437
  <Input
283
- placeholder="Enter employer ID"
438
+ placeholder="Enter deductions ID"
284
439
  {...field}
285
440
  className={dirtyFieldMarker(fieldState)}
286
441
  />
@@ -290,6 +445,47 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
290
445
  )}
291
446
  />
292
447
 
448
+ <div className="space-y-4">
449
+ <div className="flex items-center justify-between">
450
+ <Label>Annual Employer IDs</Label>
451
+ <Button
452
+ type="button"
453
+ variant="outline"
454
+ size="sm"
455
+ onClick={() => addAnnualId('socialSecurityEmployerIds')}
456
+ >
457
+ <Plus className="size-4" />
458
+ </Button>
459
+ </div>
460
+ <div className="space-y-3">
461
+ {socialSecurityFields.map((field, index) => (
462
+ <div key={field.id} className="flex gap-2 items-start">
463
+ <div className="flex-1 grid grid-cols-2 gap-2">
464
+ <Input
465
+ placeholder="Year"
466
+ type="number"
467
+ {...form.register(`socialSecurityEmployerIds.${index}.year`, {
468
+ valueAsNumber: true,
469
+ })}
470
+ />
471
+ <Input
472
+ placeholder="ID"
473
+ {...form.register(`socialSecurityEmployerIds.${index}.id`)}
474
+ />
475
+ </div>
476
+ <Button
477
+ type="button"
478
+ variant="ghost"
479
+ size="icon"
480
+ onClick={() => removeAnnualId('socialSecurityEmployerIds', index)}
481
+ >
482
+ <X className="size-4" />
483
+ </Button>
484
+ </div>
485
+ ))}
486
+ </div>
487
+ </div>
488
+
293
489
  <Separator className="md:col-span-2" />
294
490
 
295
491
  {/* Business Registration Start Date */}
package/src/gql/gql.ts CHANGED
@@ -21,7 +21,7 @@ type Documents = {
21
21
  "\n query BusinessTripsRowValidation($id: UUID!) {\n businessTrip(id: $id) {\n id\n uncategorizedTransactions {\n transaction {\n ... on Transaction @defer {\n id\n }\n }\n }\n summary {\n ... on BusinessTripSummary @defer {\n errors\n }\n }\n }\n }\n": typeof types.BusinessTripsRowValidationDocument,
22
22
  "\n query EditableBusinessTrip($businessTripId: UUID!) {\n businessTrip(id: $businessTripId) {\n id\n ...BusinessTripReportHeaderFields\n ...BusinessTripReportAttendeesFields\n ...BusinessTripUncategorizedTransactionsFields\n ...BusinessTripReportFlightsFields\n ...BusinessTripReportAccommodationsFields\n ...BusinessTripReportTravelAndSubsistenceFields\n ...BusinessTripReportCarRentalFields\n ...BusinessTripReportOtherFields\n ...BusinessTripReportSummaryFields\n ... on BusinessTrip {\n uncategorizedTransactions {\n transaction {\n id\n }\n }\n }\n }\n }\n": typeof types.EditableBusinessTripDocument,
23
23
  "\n query BusinessTripsScreen {\n allBusinessTrips {\n id\n name\n dates {\n start\n }\n ...BusinessTripsRowFields\n }\n }\n": typeof types.BusinessTripsScreenDocument,
24
- "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n withholdingTaxBookNumber\n withholdingTaxFileNumber\n socialSecurityEmployerId\n taxAdvancesRate\n taxAdvancesId\n registrationDate\n }\n }\n }\n": typeof types.BusinessAdminSectionFragmentDoc,
24
+ "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n registrationDate\n withholdingTaxAnnualIds {\n id\n year\n }\n withholdingTaxCompanyId\n socialSecurityEmployerIds {\n id\n year\n }\n socialSecurityDeductionsId\n taxAdvancesAnnualIds {\n id\n year\n }\n taxAdvancesRates {\n date\n rate\n }\n }\n }\n }\n": typeof types.BusinessAdminSectionFragmentDoc,
25
25
  "\n fragment BusinessHeader on Business {\n __typename\n id\n name\n createdAt\n isActive\n ... on LtdFinancialEntity {\n governmentId\n adminInfo {\n id\n }\n clientInfo {\n id\n }\n }\n }\n": typeof types.BusinessHeaderFragmentDoc,
26
26
  "\n query BusinessChargesSection($page: Int, $limit: Int, $filters: ChargeFilter) {\n allCharges(page: $page, limit: $limit, filters: $filters) {\n nodes {\n id\n ...ChargesTableFields\n }\n pageInfo {\n totalPages\n }\n }\n }\n": typeof types.BusinessChargesSectionDocument,
27
27
  "\n fragment BusinessConfigurationSection on Business {\n __typename\n id\n pcn874RecordType\n irsCode\n isActive\n ... on LtdFinancialEntity {\n optionalVAT\n exemptDealer\n isReceiptEnough\n isDocumentsOptional\n sortCode {\n id\n key\n defaultIrsCode\n }\n taxCategory {\n id\n }\n suggestions {\n phrases\n emails\n tags {\n id\n }\n description\n emailListener {\n internalEmailLinks\n emailBody\n attachments\n }\n }\n clientInfo {\n id\n }\n }\n }\n": typeof types.BusinessConfigurationSectionFragmentDoc,
@@ -276,7 +276,7 @@ const documents: Documents = {
276
276
  "\n query BusinessTripsRowValidation($id: UUID!) {\n businessTrip(id: $id) {\n id\n uncategorizedTransactions {\n transaction {\n ... on Transaction @defer {\n id\n }\n }\n }\n summary {\n ... on BusinessTripSummary @defer {\n errors\n }\n }\n }\n }\n": types.BusinessTripsRowValidationDocument,
277
277
  "\n query EditableBusinessTrip($businessTripId: UUID!) {\n businessTrip(id: $businessTripId) {\n id\n ...BusinessTripReportHeaderFields\n ...BusinessTripReportAttendeesFields\n ...BusinessTripUncategorizedTransactionsFields\n ...BusinessTripReportFlightsFields\n ...BusinessTripReportAccommodationsFields\n ...BusinessTripReportTravelAndSubsistenceFields\n ...BusinessTripReportCarRentalFields\n ...BusinessTripReportOtherFields\n ...BusinessTripReportSummaryFields\n ... on BusinessTrip {\n uncategorizedTransactions {\n transaction {\n id\n }\n }\n }\n }\n }\n": types.EditableBusinessTripDocument,
278
278
  "\n query BusinessTripsScreen {\n allBusinessTrips {\n id\n name\n dates {\n start\n }\n ...BusinessTripsRowFields\n }\n }\n": types.BusinessTripsScreenDocument,
279
- "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n withholdingTaxBookNumber\n withholdingTaxFileNumber\n socialSecurityEmployerId\n taxAdvancesRate\n taxAdvancesId\n registrationDate\n }\n }\n }\n": types.BusinessAdminSectionFragmentDoc,
279
+ "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n registrationDate\n withholdingTaxAnnualIds {\n id\n year\n }\n withholdingTaxCompanyId\n socialSecurityEmployerIds {\n id\n year\n }\n socialSecurityDeductionsId\n taxAdvancesAnnualIds {\n id\n year\n }\n taxAdvancesRates {\n date\n rate\n }\n }\n }\n }\n": types.BusinessAdminSectionFragmentDoc,
280
280
  "\n fragment BusinessHeader on Business {\n __typename\n id\n name\n createdAt\n isActive\n ... on LtdFinancialEntity {\n governmentId\n adminInfo {\n id\n }\n clientInfo {\n id\n }\n }\n }\n": types.BusinessHeaderFragmentDoc,
281
281
  "\n query BusinessChargesSection($page: Int, $limit: Int, $filters: ChargeFilter) {\n allCharges(page: $page, limit: $limit, filters: $filters) {\n nodes {\n id\n ...ChargesTableFields\n }\n pageInfo {\n totalPages\n }\n }\n }\n": types.BusinessChargesSectionDocument,
282
282
  "\n fragment BusinessConfigurationSection on Business {\n __typename\n id\n pcn874RecordType\n irsCode\n isActive\n ... on LtdFinancialEntity {\n optionalVAT\n exemptDealer\n isReceiptEnough\n isDocumentsOptional\n sortCode {\n id\n key\n defaultIrsCode\n }\n taxCategory {\n id\n }\n suggestions {\n phrases\n emails\n tags {\n id\n }\n description\n emailListener {\n internalEmailLinks\n emailBody\n attachments\n }\n }\n clientInfo {\n id\n }\n }\n }\n": types.BusinessConfigurationSectionFragmentDoc,
@@ -569,7 +569,7 @@ export function graphql(source: "\n query BusinessTripsScreen {\n allBusines
569
569
  /**
570
570
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
571
571
  */
572
- export function graphql(source: "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n withholdingTaxBookNumber\n withholdingTaxFileNumber\n socialSecurityEmployerId\n taxAdvancesRate\n taxAdvancesId\n registrationDate\n }\n }\n }\n"): (typeof documents)["\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n withholdingTaxBookNumber\n withholdingTaxFileNumber\n socialSecurityEmployerId\n taxAdvancesRate\n taxAdvancesId\n registrationDate\n }\n }\n }\n"];
572
+ export function graphql(source: "\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n registrationDate\n withholdingTaxAnnualIds {\n id\n year\n }\n withholdingTaxCompanyId\n socialSecurityEmployerIds {\n id\n year\n }\n socialSecurityDeductionsId\n taxAdvancesAnnualIds {\n id\n year\n }\n taxAdvancesRates {\n date\n rate\n }\n }\n }\n }\n"): (typeof documents)["\n fragment BusinessAdminSection on Business {\n id\n ... on LtdFinancialEntity {\n adminInfo {\n id\n registrationDate\n withholdingTaxAnnualIds {\n id\n year\n }\n withholdingTaxCompanyId\n socialSecurityEmployerIds {\n id\n year\n }\n socialSecurityDeductionsId\n taxAdvancesAnnualIds {\n id\n year\n }\n taxAdvancesRates {\n date\n rate\n }\n }\n }\n }\n"];
573
573
  /**
574
574
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
575
575
  */