refactor: update pricing input handling to use PriceInput component

- Replaced raw input fields for pricing with PriceInput component across various forms and modals to ensure consistent formatting and accessibility.
- Updated tests to reflect changes in pricing input handling, ensuring values are displayed in toman with proper formatting.
- Enhanced accessibility by adding aria-labels and aria-invalid attributes to PriceInput components.
- Adjusted UI elements to improve layout and user experience, particularly in forms related to service items and scheduling.
- Changed labels from "نمایش در نوبت‌دهی" to "نمایش در نوبت‌دهی آنلاین" for clarity.
This commit is contained in:
hamed
2026-08-09 08:38:23 +03:30
parent e48ab9a974
commit b49abee52f
18 changed files with 299 additions and 96 deletions
@@ -115,4 +115,23 @@ describe('PriceInput', () => {
rerender(<PriceInput value={0} onChange={vi.fn()} />);
expect(input().value).toBe('');
});
/**
* برچسبِ کنارِ بعضی فیلدهای مبلغ `<label>` واقعی نیست (span/div)، پس نامِ
* دسترسی‌پذیر باید صریح داده شود؛ پیش از این آن فیلدها input خام بودند و
* `aria-label` خودشان را داشتند.
*/
it('ariaLabel نام دسترسی‌پذیر می‌سازد', () => {
render(<PriceInput value={0} onChange={vi.fn()} ariaLabel="قیمت ویزیت" />);
expect(screen.getByRole('textbox', { name: 'قیمت ویزیت' })).toBeTruthy();
});
it('ariaInvalid فقط در حالت خطا روی فیلد می‌نشیند', () => {
const { rerender } = render(<PriceInput value={0} onChange={vi.fn()} ariaInvalid />);
expect(input().getAttribute('aria-invalid')).toBe('true');
rerender(<PriceInput value={0} onChange={vi.fn()} />);
expect(input().getAttribute('aria-invalid')).toBeNull();
});
});
+11
View File
@@ -14,6 +14,11 @@ interface PriceInputProps {
latin?: boolean;
/** واحد نمایشی داخل فیلد، مثلاً «تومان». */
suffix?: string;
/** وقتی برچسبِ کنار فیلد `<label>` واقعی نیست (span/div)، نامِ دسترسی‌پذیر. */
ariaLabel?: string;
/** حالت خطا برای صفحه‌خوان — معادل `aria-invalid` روی input خام. */
ariaInvalid?: boolean;
id?: string;
}
function formatDisplay(num: number, latin: boolean): string {
@@ -44,6 +49,9 @@ export default function PriceInput({
max,
latin = false,
suffix,
ariaLabel,
ariaInvalid,
id,
}: PriceInputProps) {
const [text, setText] = useState(() => textFromValue(value, latin));
const textRef = useRef(text);
@@ -77,6 +85,9 @@ export default function PriceInput({
<input
type="text"
inputMode="numeric"
id={id}
aria-label={ariaLabel}
aria-invalid={ariaInvalid || undefined}
value={text}
onChange={handleChange}
onBlur={handleBlur}