refactor(ui): unify selects via SearchableSelect (session form + contracts)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { TrashIcon, PlusIcon, PencilIcon } from '@heroicons/react/24/outline';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { api } from '../lib/api';
|
import { api } from '../lib/api';
|
||||||
import { formatRial } from '../lib/utils';
|
import { formatRial } from '../lib/utils';
|
||||||
|
import SearchableSelect from './ui/SearchableSelect';
|
||||||
|
|
||||||
interface Contract {
|
interface Contract {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
@@ -129,12 +130,15 @@ export default function TenantInsuranceContracts() {
|
|||||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'flex-end', padding: 14, borderRadius: 10, border: '1px solid var(--border)', background: 'var(--surface)', marginBottom: 14 }}>
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'flex-end', padding: 14, borderRadius: 10, border: '1px solid var(--border)', background: 'var(--surface)', marginBottom: 14 }}>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||||
<label style={{ fontSize: 11.5, fontWeight: 600 }}>بیمه</label>
|
<label style={{ fontSize: 11.5, fontWeight: 600 }}>بیمه</label>
|
||||||
<select className="input" style={{ minWidth: 160 }} value={insuranceId} disabled={!!editUuid} onChange={(e) => setInsuranceId(e.target.value)}>
|
<div style={{ minWidth: 200 }}>
|
||||||
<option value="">انتخاب...</option>
|
<SearchableSelect
|
||||||
{(editUuid ? allInsurances : available).map((i) => (
|
options={(editUuid ? allInsurances : available).map((i) => ({ value: String(i.insurance_id), label: `${i.insurance_name} (${KIND_LABEL[i.type] ?? i.type})` }))}
|
||||||
<option key={i.insurance_id} value={i.insurance_id}>{i.insurance_name} ({KIND_LABEL[i.type] ?? i.type})</option>
|
value={insuranceId}
|
||||||
))}
|
onChange={(v) => setInsuranceId(v ? String(v) : '')}
|
||||||
</select>
|
isDisabled={!!editUuid}
|
||||||
|
placeholder="انتخاب..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||||
<label style={{ fontSize: 11.5, fontWeight: 600 }}>درصد پوشش</label>
|
<label style={{ fontSize: 11.5, fontWeight: 600 }}>درصد پوشش</label>
|
||||||
|
|||||||
@@ -159,17 +159,11 @@ export default function NewSessionPage() {
|
|||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 12 }}>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 12 }}>
|
||||||
<div>
|
<div>
|
||||||
<label style={fieldLabel}>بیمه پایه</label>
|
<label style={fieldLabel}>بیمه پایه</label>
|
||||||
<select className="input" value={baseId} onChange={e => applyBase(e.target.value)}>
|
<SearchableSelect options={baseOpts} value={baseId} onChange={v => applyBase(v ? String(v) : '')} placeholder="بدون بیمه پایه" isClearable />
|
||||||
<option value="">بدون بیمه پایه</option>
|
|
||||||
{baseOpts.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label style={fieldLabel}>بیمه تکمیلی</label>
|
<label style={fieldLabel}>بیمه تکمیلی</label>
|
||||||
<select className="input" value={suppId} onChange={e => applySupp(e.target.value)}>
|
<SearchableSelect options={suppOpts} value={suppId} onChange={v => applySupp(v ? String(v) : '')} placeholder="بدون بیمه تکمیلی" isClearable />
|
||||||
<option value="">بدون بیمه تکمیلی</option>
|
|
||||||
{suppOpts.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
|
||||||
@@ -221,9 +215,12 @@ export default function NewSessionPage() {
|
|||||||
<h3 style={sectionTitle}>پرداخت و یادداشت</h3>
|
<h3 style={sectionTitle}>پرداخت و یادداشت</h3>
|
||||||
<div style={{ marginBottom: 12 }}>
|
<div style={{ marginBottom: 12 }}>
|
||||||
<label style={fieldLabel}>روش پرداخت</label>
|
<label style={fieldLabel}>روش پرداخت</label>
|
||||||
<select className="input" {...form.register('payment_method')}>
|
<SearchableSelect
|
||||||
{Object.entries(PAYMENT_LABELS).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
|
options={Object.entries(PAYMENT_LABELS).map(([v, l]) => ({ value: v, label: l }))}
|
||||||
</select>
|
value={form.watch('payment_method')}
|
||||||
|
onChange={v => form.setValue('payment_method', (v as FormData['payment_method']) || 'cash')}
|
||||||
|
placeholder="روش پرداخت"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label style={fieldLabel}>یادداشت</label>
|
<label style={fieldLabel}>یادداشت</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user