@hed-hog/finance 0.0.328 → 0.0.330

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 (27) hide show
  1. package/hedhog/frontend/app/_components/category-picker-field.tsx.ejs +3 -0
  2. package/hedhog/frontend/app/_components/cost-center-picker-field.tsx.ejs +3 -0
  3. package/hedhog/frontend/app/_components/finance-entity-field-with-create.tsx.ejs +9 -4
  4. package/hedhog/frontend/app/_components/finance-picker.tsx.ejs +242 -0
  5. package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +18 -15
  6. package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +13 -19
  7. package/hedhog/frontend/app/accounts-receivable/collections-default/page.tsx.ejs +4 -8
  8. package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +13 -19
  9. package/hedhog/frontend/app/administration/audit-logs/page.tsx.ejs +10 -4
  10. package/hedhog/frontend/app/administration/categories/page.tsx.ejs +3 -5
  11. package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +3 -5
  12. package/hedhog/frontend/app/administration/currencies/page.tsx.ejs +3 -5
  13. package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +3 -5
  14. package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +48 -72
  15. package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +7 -9
  16. package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +91 -73
  17. package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +33 -25
  18. package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +2 -2
  19. package/hedhog/frontend/app/reports/actual-vs-forecast/page.tsx.ejs +3 -1
  20. package/hedhog/frontend/app/reports/aging-default/page.tsx.ejs +3 -1
  21. package/hedhog/frontend/app/reports/cash-position/page.tsx.ejs +3 -1
  22. package/hedhog/frontend/app/reports/overview-results/page.tsx.ejs +15 -8
  23. package/hedhog/frontend/app/reports/top-customers/page.tsx.ejs +9 -5
  24. package/hedhog/frontend/app/reports/top-operational-expenses/page.tsx.ejs +9 -5
  25. package/hedhog/frontend/messages/en.json +110 -2
  26. package/hedhog/frontend/messages/pt.json +92 -2
  27. package/package.json +4 -4
@@ -0,0 +1,3 @@
1
+ 'use client';
2
+
3
+ export { CategoryPickerField, type FinanceCategory } from './finance-picker';
@@ -0,0 +1,3 @@
1
+ 'use client';
2
+
3
+ export { CostCenterPickerField, type CostCenter } from './finance-picker';
@@ -6,14 +6,14 @@ import { useTranslations } from 'next-intl';
6
6
  import { useMemo, useState } from 'react';
7
7
  import { FieldValues, Path, UseFormReturn } from 'react-hook-form';
8
8
 
