@archbase/components 4.0.19 → 4.0.20
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/dist/archbase-components-4.0.20.tgz +0 -0
- package/dist/datagrid/ag-grid/ag-grid-locale-ptbr.d.ts +7 -0
- package/dist/datagrid/ag-grid/ag-grid-mantine-theme.d.ts +24 -0
- package/dist/datagrid/ag-grid/archbase-data-grid-ag-formatters.d.ts +88 -0
- package/dist/datagrid/ag-grid/archbase-data-grid-ag-types.d.ts +329 -0
- package/dist/datagrid/ag-grid/archbase-data-grid-ag-utils.d.ts +71 -0
- package/dist/datagrid/ag-grid/archbase-data-grid-ag.d.ts +14 -0
- package/dist/datagrid/ag-grid/index.d.ts +14 -0
- package/dist/datagrid/index.d.ts +9 -1
- package/dist/index.js +11175 -10592
- package/package.json +6 -4
- package/src/datagrid/ag-grid/ag-grid-locale-ptbr.ts +432 -0
- package/src/datagrid/ag-grid/ag-grid-mantine-theme.ts +176 -0
- package/src/datagrid/ag-grid/archbase-data-grid-ag-formatters.tsx +470 -0
- package/src/datagrid/ag-grid/archbase-data-grid-ag-types.tsx +413 -0
- package/src/datagrid/ag-grid/archbase-data-grid-ag-utils.ts +394 -0
- package/src/datagrid/ag-grid/archbase-data-grid-ag.tsx +1241 -0
- package/src/datagrid/ag-grid/index.tsx +84 -0
- package/src/datagrid/index.tsx +59 -8
- package/src/datagrid/main/archbase-data-grid-pagination.tsx +1 -2
- package/src/datagrid/main/archbase-data-grid-toolbar.tsx +1 -2
- package/src/editors/ArchbaseAsyncMultiSelect.tsx +2 -1
- package/src/editors/ArchbaseAsyncSelect.tsx +2 -1
- package/src/editors/ArchbaseAvatarEdit.tsx +1 -0
- package/src/editors/ArchbaseCheckbox.tsx +1 -0
- package/src/editors/ArchbaseChip.tsx +1 -0
- package/src/editors/ArchbaseChipGroup.tsx +1 -0
- package/src/editors/ArchbaseColorGradientPicker.tsx +2 -1
- package/src/editors/ArchbaseDatePickerEdit.tsx +1 -0
- package/src/editors/ArchbaseDateTimePickerEdit.tsx +1 -0
- package/src/editors/ArchbaseDualListbox.tsx +1 -0
- package/src/editors/ArchbaseEdit.tsx +1 -0
- package/src/editors/ArchbaseImageEdit.tsx +1 -0
- package/src/editors/ArchbaseJsonEdit.tsx +1 -0
- package/src/editors/ArchbaseLookupEdit.tsx +2 -1
- package/src/editors/ArchbaseLookupNumber.tsx +2 -1
- package/src/editors/ArchbaseLookupSelect.tsx +2 -1
- package/src/editors/ArchbaseMarkdownEdit.tsx +1 -0
- package/src/editors/ArchbaseMaskEdit.tsx +1 -0
- package/src/editors/ArchbaseMentionInput.tsx +1 -0
- package/src/editors/ArchbaseMultiEmail.tsx +1 -0
- package/src/editors/ArchbaseMultiSelect.tsx +2 -1
- package/src/editors/ArchbaseNumberEdit.tsx +1 -0
- package/src/editors/ArchbaseNumberStepper.tsx +2 -1
- package/src/editors/ArchbasePasswordEdit.tsx +1 -0
- package/src/editors/ArchbaseRadioGroup.tsx +1 -0
- package/src/editors/ArchbaseRating.tsx +1 -0
- package/src/editors/ArchbaseRichTextEdit.tsx +1 -0
- package/src/editors/ArchbaseSelect.tsx +2 -1
- package/src/editors/ArchbaseSignaturePad.tsx +1 -0
- package/src/editors/ArchbaseSwitch.tsx +1 -0
- package/src/editors/ArchbaseTagInputEdit.tsx +1 -0
- package/src/editors/ArchbaseTextArea.tsx +1 -0
- package/src/editors/ArchbaseTimeEdit.tsx +1 -0
- package/dist/archbase-components-4.0.19.tgz +0 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArchbaseDataGridAG Cell Renderers
|
|
3
|
+
*
|
|
4
|
+
* AG Grid cell renderer components for various data types.
|
|
5
|
+
*/
|
|
6
|
+
import React, { ReactNode } from 'react';
|
|
7
|
+
import { format } from 'date-fns';
|
|
8
|
+
import { Checkbox } from '@mantine/core';
|
|
9
|
+
import { ArchbaseMasker, MaskOptions, convertISOStringToDate } from '@archbase/core';
|
|
10
|
+
import type { ICellRendererParams } from 'ag-grid-community';
|
|
11
|
+
import type { FieldDataType } from './archbase-data-grid-ag-types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check if string is valid base64
|
|
15
|
+
*/
|
|
16
|
+
const isBase64 = (str: string): boolean => {
|
|
17
|
+
if (!str || typeof str !== 'string' || str.length < 4) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
22
|
+
if (!base64Regex.test(str)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const decoded = atob(str);
|
|
28
|
+
const printableRatio =
|
|
29
|
+
decoded.split('').filter((c) => {
|
|
30
|
+
const code = c.charCodeAt(0);
|
|
31
|
+
return (code >= 32 && code <= 126) || code === 10 || code === 13 || code === 9;
|
|
32
|
+
}).length / decoded.length;
|
|
33
|
+
|
|
34
|
+
return printableRatio > 0.9;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Decode base64 to UTF-8 text
|
|
42
|
+
*/
|
|
43
|
+
const decodeBase64 = (str: string): string => {
|
|
44
|
+
try {
|
|
45
|
+
const binaryString = atob(str);
|
|
46
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
47
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
48
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
49
|
+
}
|
|
50
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
51
|
+
} catch {
|
|
52
|
+
return str;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Text cell renderer with optional mask and auto base64 decoding
|
|
58
|
+
*/
|
|
59
|
+
export const TextCellRenderer = (
|
|
60
|
+
params: ICellRendererParams,
|
|
61
|
+
maskOptions?: MaskOptions
|
|
62
|
+
): ReactNode => {
|
|
63
|
+
const value = params.value;
|
|
64
|
+
if (value === null || value === undefined) {
|
|
65
|
+
return <span></span>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let displayValue = String(value);
|
|
69
|
+
|
|
70
|
+
if (isBase64(displayValue)) {
|
|
71
|
+
displayValue = decodeBase64(displayValue);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (maskOptions) {
|
|
75
|
+
displayValue = ArchbaseMasker.toPattern(displayValue, maskOptions);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return <span>{displayValue}</span>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Integer cell renderer
|
|
83
|
+
*/
|
|
84
|
+
export const IntegerCellRenderer = (params: ICellRendererParams): ReactNode => {
|
|
85
|
+
const value = params.value;
|
|
86
|
+
if (value === null || value === undefined) {
|
|
87
|
+
return <span></span>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const numValue = Number.isNaN(Number(value)) ? 0 : Number(value);
|
|
91
|
+
|
|
92
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{numValue}</span>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Float cell renderer
|
|
97
|
+
*/
|
|
98
|
+
export const FloatCellRenderer = (params: ICellRendererParams): ReactNode => {
|
|
99
|
+
const value = params.value;
|
|
100
|
+
if (value === null || value === undefined) {
|
|
101
|
+
return <span></span>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const numValue = Number.isNaN(Number(value)) ? 0 : Number(value);
|
|
105
|
+
|
|
106
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{numValue}</span>;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Currency cell renderer (BRL format)
|
|
111
|
+
*/
|
|
112
|
+
export const CurrencyCellRenderer = (params: ICellRendererParams): ReactNode => {
|
|
113
|
+
const value = params.value;
|
|
114
|
+
if (value === null || value === undefined) {
|
|
115
|
+
return <span></span>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const numValue = Number.isNaN(Number(value)) ? 0 : Number(value);
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const formatted = new Intl.NumberFormat('pt-BR', {
|
|
122
|
+
style: 'currency',
|
|
123
|
+
currency: 'BRL',
|
|
124
|
+
}).format(numValue);
|
|
125
|
+
|
|
126
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{formatted}</span>;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.error('Error formatting currency:', e);
|
|
129
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{numValue}</span>;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Percent cell renderer
|
|
135
|
+
*/
|
|
136
|
+
export const PercentCellRenderer = (
|
|
137
|
+
params: ICellRendererParams,
|
|
138
|
+
decimalPlaces: number = 2
|
|
139
|
+
): ReactNode => {
|
|
140
|
+
const value = params.value;
|
|
141
|
+
if (value === null || value === undefined) {
|
|
142
|
+
return <span></span>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const numValue = Number.isNaN(Number(value)) ? 0 : Number(value);
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const formatted = new Intl.NumberFormat('pt-BR', {
|
|
149
|
+
style: 'percent',
|
|
150
|
+
minimumFractionDigits: decimalPlaces,
|
|
151
|
+
maximumFractionDigits: decimalPlaces,
|
|
152
|
+
}).format(numValue / 100);
|
|
153
|
+
|
|
154
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{formatted}</span>;
|
|
155
|
+
} catch (e) {
|
|
156
|
+
console.error('Error formatting percent:', e);
|
|
157
|
+
return <span style={{ textAlign: 'right', display: 'block' }}>{numValue}%</span>;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Boolean cell renderer with Mantine checkbox
|
|
163
|
+
*/
|
|
164
|
+
export const BooleanCellRenderer = (params: ICellRendererParams): ReactNode => {
|
|
165
|
+
const value = params.value;
|
|
166
|
+
const checked = Boolean(value);
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
|
170
|
+
<Checkbox readOnly checked={checked} />
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Date cell renderer
|
|
177
|
+
*/
|
|
178
|
+
export const DateCellRenderer = (
|
|
179
|
+
params: ICellRendererParams,
|
|
180
|
+
dateFormat: string = 'dd/MM/yyyy'
|
|
181
|
+
): ReactNode => {
|
|
182
|
+
const value = params.value;
|
|
183
|
+
if (!value) {
|
|
184
|
+
return <span></span>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const date = convertISOStringToDate(value);
|
|
189
|
+
const formatted = format(date, dateFormat);
|
|
190
|
+
|
|
191
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{formatted}</span>;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error('Error formatting date:', error);
|
|
194
|
+
return <span>Data inválida</span>;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* DateTime cell renderer
|
|
200
|
+
*/
|
|
201
|
+
export const DateTimeCellRenderer = (
|
|
202
|
+
params: ICellRendererParams,
|
|
203
|
+
dateTimeFormat: string = 'dd/MM/yyyy HH:mm:ss'
|
|
204
|
+
): ReactNode => {
|
|
205
|
+
const value = params.value;
|
|
206
|
+
if (!value) {
|
|
207
|
+
return <span></span>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
const date = convertISOStringToDate(value);
|
|
212
|
+
const formatted = format(date, dateTimeFormat);
|
|
213
|
+
|
|
214
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{formatted}</span>;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error('Error formatting datetime:', error);
|
|
217
|
+
return <span>Data/hora inválida</span>;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Time cell renderer
|
|
223
|
+
*/
|
|
224
|
+
export const TimeCellRenderer = (
|
|
225
|
+
params: ICellRendererParams,
|
|
226
|
+
timeFormat: string = 'HH:mm:ss'
|
|
227
|
+
): ReactNode => {
|
|
228
|
+
const value = params.value;
|
|
229
|
+
if (!value) {
|
|
230
|
+
return <span></span>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
if (typeof value === 'string') {
|
|
235
|
+
if (/^\d{2}:\d{2}(:\d{2})?$/.test(value)) {
|
|
236
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{value}</span>;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const date = new Date(value);
|
|
240
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{format(date, timeFormat)}</span>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (value instanceof Date) {
|
|
244
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{format(value, timeFormat)}</span>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (typeof value === 'number') {
|
|
248
|
+
const hours = Math.floor(value / 3600000);
|
|
249
|
+
const minutes = Math.floor((value % 3600000) / 60000);
|
|
250
|
+
const seconds = Math.floor((value % 60000) / 1000);
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<span style={{ textAlign: 'center', display: 'block' }}>
|
|
254
|
+
{`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`}
|
|
255
|
+
</span>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return <span style={{ textAlign: 'center', display: 'block' }}>{String(value)}</span>;
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error('Error formatting time:', error);
|
|
262
|
+
return <span>Hora inválida</span>;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Enum cell renderer
|
|
268
|
+
*/
|
|
269
|
+
export const EnumCellRenderer = (
|
|
270
|
+
params: ICellRendererParams,
|
|
271
|
+
enumValues: Array<{ label: string; value: string }>
|
|
272
|
+
): ReactNode => {
|
|
273
|
+
const value = params.value;
|
|
274
|
+
if (value === null || value === undefined) {
|
|
275
|
+
return <span></span>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const option = enumValues.find((opt) => opt.value === value);
|
|
279
|
+
return <span>{option ? option.label : String(value)}</span>;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* UUID cell renderer
|
|
284
|
+
*/
|
|
285
|
+
export const UUIDCellRenderer = (params: ICellRendererParams): ReactNode => {
|
|
286
|
+
const value = params.value;
|
|
287
|
+
if (!value) {
|
|
288
|
+
return <span></span>;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const str = String(value);
|
|
292
|
+
|
|
293
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str)) {
|
|
294
|
+
return <span>{str}</span>;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (/^[0-9a-f]{32}$/i.test(str)) {
|
|
298
|
+
const formatted = `${str.substring(0, 8)}-${str.substring(8, 12)}-${str.substring(12, 16)}-${str.substring(16, 20)}-${str.substring(20)}`;
|
|
299
|
+
return <span>{formatted}</span>;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return <span>{str}</span>;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Image cell renderer
|
|
307
|
+
*/
|
|
308
|
+
export const ImageCellRenderer = (
|
|
309
|
+
params: ICellRendererParams,
|
|
310
|
+
options?: { maxWidth?: number; maxHeight?: number }
|
|
311
|
+
): ReactNode => {
|
|
312
|
+
const value = params.value;
|
|
313
|
+
if (!value) {
|
|
314
|
+
return <span></span>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const { maxWidth = 40, maxHeight = 40 } = options || {};
|
|
318
|
+
let src = String(value);
|
|
319
|
+
|
|
320
|
+
// If it's base64 data without prefix, add it
|
|
321
|
+
if (isBase64(src) && !src.startsWith('data:')) {
|
|
322
|
+
src = `data:image/png;base64,${src}`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
|
327
|
+
<img
|
|
328
|
+
src={src}
|
|
329
|
+
alt=""
|
|
330
|
+
style={{
|
|
331
|
+
maxWidth,
|
|
332
|
+
maxHeight,
|
|
333
|
+
objectFit: 'contain',
|
|
334
|
+
}}
|
|
335
|
+
/>
|
|
336
|
+
</div>
|
|
337
|
+
);
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Get cell renderer by data type
|
|
342
|
+
*/
|
|
343
|
+
export const getCellRendererByDataType = (
|
|
344
|
+
dataType: FieldDataType,
|
|
345
|
+
customRender?: (params: ICellRendererParams) => ReactNode,
|
|
346
|
+
options?: {
|
|
347
|
+
maskOptions?: MaskOptions;
|
|
348
|
+
dateFormat?: string;
|
|
349
|
+
dateTimeFormat?: string;
|
|
350
|
+
timeFormat?: string;
|
|
351
|
+
enumValues?: Array<{ label: string; value: string }>;
|
|
352
|
+
decimalPlaces?: number;
|
|
353
|
+
}
|
|
354
|
+
): ((params: ICellRendererParams) => ReactNode) => {
|
|
355
|
+
if (customRender) {
|
|
356
|
+
return customRender;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
switch (dataType) {
|
|
360
|
+
case 'text':
|
|
361
|
+
return (params) => TextCellRenderer(params, options?.maskOptions);
|
|
362
|
+
case 'integer':
|
|
363
|
+
return IntegerCellRenderer;
|
|
364
|
+
case 'float':
|
|
365
|
+
return FloatCellRenderer;
|
|
366
|
+
case 'currency':
|
|
367
|
+
return CurrencyCellRenderer;
|
|
368
|
+
case 'boolean':
|
|
369
|
+
return BooleanCellRenderer;
|
|
370
|
+
case 'date':
|
|
371
|
+
return (params) => DateCellRenderer(params, options?.dateFormat);
|
|
372
|
+
case 'datetime':
|
|
373
|
+
return (params) => DateTimeCellRenderer(params, options?.dateTimeFormat);
|
|
374
|
+
case 'time':
|
|
375
|
+
return (params) => TimeCellRenderer(params, options?.timeFormat);
|
|
376
|
+
case 'enum':
|
|
377
|
+
return (params) => EnumCellRenderer(params, options?.enumValues || []);
|
|
378
|
+
case 'uuid':
|
|
379
|
+
return UUIDCellRenderer;
|
|
380
|
+
case 'image':
|
|
381
|
+
return (params) => ImageCellRenderer(params);
|
|
382
|
+
default:
|
|
383
|
+
return (params) => TextCellRenderer(params);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Get recommended alignment by data type
|
|
389
|
+
*/
|
|
390
|
+
export const getAlignmentByDataType = (
|
|
391
|
+
dataType: FieldDataType,
|
|
392
|
+
customAlign?: 'left' | 'center' | 'right'
|
|
393
|
+
): 'left' | 'center' | 'right' => {
|
|
394
|
+
if (customAlign) {
|
|
395
|
+
return customAlign;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
switch (dataType) {
|
|
399
|
+
case 'integer':
|
|
400
|
+
case 'currency':
|
|
401
|
+
case 'float':
|
|
402
|
+
return 'right';
|
|
403
|
+
case 'boolean':
|
|
404
|
+
case 'date':
|
|
405
|
+
case 'datetime':
|
|
406
|
+
case 'time':
|
|
407
|
+
case 'image':
|
|
408
|
+
return 'center';
|
|
409
|
+
default:
|
|
410
|
+
return 'left';
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Create value formatter for AG Grid column
|
|
416
|
+
*/
|
|
417
|
+
export const createValueFormatter = (
|
|
418
|
+
dataType: FieldDataType,
|
|
419
|
+
options?: {
|
|
420
|
+
dateFormat?: string;
|
|
421
|
+
dateTimeFormat?: string;
|
|
422
|
+
timeFormat?: string;
|
|
423
|
+
enumValues?: Array<{ label: string; value: string }>;
|
|
424
|
+
}
|
|
425
|
+
): ((params: any) => string) | undefined => {
|
|
426
|
+
switch (dataType) {
|
|
427
|
+
case 'date':
|
|
428
|
+
return (params) => {
|
|
429
|
+
if (!params.value) return '';
|
|
430
|
+
try {
|
|
431
|
+
const date = convertISOStringToDate(params.value);
|
|
432
|
+
return format(date, options?.dateFormat || 'dd/MM/yyyy');
|
|
433
|
+
} catch {
|
|
434
|
+
return String(params.value);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
case 'datetime':
|
|
438
|
+
return (params) => {
|
|
439
|
+
if (!params.value) return '';
|
|
440
|
+
try {
|
|
441
|
+
const date = convertISOStringToDate(params.value);
|
|
442
|
+
return format(date, options?.dateTimeFormat || 'dd/MM/yyyy HH:mm:ss');
|
|
443
|
+
} catch {
|
|
444
|
+
return String(params.value);
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
case 'currency':
|
|
448
|
+
return (params) => {
|
|
449
|
+
if (params.value === null || params.value === undefined) return '';
|
|
450
|
+
const numValue = Number.isNaN(Number(params.value)) ? 0 : Number(params.value);
|
|
451
|
+
return new Intl.NumberFormat('pt-BR', {
|
|
452
|
+
style: 'currency',
|
|
453
|
+
currency: 'BRL',
|
|
454
|
+
}).format(numValue);
|
|
455
|
+
};
|
|
456
|
+
case 'enum':
|
|
457
|
+
return (params) => {
|
|
458
|
+
if (params.value === null || params.value === undefined) return '';
|
|
459
|
+
const option = options?.enumValues?.find((opt) => opt.value === params.value);
|
|
460
|
+
return option ? option.label : String(params.value);
|
|
461
|
+
};
|
|
462
|
+
case 'boolean':
|
|
463
|
+
return (params) => {
|
|
464
|
+
if (params.value === null || params.value === undefined) return '';
|
|
465
|
+
return params.value ? 'Sim' : 'Não';
|
|
466
|
+
};
|
|
467
|
+
default:
|
|
468
|
+
return undefined;
|
|
469
|
+
}
|
|
470
|
+
};
|