@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
@@ -88,23 +88,30 @@ type TransferDraftPayload = {
88
88
 
89
89
  const TRANSFER_FORM_DRAFT_STORAGE_KEY = 'finance-transfer-form-draft';
90
90
 
91
- const transferFormSchema = z
92
- .object({
93
- sourceAccountId: z.string().trim().min(1, 'Conta de origem é obrigatória'),
94
- destinationAccountId: z
95
- .string()
96
- .trim()
97
- .min(1, 'Conta de destino é obrigatória'),
98
- date: z.string().trim().min(1, 'Data é obrigatória'),
99
- amount: z.number().min(0.01, 'Valor deve ser maior que zero'),
100
- description: z.string().optional(),
101
- })
102
- .refine((values) => values.sourceAccountId !== values.destinationAccountId, {
103
- message: 'As contas de origem e destino devem ser diferentes',
104
- path: ['destinationAccountId'],
105
- });
91
+ const createTransferFormSchema = (t: ReturnType<typeof useTranslations>) =>
92
+ z
93
+ .object({
94
+ sourceAccountId: z
95
+ .string()
96
+ .trim()
97
+ .min(1, t('formErrors.sourceAccountRequired')),
98
+ destinationAccountId: z
99
+ .string()
100
+ .trim()
101
+ .min(1, t('formErrors.destinationAccountRequired')),
102
+ date: z.string().trim().min(1, t('formErrors.dateRequired')),
103
+ amount: z.number().min(0.01, t('formErrors.amountMustBePositive')),
104
+ description: z.string().optional(),
105
+ })
106
+ .refine(
107
+ (values) => values.sourceAccountId !== values.destinationAccountId,
108
+ {
109
+ message: t('formErrors.differentAccounts'),
110
+ path: ['destinationAccountId'],
111
+ }
112
+ );
106
113
 
107
- type TransferFormValues = z.infer<typeof transferFormSchema>;
114
+ type TransferFormValues = z.infer<ReturnType<typeof createTransferFormSchema>>;
108
115
 
109
116
  function NovaTransferenciaSheet({
110
117
  contasBancarias,
@@ -118,6 +125,7 @@ function NovaTransferenciaSheet({
118
125
  const { request, showToastHandler, currentLocaleCode, getSettingValue } =
119
126
  useApp();
120
127
  const [open, setOpen] = useState(false);
128
+ const transferFormSchema = useMemo(() => createTransferFormSchema(t), [t]);
121
129
 
122
130
  const form = useForm<TransferFormValues>({
123
131
  resolver: zodResolver(transferFormSchema),
@@ -187,10 +195,8 @@ function NovaTransferenciaSheet({
187
195
  currentLocaleCode
188
196
  );
189
197
 
190
- return currentLocaleCode.startsWith('pt')
191
- ? `Rascunho salvo ${relativeLabel} Último salvamento: ${absoluteLabel}`
192
- : `Draft saved ${relativeLabel} • Last saved: ${absoluteLabel}`;
193
- }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft]);
198
+ return t('draftStatus', { relativeLabel, absoluteLabel });
199
+ }, [draftSavedAt, currentLocaleCode, getSettingValue, hasDraft, t]);
194
200
 
195
201
  useEffect(() => {
196
202
  if (!open) {
@@ -227,9 +233,9 @@ function NovaTransferenciaSheet({
227
233
  clearDraft();
228
234
  await onCreated();
229
235
  setOpen(false);
230
- showToastHandler?.('success', 'Transferência cadastrada com sucesso');
236
+ showToastHandler?.('success', t('transferCreatedSuccess'));
231
237
  } catch {
232
- showToastHandler?.('error', 'Erro ao cadastrar transferência');
238
+ showToastHandler?.('error', t('transferCreateError'));
233
239
  }
234
240
  };
235
241
 
@@ -540,7 +546,7 @@ export default function TransferenciasPage() {
540
546
  <SelectValue placeholder={t('common.select')} />
541
547
  </SelectTrigger>
542
548
  <SelectContent>
543
- <SelectItem value="all">Todas as contas</SelectItem>
549
+ <SelectItem value="all">{t('allAccounts')}</SelectItem>
544
550
  {contasBancarias.map((conta) => (
545
551
  <SelectItem key={conta.id} value={conta.id}>
546
552
  {conta.banco} - {conta.descricao}
@@ -551,7 +557,7 @@ export default function TransferenciasPage() {
551
557
 
552
558
  <div className="flex-1">
553
559
  <FilterBar
554
- searchPlaceholder="Buscar na descrição..."
560
+ searchPlaceholder={t('searchPlaceholder')}
555
561
  searchValue={search}
556
562
  onSearchChange={setSearch}
557
563
  />
@@ -575,7 +581,9 @@ export default function TransferenciasPage() {
575
581
  <TableRow>
576
582
  <TableHead>{t('table.headers.date')}</TableHead>
577
583
  <TableHead>{t('table.headers.source')}</TableHead>
578
- <TableHead className="text-center">→</TableHead>
584
+ <TableHead className="text-center">
585
+ {t('table.headers.arrow')}
586
+ </TableHead>
579
587
  <TableHead>{t('table.headers.destination')}</TableHead>
580
588
  <TableHead className="text-right">
581
589
  {t('table.headers.value')}
@@ -316,9 +316,9 @@ export default function CenariosPage() {
316
316
  });
317
317
 
318
318
  await refetch();
319
- showToastHandler?.('success', 'Cenário salvo com sucesso');
319
+ showToastHandler?.('success', t('messages.saveSuccess'));
320
320
  } catch {
321
- showToastHandler?.('error', 'Erro ao salvar cenário');
321
+ showToastHandler?.('error', t('messages.saveError'));
322
322
  } finally {
323
323
  setIsSaving(false);
324
324
  }
@@ -21,6 +21,7 @@ import {
21
21
  TableHeader,
22
22
  TableRow,
23
23
  } from '@/components/ui/table';
24
+ import { useApp } from '@hed-hog/next-app-provider';
24
25
  import {
25
26
  Download,
26
27
  Loader2,
@@ -47,6 +48,7 @@ type Scenario = 'base' | 'pessimista' | 'otimista';
47
48
 
48
49
  export default function ActualVsForecastPage() {
49
50
  const t = useTranslations('finance.ActualVsForecastPage');
51
+ const { currentLocaleCode } = useApp();
50
52
 
51
53
  const [horizonte, setHorizonte] = useState<string | null>(null);
52
54
  const [cenario, setCenario] = useState<Scenario | null>(null);
@@ -219,7 +221,7 @@ export default function ActualVsForecastPage() {
219
221
  />
220
222
  <Tooltip
221
223
  formatter={(value: number) =>
222
- new Intl.NumberFormat('pt-BR', {
224
+ new Intl.NumberFormat(currentLocaleCode || undefined, {
223
225
  style: 'currency',
224
226
  currency: 'BRL',
225
227
  }).format(value)
@@ -20,6 +20,7 @@ import {
20
20
  TableHeader,
21
21
  TableRow,
22
22
  } from '@/components/ui/table';
23
+ import { useApp } from '@hed-hog/next-app-provider';
23
24
  import { AlertTriangle, Loader2 } from 'lucide-react';
24
25
  import { useTranslations } from 'next-intl';
25
26
  import { useMemo, useState } from 'react';
@@ -46,6 +47,7 @@ function toPercent(value: number) {
46
47
 
47
48
  export default function AgingDefaultReportPage() {
48
49
  const t = useTranslations('finance.AgingDefaultReportPage');
50
+ const { currentLocaleCode } = useApp();
49
51
 
50
52
  const [horizonte, setHorizonte] = useState<string | null>(null);
51
53
  const [cenario, setCenario] = useState<Scenario | null>(null);
@@ -213,7 +215,7 @@ export default function AgingDefaultReportPage() {
213
215
  />
214
216
  <Tooltip
215
217
  formatter={(value: number) =>
216
- new Intl.NumberFormat('pt-BR', {
218
+ new Intl.NumberFormat(currentLocaleCode || undefined, {
217
219
  style: 'currency',
218
220
  currency: 'BRL',
219
221
  }).format(value)
@@ -21,6 +21,7 @@ import {
21
21
  TableHeader,
22
22
  TableRow,
23
23
  } from '@/components/ui/table';
24
+ import { useApp } from '@hed-hog/next-app-provider';
24
25
  import {
25
26
  Download,
26
27
  Loader2,
@@ -46,6 +47,7 @@ type Scenario = 'base' | 'pessimista' | 'otimista';
46
47
 
47
48
  export default function CashPositionReportPage() {
48
49
  const t = useTranslations('finance.CashPositionReportPage');
50
+ const { currentLocaleCode } = useApp();
49
51
 
50
52
  const [horizonte, setHorizonte] = useState<string | null>(null);
51
53
  const [cenario, setCenario] = useState<Scenario | null>(null);
@@ -309,7 +311,7 @@ export default function CashPositionReportPage() {
309
311
  />
310
312
  <Tooltip
311
313
  formatter={(value: number) =>
312
- new Intl.NumberFormat('pt-BR', {
314
+ new Intl.NumberFormat(currentLocaleCode || undefined, {
313
315
  style: 'currency',
314
316
  currency: 'BRL',
315
317
  }).format(value)
@@ -3,8 +3,8 @@
3
3
  import { FinancePageSection } from '@/app/(app)/(libraries)/finance/_components/finance-layout';
4
4
  import { Page, PageHeader } from '@/components/entity-list';
5
5
  import { Badge } from '@/components/ui/badge';
6
- import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
7
6
  import { Input } from '@/components/ui/input';
7
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
8
8
  import { Label } from '@/components/ui/label';
9
9
  import { Money } from '@/components/ui/money';
10
10
  import {
@@ -49,16 +49,12 @@ const LINE_COLORS = {
49
49
  diferenca: '#16a34a',
50
50
  };
51
51
 
52
- const currencyFormatter = new Intl.NumberFormat('pt-BR', {
53
- style: 'currency',
54
- currency: 'BRL',
55
- });
56
-
57
52
  function renderSolidTooltip({
58
53
  active,
59
54
  payload,
60
55
  label,
61
- }: TooltipProps<number, string>) {
56
+ currencyFormatter,
57
+ }: TooltipProps<number, string> & { currencyFormatter: Intl.NumberFormat }) {
62
58
  if (!active || !payload?.length) return null;
63
59
  return (
64
60
  <div className="rounded-lg border bg-popover px-3 py-2 shadow-xl text-popover-foreground text-sm">
@@ -84,6 +80,10 @@ function renderSolidTooltip({
84
80
  export default function OverviewResultsReportPage() {
85
81
  const t = useTranslations('finance.OverviewResultsReportPage');
86
82
  const locale = useLocale();
83
+ const currencyFormatter = new Intl.NumberFormat(locale || undefined, {
84
+ style: 'currency',
85
+ currency: 'BRL',
86
+ });
87
87
  const defaults = getDefaultDateRange();
88
88
  const [from, setFrom] = useState(defaults.from);
89
89
  const [to, setTo] = useState(defaults.to);
@@ -225,7 +225,14 @@ export default function OverviewResultsReportPage() {
225
225
  tick={{ fontSize: 12 }}
226
226
  tickFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
227
227
  />
228
- <Tooltip content={renderSolidTooltip} />
228
+ <Tooltip
229
+ content={(props) =>
230
+ renderSolidTooltip({
231
+ ...(props as TooltipProps<number, string>),
232
+ currencyFormatter,
233
+ })
234
+ }
235
+ />
229
236
  <Legend />
230
237
  <Line
231
238
  type="monotone"
@@ -28,6 +28,7 @@ import {
28
28
  TableHeader,
29
29
  TableRow,
30
30
  } from '@/components/ui/table';
31
+ import { useApp } from '@hed-hog/next-app-provider';
31
32
  import { Crown, PieChartIcon, Users } from 'lucide-react';
32
33
  import { useTranslations } from 'next-intl';
33
34
  import { type FormEvent, useState } from 'react';
@@ -64,13 +65,9 @@ const rankingColors = [
64
65
  '#B45309',
65
66
  ];
66
67
 
67
- const currencyFormatter = new Intl.NumberFormat('pt-BR', {
68
- style: 'currency',
69
- currency: 'BRL',
70
- });
71
-
72
68
  export default function TopCustomersReportPage() {
73
69
  const t = useTranslations('finance.TopCustomersReportPage');
70
+ const { currentLocaleCode } = useApp();
74
71
  const defaults = getDefaultDateRange();
75
72
  const [filters, setFilters] = useState({
76
73
  from: defaults.from,
@@ -79,6 +76,13 @@ export default function TopCustomersReportPage() {
79
76
  search: '',
80
77
  });
81
78
  const [appliedFilters, setAppliedFilters] = useState(filters);
79
+ const currencyFormatter = new Intl.NumberFormat(
80
+ currentLocaleCode || undefined,
81
+ {
82
+ style: 'currency',
83
+ currency: 'BRL',
84
+ }
85
+ );
82
86
  const { data: viewData, isFetching } = useTopCustomersReport({
83
87
  from: appliedFilters.from,
84
88
  to: appliedFilters.to,
@@ -28,6 +28,7 @@ import {
28
28
  TableHeader,
29
29
  TableRow,
30
30
  } from '@/components/ui/table';
31
+ import { useApp } from '@hed-hog/next-app-provider';
31
32
  import { Building2, CircleDollarSign, TriangleAlert } from 'lucide-react';
32
33
  import { useTranslations } from 'next-intl';
33
34
  import { type FormEvent, useState } from 'react';
@@ -62,13 +63,9 @@ const rankingColors = [
62
63
  '#1D4ED8',
63
64
  ];
64
65
 
65
- const currencyFormatter = new Intl.NumberFormat('pt-BR', {
66
- style: 'currency',
67
- currency: 'BRL',
68
- });
69
-
70
66
  export default function TopOperationalExpensesReportPage() {
71
67
  const t = useTranslations('finance.TopOperationalExpensesReportPage');
68
+ const { currentLocaleCode } = useApp();
72
69
  const defaults = getDefaultDateRange();
73
70
  const [filters, setFilters] = useState({
74
71
  from: defaults.from,
@@ -77,6 +74,13 @@ export default function TopOperationalExpensesReportPage() {
77
74
  search: '',
78
75
  });
79
76
  const [appliedFilters, setAppliedFilters] = useState(filters);
77
+ const currencyFormatter = new Intl.NumberFormat(
78
+ currentLocaleCode || undefined,
79
+ {
80
+ style: 'currency',
81
+ currency: 'BRL',
82
+ }
83
+ );
80
84
  const { data: viewData, isFetching } = useTopOperationalExpensesReport({
81
85
  from: appliedFilters.from,
82
86
  to: appliedFilters.to,
@@ -8,6 +8,13 @@
8
8
  "upcoming": {
9
9
  "payable": "To Pay",
10
10
  "receivable": "To Receive",
11
+ "messages": {
12
+ "selectBankAccount": "Select a bank account",
13
+ "createAdjustmentSuccess": "Adjustment created successfully",
14
+ "createAdjustmentError": "Could not create the adjustment",
15
+ "reconcileSuccess": "Reconciliation completed successfully",
16
+ "reconcileError": "Could not reconcile the records"
17
+ },
11
18
  "nextDueDates": "Upcoming due dates"
12
19
  },
13
20
  "alerts": {
@@ -134,6 +141,14 @@
134
141
  "title": "All good!",
135
142
  "description": "There are no pending approvals.",
136
143
  "refresh": "Refresh"
144
+ },
145
+ "messages": {
146
+ "invalidTitleForApproval": "Invalid title for approval",
147
+ "approveSuccess": "Title approved successfully",
148
+ "approveError": "Could not approve the title",
149
+ "invalidTitleForRejection": "Invalid title for rejection",
150
+ "rejectSuccess": "Title rejected successfully",
151
+ "rejectError": "Could not reject the title"
137
152
  }
138
153
  },
139
154
  "FinanceEntityFieldWithCreate": {
@@ -542,6 +557,7 @@
542
557
  },
543
558
  "CollectionsDefaultPage": {
544
559
  "common": { "cancel": "Cancel" },
560
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
545
561
  "actions": {
546
562
  "history": "History",
547
563
  "collect": "Collect",
@@ -789,7 +805,9 @@
789
805
  "channels": {
790
806
  "boleto": "Bank Slip",
791
807
  "card": "Card",
792
- "transfer": "Transfer"
808
+ "transfer": "Transfer",
809
+ "debitAutomatico": "Automatic debit",
810
+ "debitEmConta": "Account debit"
793
811
  },
794
812
  "notFound": {
795
813
  "title": "Title not found",
@@ -908,6 +926,12 @@
908
926
  "edit": "Edit",
909
927
  "save": "Save"
910
928
  },
929
+ "validation": {
930
+ "bankRequired": "Bank is required",
931
+ "typeRequired": "Type is required",
932
+ "initialBalanceInvalid": "Invalid initial balance"
933
+ },
934
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
911
935
  "messages": {
912
936
  "createSuccess": "Bank account created successfully",
913
937
  "createError": "Failed to create bank account",
@@ -945,6 +969,18 @@
945
969
  "type": "Type",
946
970
  "description": "Description",
947
971
  "descriptionPlaceholder": "Example: Main Account",
972
+ "currency": "Currency",
973
+ "currencyPlaceholder": "Select a currency",
974
+ "currencySearchPlaceholder": "Search currency...",
975
+ "currencyEntityLabel": "currency",
976
+ "currencyCreateTitle": "New currency",
977
+ "currencyCreateDescription": "Register a new currency to use in bank accounts.",
978
+ "currencyCode": "ISO Code",
979
+ "currencyCodePlaceholder": "Ex.: BRL",
980
+ "currencyName": "Name",
981
+ "currencyNamePlaceholder": "Ex.: Brazilian Real",
982
+ "currencySymbol": "Symbol",
983
+ "currencySymbolPlaceholder": "Ex.: R$",
948
984
  "initialBalance": "Initial Balance",
949
985
  "logo": "Logo",
950
986
  "logoAction": "Upload logo",
@@ -1002,6 +1038,7 @@
1002
1038
  "select": "Select...",
1003
1039
  "cancel": "Cancel"
1004
1040
  },
1041
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1005
1042
  "adjustment": {
1006
1043
  "action": "Create Adjustment",
1007
1044
  "title": "Create Adjustment",
@@ -1071,6 +1108,43 @@
1071
1108
  },
1072
1109
  "StatementsPage": {
1073
1110
  "common": { "cancel": "Cancel" },
1111
+ "formErrors": {
1112
+ "dateRequired": "Date is required",
1113
+ "descriptionRequired": "Description is required",
1114
+ "amountMustBePositive": "Amount must be greater than zero",
1115
+ "bankAccountRequired": "Bank account is required",
1116
+ "fileRequired": "File is required",
1117
+ "fileTypeNotAllowed": "Only CSV or OFX files are allowed"
1118
+ },
1119
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1120
+ "messages": {
1121
+ "importSuccess": "Statement imported successfully",
1122
+ "importError": "Could not import the statement",
1123
+ "selectBankAccount": "Select a bank account",
1124
+ "createEntrySuccess": "Transaction added successfully",
1125
+ "createEntryError": "Could not add the transaction",
1126
+ "selectBankAccountToExport": "Select a bank account to export",
1127
+ "exportError": "Could not export the statement",
1128
+ "saveChangesSuccess": "Changes saved successfully",
1129
+ "saveChangesError": "Could not save changes",
1130
+ "deleteEntrySuccess": "Transaction deleted successfully",
1131
+ "deleteEntryError": "Could not delete the transaction"
1132
+ },
1133
+ "aria": {
1134
+ "newBankAccount": "New bank account"
1135
+ },
1136
+ "newEntry": {
1137
+ "action": "New entry",
1138
+ "title": "New entry",
1139
+ "description": "Add a manual transaction to the bank account statement.",
1140
+ "submit": "Save",
1141
+ "fields": {
1142
+ "date": "Date",
1143
+ "type": "Type",
1144
+ "description": "Description",
1145
+ "amount": "Amount"
1146
+ }
1147
+ },
1074
1148
  "importDialog": {
1075
1149
  "action": "Import",
1076
1150
  "title": "Import Statement",
@@ -1090,7 +1164,11 @@
1090
1164
  "finance": "Finance",
1091
1165
  "current": "Statements"
1092
1166
  },
1093
- "actions": { "export": "Export" },
1167
+ "actions": {
1168
+ "export": "Export",
1169
+ "saveChanges": "Save changes",
1170
+ "savingChanges": "Saving..."
1171
+ },
1094
1172
  "filters": {
1095
1173
  "selectAccount": "Select account...",
1096
1174
  "searchPlaceholder": "Search in description..."
@@ -1115,6 +1193,12 @@
1115
1193
  "title": "No transactions found",
1116
1194
  "description": "Import a statement to view account transactions."
1117
1195
  },
1196
+ "deleteDialog": {
1197
+ "title": "Delete transaction",
1198
+ "description": "This action cannot be undone. The transaction will be permanently removed from the statement.",
1199
+ "confirm": "Delete",
1200
+ "deleting": "Deleting..."
1201
+ },
1118
1202
  "types": {
1119
1203
  "inflow": "Inflow",
1120
1204
  "outflow": "Outflow"
@@ -1125,6 +1209,13 @@
1125
1209
  "select": "Select...",
1126
1210
  "cancel": "Cancel"
1127
1211
  },
1212
+ "formErrors": {
1213
+ "sourceAccountRequired": "Source account is required",
1214
+ "destinationAccountRequired": "Destination account is required",
1215
+ "dateRequired": "Date is required",
1216
+ "amountMustBePositive": "Amount must be greater than zero",
1217
+ "differentAccounts": "Source and destination accounts must be different"
1218
+ },
1128
1219
  "newTransfer": {
1129
1220
  "action": "New Transfer",
1130
1221
  "title": "New Transfer",
@@ -1154,6 +1245,11 @@
1154
1245
  "activeAccounts": "Active Accounts",
1155
1246
  "available": "available"
1156
1247
  },
1248
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1249
+ "transferCreatedSuccess": "Transfer created successfully",
1250
+ "transferCreateError": "Error creating transfer",
1251
+ "allAccounts": "All accounts",
1252
+ "searchPlaceholder": "Search in description...",
1157
1253
  "table": {
1158
1254
  "title": "Recent Transfers",
1159
1255
  "description": "Transfer history between accounts",
@@ -1161,6 +1257,7 @@
1161
1257
  "date": "Date",
1162
1258
  "source": "Source",
1163
1259
  "destination": "Destination",
1260
+ "arrow": "→",
1164
1261
  "value": "Value",
1165
1262
  "description": "Description"
1166
1263
  }
@@ -1184,6 +1281,11 @@
1184
1281
  "searchPlaceholder": "Search by action, entity, summary, id or IP",
1185
1282
  "action": "Action",
1186
1283
  "allActions": "All actions",
1284
+ "actionOptions": {
1285
+ "create": "Create",
1286
+ "update": "Update",
1287
+ "delete": "Delete"
1288
+ },
1187
1289
  "userPlaceholder": "Author (User ID)",
1188
1290
  "entity": "Entity",
1189
1291
  "allEntities": "All entities",
@@ -1196,7 +1298,8 @@
1196
1298
  "action": "Action",
1197
1299
  "entity": "Entity",
1198
1300
  "record": "Record",
1199
- "summary": "Summary"
1301
+ "summary": "Summary",
1302
+ "ip": "IP"
1200
1303
  },
1201
1304
  "loading": "Loading logs...",
1202
1305
  "empty": "No logs found."
@@ -1208,6 +1311,7 @@
1208
1311
  "cancel": "Cancel",
1209
1312
  "save": "Save"
1210
1313
  },
1314
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1211
1315
  "messages": {
1212
1316
  "createSuccess": "Category created successfully",
1213
1317
  "updateSuccess": "Category updated successfully",
@@ -1275,6 +1379,7 @@
1275
1379
  "cancel": "Cancel",
1276
1380
  "save": "Save"
1277
1381
  },
1382
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1278
1383
  "messages": {
1279
1384
  "createSuccess": "Cost center created successfully",
1280
1385
  "createError": "Error creating cost center",
@@ -1332,6 +1437,7 @@
1332
1437
  "cancel": "Cancel",
1333
1438
  "save": "Save"
1334
1439
  },
1440
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1335
1441
  "messages": {
1336
1442
  "createSuccess": "Period closed successfully",
1337
1443
  "createError": "Error closing period"
@@ -1701,6 +1807,10 @@
1701
1807
  "positive": "Positive",
1702
1808
  "negative": "Negative",
1703
1809
  "withGrowth": "With growth of {value}%"
1810
+ },
1811
+ "messages": {
1812
+ "saveSuccess": "Scenario saved successfully",
1813
+ "saveError": "Error saving scenario"
1704
1814
  }
1705
1815
  },
1706
1816
  "OverviewResultsReportPage": {
@@ -1874,6 +1984,7 @@
1874
1984
  "cancel": "Cancel",
1875
1985
  "save": "Save"
1876
1986
  },
1987
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
1877
1988
  "messages": {
1878
1989
  "createSuccess": "Currency created successfully",
1879
1990
  "createError": "Error creating currency",