- Add a numeric prop to the base Input component that sets inputMode, dir=ltr, lang=en and normalizes Persian/Arabic digits to Latin via the shared toEnglishDigits on every change. - Dedupe digit conversion: PriceInput now uses toEnglishDigits instead of its local map; AppointmentsPage mobile handler uses sanitizeMobileInput. - Fix raw national-code / mobile inputs in NewAppointmentModal and NewAppointmentDrawer that stripped Persian digits without converting. - Cover the numeric Input behaviour with unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { toEnglishDigits } from '../../lib/utils';
|
|
|
|
interface PriceInputProps {
|
|
value: number | '';
|
|
onChange: (value: number) => void;
|
|
placeholder?: string;
|
|
className?: string;
|
|
style?: React.CSSProperties;
|
|
disabled?: boolean;
|
|
min?: number;
|
|
}
|
|
|
|
function formatDisplay(num: number): string {
|
|
if (num === 0) return '';
|
|
return new Intl.NumberFormat('fa-IR').format(num);
|
|
}
|
|
|
|
export default function PriceInput({
|
|
value,
|
|
onChange,
|
|
placeholder = '0',
|
|
className,
|
|
style,
|
|
disabled,
|
|
min = 0,
|
|
}: PriceInputProps) {
|
|
const [display, setDisplay] = useState(() => (value !== '' && value > 0 ? formatDisplay(value) : ''));
|
|
|
|
useEffect(() => {
|
|
setDisplay(value !== '' && Number(value) > 0 ? formatDisplay(Number(value)) : '');
|
|
}, [value]);
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const raw = toEnglishDigits(e.target.value).replace(/[^0-9]/g, '');
|
|
const num = raw === '' ? 0 : Math.max(min, parseInt(raw, 10));
|
|
onChange(num);
|
|
setDisplay(num > 0 ? formatDisplay(num) : '');
|
|
};
|
|
|
|
return (
|
|
<input
|
|
type="text"
|
|
inputMode="numeric"
|
|
value={display}
|
|
onChange={handleChange}
|
|
placeholder={placeholder}
|
|
className={className}
|
|
style={{ textAlign: 'left', direction: 'ltr', ...style }}
|
|
disabled={disabled}
|
|
/>
|
|
);
|
|
}
|