mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
feat(FE-Storyless): add FieldMessage component for consistent field feedback across inputs
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
|
||||
import { Icon } from '@iconify/react';
|
||||
import { cn } from '@/lib/helper';
|
||||
import FieldMessage from '@/components/helper/FieldMessage';
|
||||
|
||||
// Utility Functions
|
||||
const formatNumber = (
|
||||
@@ -25,7 +26,10 @@ const formatNumber = (
|
||||
if (isNaN(numValue)) return '';
|
||||
|
||||
const parts = numValue.toFixed(decimals).split('.');
|
||||
const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
|
||||
const integerPart = parts[0].replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
thousandSeparator
|
||||
);
|
||||
const decimalPart = parts[1];
|
||||
|
||||
return decimals > 0 && decimalPart
|
||||
@@ -180,11 +184,13 @@ const NumberInput = ({
|
||||
const [displayValue, setDisplayValue] = useState<string>('');
|
||||
|
||||
// Determine if decimals are allowed based on maskType
|
||||
const allowDecimal = maskType === 'decimal' || maskType === 'weight' || decimals > 0;
|
||||
const allowDecimal =
|
||||
maskType === 'decimal' || maskType === 'weight' || decimals > 0;
|
||||
|
||||
// Format value for display based on maskType
|
||||
const getFormattedValue = (rawValue: number | string): string => {
|
||||
if (rawValue === '' || rawValue === null || rawValue === undefined) return '';
|
||||
if (rawValue === '' || rawValue === null || rawValue === undefined)
|
||||
return '';
|
||||
|
||||
switch (maskType) {
|
||||
case 'currency':
|
||||
@@ -193,7 +199,12 @@ const NumberInput = ({
|
||||
return formatWeight(rawValue, weightUnit, decimals);
|
||||
case 'decimal':
|
||||
case 'number':
|
||||
return formatNumber(rawValue, decimals, thousandSeparator, decimalSeparator);
|
||||
return formatNumber(
|
||||
rawValue,
|
||||
decimals,
|
||||
thousandSeparator,
|
||||
decimalSeparator
|
||||
);
|
||||
default:
|
||||
return String(rawValue);
|
||||
}
|
||||
@@ -216,10 +227,18 @@ const NumberInput = ({
|
||||
}
|
||||
|
||||
// Clean input
|
||||
const cleaned = cleanNumericInput(inputValue, allowDecimal, decimalSeparator);
|
||||
const cleaned = cleanNumericInput(
|
||||
inputValue,
|
||||
allowDecimal,
|
||||
decimalSeparator
|
||||
);
|
||||
|
||||
// Parse to number
|
||||
let numericValue = parseNumber(cleaned, thousandSeparator, decimalSeparator);
|
||||
let numericValue = parseNumber(
|
||||
cleaned,
|
||||
thousandSeparator,
|
||||
decimalSeparator
|
||||
);
|
||||
|
||||
// Apply validation
|
||||
if (!allowNegative && numericValue < 0) {
|
||||
@@ -262,7 +281,11 @@ const NumberInput = ({
|
||||
const handleIncrement = () => {
|
||||
if (disabled || readOnly) return;
|
||||
|
||||
const currentValue = parseNumber(displayValue, thousandSeparator, decimalSeparator);
|
||||
const currentValue = parseNumber(
|
||||
displayValue,
|
||||
thousandSeparator,
|
||||
decimalSeparator
|
||||
);
|
||||
let newValue = currentValue + step;
|
||||
|
||||
// Apply max validation
|
||||
@@ -296,7 +319,11 @@ const NumberInput = ({
|
||||
const handleDecrement = () => {
|
||||
if (disabled || readOnly) return;
|
||||
|
||||
const currentValue = parseNumber(displayValue, thousandSeparator, decimalSeparator);
|
||||
const currentValue = parseNumber(
|
||||
displayValue,
|
||||
thousandSeparator,
|
||||
decimalSeparator
|
||||
);
|
||||
let newValue = currentValue - step;
|
||||
|
||||
// Apply min validation (prevent negative if not allowed)
|
||||
@@ -329,6 +356,9 @@ const NumberInput = ({
|
||||
}
|
||||
};
|
||||
|
||||
const showErrorMessage = Boolean(isError && errorMessage);
|
||||
const feedbackMessage = showErrorMessage ? errorMessage : bottomLabel;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -431,12 +461,11 @@ const NumberInput = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isError && bottomLabel && (
|
||||
<p className='w-full text-sm opacity-60'>{bottomLabel}</p>
|
||||
)}
|
||||
{isError && errorMessage && (
|
||||
<p className='w-full text-sm text-error'>{errorMessage}</p>
|
||||
)}
|
||||
<FieldMessage
|
||||
message={feedbackMessage}
|
||||
tone={showErrorMessage ? 'error' : 'info'}
|
||||
isVisible={showErrorMessage || Boolean(bottomLabel)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user