feat: toggle new-patient form on appointment create page

Show name/phone/national-code fields only after clicking 'مراجعه کننده جدید';
hide the existing-patient search while in new-patient mode, with a
'انتخاب از لیست موجود' link to switch back. Update tests to click the
toggle before filling the fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-16 09:33:16 +03:30
co-authored by Claude Opus 4.8
parent 6e040402e1
commit a40fb7e598
2 changed files with 68 additions and 43 deletions
@@ -26,6 +26,7 @@ describe('AppointmentCreatePage — افزودن نوبت', () => {
it('posts a new appointment with the entered patient (happy path)', async () => { it('posts a new appointment with the entered patient (happy path)', async () => {
renderWithProviders(<AppointmentCreatePage />, { route: '/admin/appointments/new' }); renderWithProviders(<AppointmentCreatePage />, { route: '/admin/appointments/new' });
fireEvent.click(screen.getByText('مراجعه کننده جدید'));
fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'علی محمدی' } }); fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'علی محمدی' } });
fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '09121234567' } }); fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '09121234567' } });
fireEvent.change(screen.getByPlaceholderText('کد ملی مراجعه کننده'), { target: { value: '1234567891' } }); fireEvent.change(screen.getByPlaceholderText('کد ملی مراجعه کننده'), { target: { value: '1234567891' } });
@@ -49,6 +50,7 @@ describe('AppointmentCreatePage — افزودن نوبت', () => {
renderWithProviders(<AppointmentCreatePage />, { route: '/admin/appointments/new' }); renderWithProviders(<AppointmentCreatePage />, { route: '/admin/appointments/new' });
fireEvent.click(screen.getByText('مراجعه کننده جدید'));
fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'علی محمدی' } }); fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'علی محمدی' } });
fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '09121234567' } }); fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '09121234567' } });
fireEvent.change(screen.getByPlaceholderText('کد ملی مراجعه کننده'), { target: { value: '1234567891' } }); fireEvent.change(screen.getByPlaceholderText('کد ملی مراجعه کننده'), { target: { value: '1234567891' } });
@@ -70,6 +72,10 @@ describe('AppointmentCreatePage — افزودن نوبت', () => {
const btn = screen.getByText('ثبت اطلاعات') as HTMLButtonElement; const btn = screen.getByText('ثبت اطلاعات') as HTMLButtonElement;
expect(btn).toBeDisabled(); expect(btn).toBeDisabled();
// فیلدهای مراجعه‌کنندهٔ جدید تا کلیک روی دکمه پنهان‌اند
expect(screen.queryByPlaceholderText('نام و نام خانوادگی مراجعه کننده')).toBeNull();
fireEvent.click(screen.getByText('مراجعه کننده جدید'));
// شماره ناقص → همچنان غیرفعال // شماره ناقص → همچنان غیرفعال
fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'ب' } }); fireEvent.change(screen.getByPlaceholderText('نام و نام خانوادگی مراجعه کننده'), { target: { value: 'ب' } });
fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '0912' } }); fireEvent.change(screen.getByPlaceholderText('شماره تماس مراجعه کننده'), { target: { value: '0912' } });
+22 -3
View File
@@ -55,6 +55,7 @@ export default function AppointmentCreatePage() {
// ── بیمار: جستجوی رکورد موجود یا ورود شخص جدید // ── بیمار: جستجوی رکورد موجود یا ورود شخص جدید
const [patientSearch, setPatientSearch] = useState(''); const [patientSearch, setPatientSearch] = useState('');
const [picked, setPicked] = useState<PatientRow | null>(null); const [picked, setPicked] = useState<PatientRow | null>(null);
const [newPatient, setNewPatient] = useState(false); // فرم «مراجعه کننده جدید» فعال است؟
const [name, setName] = useState(''); const [name, setName] = useState('');
const [mobile, setMobile] = useState(''); const [mobile, setMobile] = useState('');
const [nationalCode, setNationalCode] = useState(''); const [nationalCode, setNationalCode] = useState('');
@@ -172,6 +173,10 @@ export default function AppointmentCreatePage() {
{/* مراجعه کننده */} {/* مراجعه کننده */}
<div style={{ ...sectionTitle, marginTop: isDoctor ? 0 : 18 }}>اطلاعات مراجعه کننده :</div> <div style={{ ...sectionTitle, marginTop: isDoctor ? 0 : 18 }}>اطلاعات مراجعه کننده :</div>
{/* حالت جستجوی مراجعه‌کنندهٔ موجود */}
{!newPatient && (
<>
<label style={label}>انتخاب مراجعه کننده</label> <label style={label}>انتخاب مراجعه کننده</label>
<div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 12, margin: '6px 0 8px' }}> <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 12, margin: '6px 0 8px' }}>
<div className="field" style={{ width: 400, maxWidth: '100%' }}> <div className="field" style={{ width: 400, maxWidth: '100%' }}>
@@ -180,7 +185,8 @@ export default function AppointmentCreatePage() {
onChange={e => { setPicked(null); setPatientSearch(e.target.value); }} onChange={e => { setPicked(null); setPatientSearch(e.target.value); }}
placeholder="جستجوی نام، شماره تماس، شماره پرونده..." /> placeholder="جستجوی نام، شماره تماس، شماره پرونده..." />
</div> </div>
<button type="button" className="btn outline" onClick={() => { setPicked(null); setPatientSearch(''); }} <button type="button" className="btn outline"
onClick={() => { setPicked(null); setPatientSearch(''); setNewPatient(true); }}
style={{ height: 44, minWidth: 161, gap: 6 }}> style={{ height: 44, minWidth: 161, gap: 6 }}>
<PlusIcon style={{ width: 16, height: 16 }} /> مراجعه کننده جدید <PlusIcon style={{ width: 16, height: 16 }} /> مراجعه کننده جدید
</button> </button>
@@ -197,8 +203,20 @@ export default function AppointmentCreatePage() {
))} ))}
</div> </div>
)} )}
{picked === null && ( </>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginTop: 8 }}> )}
{/* حالت ثبت مراجعه‌کنندهٔ جدید */}
{newPatient && (
<>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', margin: '2px 0 6px' }}>
<span style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-2)' }}>مراجعه کننده جدید</span>
<button type="button" className="btn sm ghost"
onClick={() => { setName(''); setMobile(''); setNationalCode(''); setNewPatient(false); }}>
انتخاب از لیست موجود
</button>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginTop: 4 }}>
<div> <div>
<label style={label}>نام و نام خانوادگی مراجعه کننده</label> <label style={label}>نام و نام خانوادگی مراجعه کننده</label>
<div className="field" style={{ marginTop: 6, height: 44 }}> <div className="field" style={{ marginTop: 6, height: 44 }}>
@@ -219,6 +237,7 @@ export default function AppointmentCreatePage() {
</div> </div>
</div> </div>
</div> </div>
</>
)} )}
{/* مشخصات سرویس */} {/* مشخصات سرویس */}