Add tests and implementation for ServiceDetailPage and PriceInput components
- Implement PriceInput component tests to validate Persian and Arabic numeral handling, input formatting, and controlled behavior. - Create ServiceDetailPage component with detailed service information, including pricing, insurance coverage, and editing capabilities. - Add API tests for service item detail retrieval and coverage synchronization with insurance contracts. - Ensure proper error handling and user feedback for service item retrieval and coverage management.
This commit is contained in:
@@ -3,6 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { ShieldCheckIcon, CheckIcon } from '@heroicons/react/24/outline';
|
||||
import { toast } from 'sonner';
|
||||
import { api } from '../lib/api';
|
||||
import { digitsOnly, parseUserNumberClamped } from '../lib/utils';
|
||||
import Modal from './ui/Modal';
|
||||
import PriceInput from './ui/PriceInput';
|
||||
import type { ServiceItem } from '../types';
|
||||
@@ -46,6 +47,8 @@ function ContractCard({ contract, item }: { contract: TenantInsurance; item: Ser
|
||||
const existing = rows?.find((r) => r.service_item_uuid === item.uuid);
|
||||
|
||||
const [draft, setDraft] = useState<Draft>({ covered: true, coverage_percent: null, franchise_rials: null, ceiling_rials: null });
|
||||
// متن خام فیلد درصد جدا از مقدار عددی نگه داشته میشود تا کاربر بتواند فیلد را خالی کند.
|
||||
const [percentText, setPercentText] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
setDraft(existing
|
||||
@@ -56,6 +59,7 @@ function ContractCard({ contract, item }: { contract: TenantInsurance; item: Ser
|
||||
ceiling_rials: existing.ceiling_rials,
|
||||
}
|
||||
: { covered: true, coverage_percent: null, franchise_rials: null, ceiling_rials: null });
|
||||
setPercentText(existing?.coverage_percent == null ? '' : String(existing.coverage_percent));
|
||||
}, [existing]);
|
||||
|
||||
const saveMut = useMutation({
|
||||
@@ -129,9 +133,14 @@ function ContractCard({ contract, item }: { contract: TenantInsurance; item: Ser
|
||||
<input
|
||||
type="text" inputMode="numeric" dir="ltr" className="input"
|
||||
style={{ height: 40, textAlign: 'left' }}
|
||||
value={draft.coverage_percent ?? ''}
|
||||
placeholder="ارث"
|
||||
onChange={(e) => setDraft((d) => ({ ...d, coverage_percent: e.target.value === '' ? null : Number(e.target.value) }))}
|
||||
value={percentText}
|
||||
placeholder="ارث از قرارداد"
|
||||
onChange={(e) => {
|
||||
const digits = digitsOnly(e.target.value, 3);
|
||||
setPercentText(digits);
|
||||
setDraft((d) => ({ ...d, coverage_percent: parseUserNumberClamped(digits, 0, 100) }));
|
||||
}}
|
||||
onBlur={() => setPercentText(draft.coverage_percent == null ? '' : String(draft.coverage_percent))}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
|
||||
Reference in New Issue
Block a user