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:
@@ -12,6 +12,7 @@ import { formatRial, formatNumber, formatDate, formatResourceLimit } from '../li
|
||||
import Modal from '../components/ui/Modal';
|
||||
import ConfirmDialog from '../components/ui/ConfirmDialog';
|
||||
import PageHeader from '../components/ui/PageHeader';
|
||||
import PriceInput from '../components/ui/PriceInput';
|
||||
import Pagination from '../components/ui/Pagination';
|
||||
import { numericField } from '../lib/forms';
|
||||
|
||||
@@ -369,7 +370,11 @@ function PlansTab() {
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>قیمت (ریال) *</label>
|
||||
<input {...numericField(periodForm.register('price_rials'))} />
|
||||
<PriceInput
|
||||
value={periodForm.watch('price_rials') ?? ''}
|
||||
onChange={(v) => periodForm.setValue('price_rials', v)}
|
||||
ariaLabel="قیمت دوره (ریال)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
|
||||
|
||||
@@ -40,6 +40,7 @@ import Modal from "../components/ui/Modal";
|
||||
import PageHeader from "../components/ui/PageHeader";
|
||||
import Pagination from "../components/ui/Pagination";
|
||||
import SearchableSelect from "../components/ui/SearchableSelect";
|
||||
import PriceInput from "../components/ui/PriceInput";
|
||||
import PatientRecordInfoForm from "../components/PatientRecordInfoForm";
|
||||
import { usePermissions } from "../hooks/usePermissions";
|
||||
import {
|
||||
@@ -1470,8 +1471,10 @@ function MyPatientsPageInner() {
|
||||
>
|
||||
<div className="field">
|
||||
<label>قیمت ویزیت (تومان)</label>
|
||||
<input
|
||||
{...numericField(form.register("visit_price_rials"))}
|
||||
<PriceInput
|
||||
value={watchVisit || ''}
|
||||
onChange={(v) => form.setValue("visit_price_rials", v)}
|
||||
ariaLabel="قیمت ویزیت (تومان)"
|
||||
/>
|
||||
</div>
|
||||
<div className="field">
|
||||
|
||||
@@ -62,7 +62,7 @@ const FIELD_LABELS: Record<string, string> = {
|
||||
price_rials: 'قیمت پایه',
|
||||
active: 'وضعیت',
|
||||
duration_minutes: 'زمان متوسط',
|
||||
bookable: 'نمایش در نوبتدهی',
|
||||
bookable: 'نمایش در نوبتدهی آنلاین',
|
||||
insurance_covered: 'پوشش بیمه',
|
||||
inventory_package: 'پکیج کالا',
|
||||
};
|
||||
@@ -112,7 +112,7 @@ function InfoTab({ item }: { item: ServiceItem }) {
|
||||
? <span className="badge blue" style={{ fontSize: 11 }}>{formatNumber(Number(item.duration_minutes))} دقیقه</span>
|
||||
: '—'}
|
||||
</Row>
|
||||
<Row icon={<CalendarDaysIcon style={{ width: 15 }} />} label="نمایش در نوبتدهی">
|
||||
<Row icon={<CalendarDaysIcon style={{ width: 15 }} />} label="نمایش در نوبتدهی آنلاین">
|
||||
{item.bookable
|
||||
? <span className="badge green" style={{ fontSize: 11 }}>فعال</span>
|
||||
: <span className="badge gray" style={{ fontSize: 11 }}>غیرفعال</span>}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from '@heroicons/react/24/outline';
|
||||
import ConfirmDialog from '../components/ui/ConfirmDialog';
|
||||
import Switch from '../components/ui/Switch';
|
||||
import PriceInput from '../components/ui/PriceInput';
|
||||
|
||||
interface TaxHistoryRow {
|
||||
tax_percent: number;
|
||||
@@ -436,13 +437,27 @@ export default function SettingsPage() {
|
||||
<div className="settings-grid" style={{ marginTop: 18 }}>
|
||||
<Field label="مبلغ هر نوبت" hint="مبلغی که بیمار هنگام رزرو آنلاین پرداخت میکند (تومان).">
|
||||
<div className="input-suffix">
|
||||
<input {...numericField(register('appointment_fee_rials'))} className="input" style={{ maxWidth: 200 }} placeholder="15000" />
|
||||
<PriceInput
|
||||
className="input"
|
||||
style={{ maxWidth: 200 }}
|
||||
ariaLabel="مبلغ هر نوبت (تومان)"
|
||||
placeholder="۱۵,۰۰۰"
|
||||
value={watch('appointment_fee_rials') ? Number(watch('appointment_fee_rials')) : ''}
|
||||
onChange={(v) => setValue('appointment_fee_rials', String(v), { shouldDirty: true })}
|
||||
/>
|
||||
<span className="suf">تومان</span>
|
||||
</div>
|
||||
</Field>
|
||||
<Field label="هزینه ثابت پنل پیامک" hint="از مبلغ هر تراکنش کسر میشود (تومان).">
|
||||
<div className="input-suffix">
|
||||
<input {...numericField(register('sms_panel_fee_rials'))} className="input" style={{ maxWidth: 200 }} placeholder="150000" />
|
||||
<PriceInput
|
||||
className="input"
|
||||
style={{ maxWidth: 200 }}
|
||||
ariaLabel="هزینه ثابت پنل پیامک (تومان)"
|
||||
placeholder="۱۵۰,۰۰۰"
|
||||
value={watch('sms_panel_fee_rials') ? Number(watch('sms_panel_fee_rials')) : ''}
|
||||
onChange={(v) => setValue('sms_panel_fee_rials', String(v), { shouldDirty: true })}
|
||||
/>
|
||||
<span className="suf">تومان</span>
|
||||
</div>
|
||||
</Field>
|
||||
@@ -532,7 +547,14 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
</Field>
|
||||
<Field label="هزینه هر پیامک" hint="مبلغ کسرشده از کیف پول به ازای هر پیامک ارسالی (تومان). مبنای محاسبهٔ تعداد پیامک از موجودی.">
|
||||
<input {...numericField(register('sms_price_rials'))} className="input" style={{ maxWidth: 200 }} placeholder="50" />
|
||||
<PriceInput
|
||||
className="input"
|
||||
style={{ maxWidth: 200 }}
|
||||
ariaLabel="هزینه هر پیامک (تومان)"
|
||||
placeholder="۵۰"
|
||||
value={watch('sms_price_rials') ? Number(watch('sms_price_rials')) : ''}
|
||||
onChange={(v) => setValue('sms_price_rials', String(v), { shouldDirty: true })}
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { usePaymentConfig } from '../hooks/usePaymentConfig';
|
||||
import { formatRial, formatNumber, formatDateTime, tomanToRial } from '../lib/utils';
|
||||
import Modal from '../components/ui/Modal';
|
||||
import Pagination from '../components/ui/Pagination';
|
||||
import PriceInput from '../components/ui/PriceInput';
|
||||
import SearchableSelect from '../components/ui/SearchableSelect';
|
||||
import PageHeader from '../components/ui/PageHeader';
|
||||
import FeatureGate from '../components/ui/FeatureGate';
|
||||
@@ -536,9 +537,11 @@ function SmsWalletPageInner() {
|
||||
|
||||
<div className="field">
|
||||
<label>مبلغ (تومان)</label>
|
||||
<input
|
||||
{...numericField(chargeForm.register('amount_rials'))}
|
||||
placeholder="50000"
|
||||
<PriceInput
|
||||
value={watchAmount ?? ''}
|
||||
onChange={(v) => chargeForm.setValue('amount_rials', v, { shouldValidate: true })}
|
||||
placeholder="۵۰,۰۰۰"
|
||||
ariaLabel="مبلغ شارژ (تومان)"
|
||||
/>
|
||||
{chargeForm.formState.errors.amount_rials && (
|
||||
<span className="field-error">{chargeForm.formState.errors.amount_rials.message}</span>
|
||||
|
||||
Reference in New Issue
Block a user