106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { useTranslations } from 'next-intl';
|
|
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) {
|
|
const t = useTranslations('staff.workingHours');
|
|
|
|
useEffect(() => {
|
|
onValidationChange?.(validateEditorDays(days, t));
|
|
}, [days, onValidationChange, t]);
|
|
|
|
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">{t('recommendedTitle')}</p>
|
|
<p className="text-sm text-text-secondary mt-1">{t('recommendedBody')}</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);
|
|
|
|
const reset = useCallback((next?: { days: WorkingHoursEditorDay[]; autoRepeatWeekly: boolean }) => {
|
|
setDays(next?.days ?? emptyWorkingHoursEditorDays());
|
|
setAutoRepeatWeekly(next?.autoRepeatWeekly ?? true);
|
|
setValidationError(null);
|
|
}, []);
|
|
|
|
return {
|
|
days,
|
|
setDays,
|
|
autoRepeatWeekly,
|
|
setAutoRepeatWeekly,
|
|
validationError,
|
|
setValidationError,
|
|
reset,
|
|
};
|
|
}
|