feat(settings): manage resource schedules beside the doctors'
A resource carries its own working hours and holidays in the resource-first model, so it belongs on the same settings page as a doctor's schedule rather than on a page of its own. The page now has a scope switch — doctors or resources — with the per-item tab bar below it, and both scopes reuse the panels that already existed: ScheduleSection for a doctor, the working-hours and exceptions panels for a resource. The selection lives in the query string, so back and refresh return to the same tab. The screenshot of the finished tab caught two real defects, both fixed here: Dates in the resource panels and the holidays page read as year 57932. formatDate already multiplies seconds by 1000, and five call sites passed `x * 1000` on top of it. This predates the tab — the code was inherited from the old calendar page — but it was invisible until a two-week preview was put on screen. The working-hours panel still told the user their hours were intersected with the branch's. Branches are gone; the shift is the only source now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@ export default function NationalHolidaysCard({ canUpdate, year = currentJalaliYe
|
||||
|
||||
return (
|
||||
<div className="card" style={{ padding: 14 }}>
|
||||
<h2 className="section-title" style={{ margin: '0 0 4px' }}>تعطیلات رسمی {year}</h2>
|
||||
<h2 className="section-title" style={{ margin: '0 0 4px' }}>تعطیلات رسمی {year.toLocaleString('fa-IR', { useGrouping: false })}</h2>
|
||||
<p style={{ fontSize: 12, color: 'var(--text-3)', margin: '0 0 10px', lineHeight: 1.9 }}>
|
||||
اینها برای همهٔ پزشکان و منابع اعمال میشوند. اگر این محیط روزی را باز است،
|
||||
همینجا استثنا بزنید — مدیریت کاملشان در{' '}
|
||||
@@ -37,7 +37,7 @@ export default function NationalHolidaysCard({ canUpdate, year = currentJalaliYe
|
||||
<span style={{ fontSize: 13, color: 'var(--text-3)' }}>در حال بارگذاری...</span>
|
||||
) : holidays.length === 0 ? (
|
||||
<p style={{ fontSize: 13, color: 'var(--text-3)', margin: 0 }}>
|
||||
برای سال {year} تعطیلی رسمی ثبت نشده است.
|
||||
برای سال {year.toLocaleString('fa-IR', { useGrouping: false })} تعطیلی رسمی ثبت نشده است.
|
||||
</p>
|
||||
) : (
|
||||
<div style={{ display: 'grid', gap: 8 }}>
|
||||
@@ -51,7 +51,7 @@ export default function NationalHolidaysCard({ canUpdate, year = currentJalaliYe
|
||||
{open ? 'باز' : 'تعطیل'}
|
||||
</span>
|
||||
<span style={{ flex: 1, color: 'var(--text-2)' }}>
|
||||
{formatDate(h.date * 1000)} · {h.title}
|
||||
{formatDate(h.date)} · {h.title}
|
||||
</span>
|
||||
{canUpdate && (
|
||||
open ? (
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function ResourceExceptionsPanel({ resourceUuid, canUpdate }: {
|
||||
style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, fontSize: 13 }}
|
||||
>
|
||||
<span style={{ color: 'var(--text-2)' }}>
|
||||
{DAY_LABELS[day.day_of_week]} · {formatDate(day.date * 1000)}
|
||||
{DAY_LABELS[day.day_of_week]} · {formatDate(day.date)}
|
||||
</span>
|
||||
{day.intervals.length === 0 ? (
|
||||
<span style={{ fontSize: 12, color: 'var(--text-3)' }}>
|
||||
@@ -139,7 +139,7 @@ function ExceptionsCard({
|
||||
<div key={e.uuid} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
|
||||
<span className="badge amber" style={{ fontSize: 11 }}>{e.type_label}</span>
|
||||
<span style={{ flex: 1, color: 'var(--text-2)' }}>
|
||||
{formatDate(e.starts_at * 1000)} تا {formatDate(e.ends_at * 1000)}
|
||||
{formatDate(e.starts_at)} تا {formatDate(e.ends_at)}
|
||||
{e.reason ? ` · ${e.reason}` : ''}
|
||||
</span>
|
||||
{canUpdate && (
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
|
||||
import { useResourceCalendar } from '../../hooks/useResourceCalendar';
|
||||
|
||||
/** ۰ = شنبه — همان قرارداد بکاند و ساعت کاری شعبه. */
|
||||
/** ۰ = شنبه — همان قرارداد بکاند برای روزهای هفته. */
|
||||
export const DAY_LABELS = ['شنبه', 'یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه'];
|
||||
|
||||
const MINUTES_IN_DAY = 1440;
|
||||
@@ -23,8 +23,8 @@ function toMinutes(time: string): number | null {
|
||||
/**
|
||||
* شیفت هفتگی یک منبع — روزهای کاری و ساعت هر روز.
|
||||
*
|
||||
* ساعت واقعی منبع تقاطع این شیفتها با ساعت کاری شعبه است، نه خودشان؛ پس شیفتِ
|
||||
* بیرون از ساعت شعبه ذخیره میشود ولی در دسترسپذیری اثری ندارد.
|
||||
* با حذف دامنهٔ شعبه، این شیفت تنها مرجع ساعت کاری منبع است؛ فقط تعطیلات رسمی و
|
||||
* استثناهای خودِ منبع از آن کسر میشوند.
|
||||
*/
|
||||
export default function ResourceWorkingHoursPanel({ resourceUuid, canUpdate }: {
|
||||
resourceUuid?: string;
|
||||
@@ -88,8 +88,7 @@ export default function ResourceWorkingHoursPanel({ resourceUuid, canUpdate }: {
|
||||
<div style={{ display: 'grid', gap: 12 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
|
||||
<p style={{ margin: 0, fontSize: 12.5, color: 'var(--text-3)' }}>
|
||||
روزهای کاری و ساعت هر روز. ساعت واقعی از تقاطع این شیفتها با ساعت کاری شعبه بهدست
|
||||
میآید و تعطیلات و مرخصی از آن کسر میشود.
|
||||
روزهای کاری و ساعت هر روز. تعطیلات رسمی و مرخصی از همین ساعت کسر میشوند.
|
||||
{totalShifts > 0 && <> · {totalShifts} شیفت</>}
|
||||
</p>
|
||||
{canUpdate && (
|
||||
|
||||
Reference in New Issue
Block a user