feature: users with treatment edit permission should now have working hours defined. the appointment grid is now being drawn based on the doctor's working hours.

This commit is contained in:
2026-06-10 19:44:09 +03:30
parent 468572a50f
commit 48ecfd05e1
22 changed files with 1571 additions and 116 deletions

View File

@@ -0,0 +1,103 @@
'use client';
import { useEffect, useState } from 'react';
import { WorkingHoursEditor } from '@/components/staff/WorkingHoursEditor';
import {
blocksFromEditorDays,
editorDaysFromBlocks,
emptyWorkingHoursEditorDays,
validateEditorDays,
type WorkingHoursEditorDay,
} from '@/components/staff/workingHours';
interface StaffWorkingHoursStepProps {
days: WorkingHoursEditorDay[];
autoRepeatWeekly: boolean;
onDaysChange: (days: WorkingHoursEditorDay[]) => void;
onAutoRepeatWeeklyChange: (value: boolean) => void;
onValidationChange?: (error: string | null) => void;
disabled?: boolean;
}
export function StaffWorkingHoursStep({
days,
autoRepeatWeekly,
onDaysChange,
onAutoRepeatWeeklyChange,
onValidationChange,
disabled,
}: StaffWorkingHoursStepProps) {
useEffect(() => {
onValidationChange?.(validateEditorDays(days));
}, [days, onValidationChange]);
return (
<div className="space-y-3">
<div className="rounded-[var(--radius-md)] border border-primary/25 bg-primary/5 px-3 py-3">
<p className="text-sm text-text-primary font-medium">Working hours recommended</p>
<p className="text-sm text-text-secondary mt-1">
Staff with treatment edit access appear as provider columns in Appointments. Set their
weekly hours so the schedule grid shows the right bookable times.
</p>
</div>
<WorkingHoursEditor
days={days}
autoRepeatWeekly={autoRepeatWeekly}
onDaysChange={onDaysChange}
onAutoRepeatWeeklyChange={onAutoRepeatWeeklyChange}
disabled={disabled}
/>
</div>
);
}
export function createDefaultWorkingHoursState() {
return {
days: emptyWorkingHoursEditorDays(),
autoRepeatWeekly: true,
};
}
export function workingHoursPayloadFromState(state: {
days: WorkingHoursEditorDay[];
autoRepeatWeekly: boolean;
}) {
return {
autoRepeatWeekly: state.autoRepeatWeekly,
blocks: blocksFromEditorDays(state.days),
};
}
export function workingHoursStateFromApi(data: {
autoRepeatWeekly: boolean;
blocks: { dayOfWeek: number; startMinute: number; endMinute: number; sortOrder?: number }[];
}) {
const hasBlocks = data.blocks.length > 0;
return {
days: hasBlocks ? editorDaysFromBlocks(data.blocks) : emptyWorkingHoursEditorDays(),
autoRepeatWeekly: data.autoRepeatWeekly,
};
}
export function useWorkingHoursForm(initial?: {
days: WorkingHoursEditorDay[];
autoRepeatWeekly: boolean;
}) {
const [days, setDays] = useState(initial?.days ?? emptyWorkingHoursEditorDays());
const [autoRepeatWeekly, setAutoRepeatWeekly] = useState(initial?.autoRepeatWeekly ?? true);
const [validationError, setValidationError] = useState<string | null>(null);
return {
days,
setDays,
autoRepeatWeekly,
setAutoRepeatWeekly,
validationError,
setValidationError,
reset(next?: { days: WorkingHoursEditorDay[]; autoRepeatWeekly: boolean }) {
setDays(next?.days ?? emptyWorkingHoursEditorDays());
setAutoRepeatWeekly(next?.autoRepeatWeekly ?? true);
setValidationError(null);
},
};
}