Files
clinicpro/assets/admin/components/dashboard/NewAppointmentsTable.tsx
T
hamed 62a9fd87c3 feat: Implement Jalali calendar support for dashboard charts
- Added support for Jalali calendar in the dashboard, allowing charts to display data based on the current Jalali month and year.
- Updated the API to return `patients_year`, `patients_month`, and `revenue_year` parameters for the dashboard charts.
- Refactored the dashboard controller to handle Jalali date calculations and queries.
- Modified the frontend components to utilize the new Jalali date parameters and reflect changes in the UI.
- Removed the status column from the NewAppointmentsTable as status management is now handled on the appointments page.
- Added tests to ensure the correct functioning of the new Jalali chart period features.
2026-07-18 21:44:01 +03:30

95 lines
3.6 KiB
TypeScript

/**
* «لیست نوبت‌های جدید» 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`). Read-only —
* status display/editing lives on the appointments page, not the dashboard.
*/
import React from 'react';
import { Link } from 'react-router-dom';
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;
}
function formatTime(ts?: number | null): string {
if (!ts) return '—';
return new Intl.DateTimeFormat('fa-IR', { timeZone: 'Asia/Tehran', hour: '2-digit', minute: '2-digit' }).format(new Date(ts * 1000));
}
const HEAD = ['ردیف', 'نام بیمار', 'شماره تماس', 'شروع', 'پایان', 'سرویس', 'پرسنل', 'عملیات'];
export function NewAppointmentsTable({ rows, loading }: { rows: ApptRow[]; loading?: boolean }) {
if (loading) {
return <div className="skeleton h-[180px] rounded-[8px]" />;
}
if (!rows.length) {
return (
<p className="text-center py-[32px] text-[13.5px] text-[#7E7E7E] dark:text-[#A1A1A1]">
نوبتی برای امروز ثبت نشده
</p>
);
}
return (
<div className="w-full overflow-x-auto rounded-[8px] border border-solid border-[#E7E7E7] dark:border-[#35343D]">
<table className="w-full border-collapse">
<thead>
<tr className="bg-[#EFEFEF] dark:bg-[#35343D]">
{HEAD.map((h, i) => (
<th
key={h}
className={`text-[#616161] dark:text-[#D7D8ED] text-[14px] font-normal py-[10px] px-[18px] whitespace-nowrap ${i === 0 ? 'text-right' : 'text-start'}`}
>
{h}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((r, idx) => (
<tr
key={r.uuid}
className="border-b border-[#DBDBDB] dark:border-transparent hover:bg-[#f4f5fd] dark:hover:bg-[#2a2c3d] transition-colors"
>
<Cell className="text-right">{new Intl.NumberFormat('fa-IR').format(idx + 1)}</Cell>
<Cell className="text-start">{r.patient_name || '—'}</Cell>
<Cell className="text-start" dir="ltr">{r.patient_mobile || '—'}</Cell>
<Cell className="text-right" dir="ltr">{formatTime(r.slot_start)}</Cell>
<Cell className="text-right" dir="ltr">{formatTime(r.slot_end)}</Cell>
<Cell className="text-right">{r.service_name || '—'}</Cell>
<Cell className="text-start">{r.doctor_name ? `دکتر ${r.doctor_name}` : '—'}</Cell>
<td className="py-[10px] px-[18px] text-center">
<Link
to="/admin/appointments"
className="text-[#5559ce] text-[12px] font-medium hover:underline whitespace-nowrap"
>
مشاهده
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
function Cell({ children, className = '', dir }: { children: React.ReactNode; className?: string; dir?: 'ltr' | 'rtl' }) {
return (
<td
dir={dir}
className={`text-[#616161] dark:text-[#A1A1A1] text-[16px] font-medium py-[10px] px-[18px] whitespace-nowrap ${className}`}
>
{children}
</td>
);
}