feat: add currency input field and enhance currency formatting utilities
- Introduced `FieldCurrencyInput` component for handling currency input in forms, supporting formatted display while maintaining numeric values. - Implemented `RenderCurrency` component for displaying currency values with proper formatting. - Enhanced `CurrencyUtils` to include parsing and formatting functions for Rupiah, ensuring accurate representation in UI. - Updated various components and forms to utilize the new currency input and rendering capabilities, improving user experience in financial data entry. - Added unit tests for currency input and formatting functionalities to ensure reliability and correctness. These changes enhance the application's handling of currency inputs and displays, providing a more user-friendly experience for financial transactions.
This commit is contained in:
@@ -1,20 +1,53 @@
|
||||
import { z } from 'zod';
|
||||
import { CURRENCY_DATA_SCALE } from '@repo/utils';
|
||||
|
||||
const DECIMAL_PATTERN = /^\d+(\.\d{1,4})?$/;
|
||||
export const PRICE_DECIMAL_SCALE = CURRENCY_DATA_SCALE;
|
||||
export const QUANTITY_DECIMAL_SCALE = 4;
|
||||
|
||||
function emptyToUndefined(value: unknown) {
|
||||
function coerceDecimalInput(value: unknown) {
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
return Number.isFinite(value) ? String(value) : value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function decimalStringSchema(t: (key: string) => string, fieldKey = 'common:fields.price') {
|
||||
return z.string().regex(DECIMAL_PATTERN, {
|
||||
message: JSON.stringify({ key: 'validation:invalid_format', values: { field: t(fieldKey) } }),
|
||||
});
|
||||
export function toDecimalStringValue(value: unknown): string | undefined {
|
||||
const next = coerceDecimalInput(value);
|
||||
return typeof next === 'string' ? next : undefined;
|
||||
}
|
||||
|
||||
export function optionalDecimalStringSchema(t: (key: string) => string, fieldKey = 'common:fields.price') {
|
||||
return z.preprocess(emptyToUndefined, decimalStringSchema(t, fieldKey).optional());
|
||||
function decimalPattern(maxDecimals: number) {
|
||||
return new RegExp(`^\\d+(\\.\\d{1,${maxDecimals}})?$`);
|
||||
}
|
||||
|
||||
export function decimalStringSchema(
|
||||
t: (key: string) => string,
|
||||
fieldKey = 'common:fields.price',
|
||||
maxDecimals = QUANTITY_DECIMAL_SCALE,
|
||||
) {
|
||||
return z.preprocess(
|
||||
coerceDecimalInput,
|
||||
z.string().regex(decimalPattern(maxDecimals), {
|
||||
message: JSON.stringify({ key: 'validation:invalid_format', values: { field: t(fieldKey) } }),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function optionalDecimalStringSchema(
|
||||
t: (key: string) => string,
|
||||
fieldKey = 'common:fields.price',
|
||||
maxDecimals = PRICE_DECIMAL_SCALE,
|
||||
) {
|
||||
return z.preprocess(
|
||||
coerceDecimalInput,
|
||||
z
|
||||
.string()
|
||||
.regex(decimalPattern(maxDecimals), {
|
||||
message: JSON.stringify({ key: 'validation:invalid_format', values: { field: t(fieldKey) } }),
|
||||
})
|
||||
.optional(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user