Files
rota/src/routes/state.svelte.ts

152 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// state.svelte.ts
import { CalendarDate, getDayOfWeek } from "@internationalized/date";
export interface Resident {
id: string;
name: string;
negativeShifts: CalendarDate[];
manualShifts: CalendarDate[];
maxShifts: number | undefined;
allowedTypes: string[];
reducedLoad: boolean;
}
export interface ForbiddenPair {
id1: string;
id2: string;
}
export class RotaState {
currentStep = $state(1);
residents = $state<Resident[]>([]);
selectedMonth = $state(2);
selectedYear = $state(2026);
holidays = $state<CalendarDate[]>([]);
forbiddenPairs = $state<ForbiddenPair[]>([]);
projectMonth = $state(new CalendarDate(2026, 2, 1));
syncProjectMonth() {
this.projectMonth = new CalendarDate(this.selectedYear, this.selectedMonth, 1);
}
projectMonthDays = $derived(this.projectMonth.calendar.getDaysInMonth(this.projectMonth));
daysArray = $derived(Array.from({ length: this.projectMonthDays }, (_, i) => i + 1));
emptySlots = $derived(Array.from({ length: getDayOfWeek(this.projectMonth, "en-GB") }));
solution = $state<MonthlySchedule>({} as MonthlySchedule);
addResident() {
this.residents.push({
id: crypto.randomUUID(),
name: "",
negativeShifts: [],
manualShifts: [],
maxShifts: undefined,
allowedTypes: ["Closed", "OpenFirst", "OpenSecond"],
reducedLoad: false
});
}
removeResident(id: string) {
this.residents = this.residents.filter((r) => r.id !== id);
}
findResident(id: string) {
return this.residents.find((r) => r.id === id);
}
addForbiddenPair() {
if (this.residents.length < 2) return;
this.forbiddenPairs.push({
id1: this.residents[0].id,
id2: this.residents[1].id
});
}
removeForbiddenPair(index: number) {
this.forbiddenPairs.splice(index, 1);
}
toDTO(): UserConfigDTO {
return {
month: this.selectedMonth,
year: this.selectedYear,
holidays: this.holidays.map((d) => d.day),
residents: this.residents.map((r) => ({
id: r.id,
name: r.name,
negativeShifts: r.negativeShifts.map((d) => d.day),
manualShifts: r.manualShifts.map((s) => ({
day: s.day,
position: "First"
})),
maxShifts: r.maxShifts ?? null,
allowedTypes: r.allowedTypes as ShiftType[],
reducedLoad: r.reducedLoad
})),
toxic_pairs: this.forbiddenPairs.map((pair) => [pair.id1, pair.id2])
};
}
}
export const rota = new RotaState();
export type MonthlyScheduleDTO = {
schedule: Record<number, Record<ShiftPosition, string>>;
};
export type UserConfigDTO = {
month: number;
year: number;
holidays: Array<number>;
residents: Array<ResidentDTO>;
toxic_pairs: Array<[string, string]>;
};
export type ResidentDTO = {
id: string;
name: string;
negativeShifts: Array<number>;
manualShifts: Array<{ day: number; position: ShiftPosition }>;
maxShifts: number | null;
allowedTypes: Array<ShiftType>;
reducedLoad: boolean;
};
export type ShiftType = "Closed" | "OpenFirst" | "OpenSecond";
export type ShiftPosition = "First" | "Second";
export type SlotKey = `${number}-${"First" | "Second"}`;
export type MonthlySchedule = { [key: SlotKey]: string };
export const steps = [
{
id: 1,
title: "Περίοδος",
description: "Καθόρισε την περίοδο και τις αργίες του μήνα."
},
{
id: 2,
title: "Ειδικευόμενοι",
description: "Δημιούργησε νέα εγγραφή ειδικευόμενου."
},
{
id: 3,
title: "Προχωρημένα",
description: "Επίλεξε ζευγάρια ατόμων που δεν μπορούν να κάνουν μαζί εφημερία."
},
{
id: 4,
title: "Επισκόπηση",
description: "Έλεγξε το πρόγραμμα με τις υποχρεωτικές υπάρχουσες εφημερίες."
},
{
id: 5,
title: "Δημιουργία",
description: "Τρέξε τον αλγόριθμο ανάθεσης εφημεριών, εξήγαγε τα αποτελέσματα."
}
];