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.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user