feat: enhance staff management and payment gateway features

- Fix national code handling in staff creation and updates to support Persian digits.
- Update ClinicStaff entity to allow longer national codes (up to 15 characters).
- Implement support for clinic secretaries in SecretaryController, allowing creation without a doctor UUID.
- Add a new endpoint to retrieve doctors associated with a clinic for secretary management.
- Improve appointment management by ensuring doctors are selectable even when no appointments exist.
- Extend PatientController to allow secretaries to create patient records if they have the appropriate permissions.
- Introduce a PriceInput component for better price formatting in forms, supporting Persian digits.
- Add a MockGateway for testing payment processes without real transactions.
- Enhance SMS settings management with an approval flow for post-visit text messages, including new fields for pending text and status.
- Update migrations to reflect changes in database schema for national codes and SMS settings.
This commit is contained in:
hamed
2026-06-15 11:03:56 +03:30
parent 55f646e2d4
commit 5cdcec23a9
32 changed files with 1487 additions and 128 deletions
+16 -3
View File
@@ -551,14 +551,27 @@ export default function AppointmentsPage() {
});
const appointments: Appointment[] = apptQuery.data?.data ?? EMPTY_ARR;
// ── Unique doctors from results (for clinic tabs)
// ── Clinic: load doctors from clinic profile (not derived from appointments)
const clinicDoctorsQuery = useQuery<ApiResponse<{ data: { uuid: string; name: string }[] }>>({
queryKey: ['clinic-doctors', dbUuid],
queryFn: () => api.get(`/api/v1/clinic/doctor-list/${dbUuid}`),
enabled: isClinic && !!dbUuid,
});
const clinicDoctorsList = clinicDoctorsQuery.data?.data?.data ?? [];
// ── Unique doctors from results (for clinic tabs) + merge with clinic list
const doctors = React.useMemo(() => {
const map = new Map<string, string>();
// first from clinic API (authoritative list)
clinicDoctorsList.forEach(d => map.set(d.uuid, d.name));
// then supplement with appointment data (for admin view)
appointments.forEach(a => {
if (a.doctor_uuid && a.doctor_name) map.set(a.doctor_uuid, a.doctor_name);
if (a.doctor_uuid && a.doctor_name && !map.has(a.doctor_uuid)) {
map.set(a.doctor_uuid, a.doctor_name);
}
});
return Array.from(map.entries()).map(([uuid, name]) => ({ uuid, name }));
}, [appointments]);
}, [appointments, clinicDoctorsList]);
const showDoctorTabs = isClinic && doctors.length >= 2;
const showDoctorCol = isAdmin || (isClinic && !selectedDoctorUuid);