feat: redesign insurance pricing page with tabbed navigation for basic and supplementary insurance, expandable rows for contract details, and move free visit price card to appointment settings

This commit is contained in:
hamed
2026-07-15 14:55:16 +03:30
parent 3e5dee0ad5
commit 9f75aeedf5
8 changed files with 495 additions and 96 deletions
+14 -12
View File
@@ -76,6 +76,8 @@ interface Props {
editContract: Contract | null;
/** Insurance catalog options; in edit mode all are shown, in add mode only the available ones. */
options: InsuranceOption[];
/** Insurance kind of the active tab ('basic'|'supplementary'); assigned to new contracts, not user-editable. */
kind: string;
onClose: () => void;
onSubmit: (payload: ReturnType<typeof buildInsurancePayload>) => void;
isPending?: boolean;
@@ -86,13 +88,13 @@ interface Props {
* state, emits the built payload via onSubmit. Fields mirror the Figma "افزودن بیمه"
* modal plus the injected coverage/franchise/ceiling controls.
*/
export default function InsuranceModal({ open, editContract, options, onClose, onSubmit, isPending }: Props) {
export default function InsuranceModal({ open, editContract, options, kind, onClose, onSubmit, isPending }: Props) {
const [form, setForm] = useState<InsuranceFormValues>(EMPTY_FORM);
useEffect(() => {
if (!open) return;
setForm(editContract ? contractToForm(editContract) : EMPTY_FORM);
}, [open, editContract]);
setForm(editContract ? contractToForm(editContract) : { ...EMPTY_FORM, kind });
}, [open, editContract, kind]);
const set = (patch: Partial<InsuranceFormValues>) => setForm((f) => ({ ...f, ...patch }));
const isEdit = editContract !== null;
@@ -127,7 +129,15 @@ export default function InsuranceModal({ open, editContract, options, onClose, o
>
<div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
<div style={field}>
<label style={label}>نام بیمه</label>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
<label style={label}>نام بیمه</label>
<span style={{
fontSize: 11, fontWeight: 600, padding: '2px 10px', borderRadius: 'var(--r-pill)',
background: 'var(--primary-soft)', color: 'var(--primary)',
}}>
{KIND_LABEL[form.kind] ?? form.kind}
</span>
</div>
<SearchableSelect
options={options.map((i) => ({ value: String(i.insurance_id), label: i.insurance_name }))}
value={form.insuranceId}
@@ -137,14 +147,6 @@ export default function InsuranceModal({ open, editContract, options, onClose, o
/>
</div>
<div style={field}>
<label style={label}>نوع بیمه</label>
<select className="input" value={form.kind} onChange={(e) => set({ kind: e.target.value })}>
<option value="basic">پایه</option>
<option value="supplementary">تکمیلی</option>
</select>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
<div style={field}>
<label style={label}>تاریخ شروع قرارداد</label>