@hed-hog/finance 0.0.301 → 0.0.303
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/hedhog/data/menu.yaml +0 -17
- package/hedhog/frontend/app/_components/finance-layout.tsx.ejs +23 -0
- package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +86 -91
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +1457 -1446
- package/hedhog/frontend/app/accounts-receivable/collections-default/page.tsx.ejs +323 -324
- package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +1252 -1235
- package/hedhog/frontend/app/administration/audit-logs/page.tsx.ejs +12 -7
- package/hedhog/frontend/app/administration/categories/page.tsx.ejs +32 -14
- package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +13 -5
- package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +148 -147
- package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +400 -404
- package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +9 -10
- package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +2 -6
- package/hedhog/frontend/app/page.tsx.ejs +3 -370
- package/hedhog/frontend/app/planning/cash-flow-forecast/page.tsx.ejs +66 -74
- package/hedhog/frontend/app/planning/receivables-calendar/page.tsx.ejs +1 -5
- package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +1 -1
- package/package.json +5 -5
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
FinancePageSection,
|
|
5
|
-
FinanceSheetBody,
|
|
6
|
-
FinanceSheetSection,
|
|
7
|
-
} from '@/app/(app)/(libraries)/finance/_components/finance-layout';
|
|
8
|
-
import { EmptyState, Page, PageHeader } from '@/components/entity-list';
|
|
9
|
-
import { RichTextEditor } from '@/components/rich-text-editor';
|
|
10
|
-
import { Button } from '@/components/ui/button';
|
|
11
|
-
import {
|
|
12
|
-
Form,
|
|
13
|
-
FormControl,
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FinancePageSection,
|
|
5
|
+
FinanceSheetBody,
|
|
6
|
+
FinanceSheetSection,
|
|
7
|
+
} from '@/app/(app)/(libraries)/finance/_components/finance-layout';
|
|
8
|
+
import { EmptyState, Page, PageHeader } from '@/components/entity-list';
|
|
9
|
+
import { RichTextEditor } from '@/components/rich-text-editor';
|
|
10
|
+
import { Button } from '@/components/ui/button';
|
|
11
|
+
import {
|
|
12
|
+
Form,
|
|
13
|
+
FormControl,
|
|
14
14
|
FormField,
|
|
15
15
|
FormItem,
|
|
16
16
|
FormLabel,
|
|
17
17
|
FormMessage,
|
|
18
|
-
} from '@/components/ui/form';
|
|
19
|
-
import { Input } from '@/components/ui/input';
|
|
20
|
-
import { InputMoney } from '@/components/ui/input-money';
|
|
21
|
-
import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
|
|
22
|
-
import { Money } from '@/components/ui/money';
|
|
18
|
+
} from '@/components/ui/form';
|
|
19
|
+
import { Input } from '@/components/ui/input';
|
|
20
|
+
import { InputMoney } from '@/components/ui/input-money';
|
|
21
|
+
import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
|
|
22
|
+
import { Money } from '@/components/ui/money';
|
|
23
23
|
import {
|
|
24
24
|
Sheet,
|
|
25
25
|
SheetContent,
|
|
@@ -105,47 +105,47 @@ function HistoricoContatosSheet({
|
|
|
105
105
|
}) {
|
|
106
106
|
return (
|
|
107
107
|
<Sheet>
|
|
108
|
-
<SheetTrigger asChild>
|
|
109
|
-
<Button variant="outline" size="sm">
|
|
110
|
-
<FileText className="mr-2 h-4 w-4" />
|
|
111
|
-
{t('actions.history')}
|
|
112
|
-
</Button>
|
|
113
|
-
</SheetTrigger>
|
|
114
|
-
<SheetContent className="flex h-full w-full flex-col overflow-hidden p-0 sm:max-w-xl">
|
|
115
|
-
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
116
|
-
<SheetTitle>{t('history.title')}</SheetTitle>
|
|
117
|
-
<SheetDescription>{cliente}</SheetDescription>
|
|
118
|
-
</SheetHeader>
|
|
119
|
-
<FinanceSheetBody>
|
|
120
|
-
<FinanceSheetSection title={t('history.title')}>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
108
|
+
<SheetTrigger asChild>
|
|
109
|
+
<Button variant="outline" size="sm">
|
|
110
|
+
<FileText className="mr-2 h-4 w-4" />
|
|
111
|
+
{t('actions.history')}
|
|
112
|
+
</Button>
|
|
113
|
+
</SheetTrigger>
|
|
114
|
+
<SheetContent className="flex h-full w-full flex-col overflow-hidden p-0 sm:max-w-xl">
|
|
115
|
+
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
116
|
+
<SheetTitle>{t('history.title')}</SheetTitle>
|
|
117
|
+
<SheetDescription>{cliente}</SheetDescription>
|
|
118
|
+
</SheetHeader>
|
|
119
|
+
<FinanceSheetBody>
|
|
120
|
+
<FinanceSheetSection title={t('history.title')}>
|
|
121
|
+
{historicoContatos.length === 0 ? (
|
|
122
|
+
<div className="rounded-lg border p-4 text-sm text-muted-foreground">
|
|
123
|
+
-
|
|
124
|
+
</div>
|
|
125
|
+
) : (
|
|
126
|
+
historicoContatos.map((contato, i) => (
|
|
127
|
+
<div
|
|
128
|
+
key={`${contato.data}-${i}`}
|
|
129
|
+
className="rounded-lg border p-4"
|
|
130
|
+
>
|
|
131
|
+
<div className="flex items-center justify-between">
|
|
132
|
+
<span className="font-medium">{contato.tipo}</span>
|
|
133
|
+
<span className="text-sm text-muted-foreground">
|
|
134
|
+
{new Date(contato.data).toLocaleString()}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
<p className="mt-2 text-sm">{contato.descricao}</p>
|
|
138
|
+
<p className="mt-1 text-xs text-muted-foreground">
|
|
139
|
+
{t('history.by')} {contato.responsavel}
|
|
140
|
+
</p>
|
|
136
141
|
</div>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
</FinanceSheetSection>
|
|
145
|
-
</FinanceSheetBody>
|
|
146
|
-
</SheetContent>
|
|
147
|
-
</Sheet>
|
|
148
|
-
);
|
|
142
|
+
))
|
|
143
|
+
)}
|
|
144
|
+
</FinanceSheetSection>
|
|
145
|
+
</FinanceSheetBody>
|
|
146
|
+
</SheetContent>
|
|
147
|
+
</Sheet>
|
|
148
|
+
);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
function EnviarCobrancaDialog({
|
|
@@ -198,62 +198,63 @@ function EnviarCobrancaDialog({
|
|
|
198
198
|
{t('actions.collect')}
|
|
199
199
|
</Button>
|
|
200
200
|
</SheetTrigger>
|
|
201
|
-
<SheetContent
|
|
202
|
-
side="right"
|
|
203
|
-
className="flex h-full w-[90vw] flex-col overflow-hidden p-0 sm:max-w-xl"
|
|
204
|
-
>
|
|
205
|
-
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
206
|
-
<SheetTitle>{t('send.title')}</SheetTitle>
|
|
207
|
-
<SheetDescription>
|
|
208
|
-
{t('send.description', { cliente })}
|
|
201
|
+
<SheetContent
|
|
202
|
+
side="right"
|
|
203
|
+
className="flex h-full w-[90vw] flex-col overflow-hidden p-0 sm:max-w-xl"
|
|
204
|
+
>
|
|
205
|
+
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
206
|
+
<SheetTitle>{t('send.title')}</SheetTitle>
|
|
207
|
+
<SheetDescription>
|
|
208
|
+
{t('send.description', { cliente })}
|
|
209
209
|
</SheetDescription>
|
|
210
210
|
</SheetHeader>
|
|
211
|
-
|
|
212
|
-
<Form {...form}>
|
|
213
|
-
<form
|
|
214
|
-
className="flex h-full flex-col overflow-hidden"
|
|
215
|
-
onSubmit={form.handleSubmit(onSubmit)}
|
|
216
|
-
>
|
|
217
|
-
<FinanceSheetBody>
|
|
218
|
-
<FinanceSheetSection
|
|
219
|
-
title={t('send.title')}
|
|
220
|
-
description={t('send.description', { cliente })}
|
|
221
|
-
>
|
|
222
|
-
<FormField
|
|
223
|
-
control={form.control}
|
|
224
|
-
name="message"
|
|
225
|
-
render={({ field }) => (
|
|
226
|
-
<FormItem className="space-y-2">
|
|
227
|
-
<FormLabel>{t('send.message')}</FormLabel>
|
|
228
|
-
<FormControl>
|
|
229
|
-
<RichTextEditor
|
|
230
|
-
className="w-full max-w-full min-w-0 overflow-hidden [&_.ProseMirror]:max-w-full [&_.ProseMirror]:mx-0"
|
|
231
|
-
value={field.value ?? ''}
|
|
232
|
-
onChange={field.onChange}
|
|
233
|
-
/>
|
|
234
|
-
</FormControl>
|
|
235
|
-
<FormMessage />
|
|
236
|
-
</FormItem>
|
|
237
|
-
)}
|
|
238
|
-
/>
|
|
239
|
-
</FinanceSheetSection>
|
|
240
|
-
</FinanceSheetBody>
|
|
241
|
-
|
|
242
|
-
<div className="border-t border-border/50 px-4 py-4 sm:px-6">
|
|
243
|
-
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
|
|
244
|
-
<Button
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
>
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
211
|
+
|
|
212
|
+
<Form {...form}>
|
|
213
|
+
<form
|
|
214
|
+
className="flex h-full flex-col overflow-hidden"
|
|
215
|
+
onSubmit={form.handleSubmit(onSubmit)}
|
|
216
|
+
>
|
|
217
|
+
<FinanceSheetBody>
|
|
218
|
+
<FinanceSheetSection
|
|
219
|
+
title={t('send.title')}
|
|
220
|
+
description={t('send.description', { cliente })}
|
|
221
|
+
>
|
|
222
|
+
<FormField
|
|
223
|
+
control={form.control}
|
|
224
|
+
name="message"
|
|
225
|
+
render={({ field }) => (
|
|
226
|
+
<FormItem className="space-y-2">
|
|
227
|
+
<FormLabel>{t('send.message')}</FormLabel>
|
|
228
|
+
<FormControl>
|
|
229
|
+
<RichTextEditor
|
|
230
|
+
className="w-full max-w-full min-w-0 overflow-hidden [&_.ProseMirror]:max-w-full [&_.ProseMirror]:mx-0"
|
|
231
|
+
value={field.value ?? ''}
|
|
232
|
+
onChange={field.onChange}
|
|
233
|
+
/>
|
|
234
|
+
</FormControl>
|
|
235
|
+
<FormMessage />
|
|
236
|
+
</FormItem>
|
|
237
|
+
)}
|
|
238
|
+
/>
|
|
239
|
+
</FinanceSheetSection>
|
|
240
|
+
</FinanceSheetBody>
|
|
241
|
+
|
|
242
|
+
<div className="border-t border-border/50 px-4 py-4 sm:px-6">
|
|
243
|
+
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
|
|
244
|
+
<Button
|
|
245
|
+
type="button"
|
|
246
|
+
variant="outline"
|
|
247
|
+
onClick={() => setOpen(false)}
|
|
248
|
+
>
|
|
249
|
+
{t('common.cancel')}
|
|
250
|
+
</Button>
|
|
251
|
+
<Button type="submit" disabled={form.formState.isSubmitting}>
|
|
252
|
+
{t('send.submit')}
|
|
253
|
+
</Button>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</form>
|
|
257
|
+
</Form>
|
|
257
258
|
</SheetContent>
|
|
258
259
|
</Sheet>
|
|
259
260
|
);
|
|
@@ -312,115 +313,118 @@ function RegistrarAcordoDialog({
|
|
|
312
313
|
{t('actions.registerAgreement')}
|
|
313
314
|
</Button>
|
|
314
315
|
</SheetTrigger>
|
|
315
|
-
<SheetContent
|
|
316
|
-
side="right"
|
|
317
|
-
className="flex h-full w-[90vw] flex-col overflow-hidden p-0 sm:max-w-xl"
|
|
318
|
-
>
|
|
319
|
-
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
320
|
-
<SheetTitle>{t('agreement.title')}</SheetTitle>
|
|
321
|
-
<SheetDescription>
|
|
322
|
-
{t('agreement.description', { cliente })}
|
|
316
|
+
<SheetContent
|
|
317
|
+
side="right"
|
|
318
|
+
className="flex h-full w-[90vw] flex-col overflow-hidden p-0 sm:max-w-xl"
|
|
319
|
+
>
|
|
320
|
+
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
321
|
+
<SheetTitle>{t('agreement.title')}</SheetTitle>
|
|
322
|
+
<SheetDescription>
|
|
323
|
+
{t('agreement.description', { cliente })}
|
|
323
324
|
</SheetDescription>
|
|
324
325
|
</SheetHeader>
|
|
325
|
-
|
|
326
|
-
<Form {...form}>
|
|
327
|
-
<form
|
|
328
|
-
className="flex h-full flex-col overflow-hidden"
|
|
329
|
-
onSubmit={form.handleSubmit(onSubmit)}
|
|
330
|
-
>
|
|
331
|
-
<FinanceSheetBody>
|
|
332
|
-
<FinanceSheetSection
|
|
333
|
-
title={t('agreement.title')}
|
|
334
|
-
description={t('agreement.description', { cliente })}
|
|
335
|
-
>
|
|
336
|
-
<div className="grid grid-cols-2 gap-4">
|
|
337
|
-
<FormField
|
|
338
|
-
control={form.control}
|
|
339
|
-
name="amount"
|
|
340
|
-
render={({ field }) => (
|
|
341
|
-
<FormItem className="space-y-2">
|
|
342
|
-
<FormLabel>{t('agreement.value')}</FormLabel>
|
|
343
|
-
<FormControl>
|
|
344
|
-
<InputMoney
|
|
345
|
-
placeholder="0,00"
|
|
346
|
-
value={field.value ?? 0}
|
|
347
|
-
onValueChange={(value) =>
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
>
|
|
418
|
-
{t('
|
|
419
|
-
</Button>
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
326
|
+
|
|
327
|
+
<Form {...form}>
|
|
328
|
+
<form
|
|
329
|
+
className="flex h-full flex-col overflow-hidden"
|
|
330
|
+
onSubmit={form.handleSubmit(onSubmit)}
|
|
331
|
+
>
|
|
332
|
+
<FinanceSheetBody>
|
|
333
|
+
<FinanceSheetSection
|
|
334
|
+
title={t('agreement.title')}
|
|
335
|
+
description={t('agreement.description', { cliente })}
|
|
336
|
+
>
|
|
337
|
+
<div className="grid grid-cols-2 gap-4">
|
|
338
|
+
<FormField
|
|
339
|
+
control={form.control}
|
|
340
|
+
name="amount"
|
|
341
|
+
render={({ field }) => (
|
|
342
|
+
<FormItem className="space-y-2">
|
|
343
|
+
<FormLabel>{t('agreement.value')}</FormLabel>
|
|
344
|
+
<FormControl>
|
|
345
|
+
<InputMoney
|
|
346
|
+
placeholder="0,00"
|
|
347
|
+
value={field.value ?? 0}
|
|
348
|
+
onValueChange={(value) =>
|
|
349
|
+
field.onChange(value ?? 0)
|
|
350
|
+
}
|
|
351
|
+
/>
|
|
352
|
+
</FormControl>
|
|
353
|
+
<FormMessage />
|
|
354
|
+
</FormItem>
|
|
355
|
+
)}
|
|
356
|
+
/>
|
|
357
|
+
|
|
358
|
+
<FormField
|
|
359
|
+
control={form.control}
|
|
360
|
+
name="installments"
|
|
361
|
+
render={({ field }) => (
|
|
362
|
+
<FormItem className="space-y-2">
|
|
363
|
+
<FormLabel>{t('agreement.installments')}</FormLabel>
|
|
364
|
+
<FormControl>
|
|
365
|
+
<Input
|
|
366
|
+
type="number"
|
|
367
|
+
min={1}
|
|
368
|
+
max={120}
|
|
369
|
+
value={field.value}
|
|
370
|
+
onChange={field.onChange}
|
|
371
|
+
/>
|
|
372
|
+
</FormControl>
|
|
373
|
+
<FormMessage />
|
|
374
|
+
</FormItem>
|
|
375
|
+
)}
|
|
376
|
+
/>
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
<FormField
|
|
380
|
+
control={form.control}
|
|
381
|
+
name="first_due_date"
|
|
382
|
+
render={({ field }) => (
|
|
383
|
+
<FormItem className="space-y-2">
|
|
384
|
+
<FormLabel>{t('agreement.firstDueDate')}</FormLabel>
|
|
385
|
+
<FormControl>
|
|
386
|
+
<Input type="date" {...field} />
|
|
387
|
+
</FormControl>
|
|
388
|
+
<FormMessage />
|
|
389
|
+
</FormItem>
|
|
390
|
+
)}
|
|
391
|
+
/>
|
|
392
|
+
|
|
393
|
+
<FormField
|
|
394
|
+
control={form.control}
|
|
395
|
+
name="notes"
|
|
396
|
+
render={({ field }) => (
|
|
397
|
+
<FormItem className="space-y-2">
|
|
398
|
+
<FormLabel>{t('agreement.notes')}</FormLabel>
|
|
399
|
+
<FormControl>
|
|
400
|
+
<Textarea
|
|
401
|
+
placeholder={t('agreement.notesPlaceholder')}
|
|
402
|
+
{...field}
|
|
403
|
+
/>
|
|
404
|
+
</FormControl>
|
|
405
|
+
<FormMessage />
|
|
406
|
+
</FormItem>
|
|
407
|
+
)}
|
|
408
|
+
/>
|
|
409
|
+
</FinanceSheetSection>
|
|
410
|
+
</FinanceSheetBody>
|
|
411
|
+
|
|
412
|
+
<div className="border-t border-border/50 px-4 py-4 sm:px-6">
|
|
413
|
+
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
|
|
414
|
+
<Button
|
|
415
|
+
type="button"
|
|
416
|
+
variant="outline"
|
|
417
|
+
onClick={() => setOpen(false)}
|
|
418
|
+
>
|
|
419
|
+
{t('common.cancel')}
|
|
420
|
+
</Button>
|
|
421
|
+
<Button type="submit" disabled={form.formState.isSubmitting}>
|
|
422
|
+
{t('agreement.submit')}
|
|
423
|
+
</Button>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
</form>
|
|
427
|
+
</Form>
|
|
424
428
|
</SheetContent>
|
|
425
429
|
</Sheet>
|
|
426
430
|
);
|
|
@@ -480,39 +484,39 @@ export default function CobrancaPage() {
|
|
|
480
484
|
},
|
|
481
485
|
];
|
|
482
486
|
|
|
483
|
-
const totalInadimplencia = agingInadimplencia.reduce(
|
|
484
|
-
(acc, c) => acc + c.total,
|
|
485
|
-
0
|
|
486
|
-
);
|
|
487
|
-
const totalClientes = agingInadimplencia.length;
|
|
488
|
-
const summaryCards = [
|
|
489
|
-
{
|
|
490
|
-
key: 'default',
|
|
491
|
-
title: t('cards.totalDefault'),
|
|
492
|
-
value: <Money value={totalInadimplencia} />,
|
|
493
|
-
icon: AlertTriangle,
|
|
494
|
-
layout: 'compact' as const,
|
|
495
|
-
iconContainerClassName: 'bg-red-500/10 text-red-700',
|
|
496
|
-
accentClassName: 'from-red-500/20 via-orange-500/10 to-transparent',
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
key: 'clients',
|
|
500
|
-
title: t('cards.lateClients'),
|
|
501
|
-
value: totalClientes,
|
|
502
|
-
icon: FileText,
|
|
503
|
-
layout: 'compact' as const,
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
key: 'delay',
|
|
507
|
-
title: t('cards.maxDelay'),
|
|
508
|
-
value: t('cards.maxDelayValue'),
|
|
509
|
-
icon: AlertTriangle,
|
|
510
|
-
layout: 'compact' as const,
|
|
511
|
-
valueClassName: 'text-destructive',
|
|
512
|
-
iconContainerClassName: 'bg-orange-500/10 text-orange-700',
|
|
513
|
-
accentClassName: 'from-orange-500/20 via-amber-500/10 to-transparent',
|
|
514
|
-
},
|
|
515
|
-
];
|
|
487
|
+
const totalInadimplencia = agingInadimplencia.reduce(
|
|
488
|
+
(acc, c) => acc + c.total,
|
|
489
|
+
0
|
|
490
|
+
);
|
|
491
|
+
const totalClientes = agingInadimplencia.length;
|
|
492
|
+
const summaryCards = [
|
|
493
|
+
{
|
|
494
|
+
key: 'default',
|
|
495
|
+
title: t('cards.totalDefault'),
|
|
496
|
+
value: <Money value={totalInadimplencia} />,
|
|
497
|
+
icon: AlertTriangle,
|
|
498
|
+
layout: 'compact' as const,
|
|
499
|
+
iconContainerClassName: 'bg-red-500/10 text-red-700',
|
|
500
|
+
accentClassName: 'from-red-500/20 via-orange-500/10 to-transparent',
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
key: 'clients',
|
|
504
|
+
title: t('cards.lateClients'),
|
|
505
|
+
value: totalClientes,
|
|
506
|
+
icon: FileText,
|
|
507
|
+
layout: 'compact' as const,
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
key: 'delay',
|
|
511
|
+
title: t('cards.maxDelay'),
|
|
512
|
+
value: t('cards.maxDelayValue'),
|
|
513
|
+
icon: AlertTriangle,
|
|
514
|
+
layout: 'compact' as const,
|
|
515
|
+
valueClassName: 'text-destructive',
|
|
516
|
+
iconContainerClassName: 'bg-orange-500/10 text-orange-700',
|
|
517
|
+
accentClassName: 'from-orange-500/20 via-amber-500/10 to-transparent',
|
|
518
|
+
},
|
|
519
|
+
];
|
|
516
520
|
|
|
517
521
|
return (
|
|
518
522
|
<Page>
|
|
@@ -526,50 +530,47 @@ export default function CobrancaPage() {
|
|
|
526
530
|
]}
|
|
527
531
|
/>
|
|
528
532
|
|
|
529
|
-
<KpiCardsGrid items={summaryCards} columns={3} />
|
|
530
|
-
|
|
531
|
-
<FinancePageSection
|
|
532
|
-
title={t('aging.title')}
|
|
533
|
-
description={t('aging.description')}
|
|
534
|
-
contentClassName="p-4 sm:p-6"
|
|
535
|
-
>
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
<Table className="min-w-[980px]">
|
|
571
|
-
<TableHeader>
|
|
572
|
-
<TableRow>
|
|
533
|
+
<KpiCardsGrid items={summaryCards} columns={3} />
|
|
534
|
+
|
|
535
|
+
<FinancePageSection
|
|
536
|
+
title={t('aging.title')}
|
|
537
|
+
description={t('aging.description')}
|
|
538
|
+
contentClassName="p-4 sm:p-6"
|
|
539
|
+
>
|
|
540
|
+
<ResponsiveContainer width="100%" height={250}>
|
|
541
|
+
<BarChart data={chartData}>
|
|
542
|
+
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
|
|
543
|
+
<XAxis dataKey="name" tick={{ fontSize: 12 }} />
|
|
544
|
+
<YAxis
|
|
545
|
+
tick={{ fontSize: 12 }}
|
|
546
|
+
tickFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
|
|
547
|
+
/>
|
|
548
|
+
<Tooltip
|
|
549
|
+
formatter={(value: number) => formatarMoeda(value)}
|
|
550
|
+
contentStyle={{
|
|
551
|
+
backgroundColor: 'var(--background)',
|
|
552
|
+
border: '1px solid var(--border)',
|
|
553
|
+
borderRadius: '8px',
|
|
554
|
+
color: 'var(--foreground)',
|
|
555
|
+
}}
|
|
556
|
+
labelStyle={{ color: 'var(--foreground)' }}
|
|
557
|
+
itemStyle={{ color: 'var(--foreground)' }}
|
|
558
|
+
/>
|
|
559
|
+
<Bar dataKey="valor" radius={[4, 4, 0, 0]} fill="var(--primary)" />
|
|
560
|
+
</BarChart>
|
|
561
|
+
</ResponsiveContainer>
|
|
562
|
+
</FinancePageSection>
|
|
563
|
+
|
|
564
|
+
<FinancePageSection
|
|
565
|
+
variant="flat"
|
|
566
|
+
title={t('table.title')}
|
|
567
|
+
description={t('table.description')}
|
|
568
|
+
>
|
|
569
|
+
{agingInadimplencia.length > 0 ? (
|
|
570
|
+
<div className="overflow-x-auto">
|
|
571
|
+
<Table className="min-w-245">
|
|
572
|
+
<TableHeader>
|
|
573
|
+
<TableRow>
|
|
573
574
|
<TableHead>{t('table.headers.client')}</TableHead>
|
|
574
575
|
<TableHead className="text-right">
|
|
575
576
|
{t('table.headers.range0to30')}
|
|
@@ -590,13 +591,13 @@ export default function CobrancaPage() {
|
|
|
590
591
|
{t('table.headers.actions')}
|
|
591
592
|
</TableHead>
|
|
592
593
|
</TableRow>
|
|
593
|
-
</TableHeader>
|
|
594
|
-
<TableBody>
|
|
595
|
-
{agingInadimplencia.map((item) => (
|
|
596
|
-
<TableRow key={item.clienteId} className="hover:bg-muted/30">
|
|
597
|
-
<TableCell className="font-medium">
|
|
598
|
-
{item.cliente}
|
|
599
|
-
</TableCell>
|
|
594
|
+
</TableHeader>
|
|
595
|
+
<TableBody>
|
|
596
|
+
{agingInadimplencia.map((item) => (
|
|
597
|
+
<TableRow key={item.clienteId} className="hover:bg-muted/30">
|
|
598
|
+
<TableCell className="font-medium">
|
|
599
|
+
{item.cliente}
|
|
600
|
+
</TableCell>
|
|
600
601
|
<TableCell className="text-right">
|
|
601
602
|
{item.bucket0_30 > 0 ? (
|
|
602
603
|
<Money value={item.bucket0_30} />
|
|
@@ -654,24 +655,22 @@ export default function CobrancaPage() {
|
|
|
654
655
|
</div>
|
|
655
656
|
</TableCell>
|
|
656
657
|
</TableRow>
|
|
657
|
-
))}
|
|
658
|
-
</TableBody>
|
|
659
|
-
</Table>
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
);
|
|
677
|
-
}
|
|
658
|
+
))}
|
|
659
|
+
</TableBody>
|
|
660
|
+
</Table>
|
|
661
|
+
</div>
|
|
662
|
+
) : (
|
|
663
|
+
<EmptyState
|
|
664
|
+
icon={<FileText className="h-12 w-12" />}
|
|
665
|
+
title={t('empty.title')}
|
|
666
|
+
description={t('empty.description')}
|
|
667
|
+
actionLabel={t('empty.action')}
|
|
668
|
+
onAction={() => {
|
|
669
|
+
void refetch();
|
|
670
|
+
}}
|
|
671
|
+
/>
|
|
672
|
+
)}
|
|
673
|
+
</FinancePageSection>
|
|
674
|
+
</Page>
|
|
675
|
+
);
|
|
676
|
+
}
|