feat: add supplementary insurance select to patient record info form
The «اطلاعات پرونده» form only exposed basic insurance («نوع بیمه»). Add a
«بیمه تکمیلی» select next to it, wired to the supplementary insurances from
insurance-pricing. Backend PATCH /api/v1/patient/{uuid} already accepts
supplementary_insurance_id (UserProfile entity + controller) — frontend-only:
schema field, form select, profileToFormValues/formValuesToPayload mapping,
PatientProfileUpdate type, and the supplementary option passed from both the
case-file info tab (PatientDetailPage) and MyPatientsPage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ const options: PatientFormOptions = {
|
||||
marital: [{ value: 'single', label: 'مجرد' }],
|
||||
education: [{ value: 'bachelor', label: 'کارشناسی' }],
|
||||
insurance: [{ value: 3, label: 'تأمین اجتماعی' }],
|
||||
supplementary: [{ value: 5, label: 'بیمه دانا' }],
|
||||
province: [{ value: 8, label: 'یزد' }],
|
||||
city: [{ value: 42, label: 'یزد' }],
|
||||
referral: [{ value: 'instagram', label: 'اینستاگرام' }],
|
||||
@@ -25,6 +26,7 @@ const baseValues: PatientFormValues = {
|
||||
fathers_name: '',
|
||||
marital_status: null,
|
||||
basic_insurance_id: null,
|
||||
supplementary_insurance_id: null,
|
||||
field_of_study: '',
|
||||
education: null,
|
||||
job: '',
|
||||
@@ -54,6 +56,8 @@ describe('PatientRecordInfoForm', () => {
|
||||
it('برچسبهای اصلی و شماره پروندهٔ read-only را رندر میکند', () => {
|
||||
setup();
|
||||
expect(screen.getByText('نام و نام خانوادگی مراجعه کننده')).toBeInTheDocument();
|
||||
expect(screen.getByText('بیمه پایه')).toBeInTheDocument();
|
||||
expect(screen.getByText('بیمه تکمیلی')).toBeInTheDocument();
|
||||
expect(screen.getByText('نحوه آشنایی')).toBeInTheDocument();
|
||||
expect((screen.getByDisplayValue('123456789') as HTMLInputElement).readOnly).toBe(true);
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ export const patientFormSchema = z.object({
|
||||
fathers_name: z.string(),
|
||||
marital_status: z.string().nullable(),
|
||||
basic_insurance_id: z.union([z.number(), z.string(), z.null()]),
|
||||
supplementary_insurance_id: z.union([z.number(), z.string(), z.null()]),
|
||||
field_of_study: z.string(),
|
||||
education: z.string().nullable(),
|
||||
job: z.string(),
|
||||
@@ -42,6 +43,7 @@ export interface PatientFormOptions {
|
||||
marital: SelectOption[];
|
||||
education: SelectOption[];
|
||||
insurance: SelectOption[];
|
||||
supplementary: SelectOption[];
|
||||
province: SelectOption[];
|
||||
city: SelectOption[];
|
||||
referral: SelectOption[];
|
||||
@@ -140,7 +142,8 @@ export default function PatientRecordInfoForm({
|
||||
</Field>
|
||||
|
||||
{sel('marital_status', 'وضعیت تاهل', options.marital)}
|
||||
{sel('basic_insurance_id', 'نوع بیمه', options.insurance)}
|
||||
{sel('basic_insurance_id', 'بیمه پایه', options.insurance)}
|
||||
{sel('supplementary_insurance_id', 'بیمه تکمیلی', options.supplementary)}
|
||||
|
||||
<Field label="رشته تحصیلی">
|
||||
<Input {...register('field_of_study')} placeholder="رشته تحصیلی را وارد نمایید" />
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('formValuesToPayload', () => {
|
||||
const base: PatientFormValues = {
|
||||
name: 'ساغر', mobile: '', national_code: '0012345678', gender: 'female',
|
||||
birth_date: '2000-05-10', fathers_name: 'رضا', marital_status: 'single',
|
||||
basic_insurance_id: '3', field_of_study: 'نرمافزار', education: 'کارشناسی',
|
||||
basic_insurance_id: '3', supplementary_insurance_id: '5', field_of_study: 'نرمافزار', education: 'کارشناسی',
|
||||
job: 'مهندس', province_id: 8, city_id: '42', home_phone: '', address: 'یزد',
|
||||
postal_code: '8913746351', referral_source: 'اینستاگرام', description: '',
|
||||
};
|
||||
@@ -58,6 +58,7 @@ describe('formValuesToPayload', () => {
|
||||
const out = formValuesToPayload(base);
|
||||
expect(out.date_of_birth).toBe(dateStrToTs('2000-05-10'));
|
||||
expect(out.basic_insurance_id).toBe(3);
|
||||
expect(out.supplementary_insurance_id).toBe(5);
|
||||
expect(out.province_id).toBe(8);
|
||||
expect(out.city_id).toBe(42);
|
||||
});
|
||||
|
||||
@@ -42,6 +42,7 @@ export function profileToFormValues(p: PatientProfile | null): PatientFormValues
|
||||
fathers_name: p?.fathers_name ?? '',
|
||||
marital_status: p?.marital_status ?? null,
|
||||
basic_insurance_id: p?.basic_insurance_id ?? null,
|
||||
supplementary_insurance_id: p?.supplementary_insurance_id ?? null,
|
||||
field_of_study: p?.field_of_study ?? '',
|
||||
education: p?.education ?? null,
|
||||
job: p?.job ?? '',
|
||||
@@ -70,6 +71,7 @@ export function formValuesToPayload(v: PatientFormValues): PatientProfileUpdate
|
||||
field_of_study: v.field_of_study,
|
||||
job: v.job,
|
||||
basic_insurance_id: num(v.basic_insurance_id),
|
||||
supplementary_insurance_id: num(v.supplementary_insurance_id),
|
||||
province_id: num(v.province_id),
|
||||
city_id: num(v.city_id),
|
||||
home_phone: v.home_phone,
|
||||
|
||||
@@ -1176,6 +1176,7 @@ function MyPatientsPageInner() {
|
||||
education: EDUCATION_OPTS,
|
||||
referral: REFERRAL_OPTS,
|
||||
insurance: baseInsuranceOptions,
|
||||
supplementary: suppInsuranceOptions,
|
||||
province: locOpts(provincesQ.data),
|
||||
city: locOpts(citiesQ.data),
|
||||
}}
|
||||
|
||||
@@ -29,7 +29,10 @@ beforeEach(() => {
|
||||
if (url === '/api/v1/provinces') return Promise.resolve({ success: true, data: [{ id: 10, name: 'یزد' }] });
|
||||
if (url.startsWith('/api/v1/cities')) return Promise.resolve({ success: true, data: [{ id: 100, name: 'یزد' }] });
|
||||
if (url === '/api/v1/insurance-pricing') return Promise.resolve({ success: true, data: {
|
||||
insurances: [{ insurance_id: 1, insurance_name: 'تأمین اجتماعی', type: 'basic' }],
|
||||
insurances: [
|
||||
{ insurance_id: 1, insurance_name: 'تأمین اجتماعی', type: 'basic' },
|
||||
{ insurance_id: 5, insurance_name: 'بیمه دانا', type: 'supplementary' },
|
||||
],
|
||||
} });
|
||||
if (url === '/api/v1/patient/r1/sessions') return Promise.resolve({ success: true, data: [
|
||||
{ uuid: 's1', services: [{ service_name: 'اسکیلینگ' }], doctor_name: 'دکتر فتحی', final_price_rials: 2500000, is_paid: false, patient_debt_rials: 1500000, notes: 'یادداشت', created_at: 1700000000, visit_price_rials: 0 },
|
||||
@@ -104,6 +107,8 @@ describe('PatientDetailPage (پرونده تبدار)', () => {
|
||||
// لیبل فیلدهای فرم (معادل tauri FileInfoSection)
|
||||
expect(await screen.findByText('نام و نام خانوادگی مراجعه کننده')).toBeInTheDocument();
|
||||
expect(screen.getByText('کدملی')).toBeInTheDocument();
|
||||
expect(screen.getByText('بیمه پایه')).toBeInTheDocument();
|
||||
expect(screen.getByText('بیمه تکمیلی')).toBeInTheDocument();
|
||||
// مقادیر پیشپرشده از پروفایل
|
||||
expect(screen.getByDisplayValue('1234567890')).toBeInTheDocument();
|
||||
expect(screen.getByDisplayValue('ساغر صابری')).toBeInTheDocument();
|
||||
|
||||
@@ -108,6 +108,9 @@ export default function PatientDetailPage() {
|
||||
const baseInsuranceOptions = ((pricingQ.data?.data as any)?.insurances ?? [])
|
||||
.filter((i: any) => i.type === 'basic')
|
||||
.map((i: any) => ({ value: String(i.insurance_id), label: i.insurance_name }));
|
||||
const suppInsuranceOptions = ((pricingQ.data?.data as any)?.insurances ?? [])
|
||||
.filter((i: any) => i.type === 'supplementary')
|
||||
.map((i: any) => ({ value: String(i.insurance_id), label: i.insurance_name }));
|
||||
|
||||
const updateProfileMut = useMutation({
|
||||
mutationFn: (body: object) => api.patch(`/api/v1/patient/${uuid}`, body),
|
||||
@@ -195,6 +198,7 @@ export default function PatientDetailPage() {
|
||||
education: EDUCATION_OPTS,
|
||||
referral: REFERRAL_OPTS,
|
||||
insurance: baseInsuranceOptions,
|
||||
supplementary: suppInsuranceOptions,
|
||||
province: locOpts(provincesQ.data),
|
||||
city: locOpts(citiesQ.data),
|
||||
}}
|
||||
|
||||
@@ -531,6 +531,7 @@ export interface PatientProfileUpdate {
|
||||
field_of_study?: string | null;
|
||||
job?: string | null;
|
||||
basic_insurance_id?: number | null;
|
||||
supplementary_insurance_id?: number | null;
|
||||
province_id?: number | null;
|
||||
city_id?: number | null;
|
||||
home_phone?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user