@accounter/client 0.0.8-alpha-20251030162201-d2f279aafe537912ec3546af855cbd3a38ac0f5c → 0.0.8-alpha-20251030162303-87017b2c2addf0e61478260aac336b9343f15c98

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 (116) hide show
  1. package/CHANGELOG.md +1 -16
  2. package/dist/assets/{Checkbox-qEdmT4HE.js → Checkbox-CLE7WylX.js} +2 -2
  3. package/dist/assets/{MultiSelect-Dm9mO7pJ.js → MultiSelect-SsgUtHuW.js} +1 -1
  4. package/dist/assets/{Progress-kr0gnfBa.js → Progress-D7j8SJRp.js} +1 -1
  5. package/dist/assets/{Table-DnHfGe-y.js → Table-DpZKU9e6.js} +1 -1
  6. package/dist/assets/{Typography-Cu3puAUK.js → Typography-DOCvIzjw.js} +1 -1
  7. package/dist/assets/{YearPickerInput-oa86GF4P.js → YearPickerInput-BbyQMsmW.js} +1 -1
  8. package/dist/assets/{accordion-DLtMSqIv.js → accordion-KRd9M_7N.js} +1 -1
  9. package/dist/assets/{accountant-approvals-DsL0uiBa.js → accountant-approvals-BWkXiUJx.js} +1 -1
  10. package/dist/assets/{accounter-table-BL_yrGIl.js → accounter-table-BvOYdMv2.js} +1 -1
  11. package/dist/assets/{addDays-DqZEDZy3.js → addDays-HTdY9JyJ.js} +1 -1
  12. package/dist/assets/{all-charges-D3Xf-pEY.js → all-charges-uOrXkSoe.js} +1 -1
  13. package/dist/assets/{arrow-up-down-DchtBEG4.js → arrow-up-down-D0e6luFS.js} +1 -1
  14. package/dist/assets/{building-2-ZTKteVvf.js → building-2-BScQAy2y.js} +1 -1
  15. package/dist/assets/{business-extended-info-1mzdXJbs.js → business-extended-info-BPdDug4k.js} +4 -4
  16. package/dist/assets/{business-header-CJqfKV4d.js → business-header-ScM944FH.js} +1 -1
  17. package/dist/assets/{business-ledger-filters-BRB1r_DP.js → business-ledger-filters-C6zdPVNQ.js} +1 -1
  18. package/dist/assets/{business-ledger-single-C8FIQJ8V.js → business-ledger-single-D_gxQY7c.js} +1 -1
  19. package/dist/assets/business-qHY5sNtm.js +37 -0
  20. package/dist/assets/business-trip-BD6qMULS.js +1 -0
  21. package/dist/assets/{charge-Df3lWZH-.js → charge-CXgCTI2e.js} +1 -1
  22. package/dist/assets/charges-filters-DhYogrgu.js +1 -0
  23. package/dist/assets/{charges-ledger-validation-CtCBR3C-.js → charges-ledger-validation-K96Gpr99.js} +1 -1
  24. package/dist/assets/{charges-table-CWbe3t13.js → charges-table-Cff0tibm.js} +7 -7
  25. package/dist/assets/{chart-Cmm-jp0c.js → chart-Rag7RVt5.js} +1 -1
  26. package/dist/assets/contracts-C26gq1yS.js +16 -0
  27. package/dist/assets/{data-table-pagination-fdOZTf64.js → data-table-pagination-BenxjRXY.js} +2 -2
  28. package/dist/assets/{download-csv-button-CwK31swX.js → download-csv-button-8ow10rSS.js} +1 -1
  29. package/dist/assets/edit-issue-document-modal-2d_PTbvO.js +1 -0
  30. package/dist/assets/{editable-business-trip-Bjxkm9xV.js → editable-business-trip-BFJ_Mqji.js} +2 -2
  31. package/dist/assets/eye-off-BNMLF-BO.js +6 -0
  32. package/dist/assets/{funnel-CMG4QvaK.js → funnel-DW3_rS_8.js} +1 -1
  33. package/dist/assets/{index-BZVrGMgV.js → index-1iKxq5ag.js} +2 -2
  34. package/dist/assets/{index-C_ZNQ0Zr.js → index-2unHvdGT.js} +1 -1
  35. package/dist/assets/{index-DInU4RP4.js → index-4ufIi3AX.js} +2 -2
  36. package/dist/assets/index-B0Je179L.js +1 -0
  37. package/dist/assets/index-B2VI47XT.js +1 -0
  38. package/dist/assets/index-B86FoQmY.js +1 -0
  39. package/dist/assets/{index-CgokSIpu.js → index-BCiHeRl-.js} +1 -1
  40. package/dist/assets/{index-6G62OvEh.js → index-BDUyPP2c.js} +1 -1
  41. package/dist/assets/index-BHA96r33.js +1 -0
  42. package/dist/assets/{index-CjC_SXIA.js → index-BPS5RB7_.js} +1 -1
  43. package/dist/assets/{index-B9CbQIGq.js → index-BQyZXdTq.js} +2 -2
  44. package/dist/assets/index-BZLSFBEt.js +1 -0
  45. package/dist/assets/{index-Cw_aKL-8.js → index-Bd-SKdyy.js} +178 -173
  46. package/dist/assets/{index-C7oYbGGm.js → index-Bo2SK7RM.js} +1 -1
  47. package/dist/assets/{index-jCPWIpdP.js → index-Bp6IHcih.js} +1 -1
  48. package/dist/assets/index-BrSZxw1u.css +1 -0
  49. package/dist/assets/{index-DFW4nqx8.js → index-CEiIgRJ2.js} +7 -7
  50. package/dist/assets/{index-CTatkdRy.js → index-CKNxDyu9.js} +2 -2
  51. package/dist/assets/index-CqIav7Xr.js +1 -0
  52. package/dist/assets/index-Dp9F68vS.js +1 -0
  53. package/dist/assets/{index-CriBDqbK.js → index-DvvRs9Ha.js} +1 -1
  54. package/dist/assets/{index-DLwMwjDQ.js → index-DyLWk3js.js} +1 -1
  55. package/dist/assets/index-NdA_oCxx.js +1 -0
  56. package/dist/assets/{index-BEahR51x.js → index-VD71ra9C.js} +2 -2
  57. package/dist/assets/{index-xxe8M91O.js → index-lMXNkFuw.js} +2 -2
  58. package/dist/assets/index-q3ev6JER.js +1 -0
  59. package/dist/assets/{index.es-B_Bf6nNm.js → index.es-C9I2aTP4.js} +1 -1
  60. package/dist/assets/{insert-business-trip-modal-Ds3RIlmF.js → insert-business-trip-modal-DVcWpJHr.js} +2 -2
  61. package/dist/assets/issue-document-BxTTlJ1T.js +1 -0
  62. package/dist/assets/{list-plus-B3EB-dKe.js → list-plus-B7wBrICK.js} +1 -1
  63. package/dist/assets/login-page-BpgscuKm.js +1 -0
  64. package/dist/assets/{match-document-modal-Bo9pBr8W.js → match-document-modal-CqP2SE2c.js} +4 -4
  65. package/dist/assets/{missing-info-charges-BQYXI7bj.js → missing-info-charges-CIs_kE3P.js} +1 -1
  66. package/dist/assets/{modal-Pj_6bAFk.js → modal-CwuHXtxz.js} +1 -1
  67. package/dist/assets/modify-contract-dialog-BoeamC68.js +1 -0
  68. package/dist/assets/{page-layout-CVTeUSZp.js → page-layout-XgNPsCmr.js} +1 -1
  69. package/dist/assets/{page-not-found-TvTAiAs4.js → page-not-found-CrFJMQNO.js} +1 -1
  70. package/dist/assets/{panel-top-open-DzBY_TuM.js → panel-top-open-DU7alj-S.js} +1 -1
  71. package/dist/assets/{pencil-BBmFhuZN.js → pencil-9DTTP5vx.js} +1 -1
  72. package/dist/assets/{report-commentary-row-Dqw62LLo.js → report-commentary-row-BdS3qqMS.js} +1 -1
  73. package/dist/assets/{save-BW18gNVs.js → save-i8sPy_OW.js} +1 -1
  74. package/dist/assets/similar-transactions-modal-CZAOYt-d.js +1 -0
  75. package/dist/assets/sub-BL9nfaPD.js +1 -0
  76. package/dist/assets/subMonths-DHPWOZP6.js +1 -0
  77. package/dist/assets/{summary-Bbsq64IN.js → summary-Dfiju7xJ.js} +1 -1
  78. package/dist/assets/{toggle-expansion-button-BrKkZtGj.js → toggle-expansion-button-BbVh8z6s.js} +1 -1
  79. package/dist/assets/tooltip-C-fd9L1l.js +1 -0
  80. package/dist/assets/{use-url-query-C0mVgO2i.js → use-url-query-5TFyEk1x.js} +1 -1
  81. package/dist/index.html +2 -2
  82. package/package.json +1 -1
  83. package/src/components/business/admin-business-section.tsx +103 -282
  84. package/src/components/clients/contracts/modify-contract-dialog.tsx +341 -253
  85. package/src/components/contracts/cells/client.tsx +24 -0
  86. package/src/components/contracts/cells/date.tsx +10 -0
  87. package/src/components/contracts/cells/index.ts +2 -0
  88. package/src/components/contracts/columns.tsx +182 -0
  89. package/src/components/contracts/contracts-filter.tsx +160 -0
  90. package/src/components/contracts/index.tsx +264 -0
  91. package/src/components/contracts/issue-documents-modal.tsx +234 -0
  92. package/src/components/layout/sidelinks.tsx +7 -0
  93. package/src/components/screens/businesses/clients/contracts/contracts.tsx +56 -0
  94. package/src/gql/gql.ts +27 -3
  95. package/src/gql/graphql.ts +73 -52
  96. package/src/router/config.tsx +13 -0
  97. package/src/router/routes.ts +1 -0
  98. package/dist/assets/business-CAcKSrnu.js +0 -37
  99. package/dist/assets/business-trip-DkTEY8b1.js +0 -1
  100. package/dist/assets/charges-filters-DUuY-N0H.js +0 -1
  101. package/dist/assets/index-BD4s2ucv.css +0 -1
  102. package/dist/assets/index-BFwWHKS1.js +0 -1
  103. package/dist/assets/index-BI0XToIk.js +0 -1
  104. package/dist/assets/index-BQb_C-JL.js +0 -1
  105. package/dist/assets/index-CJQlHnFs.js +0 -1
  106. package/dist/assets/index-Cm6Blkgf.js +0 -1
  107. package/dist/assets/index-DJLQkpmI.js +0 -6
  108. package/dist/assets/index-DcwGbXWr.js +0 -1
  109. package/dist/assets/index-Dlj3jpuW.js +0 -1
  110. package/dist/assets/index-iya2tfvn.js +0 -1
  111. package/dist/assets/issue-document-_iHCFO9h.js +0 -1
  112. package/dist/assets/login-page-BtT_TCEJ.js +0 -1
  113. package/dist/assets/similar-transactions-modal-B39q1NLa.js +0 -1
  114. package/dist/assets/sub-DOjETdwl.js +0 -1
  115. package/dist/assets/subMonths-DqeFZ4O6.js +0 -1
  116. package/dist/assets/tooltip-CbnJYNc4.js +0 -1
