@hed-hog/finance 0.0.329 → 0.0.331

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 (24) hide show
  1. package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +18 -15
  2. package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +10 -18
  3. package/hedhog/frontend/app/accounts-receivable/collections-default/page.tsx.ejs +4 -8
  4. package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +2 -2
  5. package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +16 -24
  6. package/hedhog/frontend/app/administration/audit-logs/page.tsx.ejs +22 -11
  7. package/hedhog/frontend/app/administration/categories/page.tsx.ejs +3 -5
  8. package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +3 -5
  9. package/hedhog/frontend/app/administration/currencies/page.tsx.ejs +3 -5
  10. package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +12 -9
  11. package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +49 -73
  12. package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +7 -9
  13. package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +98 -74
  14. package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +33 -25
  15. package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +2 -2
  16. package/hedhog/frontend/app/reports/actual-vs-forecast/page.tsx.ejs +3 -1
  17. package/hedhog/frontend/app/reports/aging-default/page.tsx.ejs +3 -1
  18. package/hedhog/frontend/app/reports/cash-position/page.tsx.ejs +3 -1
  19. package/hedhog/frontend/app/reports/overview-results/page.tsx.ejs +15 -8
  20. package/hedhog/frontend/app/reports/top-customers/page.tsx.ejs +9 -5
  21. package/hedhog/frontend/app/reports/top-operational-expenses/page.tsx.ejs +9 -5
  22. package/hedhog/frontend/messages/en.json +114 -3
  23. package/hedhog/frontend/messages/pt.json +99 -3
  24. package/package.json +5 -5
