diff --git a/ui/src/components/AvailabilityCard.tsx b/ui/src/components/AvailabilityCard.tsx
index f829b62..52247a5 100644
--- a/ui/src/components/AvailabilityCard.tsx
+++ b/ui/src/components/AvailabilityCard.tsx
@@ -2,7 +2,7 @@ import { useState } from "react";
import { Switch } from "@ui/ui-library/switch";
import { Text } from "@ui/ui-library/text";
import { Button } from "@ui/ui-library/button";
-import { MinusIcon, PlusIcon } from "@ui/ui-library/icons";
+import { MinusIcon, PlusIcon, CopyIcon } from "@ui/ui-library/icons";
import {
Select,
SelectButton,
@@ -22,6 +22,11 @@ interface AvailabilityCardProps {
onEnabledChange: (enabled: boolean) => void;
timeRanges: TimeRange[];
onTimeRangesChange: (ranges: TimeRange[]) => void;
+ onCopyToOtherDays?: (
+ sourceDay: number,
+ enabled: boolean,
+ timeRanges: TimeRange[]
+ ) => void;
}
const MINUTES_IN_DAY = 24 * 60;
@@ -146,6 +151,7 @@ export function AvailabilityCard({
onEnabledChange,
timeRanges,
onTimeRangesChange,
+ onCopyToOtherDays,
}: AvailabilityCardProps) {
const dayDisplay = DAYS_OF_WEEK_DISPLAY[day];
@@ -239,6 +245,17 @@ export function AvailabilityCard({
{dayDisplay}
+ {onCopyToOtherDays && enabled && timeRanges.length > 0 && (
+
+ )}
void;
+ title: string;
+ children: React.ReactNode;
+}
+
+function CustomModal({ isOpen, onClose, title, children }: CustomModalProps) {
+ if (!isOpen) return null;
+
+ return (
+
+ {/* Backdrop */}
+
+
+ {/* Modal */}
+
+ {/* Header */}
+
+
+ {title}
+
+
+
+
+ {/* Content */}
+
{children}
+
+
+ );
+}
const DAYS_OF_WEEK = [0, 1, 2, 3, 4, 5, 6];
+const DAYS_OF_WEEK_DISPLAY = [
+ "Lundi",
+ "Mardi",
+ "Mercredi",
+ "Jeudi",
+ "Vendredi",
+ "Samedi",
+ "Dimanche",
+];
+
+interface TimeRange {
+ start: string;
+ end: string;
+}
export function AvailabilitiesPage() {
const {
@@ -19,6 +88,47 @@ export function AvailabilitiesPage() {
setDraftAvailabilities,
} = useAvailabilities();
+ const [copyModalOpen, setCopyModalOpen] = useState(false);
+ const [sourceDayData, setSourceDayData] = useState<{
+ day: number;
+ enabled: boolean;
+ timeRanges: TimeRange[];
+ } | null>(null);
+ const [selectedDays, setSelectedDays] = useState([]);
+
+ const handleCopyToOtherDays = (
+ sourceDay: number,
+ enabled: boolean,
+ timeRanges: TimeRange[]
+ ) => {
+ setSourceDayData({ day: sourceDay, enabled, timeRanges });
+ setSelectedDays([]);
+ setCopyModalOpen(true);
+ };
+
+ const applyCopyToSelectedDays = () => {
+ if (!sourceDayData) return;
+
+ const updatedAvailabilities = { ...draftAvailabilities };
+ selectedDays.forEach((day) => {
+ updatedAvailabilities[day] = {
+ enabled: sourceDayData.enabled,
+ timeRanges: [...sourceDayData.timeRanges],
+ };
+ });
+
+ setDraftAvailabilities(updatedAvailabilities);
+ setCopyModalOpen(false);
+ setSourceDayData(null);
+ setSelectedDays([]);
+
+ toast.add({
+ title: "Succès",
+ description: `Horaires copiés vers ${selectedDays.length} jour(s)`,
+ type: "success",
+ });
+ };
+
return (
@@ -91,6 +201,7 @@ export function AvailabilitiesPage() {
},
});
}}
+ onCopyToOtherDays={handleCopyToOtherDays}
/>
@@ -164,6 +275,57 @@ export function AvailabilitiesPage() {
{isUpdating ? "Enregistrement..." : "Enregistrer les disponibilités"}
+
+ {/* Copy Modal */}
+
setCopyModalOpen(false)}
+ title={`Copier les horaires de ${
+ sourceDayData ? DAYS_OF_WEEK_DISPLAY[sourceDayData.day] : ""
+ }`}
+ >
+
+
+ Sélectionnez les jours vers lesquels vous souhaitez copier ces
+ horaires :
+
+
+
+ {DAYS_OF_WEEK.filter((day) => day !== sourceDayData?.day).map(
+ (day) => (
+ {
+ if (isSelected) {
+ setSelectedDays([...selectedDays, day]);
+ } else {
+ setSelectedDays(selectedDays.filter((d) => d !== day));
+ }
+ }}
+ >
+
+ {DAYS_OF_WEEK_DISPLAY[day]}
+
+
+ )
+ )}
+
+
+
+
+
+
+
+
);
}