@hed-hog/operations 0.0.306 → 0.0.310

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 (123) hide show
  1. package/dist/controllers/operations-approvals.controller.d.ts +114 -1
  2. package/dist/controllers/operations-approvals.controller.d.ts.map +1 -1
  3. package/dist/controllers/operations-approvals.controller.js +16 -3
  4. package/dist/controllers/operations-approvals.controller.js.map +1 -1
  5. package/dist/controllers/operations-collaborators.controller.d.ts +16 -1
  6. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  7. package/dist/controllers/operations-collaborators.controller.js +16 -3
  8. package/dist/controllers/operations-collaborators.controller.js.map +1 -1
  9. package/dist/controllers/operations-contracts.controller.d.ts +14 -453
  10. package/dist/controllers/operations-contracts.controller.d.ts.map +1 -1
  11. package/dist/controllers/operations-contracts.controller.js +11 -112
  12. package/dist/controllers/operations-contracts.controller.js.map +1 -1
  13. package/dist/controllers/operations-org-structure.controller.d.ts +65 -2
  14. package/dist/controllers/operations-org-structure.controller.d.ts.map +1 -1
  15. package/dist/controllers/operations-org-structure.controller.js +18 -5
  16. package/dist/controllers/operations-org-structure.controller.js.map +1 -1
  17. package/dist/controllers/operations-projects.controller.d.ts +28 -4
  18. package/dist/controllers/operations-projects.controller.d.ts.map +1 -1
  19. package/dist/controllers/operations-projects.controller.js +17 -5
  20. package/dist/controllers/operations-projects.controller.js.map +1 -1
  21. package/dist/controllers/operations-timesheets.controller.d.ts +31 -4
  22. package/dist/controllers/operations-timesheets.controller.d.ts.map +1 -1
  23. package/dist/controllers/operations-timesheets.controller.js +16 -11
  24. package/dist/controllers/operations-timesheets.controller.js.map +1 -1
  25. package/dist/dto/list-approvals.dto.d.ts +6 -0
  26. package/dist/dto/list-approvals.dto.d.ts.map +1 -0
  27. package/dist/dto/list-approvals.dto.js +28 -0
  28. package/dist/dto/list-approvals.dto.js.map +1 -0
  29. package/dist/dto/list-collaborator-types.dto.d.ts +3 -1
  30. package/dist/dto/list-collaborator-types.dto.d.ts.map +1 -1
  31. package/dist/dto/list-collaborator-types.dto.js +7 -1
  32. package/dist/dto/list-collaborator-types.dto.js.map +1 -1
  33. package/dist/dto/list-collaborators.dto.d.ts +1 -0
  34. package/dist/dto/list-collaborators.dto.d.ts.map +1 -1
  35. package/dist/dto/list-collaborators.dto.js +5 -0
  36. package/dist/dto/list-collaborators.dto.js.map +1 -1
  37. package/dist/dto/list-contracts.dto.d.ts +8 -0
  38. package/dist/dto/list-contracts.dto.d.ts.map +1 -0
  39. package/dist/dto/list-contracts.dto.js +38 -0
  40. package/dist/dto/list-contracts.dto.js.map +1 -0
  41. package/dist/dto/list-departments.dto.d.ts +5 -0
  42. package/dist/dto/list-departments.dto.d.ts.map +1 -0
  43. package/dist/dto/list-departments.dto.js +23 -0
  44. package/dist/dto/list-departments.dto.js.map +1 -0
  45. package/dist/dto/list-projects.dto.d.ts +5 -0
  46. package/dist/dto/list-projects.dto.d.ts.map +1 -0
  47. package/dist/dto/list-projects.dto.js +23 -0
  48. package/dist/dto/list-projects.dto.js.map +1 -0
  49. package/dist/dto/list-schedule-adjustments.dto.d.ts +5 -0
  50. package/dist/dto/list-schedule-adjustments.dto.d.ts.map +1 -0
  51. package/dist/dto/list-schedule-adjustments.dto.js +23 -0
  52. package/dist/dto/list-schedule-adjustments.dto.js.map +1 -0
  53. package/dist/dto/list-time-off-requests.dto.d.ts +5 -0
  54. package/dist/dto/list-time-off-requests.dto.d.ts.map +1 -0
  55. package/dist/dto/list-time-off-requests.dto.js +23 -0
  56. package/dist/dto/list-time-off-requests.dto.js.map +1 -0
  57. package/dist/dto/list-timesheets.dto.d.ts +5 -0
  58. package/dist/dto/list-timesheets.dto.d.ts.map +1 -0
  59. package/dist/dto/list-timesheets.dto.js +23 -0
  60. package/dist/dto/list-timesheets.dto.js.map +1 -0
  61. package/dist/dto/reorder-collaborator-types.dto.d.ts +4 -0
  62. package/dist/dto/reorder-collaborator-types.dto.d.ts.map +1 -0
  63. package/dist/dto/reorder-collaborator-types.dto.js +25 -0
  64. package/dist/dto/reorder-collaborator-types.dto.js.map +1 -0
  65. package/dist/operations.service.d.ts +340 -271
  66. package/dist/operations.service.d.ts.map +1 -1
  67. package/dist/operations.service.js +1007 -1043
  68. package/dist/operations.service.js.map +1 -1
  69. package/dist/operations.service.spec.js +0 -22
  70. package/dist/operations.service.spec.js.map +1 -1
  71. package/hedhog/data/menu.yaml +0 -36
  72. package/hedhog/data/route.yaml +42 -73
  73. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +8 -1
  74. package/hedhog/frontend/app/_components/collaborator-select-with-create.tsx.ejs +15 -10
  75. package/hedhog/frontend/app/_components/contract-details-screen.tsx.ejs +108 -213
  76. package/hedhog/frontend/app/_components/contract-form-screen.tsx.ejs +251 -2039
  77. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +167 -60
  78. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +70 -301
  79. package/hedhog/frontend/app/_components/system-user-select-with-create.tsx.ejs +102 -51
  80. package/hedhog/frontend/app/_lib/types.ts.ejs +19 -24
  81. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +14 -9
  82. package/hedhog/frontend/app/approvals/page.tsx.ejs +842 -150
  83. package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +445 -153
  84. package/hedhog/frontend/app/collaborators/page.tsx.ejs +118 -49
  85. package/hedhog/frontend/app/contracts/[id]/page.tsx.ejs +2 -2
  86. package/hedhog/frontend/app/contracts/page.tsx.ejs +215 -617
  87. package/hedhog/frontend/app/departments/page.tsx.ejs +257 -113
  88. package/hedhog/frontend/app/projects/page.tsx.ejs +90 -51
  89. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +412 -147
  90. package/hedhog/frontend/app/time-off/page.tsx.ejs +400 -123
  91. package/hedhog/frontend/app/timesheets/page.tsx.ejs +460 -365
  92. package/hedhog/frontend/messages/en.json +143 -14
  93. package/hedhog/frontend/messages/pt.json +192 -54
  94. package/hedhog/table/operations_contract.yaml +0 -9
  95. package/package.json +4 -4
  96. package/src/controllers/operations-approvals.controller.ts +9 -3
  97. package/src/controllers/operations-collaborators.controller.ts +15 -2
  98. package/src/controllers/operations-contracts.controller.ts +8 -92
  99. package/src/controllers/operations-org-structure.controller.ts +17 -4
  100. package/src/controllers/operations-projects.controller.ts +10 -4
  101. package/src/controllers/operations-timesheets.controller.ts +17 -8
  102. package/src/dto/list-approvals.dto.ts +12 -0
  103. package/src/dto/list-collaborator-types.dto.ts +7 -2
  104. package/src/dto/list-collaborators.dto.ts +4 -0
  105. package/src/dto/list-contracts.dto.ts +20 -0
  106. package/src/dto/list-departments.dto.ts +8 -0
  107. package/src/dto/list-projects.dto.ts +8 -0
  108. package/src/dto/list-schedule-adjustments.dto.ts +8 -0
  109. package/src/dto/list-time-off-requests.dto.ts +8 -0
  110. package/src/dto/list-timesheets.dto.ts +8 -0
  111. package/src/dto/reorder-collaborator-types.dto.ts +10 -0
  112. package/src/operations.service.spec.ts +0 -30
  113. package/src/operations.service.ts +1557 -1806
  114. package/hedhog/frontend/app/_components/contract-creation-wizard.tsx.ejs +0 -631
  115. package/hedhog/frontend/app/_components/contract-template-form-screen.tsx.ejs +0 -526
  116. package/hedhog/frontend/app/_components/contract-template-select-with-create.tsx.ejs +0 -247
  117. package/hedhog/frontend/app/_components/contract-wizard-sheet.tsx.ejs +0 -3520
  118. package/hedhog/frontend/app/contracts/templates/page.tsx.ejs +0 -380
  119. package/hedhog/frontend/app/team/page.tsx.ejs +0 -352
  120. package/hedhog/table/operations_contract_financial_term.yaml +0 -40
  121. package/hedhog/table/operations_contract_revision.yaml +0 -38
  122. package/hedhog/table/operations_contract_signature.yaml +0 -38
  123. package/hedhog/table/operations_contract_template.yaml +0 -58
