feat: complete notdienst planning, quick wins and notifications
This commit is contained in:
@@ -26,7 +26,8 @@ import { de } from "date-fns/locale";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { formatDateKey, getWorkingDaysOfMonth } from "@/lib/date-utils";
|
||||
import { formatDateKey, formatUtcDateKey } from "@/lib/date-utils";
|
||||
import { getNotdienstDays } from "@/lib/notdienst-days";
|
||||
import { saveNotdienstAvailabilities } from "./actions";
|
||||
|
||||
export const notdienstEventCategories = {
|
||||
@@ -100,23 +101,21 @@ export function NotdienstForm({
|
||||
}: NotdienstFormProps) {
|
||||
const router = useRouter();
|
||||
// Lokaler State für die Auswahl. Ein Datum liegt als stabiler yyyy-MM-dd-Schlüssel vor.
|
||||
const [selectedDates, setSelectedDates] = useState<Set<string>>(
|
||||
const [selection, setSelectedDates] = useState<Set<string>>(
|
||||
new Set(initialSelectedDates),
|
||||
);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
const closureDateKeys = useMemo(
|
||||
() => getClosureDateKeys(calendarItems),
|
||||
[calendarItems],
|
||||
const selectableDateKeys = useMemo(
|
||||
() => new Set(getNotdienstDays(targetYear, targetMonth,
|
||||
calendarItems.filter((item) => item.category === "closure" || item.category === "team"),
|
||||
).map(formatUtcDateKey)),
|
||||
[calendarItems, targetMonth, targetYear],
|
||||
);
|
||||
const selectedDates = useMemo(
|
||||
() => new Set(Array.from(selection).filter((key) => selectableDateKeys.has(key))),
|
||||
[selection, selectableDateKeys],
|
||||
);
|
||||
const selectableDateKeys = useMemo(() => {
|
||||
const workingDays = getWorkingDaysOfMonth(targetYear, targetMonth);
|
||||
return new Set(
|
||||
workingDays
|
||||
.map(formatDateKey)
|
||||
.filter((dateKey) => !closureDateKeys.has(dateKey)),
|
||||
);
|
||||
}, [closureDateKeys, targetMonth, targetYear]);
|
||||
const monthStart = startOfMonth(new Date(targetYear, targetMonth - 1));
|
||||
const selectedCount = selectedDates.size;
|
||||
const hasMinimumRequirement = requiredDaysTotal > 0;
|
||||
@@ -375,12 +374,9 @@ export function NotdienstCalendar({
|
||||
const isInTargetMonth = isSameMonth(day, visibleMonthStart);
|
||||
const isSelected = selected.has(dateKey);
|
||||
const dayEvents = getCalendarItemsForDay(events, day);
|
||||
const hasClosure = dayEvents.some(
|
||||
(event) => event.category === "closure",
|
||||
);
|
||||
const isSelectable =
|
||||
isInTargetMonth && selectableDateKeys.has(dateKey) && !hasClosure;
|
||||
const isWeekend = day.getDay() === 0 || day.getDay() === 6;
|
||||
const hasClosure = isInTargetMonth && !isWeekend && !selectableDateKeys.has(dateKey);
|
||||
const isSelectable = isInTargetMonth && selectableDateKeys.has(dateKey);
|
||||
|
||||
return (
|
||||
<CalendarTile
|
||||
@@ -603,25 +599,6 @@ function getCalendarItemsForDay(
|
||||
});
|
||||
}
|
||||
|
||||
function getClosureDateKeys(items: NotdienstCalendarItem[]) {
|
||||
const closureKeys = new Set<string>();
|
||||
|
||||
for (const item of items) {
|
||||
if (item.category !== "closure") continue;
|
||||
|
||||
const days = eachDayOfInterval({
|
||||
start: startOfDay(item.startDate),
|
||||
end: startOfDay(item.endDate),
|
||||
});
|
||||
|
||||
for (const day of days) {
|
||||
closureKeys.add(formatDateKey(day));
|
||||
}
|
||||
}
|
||||
|
||||
return closureKeys;
|
||||
}
|
||||
|
||||
function formatEventDate(event: NotdienstCalendarItem) {
|
||||
const date = format(event.startDate, "EEEE, d. MMMM yyyy", { locale: de });
|
||||
return event.allDay
|
||||
|
||||
Reference in New Issue
Block a user