9
- type FinanceCategory = {
9
+ export type FinanceCategory = {
10
10
  id: number | string;
11
11
  codigo?: string;
12
12
  nome: string;
13
13
  natureza?: string;
14
14
  };
15
15
 
16
- type CostCenter = {
16
+ export type CostCenter = {
17
17
  id: number | string;
18
18
  codigo?: string;
19
19
  nome: string;
@@ -44,7 +44,7 @@ const extractCreatedId = (
44
44
  return String(id);
45
45
  };
46
46
 
47
- export function CategoryFieldWithCreate<TFieldValues extends FieldValues>({
47
+ export function CategoryPickerField<TFieldValues extends FieldValues>({
48
48
  form,
49
49
  name,
50
50
  label,
@@ -144,7 +144,7 @@ export function CategoryFieldWithCreate<TFieldValues extends FieldValues>({
144
144
  );
145
145
  }
146
146
 
147
- export function CostCenterFieldWithCreate<TFieldValues extends FieldValues>({
147
+ export function CostCenterPickerField<TFieldValues extends FieldValues>({
148
148
  form,
149
149
  name,
150
150
  label,
@@ -235,3 +235,8 @@ export function CostCenterFieldWithCreate<TFieldValues extends FieldValues>({
235
235
  />
236
236
  );
237
237
  }
238
+
239
+ export {
240
+ CategoryPickerField as CategoryFieldWithCreate,
241
+ CostCenterPickerField as CostCenterFieldWithCreate,
242
+ };
@@ -0,0 +1,242 @@
1
+ 'use client';
2
+
3
+ import { EntityPicker } from '@/components/ui/entity-picker';
4
+ import { useApp } from '@hed-hog/next-app-provider';
5
+ import { useTranslations } from 'next-intl';
6
+ import { useMemo, useState } from 'react';
7
+ import { FieldValues, Path, UseFormReturn } from 'react-hook-form';
8
+
9
+ export type FinanceCategory = {
10
+ id: number | string;
11
+ codigo?: string;
12
+ nome: string;
13
+ natureza?: string;
14
+ };
15
+
16
+ export type CostCenter = {
17
+ id: number | string;
18
+ codigo?: string;
19
+ nome: string;
20
+ };
21
+
22
+ type CreatedEntityResponse = {
23
+ id?: number | string | null;
24
+ data?: {
25
+ id?: number | string | null;
26
+ } | null;
27
+ category_id?: number | string | null;
28
+ cost_center_id?: number | string | null;
29
+ };
30
+
31
+ const extractCreatedId = (
32
+ payload: CreatedEntityResponse | null | undefined
33
+ ): string | null => {
34
+ const id =
35
+ payload?.id ??
36
+ payload?.data?.id ??
37
+ payload?.category_id ??
38
+ payload?.cost_center_id;
39
+
40
+ if (id === undefined || id === null || id === '') {
41
+ return null;
42
+ }
43
+
44
+ return String(id);
45
+ };
46
+
47
+ export function CategoryPickerField<TFieldValues extends FieldValues>({
48
+ form,
49
+ name,
50
+ label,
51
+ selectPlaceholder,
52
+ categories,
53
+ categoryKind,
54
+ onCreated,
55
+ }: {
56
+ form: UseFormReturn<TFieldValues>;
57
+ name: Path<TFieldValues>;
58
+ label: string;
59
+ selectPlaceholder: string;
60
+ categories: FinanceCategory[];
61
+ categoryKind: 'receita' | 'despesa';
62
+ onCreated?: () => Promise<unknown> | void;
63
+ }) {
64
+ const { request, showToastHandler } = useApp();
65
+ const t = useTranslations('finance.FinanceEntityFieldWithCreate');
66
+ const [localCategories, setLocalCategories] = useState<FinanceCategory[]>([]);
67
+
68
+ const filteredCategories = useMemo(() => {
69
+ const merged = [...(categories || []), ...localCategories];
70
+ const uniqueById = merged.filter(
71
+ (item, index, arr) =>
72
+ arr.findIndex(
73
+ (candidate) => String(candidate.id) === String(item.id)
74
+ ) === index
75
+ );
76
+
77
+ return uniqueById.filter((item) => item.natureza === categoryKind);
78
+ }, [categories, categoryKind, localCategories]);
79
+
80
+ return (
81
+ <EntityPicker<FinanceCategory, TFieldValues>
82
+ form={form}
83
+ name={name}
84
+ label={label}
85
+ placeholder={selectPlaceholder}
86
+ searchPlaceholder={selectPlaceholder}
87
+ emptySelectionLabel={selectPlaceholder}
88
+ clearable
89
+ allowEmptySelection
90
+ options={filteredCategories}
91
+ createActionLabel={t('actions.createCategoryAria')}
92
+ createTitle={t('categorySheet.title')}
93
+ createDescription={t('categorySheet.description')}
94
+ createFields={[
95
+ {
96
+ name: 'nome',
97
+ label: t('fields.name'),
98
+ placeholder: t('categorySheet.namePlaceholder'),
99
+ required: true,
100
+ },
101
+ ]}
102
+ getOptionValue={(category) => String(category.id)}
103
+ getOptionLabel={(category) =>
104
+ category.codigo
105
+ ? `${category.codigo} - ${category.nome}`
106
+ : category.nome
107
+ }
108
+ onCreate={async (values) => {
109
+ try {
110
+ const createdName = values.nome?.trim() ?? '';
111
+ const response = await request<CreatedEntityResponse>({
112
+ url: '/finance/categories',
113
+ method: 'POST',
114
+ data: {
115
+ name: createdName,
116
+ kind: categoryKind,
117
+ parent_id: null,
118
+ },
119
+ });
120
+
121
+ const createdId = extractCreatedId(response?.data);
122
+ const createdCategory = createdId
123
+ ? {
124
+ id: String(createdId),
125
+ nome: createdName,
126
+ natureza: categoryKind,
127
+ }
128
+ : null;
129
+
130
+ if (createdCategory) {
131
+ setLocalCategories((prev) => [...prev, createdCategory]);
132
+ }
133
+
134
+ await onCreated?.();
135
+ showToastHandler?.('success', t('messages.categoryCreateSuccess'));
136
+
137
+ return createdCategory;
138
+ } catch {
139
+ showToastHandler?.('error', t('messages.categoryCreateError'));
140
+ return null;
141
+ }
142
+ }}
143
+ />
144
+ );
145
+ }
146
+
147
+ export function CostCenterPickerField<TFieldValues extends FieldValues>({
148
+ form,
149
+ name,
150
+ label,
151
+ selectPlaceholder,
152
+ costCenters,
153
+ onCreated,
154
+ }: {
155
+ form: UseFormReturn<TFieldValues>;
156
+ name: Path<TFieldValues>;
157
+ label: string;
158
+ selectPlaceholder: string;
159
+ costCenters: CostCenter[];
160
+ onCreated?: () => Promise<unknown> | void;
161
+ }) {
162
+ const { request, showToastHandler } = useApp();
163
+ const t = useTranslations('finance.FinanceEntityFieldWithCreate');
164
+ const [localCostCenters, setLocalCostCenters] = useState<CostCenter[]>([]);
165
+
166
+ const mergedCostCenters = useMemo(() => {
167
+ const merged = [...(costCenters || []), ...localCostCenters];
168
+
169
+ return merged.filter(
170
+ (item, index, arr) =>
171
+ arr.findIndex(
172
+ (candidate) => String(candidate.id) === String(item.id)
173
+ ) === index
174
+ );
175
+ }, [costCenters, localCostCenters]);
176
+
177
+ return (
178
+ <EntityPicker<CostCenter, TFieldValues>
179
+ form={form}
180
+ name={name}
181
+ label={label}
182
+ placeholder={selectPlaceholder}
183
+ searchPlaceholder={selectPlaceholder}
184
+ emptySelectionLabel={selectPlaceholder}
185
+ clearable
186
+ allowEmptySelection
187
+ options={mergedCostCenters}
188
+ createActionLabel={t('actions.createCostCenterAria')}
189
+ createTitle={t('costCenterSheet.title')}
190
+ createDescription={t('costCenterSheet.description')}
191
+ createFields={[
192
+ {
193
+ name: 'nome',
194
+ label: t('fields.name'),
195
+ placeholder: t('costCenterSheet.namePlaceholder'),
196
+ required: true,
197
+ },
198
+ ]}
199
+ getOptionValue={(center) => String(center.id)}
200
+ getOptionLabel={(center) =>
201
+ center.codigo ? `${center.codigo} - ${center.nome}` : center.nome
202
+ }
203
+ onCreate={async (values) => {
204
+ try {
205
+ const createdName = values.nome?.trim() ?? '';
206
+ const response = await request<CreatedEntityResponse>({
207
+ url: '/finance/cost-centers',
208
+ method: 'POST',
209
+ data: {
210
+ name: createdName,
211
+ },
212
+ });
213
+
214
+ const createdId = extractCreatedId(response?.data);
215
+ const createdCostCenter = createdId
216
+ ? {
217
+ id: String(createdId),
218
+ nome: createdName,
219
+ }
220
+ : null;
221
+
222
+ if (createdCostCenter) {
223
+ setLocalCostCenters((prev) => [...prev, createdCostCenter]);
224
+ }
225
+
226
+ await onCreated?.();
227
+ showToastHandler?.('success', t('messages.costCenterCreateSuccess'));
228
+
229
+ return createdCostCenter;
230
+ } catch {
231
+ showToastHandler?.('error', t('messages.costCenterCreateError'));
232
+ return null;
233
+ }
234
+ }}
235
+ />
236
+ );
237
+ }
238
+
239
+ export {
240
+ CategoryPickerField as CategoryFieldWithCreate,
241
+ CostCenterPickerField as CostCenterFieldWithCreate,
242
+ };
@@ -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,10 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { PersonFieldWithCreate } from '@/app/(app)/(libraries)/contact/person/_components/person-field-with-create';
4
- import {
5
- CategoryFieldWithCreate,
6
- CostCenterFieldWithCreate,
7
- } from '@/app/(app)/(libraries)/finance/_components/finance-entity-field-with-create';
3
+ import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
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';
8
6
  import {
9
7
  FinancePageSection,
10
8
  FinanceSheetBody,
@@ -444,10 +442,8 @@ function NovoTituloSheet({
444
442
  currentLocaleCode
445
443
  );
446
444
 
447
- return currentLocaleCode.startsWith('pt')
448
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
449
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
450
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
445
+ return t('draftStatus', { relativeLabel, absoluteLabel });
446
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
451
447
 
452
448
  const watchedInstallmentsCount = form.watch('installmentsCount');
453
449
  const watchedTotalValue = form.watch('valor');
@@ -963,7 +959,7 @@ function NovoTituloSheet({
963
959
  />
964
960
  </div>
965
961
 
966
- <PersonFieldWithCreate
962
+ <PersonPickerField
967
963
  form={form}
968
964
  name="fornecedorId"
969
965
  label={t('fields.supplier')}
@@ -1216,7 +1212,7 @@ function NovoTituloSheet({
1216
1212
  description={t('sections.classification.description')}
1217
1213
  >
1218
1214
  <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
1219
- <CategoryFieldWithCreate
1215
+ <CategoryPickerField
1220
1216
  form={form}
1221
1217
  name="categoriaId"
1222
1218
  label={t('fields.category')}
@@ -1226,7 +1222,7 @@ function NovoTituloSheet({
1226
1222
  onCreated={onCategoriesUpdated}
1227
1223
  />
1228
1224
 
1229
- <CostCenterFieldWithCreate
1225
+ <CostCenterPickerField
1230
1226
  form={form}
1231
1227
  name="centroCustoId"
1232
1228
  label={t('fields.costCenter')}
@@ -1503,10 +1499,8 @@ function EditarTituloSheet({
1503
1499
  currentLocaleCode
1504
1500
  );
1505
1501
 
1506
- return currentLocaleCode.startsWith('pt')
1507
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
1508
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
1509
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
1502
+ return t('draftStatus', { relativeLabel, absoluteLabel });
1503
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
1510
1504
 
1511
1505
  const watchedInstallmentsCount = form.watch('installmentsCount');
1512
1506
  const watchedTotalValue = form.watch('valor');
@@ -2079,7 +2073,7 @@ function EditarTituloSheet({
2079
2073
  />
2080
2074
  </div>
2081
2075
 
2082
- <PersonFieldWithCreate
2076
+ <PersonPickerField
2083
2077
  form={form}
2084
2078
  name="fornecedorId"
2085
2079
  label={t('fields.supplier')}
@@ -2333,7 +2327,7 @@ function EditarTituloSheet({
2333
2327
  description={t('sections.classification.description')}
2334
2328
  >
2335
2329
  <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
2336
- <CategoryFieldWithCreate
2330
+ <CategoryPickerField
2337
2331
  form={form}
2338
2332
  name="categoriaId"
2339
2333
  label={t('fields.category')}
@@ -2343,7 +2337,7 @@ function EditarTituloSheet({
2343
2337
  onCreated={onCategoriesUpdated}
2344
2338
  />
2345
2339
 
2346
- <CostCenterFieldWithCreate
2340
+ <CostCenterPickerField
2347
2341
  form={form}
2348
2342
  name="centroCustoId"
2349
2343
  label={t('fields.costCenter')}
@@ -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) {
@@ -1,10 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { PersonFieldWithCreate } from '@/app/(app)/(libraries)/contact/person/_components/person-field-with-create';
4
- import {
5
- CategoryFieldWithCreate,
6
- CostCenterFieldWithCreate,
7
- } from '@/app/(app)/(libraries)/finance/_components/finance-entity-field-with-create';
3
+ import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
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';
8
6
  import {
9
7
  FinancePageSection,
10
8
  FinanceSheetBody,
@@ -424,10 +422,8 @@ function NovoTituloSheet({
424
422
  currentLocaleCode
425
423
  );
426
424
 
427
- return currentLocaleCode.startsWith('pt')
428
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
429
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
430
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
425
+ return t('draftStatus', { relativeLabel, absoluteLabel });
426
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
431
427
 
432
428
  const watchedInstallmentsCount = form.watch('installmentsCount');
433
429
  const watchedTotalValue = form.watch('valor');
@@ -943,7 +939,7 @@ function NovoTituloSheet({
943
939
  />
944
940
  </div>
945
941
 
946
- <PersonFieldWithCreate
942
+ <PersonPickerField
947
943
  form={form}
948
944
  name="clienteId"
949
945
  label={t('fields.client')}
@@ -1194,7 +1190,7 @@ function NovoTituloSheet({
1194
1190
  description={t('sections.classification.description')}
1195
1191
  >
1196
1192
  <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
1197
- <CategoryFieldWithCreate
1193
+ <CategoryPickerField
1198
1194
  form={form}
1199
1195
  name="categoriaId"
1200
1196
  label={t('fields.category')}
@@ -1204,7 +1200,7 @@ function NovoTituloSheet({
1204
1200
  onCreated={onOptionsUpdated}
1205
1201
  />
1206
1202
 
1207
- <CostCenterFieldWithCreate
1203
+ <CostCenterPickerField
1208
1204
  form={form}
1209
1205
  name="centroCustoId"
1210
1206
  label={t('fields.costCenter')}
@@ -1473,10 +1469,8 @@ function EditarTituloSheet({
1473
1469
  currentLocaleCode
1474
1470
  );
1475
1471
 
1476
- return currentLocaleCode.startsWith('pt')
1477
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
1478
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
1479
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
1472
+ return t('draftStatus', { relativeLabel, absoluteLabel });
1473
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
1480
1474
 
1481
1475
  const watchedInstallmentsCount = form.watch('installmentsCount');
1482
1476
  const watchedTotalValue = form.watch('valor');
@@ -2049,7 +2043,7 @@ function EditarTituloSheet({
2049
2043
  />
2050
2044
  </div>
2051
2045
 
2052
- <PersonFieldWithCreate
2046
+ <PersonPickerField
2053
2047
  form={form}
2054
2048
  name="clienteId"
2055
2049
  label={t('fields.client')}
@@ -2302,7 +2296,7 @@ function EditarTituloSheet({
2302
2296
  description={t('sections.classification.description')}
2303
2297
  >
2304
2298
  <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
2305
- <CategoryFieldWithCreate
2299
+ <CategoryPickerField
2306
2300
  form={form}
2307
2301
  name="categoriaId"
2308
2302
  label={t('fields.category')}
@@ -2312,7 +2306,7 @@ function EditarTituloSheet({
2312
2306
  onCreated={onOptionsUpdated}
2313
2307
  />
2314
2308
 
2315
- <CostCenterFieldWithCreate
2309
+ <CostCenterPickerField
2316
2310
  form={form}
2317
2311
  name="centroCustoId"
2318
2312
  label={t('fields.costCenter')}
@@ -150,9 +150,15 @@ export default function AuditLogsPage() {
150
150
  </SelectTrigger>
151
151
  <SelectContent>
152
152
  <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>
153
+ <SelectItem value="create">
154
+ {t('filters.actionOptions.create')}
155
+ </SelectItem>
156
+ <SelectItem value="update">
157
+ {t('filters.actionOptions.update')}
158
+ </SelectItem>
159
+ <SelectItem value="delete">
160
+ {t('filters.actionOptions.delete')}
161
+ </SelectItem>
156
162
  </SelectContent>
157
163
  </Select>
158
164
 
@@ -234,7 +240,7 @@ export default function AuditLogsPage() {
234
240
  <TableHead>{t('table.headers.entity')}</TableHead>
235
241
  <TableHead>{t('table.headers.record')}</TableHead>
236
242
  <TableHead>{t('table.headers.summary')}</TableHead>
237
- <TableHead>IP</TableHead>
243
+ <TableHead>{t('table.headers.ip')}</TableHead>
238
244
  </TableRow>
239
245
  </TableHeader>
240
246
  <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')}