@@ -19,8 +19,6 @@ import { fetchOperations } from '../_lib/api';
19
19
  import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
20
20
  import type { OperationsContractDetails } from '../_lib/types';
21
21
  import {
22
- formatCurrency,
23
- formatDate,
24
22
  formatDateTime,
25
23
  formatEnumLabel,
26
24
  getStatusBadgeClass,
@@ -41,14 +39,10 @@ function downloadBase64File(
41
39
  link.click();
42
40
  }
43
41
 
44
- function openStoredFile(fileId?: number | null) {
45
- if (!fileId) return;
42
+ function buildStoredFileUrl(fileId?: number | null) {
43
+ if (!fileId) return null;
46
44
  const baseUrl = String(process.env.NEXT_PUBLIC_API_BASE_URL || '');
47
- window.open(
48
- `${baseUrl}/file/open/${fileId}`,
49
- '_blank',
50
- 'noopener,noreferrer'
51
- );
45
+ return `${baseUrl}/file/open/${fileId}`;
52
46
  }
53
47
 
54
48
  export function ContractDetailsScreen({ contractId }: { contractId: number }) {
@@ -86,9 +80,23 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
86
80
  );
87
81
  }
88
82
 
89
- const currentPdf = contract.documents.find((document) => document.isCurrent);
83
+ const currentDocument =
84
+ contract.documents.find(
85
+ (document) =>
86
+ document.isCurrent &&
87
+ ['generated_pdf', 'source_upload'].includes(document.documentType)
88
+ ) ??
89
+ contract.documents.find((document) => document.isCurrent) ??
90
+ null;
91
+
92
+ const previewSource = currentDocument?.fileContentBase64
93
+ ? `data:${currentDocument.mimeType};base64,${currentDocument.fileContentBase64}`
94
+ : buildStoredFileUrl(currentDocument?.fileId);
95
+ const canPreview =
96
+ Boolean(previewSource) && currentDocument?.mimeType?.includes('pdf');
90
97
  const contractTitle =
91
98
  contract.name || contract.code || commonT('labels.notAvailable');
99
+
92
100
  const getOptionLabel = (group: string, value?: string | null) => {
93
101
  if (!value) {
94
102
  return '-';
@@ -105,24 +113,35 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
105
113
  description={t('description')}
106
114
  current={t('breadcrumb')}
107
115
  actions={
108
- <div className="flex gap-2">
109
- {currentPdf?.fileId || currentPdf?.fileContentBase64 ? (
110
- <Button
111
- variant="outline"
112
- size="sm"
113
- onClick={() =>
114
- currentPdf?.fileId
115
- ? openStoredFile(currentPdf.fileId)
116
- : downloadBase64File(
117
- currentPdf.fileName,
118
- currentPdf.mimeType,
119
- currentPdf.fileContentBase64 || ''
120
- )
121
- }
122
- >
123
- <Download className="size-4" />
124
- {t('actions.downloadPdf')}
125
- </Button>
116
+ <div className="flex flex-wrap gap-2">
117
+ {currentDocument?.fileId || currentDocument?.fileContentBase64 ? (
118
+ currentDocument.fileId ? (
119
+ <Button variant="outline" size="sm" asChild>
120
+ <a
121
+ href={buildStoredFileUrl(currentDocument.fileId) || '#'}
122
+ target="_blank"
123
+ rel="noreferrer"
124
+ >
125
+ <Download className="size-4" />
126
+ {t('actions.downloadPdf')}
127
+ </a>
128
+ </Button>
129
+ ) : (
130
+ <Button
131
+ variant="outline"
132
+ size="sm"
133
+ onClick={() =>
134
+ downloadBase64File(
135
+ currentDocument.fileName,
136
+ currentDocument.mimeType,
137
+ currentDocument.fileContentBase64 || ''
138
+ )
139
+ }
140
+ >
141
+ <Download className="size-4" />
142
+ {t('actions.downloadPdf')}
143
+ </Button>
144
+ )
126
145
  ) : null}
127
146
  {access.isDirector ? (
128
147
  <Button size="sm" asChild>
@@ -136,105 +155,73 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
136
155
  }
137
156
  />
138
157
 
139
- <Tabs defaultValue="overview">
158
+ <Tabs defaultValue="preview">
140
159
  <TabsList className="flex-wrap">
160
+ <TabsTrigger value="preview">{t('tabs.preview')}</TabsTrigger>
141
161
  <TabsTrigger value="overview">{t('tabs.overview')}</TabsTrigger>
142
- <TabsTrigger value="parties">{t('tabs.parties')}</TabsTrigger>
143
- <TabsTrigger value="signatures">{t('tabs.signatures')}</TabsTrigger>
144
- <TabsTrigger value="financials">{t('tabs.financials')}</TabsTrigger>
145
162
  <TabsTrigger value="documents">{t('tabs.documents')}</TabsTrigger>
146
- <TabsTrigger value="revisions">{t('tabs.revisions')}</TabsTrigger>
147
- <TabsTrigger value="history">{t('tabs.history')}</TabsTrigger>
148
163
  </TabsList>
149
164
 
165
+ <TabsContent value="preview">
166
+ <SectionCard title={t('sections.preview')}>
167
+ {canPreview && previewSource ? (
168
+ <iframe
169
+ title={t('sections.preview')}
170
+ src={previewSource}
171
+ className="h-180 w-full rounded-lg border"
172
+ />
173
+ ) : (
174
+ <div className="rounded-lg border border-dashed px-4 py-12 text-center text-sm text-muted-foreground">
175
+ {t('states.previewUnavailable')}
176
+ </div>
177
+ )}
178
+ </SectionCard>
179
+ </TabsContent>
180
+
150
181
  <TabsContent value="overview">
151
182
  <SectionCard title={t('sections.overview')}>
152
- <dl className="grid gap-3 text-sm md:grid-cols-3">
183
+ <dl className="grid gap-3 text-sm md:grid-cols-4">
153
184
  <div>
154
185
  <dt className="text-muted-foreground">
155
186
  {commonT('labels.contract')}
156
187
  </dt>
157
188
  <dd className="font-medium">{contractTitle}</dd>
158
189
  </div>
159
- <div>
160
- <dt className="text-muted-foreground">{t('labels.origin')}</dt>
161
- <dd className="font-medium">
162
- {getOptionLabel('originTypes', contract.originType)}
163
- </dd>
164
- </div>
165
190
  <div>
166
191
  <dt className="text-muted-foreground">
167
- {t('labels.mainParty')}
168
- </dt>
169
- <dd className="font-medium">
170
- {contract.mainRelatedPartyName ||
171
- commonT('labels.notAvailable')}
172
- </dd>
173
- </div>
174
- <div>
175
- <dt className="text-muted-foreground">
176
- {t('labels.contractType')}
177
- </dt>
178
- <dd className="font-medium">
179
- {getOptionLabel('contractTypes', contract.contractType)}
180
- </dd>
181
- </div>
182
- <div>
183
- <dt className="text-muted-foreground">
184
- {t('labels.signatureStatus')}
192
+ {commonT('labels.status')}
185
193
  </dt>
186
194
  <dd className="font-medium">
187
195
  <StatusBadge
188
- label={getOptionLabel(
189
- 'signatureStatuses',
190
- contract.signatureStatus
196
+ label={
197
+ contract.isActive
198
+ ? t('labels.active')
199
+ : t('labels.inactive')
200
+ }
201
+ className={getStatusBadgeClass(
202
+ contract.isActive ? 'active' : 'archived'
191
203
  )}
192
- className={getStatusBadgeClass(contract.signatureStatus)}
193
204
  />
194
205
  </dd>
195
206
  </div>
196
207
  <div>
197
208
  <dt className="text-muted-foreground">
198
- {t('labels.activeState')}
199
- </dt>
200
- <dd className="font-medium">
201
- {contract.isActive
202
- ? t('labels.active')
203
- : t('labels.inactive')}
204
- </dd>
205
- </div>
206
- <div>
207
- <dt className="text-muted-foreground">
208
- {commonT('labels.startDate')}
209
+ {t('labels.mainParty')}
209
210
  </dt>
210
211
  <dd className="font-medium">
211
- {formatDate(contract.startDate)}
212
+ {contract.mainRelatedPartyName ||
213
+ commonT('labels.notAvailable')}
212
214
  </dd>
213
215
  </div>
214
216
  <div>
215
217
  <dt className="text-muted-foreground">
216
- {commonT('labels.endDate')}
217
- </dt>
218
- <dd className="font-medium">{formatDate(contract.endDate)}</dd>
219
- </div>
220
- <div>
221
- <dt className="text-muted-foreground">
222
- {commonT('labels.status')}
218
+ {t('labels.contractType')}
223
219
  </dt>
224
220
  <dd className="font-medium">
225
- <StatusBadge
226
- label={getOptionLabel('statuses', contract.status)}
227
- className={getStatusBadgeClass(contract.status)}
228
- />
221
+ {getOptionLabel('contractTypes', contract.contractType)}
229
222
  </dd>
230
223
  </div>
231
224
  </dl>
232
- {contract.contentHtml ? (
233
- <div
234
- className="prose prose-sm mt-4 max-w-none rounded-lg border p-4"
235
- dangerouslySetInnerHTML={{ __html: contract.contentHtml }}
236
- />
237
- ) : null}
238
225
  </SectionCard>
239
226
  </TabsContent>
240
227
 
@@ -277,74 +264,7 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
277
264
  )}
278
265
  </SectionCard>
279
266
  </TabsContent>
280
- <TabsContent value="signatures">
281
- <SectionCard title={t('sections.signatures')}>
282
- {contract.signatures.length ? (
283
- <div className="overflow-x-auto rounded-md border">
284
- <Table>
285
- <TableHeader>
286
- <TableRow>
287
- <TableHead>{t('labels.signer')}</TableHead>
288
- <TableHead>{commonT('labels.status')}</TableHead>
289
- <TableHead>{t('labels.signedAt')}</TableHead>
290
- </TableRow>
291
- </TableHeader>
292
- <TableBody>
293
- {contract.signatures.map((signature) => (
294
- <TableRow key={signature.id}>
295
- <TableCell>{signature.signerName}</TableCell>
296
- <TableCell>
297
- <StatusBadge
298
- label={getOptionLabel(
299
- 'signatureStatuses',
300
- signature.status
301
- )}
302
- className={getStatusBadgeClass(signature.status)}
303
- />
304
- </TableCell>
305
- <TableCell>{formatDate(signature.signedAt)}</TableCell>
306
- </TableRow>
307
- ))}
308
- </TableBody>
309
- </Table>
310
- </div>
311
- ) : (
312
- <p className="text-sm text-muted-foreground">
313
- {t('states.noSignatures')}
314
- </p>
315
- )}
316
- </SectionCard>
317
- </TabsContent>
318
- <TabsContent value="financials">
319
- <SectionCard title={t('sections.financials')}>
320
- <dl className="grid gap-3 text-sm md:grid-cols-4">
321
- <div>
322
- <dt className="text-muted-foreground">{t('labels.value')}</dt>
323
- <dd className="font-medium">
324
- {formatCurrency(contract.valueAmount ?? 0)}
325
- </dd>
326
- </div>
327
- <div>
328
- <dt className="text-muted-foreground">{t('labels.payment')}</dt>
329
- <dd className="font-medium">
330
- {formatCurrency(contract.paymentAmount ?? 0)}
331
- </dd>
332
- </div>
333
- <div>
334
- <dt className="text-muted-foreground">{t('labels.revenue')}</dt>
335
- <dd className="font-medium">
336
- {formatCurrency(contract.revenueAmount ?? 0)}
337
- </dd>
338
- </div>
339
- <div>
340
- <dt className="text-muted-foreground">{t('labels.fine')}</dt>
341
- <dd className="font-medium">
342
- {formatCurrency(contract.fineAmount ?? 0)}
343
- </dd>
344
- </div>
345
- </dl>
346
- </SectionCard>
347
- </TabsContent>
267
+
348
268
  <TabsContent value="documents">
349
269
  <SectionCard title={t('sections.documents')}>
350
270
  {contract.documents.length ? (
@@ -362,22 +282,33 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
362
282
  </div>
363
283
  </div>
364
284
  {document.fileId || document.fileContentBase64 ? (
365
- <Button
366
- variant="outline"
367
- size="sm"
368
- onClick={() =>
369
- document.fileId
370
- ? openStoredFile(document.fileId)
371
- : downloadBase64File(
372
- document.fileName,
373
- document.mimeType,
374
- document.fileContentBase64 || ''
375
- )
376
- }
377
- >
378
- <Download className="size-4" />
379
- {t('actions.download')}
380
- </Button>
285
+ document.fileId ? (
286
+ <Button variant="outline" size="sm" asChild>
287
+ <a
288
+ href={buildStoredFileUrl(document.fileId) || '#'}
289
+ target="_blank"
290
+ rel="noreferrer"
291
+ >
292
+ <Download className="size-4" />
293
+ {t('actions.download')}
294
+ </a>
295
+ </Button>
296
+ ) : (
297
+ <Button
298
+ variant="outline"
299
+ size="sm"
300
+ onClick={() =>
301
+ downloadBase64File(
302
+ document.fileName,
303
+ document.mimeType,
304
+ document.fileContentBase64 || ''
305
+ )
306
+ }
307
+ >
308
+ <Download className="size-4" />
309
+ {t('actions.download')}
310
+ </Button>
311
+ )
381
312
  ) : null}
382
313
  </div>
383
314
  ))}
@@ -389,43 +320,7 @@ export function ContractDetailsScreen({ contractId }: { contractId: number }) {
389
320
  )}
390
321
  </SectionCard>
391
322
  </TabsContent>
392
- <TabsContent value="revisions">
393
- <SectionCard title={t('sections.revisions')}>
394
- {contract.revisions.length ? (
395
- <div className="overflow-x-auto rounded-md border">
396
- <Table>
397
- <TableHeader>
398
- <TableRow>
399
- <TableHead>{t('labels.revision')}</TableHead>
400
- <TableHead>{commonT('labels.status')}</TableHead>
401
- <TableHead>{commonT('labels.startDate')}</TableHead>
402
- </TableRow>
403
- </TableHeader>
404
- <TableBody>
405
- {contract.revisions.map((revision) => (
406
- <TableRow key={revision.id}>
407
- <TableCell>{revision.title}</TableCell>
408
- <TableCell>
409
- <StatusBadge
410
- label={getOptionLabel('statuses', revision.status)}
411
- className={getStatusBadgeClass(revision.status)}
412
- />
413
- </TableCell>
414
- <TableCell>
415
- {formatDate(revision.effectiveDate)}
416
- </TableCell>
417
- </TableRow>
418
- ))}
419
- </TableBody>
420
- </Table>
421
- </div>
422
- ) : (
423
- <p className="text-sm text-muted-foreground">
424
- {t('states.noRevisions')}
425
- </p>
426
- )}
427
- </SectionCard>
428
- </TabsContent>
323
+
429
324
  <TabsContent value="history">
430
325
  <SectionCard title={t('sections.history')}>
431
326
  {contract.history.length ? (