Rebuild the /admin/appointments page visual layer to match the tauri
clinic-pro-tauri "turns" design while keeping all existing data wiring and
backend endpoints unchanged (add/edit/move/transfer-reserve/replace already
supported via PATCH /api/v1/appointment/{uuid} and POST /api/v1/my/appointment).
Frontend (assets/admin):
- Sidebar: نوبتها becomes an expandable parent with sub-items
«نوبت های تایید شده» (/admin/appointments) and «افزودن نوبت»
(/admin/appointments/new); auto-expands on active child. Applied to
admin/clinic/doctor/secretary roles. Adds nav-subitem styling.
- New presentational components under components/appointments/: tauri status
palette (turnStatus), TurnsStatInfo, TurnsViewToggle (sliding), DoctorTabs
(underline), TurnsTimeline (marker rail + status cards, empty slot → افزودن
نوبت), TurnsTable.
- AppointmentsPage recomposed with the new components (stats bar, doctor tabs,
view toggle, timeline/table), preserving queries, filters, pagination,
quick-book modal and the row actions menu.
- AppointmentCreatePage: full-page create form (CreateTurn layout) at
/admin/appointments/new, reusing POST /api/v1/my|admin/appointment.
Tests: TurnsStatInfo, TurnsTimeline, Sidebar (expandable), AppointmentsPage,
AppointmentCreatePage. Backend move/reserve/replace verified green via existing
tests/Appointment/AppointmentUpdateTest + AppointmentWorkflowFieldsTest.
No API endpoints changed → no docs/api change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
99 lines
4.1 KiB
TypeScript
99 lines
4.1 KiB
TypeScript
/**
|
|
* پیکربندی وضعیت نوبتها — رنگها عیناً از طرح tauri (`clinic-pro-tauri`
|
|
* `src/components/turns/Timeline.jsx` → `statusConfig`) برداشته شده و به وضعیتهای
|
|
* واقعی بکاند (Appointment::STATUS_*) نگاشت شدهاند. لیبلها فارسی مطابق همان طرح.
|
|
*/
|
|
export interface TurnStatusConfig {
|
|
label: string;
|
|
bgColor: string;
|
|
darkBgColor: string;
|
|
borderColor: string;
|
|
darkBorderColor: string;
|
|
dotColor: string;
|
|
textColor: string;
|
|
darkTextColor: string;
|
|
}
|
|
|
|
// وضعیتهای بکاند → رنگ طرح tauri.
|
|
const STATUS: Record<string, TurnStatusConfig> = {
|
|
// pending = «ثبت شده» (tauri: registered)
|
|
pending: {
|
|
label: 'ثبت شده',
|
|
bgColor: '#E3F2FD', darkBgColor: 'rgba(85, 89, 206, 0.18)',
|
|
borderColor: '#2196F3', darkBorderColor: 'rgba(199, 206, 244, 0.42)',
|
|
dotColor: '#2196F3', textColor: '#2196F3', darkTextColor: '#C7CEF4',
|
|
},
|
|
// confirmed = «قطعی شده» (tauri: finalized)
|
|
confirmed: {
|
|
label: 'قطعی شده',
|
|
bgColor: '#E0F2F1', darkBgColor: 'rgba(25, 191, 211, 0.14)',
|
|
borderColor: '#009688', darkBorderColor: 'rgba(25, 191, 211, 0.44)',
|
|
dotColor: '#009688', textColor: '#009688', darkTextColor: '#19BFD3',
|
|
},
|
|
// following_up = «در حال پیگیری» (tauri: in_progress)
|
|
following_up: {
|
|
label: 'در حال پیگیری',
|
|
bgColor: '#FFF3E0', darkBgColor: 'rgba(241, 119, 50, 0.16)',
|
|
borderColor: '#FF9800', darkBorderColor: 'rgba(241, 119, 50, 0.46)',
|
|
dotColor: '#FF9800', textColor: '#d87f00', darkTextColor: '#F17732',
|
|
},
|
|
// salon = «سالن»
|
|
salon: {
|
|
label: 'سالن',
|
|
bgColor: '#F3E5F5', darkBgColor: 'rgba(199, 206, 244, 0.16)',
|
|
borderColor: '#9C27B0', darkBorderColor: 'rgba(199, 206, 244, 0.42)',
|
|
dotColor: '#9C27B0', textColor: '#9C27B0', darkTextColor: '#C7CEF4',
|
|
},
|
|
// completed = «ویزیت شده» (tauri: success)
|
|
completed: {
|
|
label: 'ویزیت شده',
|
|
bgColor: '#E8F5E9', darkBgColor: 'rgba(34, 197, 94, 0.14)',
|
|
borderColor: '#4CAF50', darkBorderColor: 'rgba(34, 197, 94, 0.42)',
|
|
dotColor: '#4CAF50', textColor: '#0d9f43', darkTextColor: '#4ADE80',
|
|
},
|
|
// cancel variants = «لغو شده» (tauri: failed)
|
|
cancelled_by_doctor: {
|
|
label: 'لغو شده',
|
|
bgColor: '#fde7e9', darkBgColor: 'rgba(255, 84, 80, 0.16)',
|
|
borderColor: '#ee5c6d', darkBorderColor: 'rgba(255, 84, 80, 0.44)',
|
|
dotColor: '#ee5c6d', textColor: '#ee5c6d', darkTextColor: '#FF7A76',
|
|
},
|
|
cancelled_by_user: {
|
|
label: 'لغو توسط بیمار',
|
|
bgColor: '#fde7e9', darkBgColor: 'rgba(255, 84, 80, 0.16)',
|
|
borderColor: '#ee5c6d', darkBorderColor: 'rgba(255, 84, 80, 0.44)',
|
|
dotColor: '#ee5c6d', textColor: '#ee5c6d', darkTextColor: '#FF7A76',
|
|
},
|
|
// no_show / expired = خنثی (tauri: pending amber-ish → اینجا خاکستری)
|
|
no_show: {
|
|
label: 'غیبت',
|
|
bgColor: '#f4f4f5', darkBgColor: 'rgba(160, 160, 160, 0.14)',
|
|
borderColor: '#9E9E9E', darkBorderColor: 'rgba(160, 160, 160, 0.4)',
|
|
dotColor: '#9E9E9E', textColor: '#757575', darkTextColor: '#A1A1A1',
|
|
},
|
|
expired: {
|
|
label: 'منقضی',
|
|
bgColor: '#f4f4f5', darkBgColor: 'rgba(160, 160, 160, 0.14)',
|
|
borderColor: '#9E9E9E', darkBorderColor: 'rgba(160, 160, 160, 0.4)',
|
|
dotColor: '#9E9E9E', textColor: '#757575', darkTextColor: '#A1A1A1',
|
|
},
|
|
};
|
|
|
|
// اسلات خالی (نوبت جدید) — tauri: empty.
|
|
export const EMPTY_SLOT_CONFIG: TurnStatusConfig = {
|
|
label: 'نوبت جدید',
|
|
bgColor: '#E3F2FD', darkBgColor: 'rgba(85, 89, 206, 0.16)',
|
|
borderColor: '#2196F3', darkBorderColor: 'rgba(199, 206, 244, 0.38)',
|
|
dotColor: '#2196F3', textColor: '#5559ce', darkTextColor: '#C7CEF4',
|
|
};
|
|
|
|
export function turnStatusConfig(status: string): TurnStatusConfig {
|
|
return STATUS[status] ?? EMPTY_SLOT_CONFIG;
|
|
}
|
|
|
|
/** وضعیتهایی که نوبت را «لغوشده» میکنند (برای منطق تایملاین/آمار). */
|
|
export const CANCELLED_STATUSES = new Set([
|
|
'cancelled_by_doctor', 'cancelled_by_user', 'cancelled_by_admin',
|
|
'auto_cancel_unpaid', 'no_show', 'expired',
|
|
]);
|