Files
clinicpro/assets/admin/components/ui/PriceInput.tsx
T
hamed 5cdcec23a9 feat: enhance staff management and payment gateway features
- Fix national code handling in staff creation and updates to support Persian digits.
- Update ClinicStaff entity to allow longer national codes (up to 15 characters).
- Implement support for clinic secretaries in SecretaryController, allowing creation without a doctor UUID.
- Add a new endpoint to retrieve doctors associated with a clinic for secretary management.
- Improve appointment management by ensuring doctors are selectable even when no appointments exist.
- Extend PatientController to allow secretaries to create patient records if they have the appropriate permissions.
- Introduce a PriceInput component for better price formatting in forms, supporting Persian digits.
- Add a MockGateway for testing payment processes without real transactions.
- Enhance SMS settings management with an approval flow for post-visit text messages, including new fields for pending text and status.
- Update migrations to reflect changes in database schema for national codes and SMS settings.
2026-06-15 11:03:56 +03:30

64 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useEffect, useState } from 'react';
interface PriceInputProps {
value: number | '';
onChange: (value: number) => void;
placeholder?: string;
className?: string;
style?: React.CSSProperties;
disabled?: boolean;
min?: number;
}
const PERSIAN_TO_LATIN: Record<string, string> = {
'۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4',
'۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9',
'٠': '0', '١': '1', '٢': '2', '٣': '3', '٤': '4',
'٥': '5', '٦': '6', '٧': '7', '٨': '8', '٩': '9',
};
function toLatinDigits(str: string): string {
return str.replace(/[۰-۹٠-٩]/g, (ch) => PERSIAN_TO_LATIN[ch] ?? ch);
}
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 = toLatinDigits(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}
/>
);
}