@@ -131,10 +131,9 @@ export default function AprovacoesPage() {
131
131
  const { request, showToastHandler } = useApp();
132
132
  const [page, setPage] = useState(1);
133
133
  const pageSize = 10;
134
- const {
135
- data: approvalsResponse,
136
- refetch,
137
- } = useQuery<PaginatedResponse<ApprovalTitle>>({
134
+ const { data: approvalsResponse, refetch } = useQuery<
135
+ PaginatedResponse<ApprovalTitle>
136
+ >({
138
137
  queryKey: ['finance-payable-approvals', page, pageSize],
139
138
  queryFn: async () => {
140
139
  const response = await request({
@@ -165,7 +164,7 @@ export default function AprovacoesPage() {
165
164
 
166
165
  const handleAprovacao = async (_id: string, tituloId?: string) => {
167
166
  if (!tituloId) {
168
- showToastHandler?.('error', 'Título inválido para aprovação');
167
+ showToastHandler?.('error', t('messages.invalidTitleForApproval'));
169
168
  return;
170
169
  }
171
170
 
@@ -176,9 +175,9 @@ export default function AprovacoesPage() {
176
175
  });
177
176
 
178
177
  await refetch();
179
- showToastHandler?.('success', 'Título aprovado com sucesso');
178
+ showToastHandler?.('success', t('messages.approveSuccess'));
180
179
  } catch {
181
- showToastHandler?.('error', 'Não foi possível aprovar o título');
180
+ showToastHandler?.('error', t('messages.approveError'));
182
181
  }
183
182
  };
184
183
 
@@ -188,7 +187,7 @@ export default function AprovacoesPage() {
188
187
  reason?: string
189
188
  ) => {
190
189
  if (!tituloId) {
191
- showToastHandler?.('error', 'Título inválido para reprovação');
190
+ showToastHandler?.('error', t('messages.invalidTitleForRejection'));
192
191
  return;
193
192
  }
194
193
 
@@ -202,9 +201,9 @@ export default function AprovacoesPage() {
202
201
  });
203
202
 
204
203
  await refetch();
205
- showToastHandler?.('success', 'Título reprovado com sucesso');
204
+ showToastHandler?.('success', t('messages.rejectSuccess'));
206
205
  } catch {
207
- showToastHandler?.('error', 'Não foi possível reprovar o título');
206
+ showToastHandler?.('error', t('messages.rejectError'));
208
207
  }
209
208
  };
210
209
 
@@ -316,21 +315,25 @@ export default function AprovacoesPage() {
316
315
  {urgencia.label}
317
316
  </Badge>
318
317
  </TableCell>
319
- <TableCell>
320
- {formatarData(aprovacao.criadoEm)}
321
- </TableCell>
318
+ <TableCell>{formatarData(aprovacao.criadoEm)}</TableCell>
322
319
  <TableCell>
323
320
  <div className="flex justify-end gap-2">
324
321
  <AprovacaoDialog
325
322
  tipo="aprovar"
326
323
  t={t}
327
- onConfirm={() => void handleAprovacao(aprovacao.id, aprovacao.id)}
324
+ onConfirm={() =>
325
+ void handleAprovacao(aprovacao.id, aprovacao.id)
326
+ }
328
327
  />
329
328
  <AprovacaoDialog
330
329
  tipo="reprovar"
331
330
  t={t}
332
331
  onConfirm={(comment) =>
333
- void handleReprovacao(aprovacao.id, aprovacao.id, comment)
332
+ void handleReprovacao(
333
+ aprovacao.id,
334
+ aprovacao.id,
335
+ comment
336
+ )
334
337
  }
335
338
  />
336
339
  </div>
@@ -1,12 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
4
- import {
5
- CategoryPickerField,
6
- } from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
7
- import {
8
- CostCenterPickerField,
9
- } from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
4
+ import { CategoryPickerField } from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
5
+ import { CostCenterPickerField } from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
10
6
  import {
11
7
  FinancePageSection,
12
8
  FinanceSheetBody,
@@ -446,10 +442,8 @@ function NovoTituloSheet({
446
442
  currentLocaleCode
447
443
  );
448
444
 
449
- return currentLocaleCode.startsWith('pt')
450
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
451
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
452
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
445
+ return t('draftStatus', { relativeLabel, absoluteLabel });
446
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
453
447
 
454
448
  const watchedInstallmentsCount = form.watch('installmentsCount');
455
449
  const watchedTotalValue = form.watch('valor');
@@ -774,7 +768,7 @@ function NovoTituloSheet({
774
768
  }
775
769
 
776
770
  if (extracted.descricao) {
777
- form.setValue('descricao', extracted.descricao, {
771
+ form.setValue('descricao', extracted.descricao, {
778
772
  shouldValidate: true,
779
773
  });
780
774
  }
@@ -1290,7 +1284,7 @@ function NovoTituloSheet({
1290
1284
  >
1291
1285
  <FormField
1292
1286
  control={form.control}
1293
- name="descricao"
1287
+ name="descricao"
1294
1288
  render={({ field }) => (
1295
1289
  <FormItem>
1296
1290
  <FormLabel>{t('fields.description')}</FormLabel>
@@ -1505,10 +1499,8 @@ function EditarTituloSheet({
1505
1499
  currentLocaleCode
1506
1500
  );
1507
1501
 
1508
- return currentLocaleCode.startsWith('pt')
1509
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
1510
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
1511
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
1502
+ return t('draftStatus', { relativeLabel, absoluteLabel });
1503
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
1512
1504
 
1513
1505
  const watchedInstallmentsCount = form.watch('installmentsCount');
1514
1506
  const watchedTotalValue = form.watch('valor');
@@ -1893,7 +1885,7 @@ function EditarTituloSheet({
1893
1885
  }
1894
1886
 
1895
1887
  if (extracted.descricao) {
1896
- form.setValue('descricao', extracted.descricao, {
1888
+ form.setValue('descricao', extracted.descricao, {
1897
1889
  shouldValidate: true,
1898
1890
  });
1899
1891
  }
@@ -2407,7 +2399,7 @@ function EditarTituloSheet({
2407
2399
  >
2408
2400
  <FormField
2409
2401
  control={form.control}
2410
- name="descricao"
2402
+ name="descricao"
2411
2403
  render={({ field }) => (
2412
2404
  <FormItem>
2413
2405
  <FormLabel>{t('fields.description')}</FormLabel>
@@ -232,10 +232,8 @@ function EnviarCobrancaDialog({
232
232
  currentLocaleCode
233
233
  );
234
234
 
235
- return currentLocaleCode.startsWith('pt')
236
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
237
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
238
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
235
+ return t('draftStatus', { relativeLabel, absoluteLabel });
236
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
239
237
 
240
238
  useEffect(() => {
241
239
  if (!open) {
@@ -425,10 +423,8 @@ function RegistrarAcordoDialog({
425
423
  currentLocaleCode
426
424
  );
427
425
 
428
- return currentLocaleCode.startsWith('pt')
429
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
430
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
431
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
426
+ return t('draftStatus', { relativeLabel, absoluteLabel });
427
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
432
428
 
433
429
  useEffect(() => {
434
430
  if (!open) {
@@ -186,11 +186,11 @@ export default function TituloReceberDetalhePage() {
186
186
  className: 'bg-orange-100 text-orange-700',
187
187
  },
188
188
  debito_automatico: {
189
- label: 'D\u00e9bito autom\u00e1tico',
189
+ label: t('channels.debitAutomatico'),
190
190
  className: 'bg-emerald-100 text-emerald-700',
191
191
  },
192
192
  debito_em_conta: {
193
- label: 'D\u00e9bito em conta',
193
+ label: t('channels.debitEmConta'),
194
194
  className: 'bg-cyan-100 text-cyan-700',
195
195
  },
196
196
  };
@@ -1,12 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
4
- import {
5
- CategoryPickerField,
6
- } from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
7
- import {
8
- CostCenterPickerField,
9
- } from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
4
+ import { CategoryPickerField } from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
5
+ import { CostCenterPickerField } from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
10
6
  import {
11
7
  FinancePageSection,
12
8
  FinanceSheetBody,
@@ -426,10 +422,8 @@ function NovoTituloSheet({
426
422
  currentLocaleCode
427
423
  );
428
424
 
429
- return currentLocaleCode.startsWith('pt')
430
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
431
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
432
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
425
+ return t('draftStatus', { relativeLabel, absoluteLabel });
426
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
433
427
 
434
428
  const watchedInstallmentsCount = form.watch('installmentsCount');
435
429
  const watchedTotalValue = form.watch('valor');
@@ -754,7 +748,7 @@ function NovoTituloSheet({
754
748
  }
755
749
 
756
750
  if (extracted.descricao) {
757
- form.setValue('descricao', extracted.descricao, {
751
+ form.setValue('descricao', extracted.descricao, {
758
752
  shouldValidate: true,
759
753
  });
760
754
  }
@@ -1242,10 +1236,10 @@ function NovoTituloSheet({
1242
1236
  {t('channels.transfer')}
1243
1237
  </SelectItem>
1244
1238
  <SelectItem value="debito_automatico">
1245
- D&#233;bito autom&#225;tico
1239
+ {t('channels.debitAutomatico')}
1246
1240
  </SelectItem>
1247
1241
  <SelectItem value="debito_em_conta">
1248
- D&#233;bito em conta
1242
+ {t('channels.debitEmConta')}
1249
1243
  </SelectItem>
1250
1244
  </SelectContent>
1251
1245
  </Select>
@@ -1262,7 +1256,7 @@ function NovoTituloSheet({
1262
1256
  >
1263
1257
  <FormField
1264
1258
  control={form.control}
1265
- name="descricao"
1259
+ name="descricao"
1266
1260
  render={({ field }) => (
1267
1261
  <FormItem>
1268
1262
  <FormLabel>{t('fields.description')}</FormLabel>
@@ -1475,10 +1469,8 @@ function EditarTituloSheet({
1475
1469
  currentLocaleCode
1476
1470
  );
1477
1471
 
1478
- return currentLocaleCode.startsWith('pt')
1479
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
1480
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
1481
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
1472
+ return t('draftStatus', { relativeLabel, absoluteLabel });
1473
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
1482
1474
 
1483
1475
  const watchedInstallmentsCount = form.watch('installmentsCount');
1484
1476
  const watchedTotalValue = form.watch('valor');
@@ -1815,7 +1807,7 @@ function EditarTituloSheet({
1815
1807
  }
1816
1808
 
1817
1809
  if (extracted.descricao) {
1818
- form.setValue('descricao', extracted.descricao, {
1810
+ form.setValue('descricao', extracted.descricao, {
1819
1811
  shouldValidate: true,
1820
1812
  });
1821
1813
  }
@@ -2350,10 +2342,10 @@ function EditarTituloSheet({
2350
2342
  {t('channels.transfer')}
2351
2343
  </SelectItem>
2352
2344
  <SelectItem value="debito_automatico">
2353
- D&#233;bito autom&#225;tico
2345
+ {t('channels.debitAutomatico')}
2354
2346
  </SelectItem>
2355
2347
  <SelectItem value="debito_em_conta">
2356
- D&#233;bito em conta
2348
+ {t('channels.debitEmConta')}
2357
2349
  </SelectItem>
2358
2350
  </SelectContent>
2359
2351
  </Select>
@@ -2370,7 +2362,7 @@ function EditarTituloSheet({
2370
2362
  >
2371
2363
  <FormField
2372
2364
  control={form.control}
2373
- name="descricao"
2365
+ name="descricao"
2374
2366
  render={({ field }) => (
2375
2367
  <FormItem>
2376
2368
  <FormLabel>{t('fields.description')}</FormLabel>
@@ -2742,7 +2734,7 @@ export default function TitulosReceberPage() {
2742
2734
  <FinancePageSection variant="flat">
2743
2735
  {titulosReceber.length > 0 ? (
2744
2736
  <div className="overflow-x-auto">
2745
- <Table className="min-w-[760px]">
2737
+ <Table className="min-w-190">
2746
2738
  <TableHeader>
2747
2739
  <TableRow>
2748
2740
  <TableHead>{t('table.headers.document')}</TableHead>
@@ -2754,7 +2746,7 @@ export default function TitulosReceberPage() {
2754
2746
  </TableHead>
2755
2747
  <TableHead>{t('table.headers.channel')}</TableHead>
2756
2748
  <TableHead>{t('table.headers.status')}</TableHead>
2757
- <TableHead className="w-[50px]" />
2749
+ <TableHead className="w-12.5" />
2758
2750
  </TableRow>
2759
2751
  </TableHeader>
2760
2752
  <TableBody>
@@ -4,6 +4,7 @@ import { Page, PageHeader, PaginationFooter } from '@/components/entity-list';
4
4
  import { Badge } from '@/components/ui/badge';
5
5
  import { Button } from '@/components/ui/button';
6
6
  import { Input } from '@/components/ui/input';
7
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
7
8
  import {
8
9
  Select,
9
10
  SelectContent,
@@ -52,7 +53,11 @@ export default function AuditLogsPage() {
52
53
  const { request } = useApp();
53
54
 
54
55
  const [page, setPage] = useState(1);
55
- const [pageSize, setPageSize] = useState(10);
56
+ const [pageSize, setPageSize] = usePersistedPageSize({
57
+ storageKey: 'pagination:finance-audit-logs:pageSize',
58
+ defaultValue: 10,
59
+ allowedValues: [10, 20, 30, 40, 50],
60
+ });
56
61
  const [search, setSearch] = useState('');
57
62
  const [action, setAction] = useState('all');
58
63
  const [entityTable, setEntityTable] = useState('all');
@@ -125,7 +130,7 @@ export default function AuditLogsPage() {
125
130
  />
126
131
 
127
132
  <div className="flex flex-col gap-4 xl:flex-row xl:flex-wrap xl:items-center">
128
- <div className="relative min-w-[260px] flex-1">
133
+ <div className="relative min-w-65 flex-1">
129
134
  <Search className="pointer-events-none absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
130
135
  <Input
131
136
  placeholder={t('filters.searchPlaceholder')}
@@ -145,14 +150,20 @@ export default function AuditLogsPage() {
145
150
  setPage(1);
146
151
  }}
147
152
  >
148
- <SelectTrigger className="w-full sm:w-[180px]">
153
+ <SelectTrigger className="w-full sm:w-45">
149
154
  <SelectValue placeholder={t('filters.action')} />
150
155
  </SelectTrigger>
151
156
  <SelectContent>
152
157
  <SelectItem value="all">{t('filters.allActions')}</SelectItem>
153
- <SelectItem value="create">create</SelectItem>
154
- <SelectItem value="update">update</SelectItem>
155
- <SelectItem value="delete">delete</SelectItem>
158
+ <SelectItem value="create">
159
+ {t('filters.actionOptions.create')}
160
+ </SelectItem>
161
+ <SelectItem value="update">
162
+ {t('filters.actionOptions.update')}
163
+ </SelectItem>
164
+ <SelectItem value="delete">
165
+ {t('filters.actionOptions.delete')}
166
+ </SelectItem>
156
167
  </SelectContent>
157
168
  </Select>
158
169
 
@@ -163,7 +174,7 @@ export default function AuditLogsPage() {
163
174
  setActorUserId(event.target.value);
164
175
  setPage(1);
165
176
  }}
166
- className="w-full sm:w-[220px]"
177
+ className="w-full sm:w-55"
167
178
  />
168
179
 
169
180
  <Select
@@ -173,7 +184,7 @@ export default function AuditLogsPage() {
173
184
  setPage(1);
174
185
  }}
175
186
  >
176
- <SelectTrigger className="w-full sm:w-[180px]">
187
+ <SelectTrigger className="w-full sm:w-45">
177
188
  <SelectValue placeholder={t('filters.entity')} />
178
189
  </SelectTrigger>
179
190
  <SelectContent>
@@ -192,7 +203,7 @@ export default function AuditLogsPage() {
192
203
  setFrom(event.target.value);
193
204
  setPage(1);
194
205
  }}
195
- className="w-full sm:w-[220px]"
206
+ className="w-full sm:w-55"
196
207
  />
197
208
 
198
209
  <Input
@@ -202,7 +213,7 @@ export default function AuditLogsPage() {
202
213
  setTo(event.target.value);
203
214
  setPage(1);
204
215
  }}
205
- className="w-full sm:w-[220px]"
216
+ className="w-full sm:w-55"
206
217
  />
207
218
 
208
219
  <Button
@@ -234,7 +245,7 @@ export default function AuditLogsPage() {
234
245
  <TableHead>{t('table.headers.entity')}</TableHead>
235
246
  <TableHead>{t('table.headers.record')}</TableHead>
236
247
  <TableHead>{t('table.headers.summary')}</TableHead>
237
- <TableHead>IP</TableHead>
248
+ <TableHead>{t('table.headers.ip')}</TableHead>
238
249
  </TableRow>
239
250
  </TableHeader>
240
251
  <TableBody>
@@ -214,10 +214,8 @@ function CategoriaSheet({
214
214
  currentLocaleCode
215
215
  );
216
216
 
217
- return currentLocaleCode.startsWith('pt')
218
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
219
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
220
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
217
+ return t('draftStatus', { relativeLabel, absoluteLabel });
218
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
221
219
 
222
220
  useEffect(() => {
223
221
  if (!open) {
@@ -300,7 +298,7 @@ function CategoriaSheet({
300
298
 
301
299
  return (
302
300
  <Sheet open={open} onOpenChange={handleOpenChange}>
303
- <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
301
+ <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
304
302
  <SheetHeader>
305
303
  <SheetTitle>
306
304
  {editing ? t('sheet.editTitle') : t('sheet.newTitle')}
@@ -133,10 +133,8 @@ function CentroCustoSheet({
133
133
  currentLocaleCode
134
134
  );
135
135
 
136
- return currentLocaleCode.startsWith('pt')
137
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
138
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
139
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
136
+ return t('draftStatus', { relativeLabel, absoluteLabel });
137
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
140
138
 
141
139
  useEffect(() => {
142
140
  if (!open) {
@@ -216,7 +214,7 @@ function CentroCustoSheet({
216
214
 
217
215
  return (
218
216
  <Sheet open={open} onOpenChange={handleOpenChange}>
219
- <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
217
+ <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
220
218
  <SheetHeader>
221
219
  <SheetTitle>
222
220
  {editingCostCenter ? t('sheet.editTitle') : t('sheet.newTitle')}
@@ -141,10 +141,8 @@ function CurrencySheet({
141
141
  getSettingValue,
142
142
  currentLocaleCode
143
143
  );
144
- return currentLocaleCode.startsWith('pt')
145
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
146
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
147
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
144
+ return t('draftStatus', { relativeLabel, absoluteLabel });
145
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
148
146
 
149
147
  useEffect(() => {
150
148
  if (!open) return;
@@ -225,7 +223,7 @@ function CurrencySheet({
225
223
 
226
224
  return (
227
225
  <Sheet open={open} onOpenChange={handleOpenChange}>
228
- <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
226
+ <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
229
227
  <SheetHeader>
230
228
  <SheetTitle>
231
229
  {editingCurrency ? t('sheet.editTitle') : t('sheet.newTitle')}
@@ -35,6 +35,7 @@ import {
35
35
  TableRow,
36
36
  } from '@/components/ui/table';
37
37
  import { useFormDraft } from '@/hooks/use-form-draft';
38
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
38
39
  import { formatDateTime } from '@/lib/format-date';
39
40
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
40
41
  import { zodResolver } from '@hookform/resolvers/zod';
@@ -160,10 +161,8 @@ function ClosePeriodSheet({
160
161
  currentLocaleCode
161
162
  );
162
163
 
163
- return currentLocaleCode.startsWith('pt')
164
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
165
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
166
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
164
+ return t('draftStatus', { relativeLabel, absoluteLabel });
165
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
167
166
 
168
167
  useEffect(() => {
169
168
  if (!open) {
@@ -212,7 +211,7 @@ function ClosePeriodSheet({
212
211
  onOpenChange(nextOpen);
213
212
  }}
214
213
  >
215
- <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
214
+ <SheetContent className="w-full overflow-y-auto sm:max-w-lg">
216
215
  <SheetHeader>
217
216
  <SheetTitle>{t('sheet.title')}</SheetTitle>
218
217
  <SheetDescription>{t('sheet.description')}</SheetDescription>
@@ -326,7 +325,11 @@ export default function PeriodClosePage() {
326
325
 
327
326
  const [sheetOpen, setSheetOpen] = useState(false);
328
327
  const [page, setPage] = useState(1);
329
- const [pageSize, setPageSize] = useState(10);
328
+ const [pageSize, setPageSize] = usePersistedPageSize({
329
+ storageKey: 'pagination:finance-period-close:pageSize',
330
+ defaultValue: 10,
331
+ allowedValues: [10, 20, 30, 40, 50],
332
+ });
330
333
  const [search, setSearch] = useState('');
331
334
  const [status, setStatus] = useState('all');
332
335
  const [user, setUser] = useState('');
@@ -434,7 +437,7 @@ export default function PeriodClosePage() {
434
437
  setUser(event.target.value);
435
438
  setPage(1);
436
439
  }}
437
- className="w-full sm:w-[220px]"
440
+ className="w-full sm:w-55"
438
441
  />
439
442
 
440
443
  <Input
@@ -444,7 +447,7 @@ export default function PeriodClosePage() {
444
447
  setFrom(event.target.value);
445
448
  setPage(1);
446
449
  }}
447
- className="w-full sm:w-[220px]"
450
+ className="w-full sm:w-55"
448
451
  />
449
452
 
450
453
  <Input
@@ -454,7 +457,7 @@ export default function PeriodClosePage() {
454
457
  setTo(event.target.value);
455
458
  setPage(1);
456
459
  }}
457
- className="w-full sm:w-[220px]"
460
+ className="w-full sm:w-55"
458
461
  />
459
462
 
460
463
  <Button