@@ -1,7 +1,8 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
2
  import { format } from 'date-fns';
3
- import { Plus, X } from 'lucide-react';
3
+ import { Edit, Plus, X } from 'lucide-react';
4
4
  import { useForm } from 'react-hook-form';
5
+ import { useQuery } from 'urql';
5
6
  import { z } from 'zod';
6
7
  import { Badge } from '@/components/ui/badge.js';
7
8
  import { Button } from '@/components/ui/button.js';
@@ -32,7 +33,14 @@ import {
32
33
  } from '@/components/ui/select.js';
33
34
  import { Switch } from '@/components/ui/switch.js';
34
35
  import { Textarea } from '@/components/ui/textarea.js';
35
- import { BillingCycle, Currency, DocumentType, Product, SubscriptionPlan } from '@/gql/graphql.js';
36
+ import {
37
+ BillingCycle,
38
+ ContractsEditModalDocument,
39
+ Currency,
40
+ DocumentType,
41
+ Product,
42
+ SubscriptionPlan,
43
+ } from '@/gql/graphql.js';
36
44
  import {
37
45
  getDocumentNameFromType,
38
46
  standardBillingCycle,
@@ -43,6 +51,30 @@ import { useCreateContract } from '@/hooks/use-create-contract.js';
43
51
  import { useUpdateContract } from '@/hooks/use-update-contract.js';
44
52
  import { zodResolver } from '@hookform/resolvers/zod';
45
53
 
54
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
55
+ /* GraphQL */ `
56
+ query ContractsEditModal($contractId: UUID!) {
57
+ contractsById(id: $contractId) {
58
+ id
59
+ startDate
60
+ endDate
61
+ purchaseOrders
62
+ amount {
63
+ raw
64
+ currency
65
+ }
66
+ product
67
+ msCloud
68
+ billingCycle
69
+ plan
70
+ isActive
71
+ remarks
72
+ documentType
73
+ operationsLimit
74
+ }
75
+ }
76
+ `;
77
+
46
78
  const contractFormSchema = z.object({
47
79
  id: z.uuid().optional(),
48
80
  // TODO: activate this field later. requires additional backend support
@@ -85,10 +117,11 @@ const newContractDefaultValues: ContractFormValues = {
85
117
  interface Props {
86
118
  clientId: string;
87
119
  contract?: ContractFormValues | null;
120
+ contractId?: string;
88
121
  onDone?: () => void;
89
122
  }
90
123
 
91
- export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
124
+ export function ModifyContractDialog({ clientId, contract, contractId, onDone }: Props) {
92
125
  const [isDialogOpen, setIsDialogOpen] = useState(false);
93
126
  const [editingContract, setEditingContract] = useState<ContractFormValues | null>(null);
94
127
  const [newPO, setNewPO] = useState('');
@@ -96,6 +129,21 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
96
129
  const { updateContract, updating } = useUpdateContract();
97
130
  const { createContract, creating } = useCreateContract();
98
131
 
132
+ // Only fetch if we don't have loader data
133
+ const [{ data: fetchedContractData, fetching }, fetchContract] = useQuery({
134
+ query: ContractsEditModalDocument,
135
+ pause: !contractId || !isDialogOpen,
136
+ variables: {
137
+ contractId: contractId ?? '',
138
+ },
139
+ });
140
+
141
+ useEffect(() => {
142
+ if (isDialogOpen && contractId) {
143
+ fetchContract();
144
+ }
145
+ }, [isDialogOpen, contractId, fetchContract]);
146
+
99
147
  const form = useForm<ContractFormValues>({
100
148
  resolver: zodResolver(contractFormSchema),
101
149
  defaultValues: contract || newContractDefaultValues,
@@ -145,6 +193,32 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
145
193
  }
146
194
  }, [contract, form]);
147
195
 
196
+ useEffect(() => {
197
+ if (fetchedContractData?.contractsById) {
198
+ const fetchedContract = fetchedContractData.contractsById;
199
+ const formData: ContractFormValues = {
200
+ startDate: fetchedContract.startDate,
201
+ endDate: fetchedContract.endDate,
202
+ pos: fetchedContract.purchaseOrders,
203
+ paymentAmount: fetchedContract.amount.raw,
204
+ paymentCurrency: fetchedContract.amount.currency,
205
+ productType: fetchedContract.product ?? undefined,
206
+ msCloudLink: fetchedContract.msCloud?.toString() ?? undefined,
207
+ billingCycle: fetchedContract.billingCycle,
208
+ subscriptionPlan: fetchedContract.plan ?? undefined,
209
+ isActive: fetchedContract.isActive,
210
+ defaultRemark: fetchedContract.remarks ?? undefined,
211
+ defaultDocumentType: fetchedContract.documentType,
212
+ operationsLimit: fetchedContract.operationsLimit,
213
+ };
214
+ setEditingContract({
215
+ id: fetchedContract.id,
216
+ ...formData,
217
+ });
218
+ form.reset(formData);
219
+ }
220
+ }, [fetchedContractData, form]);
221
+
148
222
  const handleNew = () => {
149
223
  setEditingContract(null);
150
224
  form.reset(newContractDefaultValues);
@@ -207,8 +281,14 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
207
281
  <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
208
282
  <DialogTrigger asChild>
209
283
  <Button size="sm" onClick={handleNew}>
210
- <Plus className="h-4 w-4 mr-2" />
211
- New Contract
284
+ {contractId ? (
285
+ <Edit className="size-4" />
286
+ ) : (
287
+ <>
288
+ <Plus className="size-4 mr-2" />
289
+ New Contract
290
+ </>
291
+ )}
212
292
  </Button>
213
293
  </DialogTrigger>
214
294
  <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
@@ -220,166 +300,260 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
220
300
  : 'Add a new contract with all required details'}
221
301
  </DialogDescription>
222
302
  </DialogHeader>
223
- <Form {...form}>
224
- <form onSubmit={form.handleSubmit(onSubmit)}>
225
- <div className="grid gap-4 py-4">
226
- <div className="grid gap-4 md:grid-cols-2">
227
- <FormField
228
- control={form.control}
229
- name="operationsLimit"
230
- render={({ field }) => (
231
- <FormItem>
232
- <FormLabel>Operations Limit</FormLabel>
233
- <FormControl>
234
- <Input type="number" placeholder="500" {...field} />
235
- </FormControl>
236
- <FormMessage />
237
- </FormItem>
238
- )}
239
- />
240
- <FormField
241
- control={form.control}
242
- name="pos"
243
- render={({ field }) => (
244
- <FormItem>
245
- <FormLabel>Purchase Orders</FormLabel>
246
- <div className="flex gap-2">
247
- <Input
248
- placeholder="Add PO..."
249
- value={newPO}
250
- onChange={e => setNewPO(e.target.value)}
251
- onKeyDown={e => {
252
- if (e.key === 'Enter') {
253
- e.preventDefault();
254
- addPO();
255
- }
256
- }}
257
- />
258
- <Button type="button" size="sm" onClick={addPO}>
259
- <Plus className="h-4 w-4" />
260
- </Button>
261
- </div>
262
- <div className="flex flex-wrap gap-2 mt-2">
263
- {field.value?.map((link, index) => (
264
- <Badge key={link} variant="secondary" className="gap-1 max-w-xs truncate">
265
- {link}
266
- {index === field.value.length - 1 && (
267
- <Button
268
- variant="ghost"
269
- size="icon"
270
- className="p-0 size-3"
271
- onClick={() => removePO(index)}
272
- >
273
- <X className="size-3 cursor-pointer flex-shrink-0" />
274
- </Button>
275
- )}
276
- </Badge>
277
- ))}
278
- </div>
279
- <FormMessage />
280
- </FormItem>
281
- )}
282
- />
283
- </div>
303
+ {fetching ? (
304
+ <>Fetching contract details...</>
305
+ ) : (
306
+ <Form {...form}>
307
+ <form onSubmit={form.handleSubmit(onSubmit)}>
308
+ <div className="grid gap-4 py-4">
309
+ <div className="grid gap-4 md:grid-cols-2">
310
+ <FormField
311
+ control={form.control}
312
+ name="operationsLimit"
313
+ render={({ field }) => (
314
+ <FormItem>
315
+ <FormLabel>Operations Limit</FormLabel>
316
+ <FormControl>
317
+ <Input type="number" placeholder="500" {...field} />
318
+ </FormControl>
319
+ <FormMessage />
320
+ </FormItem>
321
+ )}
322
+ />
323
+ <FormField
324
+ control={form.control}
325
+ name="pos"
326
+ render={({ field }) => (
327
+ <FormItem>
328
+ <FormLabel>Purchase Orders</FormLabel>
329
+ <div className="flex gap-2">
330
+ <Input
331
+ placeholder="Add PO..."
332
+ value={newPO}
333
+ onChange={e => setNewPO(e.target.value)}
334
+ onKeyDown={e => {
335
+ if (e.key === 'Enter') {
336
+ e.preventDefault();
337
+ addPO();
338
+ }
339
+ }}
340
+ />
341
+ <Button type="button" size="sm" onClick={addPO}>
342
+ <Plus className="h-4 w-4" />
343
+ </Button>
344
+ </div>
345
+ <div className="flex flex-wrap gap-2 mt-2">
346
+ {field.value?.map((link, index) => (
347
+ <Badge
348
+ key={link}
349
+ variant="secondary"
350
+ className="gap-1 max-w-xs truncate"
351
+ >
352
+ {link}
353
+ {index === field.value.length - 1 && (
354
+ <Button
355
+ variant="ghost"
356
+ size="icon"
357
+ className="p-0 size-3"
358
+ onClick={() => removePO(index)}
359
+ >
360
+ <X className="size-3 cursor-pointer flex-shrink-0" />
361
+ </Button>
362
+ )}
363
+ </Badge>
364
+ ))}
365
+ </div>
366
+ <FormMessage />
367
+ </FormItem>
368
+ )}
369
+ />
370
+ </div>
284
371
 
285
- <div className="grid gap-4 md:grid-cols-2">
286
- <FormField
287
- control={form.control}
288
- name="startDate"
289
- render={({ field: { onChange, ...field } }) => (
290
- <FormItem>
291
- <FormLabel>Start Date</FormLabel>
292
- <FormControl>
293
- <Input type="date" {...field} onInput={date => onChange(date)} />
294
- </FormControl>
295
- <FormMessage />
296
- </FormItem>
297
- )}
298
- />
299
- <FormField
300
- control={form.control}
301
- name="endDate"
302
- render={({ field: { onChange, ...field } }) => (
303
- <FormItem>
304
- <FormLabel>End Date</FormLabel>
305
- <FormControl>
306
- <Input type="date" {...field} onInput={date => onChange(date)} />
307
- </FormControl>
308
- <FormMessage />
309
- </FormItem>
310
- )}
311
- />
312
- </div>
372
+ <div className="grid gap-4 md:grid-cols-2">
373
+ <FormField
374
+ control={form.control}
375
+ name="startDate"
376
+ render={({ field: { onChange, ...field } }) => (
377
+ <FormItem>
378
+ <FormLabel>Start Date</FormLabel>
379
+ <FormControl>
380
+ <Input type="date" {...field} onInput={date => onChange(date)} />
381
+ </FormControl>
382
+ <FormMessage />
383
+ </FormItem>
384
+ )}
385
+ />
386
+ <FormField
387
+ control={form.control}
388
+ name="endDate"
389
+ render={({ field: { onChange, ...field } }) => (
390
+ <FormItem>
391
+ <FormLabel>End Date</FormLabel>
392
+ <FormControl>
393
+ <Input type="date" {...field} onInput={date => onChange(date)} />
394
+ </FormControl>
395
+ <FormMessage />
396
+ </FormItem>
397
+ )}
398
+ />
399
+ </div>
313
400
 
314
- <div className="grid gap-4 md:grid-cols-3">
315
- <FormField
316
- control={form.control}
317
- name="paymentAmount"
318
- render={({ field }) => (
319
- <FormItem className="md:col-span-2">
320
- <FormLabel>Payment Amount</FormLabel>
321
- <FormControl>
322
- <Input
323
- type="number"
324
- placeholder="24000"
325
- {...field}
326
- onChange={event => {
327
- field.onChange(
328
- event?.target.value ? Number(event?.target.value) : undefined,
329
- );
330
- }}
331
- />
332
- </FormControl>
333
- <FormMessage />
334
- </FormItem>
335
- )}
336
- />
337
- <FormField
338
- control={form.control}
339
- name="paymentCurrency"
340
- render={({ field }) => (
341
- <FormItem>
342
- <FormLabel>Currency</FormLabel>
343
- <Select onValueChange={field.onChange} defaultValue={field.value}>
401
+ <div className="grid gap-4 md:grid-cols-3">
402
+ <FormField
403
+ control={form.control}
404
+ name="paymentAmount"
405
+ render={({ field }) => (
406
+ <FormItem className="md:col-span-2">
407
+ <FormLabel>Payment Amount</FormLabel>
344
408
  <FormControl>
345
- <SelectTrigger>
346
- <SelectValue />
347
- </SelectTrigger>
409
+ <Input
410
+ type="number"
411
+ placeholder="24000"
412
+ {...field}
413
+ onChange={event => {
414
+ field.onChange(
415
+ event?.target.value ? Number(event?.target.value) : undefined,
416
+ );
417
+ }}
418
+ />
348
419
  </FormControl>
349
- <SelectContent>
350
- {Object.values(Currency).map(currency => (
351
- <SelectItem key={currency} value={currency}>
352
- {currency}
353
- </SelectItem>
354
- ))}
355
- </SelectContent>
356
- </Select>
357
- <FormMessage />
358
- </FormItem>
359
- )}
360
- />
361
- </div>
420
+ <FormMessage />
421
+ </FormItem>
422
+ )}
423
+ />
424
+ <FormField
425
+ control={form.control}
426
+ name="paymentCurrency"
427
+ render={({ field }) => (
428
+ <FormItem>
429
+ <FormLabel>Currency</FormLabel>
430
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
431
+ <FormControl>
432
+ <SelectTrigger>
433
+ <SelectValue />
434
+ </SelectTrigger>
435
+ </FormControl>
436
+ <SelectContent>
437
+ {Object.values(Currency).map(currency => (
438
+ <SelectItem key={currency} value={currency}>
439
+ {currency}
440
+ </SelectItem>
441
+ ))}
442
+ </SelectContent>
443
+ </Select>
444
+ <FormMessage />
445
+ </FormItem>
446
+ )}
447
+ />
448
+ </div>
449
+
450
+ <div className="grid gap-4 md:grid-cols-2">
451
+ <FormField
452
+ control={form.control}
453
+ name="productType"
454
+ render={({ field }) => (
455
+ <FormItem>
456
+ <FormLabel>Product Type</FormLabel>
457
+ <FormControl>
458
+ <Input placeholder="Cloud Services" {...field} />
459
+ </FormControl>
460
+ <FormMessage />
461
+ </FormItem>
462
+ )}
463
+ />
464
+ <FormField
465
+ control={form.control}
466
+ name="billingCycle"
467
+ render={({ field }) => (
468
+ <FormItem>
469
+ <FormLabel>Billing Cycle</FormLabel>
470
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
471
+ <FormControl>
472
+ <SelectTrigger>
473
+ <SelectValue />
474
+ </SelectTrigger>
475
+ </FormControl>
476
+ <SelectContent>
477
+ {Object.values(BillingCycle).map(cycle => (
478
+ <SelectItem key={cycle} value={cycle}>
479
+ {standardBillingCycle(cycle)}
480
+ </SelectItem>
481
+ ))}
482
+ </SelectContent>
483
+ </Select>
484
+ <FormMessage />
485
+ </FormItem>
486
+ )}
487
+ />
488
+ </div>
489
+
490
+ <div className="grid gap-4 md:grid-cols-2">
491
+ <FormField
492
+ control={form.control}
493
+ name="subscriptionPlan"
494
+ render={({ field }) => (
495
+ <FormItem>
496
+ <FormLabel>Subscription Plan</FormLabel>
497
+ <FormControl>
498
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
499
+ <FormControl>
500
+ <SelectTrigger>
501
+ <SelectValue />
502
+ </SelectTrigger>
503
+ </FormControl>
504
+ <SelectContent>
505
+ {Object.values(SubscriptionPlan).map(plan => (
506
+ <SelectItem key={plan} value={plan}>
507
+ {standardPlan(plan)}
508
+ </SelectItem>
509
+ ))}
510
+ </SelectContent>
511
+ </Select>
512
+ </FormControl>
513
+ <FormMessage />
514
+ </FormItem>
515
+ )}
516
+ />
517
+ <FormField
518
+ control={form.control}
519
+ name="isActive"
520
+ render={({ field }) => (
521
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
522
+ <div className="space-y-0.5">
523
+ <FormLabel className="text-base">Active Status</FormLabel>
524
+ </div>
525
+ <FormControl>
526
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
527
+ </FormControl>
528
+ </FormItem>
529
+ )}
530
+ />
531
+ </div>
362
532
 
363
- <div className="grid gap-4 md:grid-cols-2">
364
533
  <FormField
365
534
  control={form.control}
366
- name="productType"
535
+ name="msCloudLink"
367
536
  render={({ field }) => (
368
537
  <FormItem>
369
- <FormLabel>Product Type</FormLabel>
538
+ <FormLabel>MS Cloud Link</FormLabel>
370
539
  <FormControl>
371
- <Input placeholder="Cloud Services" {...field} />
540
+ <Input
541
+ type="url"
542
+ placeholder="https://portal.azure.com/contract-id"
543
+ {...field}
544
+ />
372
545
  </FormControl>
373
546
  <FormMessage />
374
547
  </FormItem>
375
548
  )}
376
549
  />
550
+
377
551
  <FormField
378
552
  control={form.control}
379
- name="billingCycle"
553
+ name="defaultDocumentType"
380
554
  render={({ field }) => (
381
555
  <FormItem>
382
- <FormLabel>Billing Cycle</FormLabel>
556
+ <FormLabel>Default Document Type</FormLabel>
383
557
  <Select onValueChange={field.onChange} defaultValue={field.value}>
384
558
  <FormControl>
385
559
  <SelectTrigger>
@@ -387,9 +561,9 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
387
561
  </SelectTrigger>
388
562
  </FormControl>
389
563
  <SelectContent>
390
- {Object.values(BillingCycle).map(cycle => (
391
- <SelectItem key={cycle} value={cycle}>
392
- {standardBillingCycle(cycle)}
564
+ {Object.values(DocumentType).map(type => (
565
+ <SelectItem key={type} value={type}>
566
+ {getDocumentNameFromType(type)}
393
567
  </SelectItem>
394
568
  ))}
395
569
  </SelectContent>
@@ -398,122 +572,36 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
398
572
  </FormItem>
399
573
  )}
400
574
  />
401
- </div>
402
575
 
403
- <div className="grid gap-4 md:grid-cols-2">
404
576
  <FormField
405
577
  control={form.control}
406
- name="subscriptionPlan"
578
+ name="defaultRemark"
407
579
  render={({ field }) => (
408
580
  <FormItem>
409
- <FormLabel>Subscription Plan</FormLabel>
581
+ <FormLabel>Default Remark</FormLabel>
410
582
  <FormControl>
411
- <Select onValueChange={field.onChange} defaultValue={field.value}>
412
- <FormControl>
413
- <SelectTrigger>
414
- <SelectValue />
415
- </SelectTrigger>
416
- </FormControl>
417
- <SelectContent>
418
- {Object.values(SubscriptionPlan).map(plan => (
419
- <SelectItem key={plan} value={plan}>
420
- {standardPlan(plan)}
421
- </SelectItem>
422
- ))}
423
- </SelectContent>
424
- </Select>
583
+ <Textarea
584
+ placeholder="Enter default remark for this contract..."
585
+ rows={3}
586
+ {...field}
587
+ />
425
588
  </FormControl>
426
589
  <FormMessage />
427
590
  </FormItem>
428
591
  )}
429
592
  />
430
- <FormField
431
- control={form.control}
432
- name="isActive"
433
- render={({ field }) => (
434
- <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
435
- <div className="space-y-0.5">
436
- <FormLabel className="text-base">Active Status</FormLabel>
437
- </div>
438
- <FormControl>
439
- <Switch checked={field.value} onCheckedChange={field.onChange} />
440
- </FormControl>
441
- </FormItem>
442
- )}
443
- />
444
593
  </div>
445
-
446
- <FormField
447
- control={form.control}
448
- name="msCloudLink"
449
- render={({ field }) => (
450
- <FormItem>
451
- <FormLabel>MS Cloud Link</FormLabel>
452
- <FormControl>
453
- <Input
454
- type="url"
455
- placeholder="https://portal.azure.com/contract-id"
456
- {...field}
457
- />
458
- </FormControl>
459
- <FormMessage />
460
- </FormItem>
461
- )}
462
- />
463
-
464
- <FormField
465
- control={form.control}
466
- name="defaultDocumentType"
467
- render={({ field }) => (
468
- <FormItem>
469
- <FormLabel>Default Document Type</FormLabel>
470
- <Select onValueChange={field.onChange} defaultValue={field.value}>
471
- <FormControl>
472
- <SelectTrigger>
473
- <SelectValue />
474
- </SelectTrigger>
475
- </FormControl>
476
- <SelectContent>
477
- {Object.values(DocumentType).map(type => (
478
- <SelectItem key={type} value={type}>
479
- {getDocumentNameFromType(type)}
480
- </SelectItem>
481
- ))}
482
- </SelectContent>
483
- </Select>
484
- <FormMessage />
485
- </FormItem>
486
- )}
487
- />
488
-
489
- <FormField
490
- control={form.control}
491
- name="defaultRemark"
492
- render={({ field }) => (
493
- <FormItem>
494
- <FormLabel>Default Remark</FormLabel>
495
- <FormControl>
496
- <Textarea
497
- placeholder="Enter default remark for this contract..."
498
- rows={3}
499
- {...field}
500
- />
501
- </FormControl>
502
- <FormMessage />
503
- </FormItem>
504
- )}
505
- />
506
- </div>
507
- <DialogFooter>
508
- <Button type="button" variant="outline" onClick={() => setIsDialogOpen(false)}>
509
- Cancel
510
- </Button>
511
- <Button type="submit" disabled={creating || updating}>
512
- {editingContract ? 'Update Contract' : 'Create Contract'}
513
- </Button>
514
- </DialogFooter>
515
- </form>
516
- </Form>
594
+ <DialogFooter>
595
+ <Button type="button" variant="outline" onClick={() => setIsDialogOpen(false)}>
596
+ Cancel
597
+ </Button>
598
+ <Button type="submit" disabled={creating || updating}>
599
+ {editingContract ? 'Update Contract' : 'Create Contract'}
600
+ </Button>
601
+ </DialogFooter>
602
+ </form>
603
+ </Form>
604
+ )}
517
605
  </DialogContent>
518
606
  </Dialog>
519
607
  );