/** * «لیست نوبت‌های جدید» table — ported from clinic-pro-tauri * `src/components/dashboard/list/` (CustomTable + DetailT + Status). * * Source data was static mock; here it is fed by the real dashboard API * (`/api/v1/dashboard/{clinic,doctor}` → `today_appointments`). Statuses are * clinicpro's real appointment statuses, mapped to the source's pill palette. */ import React from 'react'; import { Link } from 'react-router-dom'; import { ChevronDownIcon } from './dashboardIcons'; export interface ApptRow { uuid: string; patient_name: string | null; patient_mobile?: string | null; doctor_name?: string | null; service_name?: string | null; slot_start: number; slot_end?: number | null; status: string; } interface StatusStyle { label: string; /** text + chevron color */ fg: string; /** pill background classes (light + dark) */ bg: string; } /** * Map a clinicpro appointment status to the source pill palette * (green/amber/blue/violet/red pastels). Unknown → neutral gray. */ const STATUS_STYLE: Record = { visited: { label: 'ویزیت شده', fg: '#3c9a4f', bg: 'bg-[#e4f2ea] dark:bg-[#324A32]' }, completed: { label: 'تکمیل شده', fg: '#3c9a4f', bg: 'bg-[#e4f2ea] dark:bg-[#324A32]' }, reserved: { label: 'رزرو شده', fg: '#0088ff', bg: 'bg-[#E3F2FD] dark:bg-[#1A2836]' }, checked_in: { label: 'ورود به مطب', fg: '#0088ff', bg: 'bg-[#E3F2FD] dark:bg-[#1A2836]' }, waiting_for_payment: { label: 'انتظار پرداخت', fg: '#f59e0b', bg: 'bg-[#FFF3E0] dark:bg-[#3E2E1B]' }, waiting: { label: 'صف انتظار', fg: '#f59e0b', bg: 'bg-[#FFF3E0] dark:bg-[#3E2E1B]' }, in_progress: { label: 'در حال ویزیت', fg: '#7c3aed', bg: 'bg-[#F3E5F5] dark:bg-[#2D1B36]' }, cancelled_by_doctor: { label: 'لغو پزشک', fg: '#d32f2f', bg: 'bg-[#fde7e9] dark:bg-[rgba(255,84,80,0.20)]' }, cancelled_by_user: { label: 'لغو بیمار', fg: '#d32f2f', bg: 'bg-[#fde7e9] dark:bg-[rgba(255,84,80,0.20)]' }, auto_cancel_unpaid: { label: 'لغو خودکار', fg: '#d32f2f', bg: 'bg-[#fde7e9] dark:bg-[rgba(255,84,80,0.20)]' }, no_show: { label: 'غیبت', fg: '#d32f2f', bg: 'bg-[#fde7e9] dark:bg-[rgba(255,84,80,0.20)]' }, }; function StatusChip({ status }: { status: string }) { const s = STATUS_STYLE[status] ?? { label: status, fg: '#616161', bg: 'bg-[#EFEFEF] dark:bg-[#35343D]' }; return (
{s.label}
); } function formatTime(ts?: number | null): string { if (!ts) return '—'; return new Date(ts * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }); } const HEAD = ['ردیف', 'نام بیمار', 'شماره تماس', 'شروع', 'پایان', 'سرویس', 'پرسنل', 'وضعیت', 'عملیات']; export function NewAppointmentsTable({ rows, loading }: { rows: ApptRow[]; loading?: boolean }) { if (loading) { return
; } if (!rows.length) { return (

نوبتی برای امروز ثبت نشده

); } return (
{HEAD.map((h, i) => ( ))} {rows.map((r, idx) => ( {new Intl.NumberFormat('fa-IR').format(idx + 1)}{r.patient_name || '—'}{r.patient_mobile || '—'}{formatTime(r.slot_start)}{formatTime(r.slot_end)}{r.service_name || '—'}{r.doctor_name ? `دکتر ${r.doctor_name}` : '—'} ))}
{h}
مشاهده
); } function Cell({ children, className = '', dir }: { children: React.ReactNode; className?: string; dir?: 'ltr' | 'rtl' }) { return ( {children} ); }