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:
hamed
2026-08-02 15:49:01 +03:30
co-authored by Claude Opus 5
parent f144401dd3
commit 9ba4c8d948
6 changed files with 286 additions and 63 deletions
@@ -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 && (