mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-05 12:41:27 +00:00
fix: Mise à jour des plannings
This commit is contained in:
@ -9,6 +9,7 @@ import EventModal from '@/components/Calendar/EventModal';
|
|||||||
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
|
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||||
|
import { usePlanning } from '@/context/PlanningContext';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
@ -29,33 +30,36 @@ export default function Page() {
|
|||||||
});
|
});
|
||||||
const { selectedEstablishmentId } = useEstablishment();
|
const { selectedEstablishmentId } = useEstablishment();
|
||||||
|
|
||||||
const initializeNewEvent = (date = new Date()) => {
|
const PlanningContent = ({ isDrawerOpen, setIsDrawerOpen, isModalOpen, setIsModalOpen, eventData, setEventData }) => {
|
||||||
// S'assurer que date est un objet Date valide
|
const { selectedSchedule, schedules } = usePlanning();
|
||||||
const eventDate = date instanceof Date ? date : new Date();
|
|
||||||
|
|
||||||
setEventData({
|
const initializeNewEvent = (date = new Date()) => {
|
||||||
title: '',
|
const eventDate = date instanceof Date ? date : new Date();
|
||||||
description: '',
|
|
||||||
start: eventDate.toISOString(),
|
|
||||||
end: new Date(eventDate.getTime() + 2 * 60 * 60 * 1000).toISOString(),
|
|
||||||
location: '',
|
|
||||||
planning: '', // Ne pas définir de valeur par défaut ici non plus
|
|
||||||
recursionType: RecurrenceType.NONE,
|
|
||||||
selectedDays: [],
|
|
||||||
recursionEnd: new Date(
|
|
||||||
eventDate.getTime() + 2 * 60 * 60 * 1000
|
|
||||||
).toISOString(),
|
|
||||||
customInterval: 1,
|
|
||||||
customUnit: 'days',
|
|
||||||
});
|
|
||||||
setIsModalOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
const selected =
|
||||||
<PlanningProvider
|
schedules.find((schedule) => Number(schedule.id) === Number(selectedSchedule)) ||
|
||||||
establishmentId={selectedEstablishmentId}
|
schedules[0];
|
||||||
modeSet={PlanningModes.PLANNING}
|
|
||||||
>
|
setEventData({
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
start: eventDate.toISOString(),
|
||||||
|
end: new Date(eventDate.getTime() + 2 * 60 * 60 * 1000).toISOString(),
|
||||||
|
location: '',
|
||||||
|
planning: selected?.id || '',
|
||||||
|
color: selected?.color || '',
|
||||||
|
recursionType: RecurrenceType.NONE,
|
||||||
|
selectedDays: [],
|
||||||
|
recursionEnd: new Date(
|
||||||
|
eventDate.getTime() + 2 * 60 * 60 * 1000
|
||||||
|
).toISOString(),
|
||||||
|
customInterval: 1,
|
||||||
|
customUnit: 'days',
|
||||||
|
});
|
||||||
|
setIsModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
<div className="flex h-full overflow-hidden">
|
<div className="flex h-full overflow-hidden">
|
||||||
<ScheduleNavigation
|
<ScheduleNavigation
|
||||||
isOpen={isDrawerOpen}
|
isOpen={isDrawerOpen}
|
||||||
@ -76,6 +80,22 @@ export default function Page() {
|
|||||||
setEventData={setEventData}
|
setEventData={setEventData}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PlanningProvider
|
||||||
|
establishmentId={selectedEstablishmentId}
|
||||||
|
modeSet={PlanningModes.PLANNING}
|
||||||
|
>
|
||||||
|
<PlanningContent
|
||||||
|
isDrawerOpen={isDrawerOpen}
|
||||||
|
setIsDrawerOpen={setIsDrawerOpen}
|
||||||
|
isModalOpen={isModalOpen}
|
||||||
|
setIsModalOpen={setIsModalOpen}
|
||||||
|
eventData={eventData}
|
||||||
|
setEventData={setEventData}
|
||||||
|
/>
|
||||||
</PlanningProvider>
|
</PlanningProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { getWeekEvents } from '@/utils/events';
|
|||||||
import { CalendarDays, ChevronLeft, ChevronRight, Plus } from 'lucide-react';
|
import { CalendarDays, ChevronLeft, ChevronRight, Plus } from 'lucide-react';
|
||||||
|
|
||||||
const DayView = ({ onDateClick, onEventClick, events, onOpenDrawer }) => {
|
const DayView = ({ onDateClick, onEventClick, events, onOpenDrawer }) => {
|
||||||
const { currentDate, setCurrentDate, parentView } = usePlanning();
|
const { currentDate, setCurrentDate, parentView, schedules } = usePlanning();
|
||||||
const [currentTime, setCurrentTime] = useState(new Date());
|
const [currentTime, setCurrentTime] = useState(new Date());
|
||||||
const scrollRef = useRef(null);
|
const scrollRef = useRef(null);
|
||||||
|
|
||||||
@ -43,11 +43,28 @@ const DayView = ({ onDateClick, onEventClick, events, onOpenDrawer }) => {
|
|||||||
return `${(hours + minutes / 60) * 5}rem`;
|
return `${(hours + minutes / 60) * 5}rem`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getScheduleColor = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
return schedule?.color || event.color || '#6B7280';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScheduleClassLevelLabel = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
const scheduleName = schedule?.name || '';
|
||||||
|
if (!scheduleName) return '';
|
||||||
|
return scheduleName;
|
||||||
|
};
|
||||||
|
|
||||||
const calculateEventStyle = (event, allDayEvents) => {
|
const calculateEventStyle = (event, allDayEvents) => {
|
||||||
const start = new Date(event.start);
|
const start = new Date(event.start);
|
||||||
const end = new Date(event.end);
|
const end = new Date(event.end);
|
||||||
const startMinutes = (start.getMinutes() / 60) * 5;
|
const startMinutes = (start.getMinutes() / 60) * 5;
|
||||||
const duration = ((end - start) / (1000 * 60 * 60)) * 5;
|
const duration = ((end - start) / (1000 * 60 * 60)) * 5;
|
||||||
|
const scheduleColor = getScheduleColor(event);
|
||||||
|
|
||||||
const overlapping = allDayEvents.filter((other) => {
|
const overlapping = allDayEvents.filter((other) => {
|
||||||
if (other.id === event.id) return false;
|
if (other.id === event.id) return false;
|
||||||
@ -179,8 +196,11 @@ const DayView = ({ onDateClick, onEventClick, events, onOpenDrawer }) => {
|
|||||||
>
|
>
|
||||||
{dayEvents
|
{dayEvents
|
||||||
.filter((e) => new Date(e.start).getHours() === hour)
|
.filter((e) => new Date(e.start).getHours() === hour)
|
||||||
.map((event) => (
|
.map((event) => {
|
||||||
<div
|
const scheduleColor = getScheduleColor(event);
|
||||||
|
const classLevelLabel = getScheduleClassLevelLabel(event);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
key={event.id}
|
key={event.id}
|
||||||
className="rounded-sm overflow-hidden cursor-pointer hover:shadow-lg"
|
className="rounded-sm overflow-hidden cursor-pointer hover:shadow-lg"
|
||||||
style={calculateEventStyle(event, dayEvents)}
|
style={calculateEventStyle(event, dayEvents)}
|
||||||
@ -192,32 +212,53 @@ const DayView = ({ onDateClick, onEventClick, events, onOpenDrawer }) => {
|
|||||||
onEventClick(event);
|
onEventClick(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="p-1">
|
{classLevelLabel && (
|
||||||
<div
|
|
||||||
className="font-semibold text-xs truncate"
|
|
||||||
style={{ color: event.color }}
|
|
||||||
>
|
|
||||||
{event.title}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="text-xs"
|
|
||||||
style={{ color: event.color, opacity: 0.75 }}
|
|
||||||
>
|
|
||||||
{format(new Date(event.start), 'HH:mm')} –{' '}
|
|
||||||
{format(new Date(event.end), 'HH:mm')}
|
|
||||||
</div>
|
|
||||||
{event.location && (
|
|
||||||
<div
|
<div
|
||||||
className="text-xs truncate"
|
className="px-1 py-0.5 border-t-2"
|
||||||
style={{ color: event.color, opacity: 0.75 }}
|
style={{
|
||||||
|
borderTopColor: scheduleColor,
|
||||||
|
backgroundColor: `${scheduleColor}22`,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{event.location}
|
<span
|
||||||
|
className="text-[10px] font-semibold uppercase tracking-wide truncate block text-center"
|
||||||
|
style={{ color: scheduleColor }}
|
||||||
|
>
|
||||||
|
{classLevelLabel}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className="p-1">
|
||||||
|
<div
|
||||||
|
className="font-semibold text-xs truncate flex items-center gap-1"
|
||||||
|
style={{ color: event.color }}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="w-2 h-2 rounded-full shrink-0"
|
||||||
|
style={{ backgroundColor: event.color }}
|
||||||
|
/>
|
||||||
|
<span className="truncate flex-1">{event.title}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="text-xs"
|
||||||
|
style={{ color: event.color, opacity: 0.75 }}
|
||||||
|
>
|
||||||
|
{format(new Date(event.start), 'HH:mm')} –{' '}
|
||||||
|
{format(new Date(event.end), 'HH:mm')}
|
||||||
|
</div>
|
||||||
|
{event.location && (
|
||||||
|
<div
|
||||||
|
className="text-xs truncate"
|
||||||
|
style={{ color: event.color, opacity: 0.75 }}
|
||||||
|
>
|
||||||
|
{event.location}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -10,20 +10,31 @@ export default function EventModal({
|
|||||||
eventData,
|
eventData,
|
||||||
setEventData,
|
setEventData,
|
||||||
}) {
|
}) {
|
||||||
const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } =
|
const {
|
||||||
|
addEvent,
|
||||||
|
handleUpdateEvent,
|
||||||
|
handleDeleteEvent,
|
||||||
|
schedules,
|
||||||
|
selectedSchedule,
|
||||||
|
} =
|
||||||
usePlanning();
|
usePlanning();
|
||||||
const { showNotification } = useNotification();
|
const { showNotification } = useNotification();
|
||||||
|
|
||||||
// S'assurer que planning est défini lors du premier rendu
|
// S'assurer que planning est défini lors du premier rendu
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!eventData?.planning && schedules.length > 0) {
|
if (!eventData?.planning && schedules.length > 0) {
|
||||||
|
const defaultSchedule =
|
||||||
|
schedules.find(
|
||||||
|
(schedule) => Number(schedule.id) === Number(selectedSchedule)
|
||||||
|
) || schedules[0];
|
||||||
|
|
||||||
setEventData((prev) => ({
|
setEventData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
planning: schedules[0].id,
|
planning: defaultSchedule.id,
|
||||||
color: schedules[0].color,
|
color: defaultSchedule.color,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}, [schedules, eventData?.planning]);
|
}, [schedules, selectedSchedule, eventData?.planning]);
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,24 @@ import { fr } from 'date-fns/locale';
|
|||||||
import { getEventsForDate } from '@/utils/events';
|
import { getEventsForDate } from '@/utils/events';
|
||||||
|
|
||||||
const MonthView = ({ onDateClick, onEventClick }) => {
|
const MonthView = ({ onDateClick, onEventClick }) => {
|
||||||
const { currentDate, setViewType, setCurrentDate, events } = usePlanning();
|
const { currentDate, setViewType, setCurrentDate, events, schedules } =
|
||||||
|
usePlanning();
|
||||||
|
|
||||||
|
const getScheduleColor = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
return schedule?.color || event.color || '#6B7280';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScheduleClassLevelLabel = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
const scheduleName = schedule?.name || '';
|
||||||
|
if (!scheduleName) return '';
|
||||||
|
return scheduleName;
|
||||||
|
};
|
||||||
|
|
||||||
// Obtenir tous les jours du mois actuel
|
// Obtenir tous les jours du mois actuel
|
||||||
const monthStart = startOfMonth(currentDate);
|
const monthStart = startOfMonth(currentDate);
|
||||||
@ -53,8 +70,11 @@ const MonthView = ({ onDateClick, onEventClick }) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1 flex-1">
|
<div className="space-y-1 flex-1">
|
||||||
{dayEvents.map((event, index) => (
|
{dayEvents.map((event) => {
|
||||||
<div
|
const scheduleColor = getScheduleColor(event);
|
||||||
|
const classLevelLabel = getScheduleClassLevelLabel(event);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
key={event.id}
|
key={event.id}
|
||||||
className="text-xs p-1 rounded truncate cursor-pointer"
|
className="text-xs p-1 rounded truncate cursor-pointer"
|
||||||
style={{
|
style={{
|
||||||
@ -67,9 +87,32 @@ const MonthView = ({ onDateClick, onEventClick }) => {
|
|||||||
onEventClick(event);
|
onEventClick(event);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{event.title}
|
{classLevelLabel && (
|
||||||
|
<div
|
||||||
|
className="-mx-1 -mt-1 mb-1 px-1 py-0.5 border-t-2"
|
||||||
|
style={{
|
||||||
|
borderTopColor: scheduleColor,
|
||||||
|
backgroundColor: `${scheduleColor}22`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="text-[10px] font-semibold uppercase tracking-wide truncate block text-center"
|
||||||
|
style={{ color: scheduleColor }}
|
||||||
|
>
|
||||||
|
{classLevelLabel}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<span className="inline-flex items-center gap-1 max-w-full">
|
||||||
|
<span
|
||||||
|
className="w-2 h-2 rounded-full shrink-0"
|
||||||
|
style={{ backgroundColor: event.color }}
|
||||||
|
/>
|
||||||
|
<span className="truncate flex-1">{event.title}</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { isToday } from 'date-fns';
|
|||||||
|
|
||||||
|
|
||||||
const WeekView = ({ onDateClick, onEventClick, events }) => {
|
const WeekView = ({ onDateClick, onEventClick, events }) => {
|
||||||
const { currentDate, planningMode, parentView } = usePlanning();
|
const { currentDate, planningMode, parentView, schedules } = usePlanning();
|
||||||
const [currentTime, setCurrentTime] = useState(new Date());
|
const [currentTime, setCurrentTime] = useState(new Date());
|
||||||
const scrollContainerRef = useRef(null); // Ajouter cette référence
|
const scrollContainerRef = useRef(null); // Ajouter cette référence
|
||||||
|
|
||||||
@ -71,11 +71,28 @@ const WeekView = ({ onDateClick, onEventClick, events }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getScheduleColor = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
return schedule?.color || event.color || '#6B7280';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScheduleClassLevelLabel = (event) => {
|
||||||
|
const schedule = schedules?.find(
|
||||||
|
(item) => Number(item.id) === Number(event.planning)
|
||||||
|
);
|
||||||
|
const scheduleName = schedule?.name || '';
|
||||||
|
if (!scheduleName) return '';
|
||||||
|
return scheduleName;
|
||||||
|
};
|
||||||
|
|
||||||
const calculateEventStyle = (event, dayEvents) => {
|
const calculateEventStyle = (event, dayEvents) => {
|
||||||
const start = new Date(event.start);
|
const start = new Date(event.start);
|
||||||
const end = new Date(event.end);
|
const end = new Date(event.end);
|
||||||
const startMinutes = (start.getMinutes() / 60) * 5;
|
const startMinutes = (start.getMinutes() / 60) * 5;
|
||||||
const duration = ((end - start) / (1000 * 60 * 60)) * 5;
|
const duration = ((end - start) / (1000 * 60 * 60)) * 5;
|
||||||
|
const scheduleColor = getScheduleColor(event);
|
||||||
|
|
||||||
// Trouver les événements qui se chevauchent
|
// Trouver les événements qui se chevauchent
|
||||||
const overlappingEvents = findOverlappingEvents(event, dayEvents);
|
const overlappingEvents = findOverlappingEvents(event, dayEvents);
|
||||||
@ -101,6 +118,8 @@ const WeekView = ({ onDateClick, onEventClick, events }) => {
|
|||||||
|
|
||||||
const renderEventInCell = (event, dayEvents) => {
|
const renderEventInCell = (event, dayEvents) => {
|
||||||
const eventStyle = calculateEventStyle(event, dayEvents);
|
const eventStyle = calculateEventStyle(event, dayEvents);
|
||||||
|
const scheduleColor = getScheduleColor(event);
|
||||||
|
const classLevelLabel = getScheduleClassLevelLabel(event);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -116,12 +135,32 @@ const WeekView = ({ onDateClick, onEventClick, events }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
{classLevelLabel && (
|
||||||
|
<div
|
||||||
|
className="px-1 py-0.5 border-t-2"
|
||||||
|
style={{
|
||||||
|
borderTopColor: scheduleColor,
|
||||||
|
backgroundColor: `${scheduleColor}22`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="text-[10px] font-semibold uppercase tracking-wide truncate block text-center"
|
||||||
|
style={{ color: scheduleColor }}
|
||||||
|
>
|
||||||
|
{classLevelLabel}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="p-1">
|
<div className="p-1">
|
||||||
<div
|
<div
|
||||||
className="font-semibold text-xs truncate"
|
className="font-semibold text-xs truncate flex items-center gap-1"
|
||||||
style={{ color: event.color }}
|
style={{ color: event.color }}
|
||||||
>
|
>
|
||||||
{event.title}
|
<span
|
||||||
|
className="w-2 h-2 rounded-full shrink-0"
|
||||||
|
style={{ backgroundColor: event.color }}
|
||||||
|
/>
|
||||||
|
<span className="truncate flex-1">{event.title}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="text-xs"
|
className="text-xs"
|
||||||
|
|||||||
@ -24,6 +24,29 @@ const ItemTypes = {
|
|||||||
TEACHER: 'teacher',
|
TEACHER: 'teacher',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CLASS_PLANNING_COLORS = [
|
||||||
|
'#EF4444',
|
||||||
|
'#3B82F6',
|
||||||
|
'#F59E0B',
|
||||||
|
'#8B5CF6',
|
||||||
|
'#EC4899',
|
||||||
|
'#14B8A6',
|
||||||
|
'#F97316',
|
||||||
|
'#6366F1',
|
||||||
|
'#06B6D4',
|
||||||
|
'#84CC16',
|
||||||
|
];
|
||||||
|
|
||||||
|
const getClassPlanningColor = (schoolClass) => {
|
||||||
|
const numericId = Number(schoolClass?.id);
|
||||||
|
if (!Number.isFinite(numericId) || numericId <= 0) {
|
||||||
|
return CLASS_PLANNING_COLORS[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = (numericId - 1) % CLASS_PLANNING_COLORS.length;
|
||||||
|
return CLASS_PLANNING_COLORS[index];
|
||||||
|
};
|
||||||
|
|
||||||
const TeachersDropZone = ({
|
const TeachersDropZone = ({
|
||||||
classe,
|
classe,
|
||||||
handleTeachersChange,
|
handleTeachersChange,
|
||||||
@ -245,13 +268,14 @@ const ClassesSection = ({
|
|||||||
setNewClass(null);
|
setNewClass(null);
|
||||||
setLocalErrors({});
|
setLocalErrors({});
|
||||||
// Creation des plannings associé à la classe
|
// Creation des plannings associé à la classe
|
||||||
|
const classPlanningColor = getClassPlanningColor(createdClass);
|
||||||
|
|
||||||
createdClass.levels.forEach((level) => {
|
createdClass.levels.forEach((level) => {
|
||||||
const levelName = allNiveaux.find((lvl) => lvl.id === level)?.name;
|
const levelName = allNiveaux.find((lvl) => lvl.id === level)?.name;
|
||||||
const planningName = `${createdClass.atmosphere_name} - ${levelName}`;
|
const planningName = `${createdClass.atmosphere_name} - ${levelName}`;
|
||||||
const newPlanning = {
|
const newPlanning = {
|
||||||
name: planningName,
|
name: planningName,
|
||||||
color: '#FF5733', // Couleur par défaut
|
color: classPlanningColor,
|
||||||
school_class: createdClass.id,
|
school_class: createdClass.id,
|
||||||
};
|
};
|
||||||
addSchedule(newPlanning);
|
addSchedule(newPlanning);
|
||||||
|
|||||||
@ -12,13 +12,22 @@ export default function ScheduleEventModal({
|
|||||||
teachers,
|
teachers,
|
||||||
classes,
|
classes,
|
||||||
}) {
|
}) {
|
||||||
const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } =
|
const {
|
||||||
|
addEvent,
|
||||||
|
handleUpdateEvent,
|
||||||
|
handleDeleteEvent,
|
||||||
|
schedules,
|
||||||
|
selectedSchedule,
|
||||||
|
} =
|
||||||
usePlanning();
|
usePlanning();
|
||||||
const { showNotification } = useNotification();
|
const { showNotification } = useNotification();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!eventData?.planning && schedules.length > 0) {
|
if (!eventData?.planning && schedules.length > 0) {
|
||||||
const defaultSchedule = schedules[0];
|
const defaultSchedule =
|
||||||
|
schedules.find(
|
||||||
|
(schedule) => Number(schedule.id) === Number(selectedSchedule)
|
||||||
|
) || schedules[0];
|
||||||
if (eventData?.planning !== defaultSchedule.id) {
|
if (eventData?.planning !== defaultSchedule.id) {
|
||||||
setEventData((prev) => ({
|
setEventData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@ -26,7 +35,7 @@ export default function ScheduleEventModal({
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [schedules, eventData?.planning]);
|
}, [schedules, selectedSchedule, eventData?.planning]);
|
||||||
|
|
||||||
const handleSpecialityChange = (specialityId) => {
|
const handleSpecialityChange = (specialityId) => {
|
||||||
const selectedSpeciality = specialities.find(
|
const selectedSpeciality = specialities.find(
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { RecurrenceType } from '@/context/PlanningContext';
|
import { RecurrenceType, usePlanning } from '@/context/PlanningContext';
|
||||||
import Calendar from '@/components/Calendar/Calendar';
|
import Calendar from '@/components/Calendar/Calendar';
|
||||||
import ScheduleEventModal from '@/components/Structure/Planning/ScheduleEventModal';
|
import ScheduleEventModal from '@/components/Structure/Planning/ScheduleEventModal';
|
||||||
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
|
import ScheduleNavigation from '@/components/Calendar/ScheduleNavigation';
|
||||||
@ -12,6 +12,7 @@ export default function ScheduleManagement({
|
|||||||
specialities,
|
specialities,
|
||||||
teachers,
|
teachers,
|
||||||
}) {
|
}) {
|
||||||
|
const { selectedSchedule, schedules } = usePlanning();
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [eventData, setEventData] = useState({
|
const [eventData, setEventData] = useState({
|
||||||
title: '',
|
title: '',
|
||||||
@ -32,13 +33,18 @@ export default function ScheduleManagement({
|
|||||||
// S'assurer que date est un objet Date valide
|
// S'assurer que date est un objet Date valide
|
||||||
const eventDate = date instanceof Date ? date : new Date();
|
const eventDate = date instanceof Date ? date : new Date();
|
||||||
|
|
||||||
|
const selected =
|
||||||
|
schedules.find((schedule) => Number(schedule.id) === Number(selectedSchedule)) ||
|
||||||
|
schedules[0];
|
||||||
|
|
||||||
setEventData({
|
setEventData({
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
start: eventDate.toISOString(),
|
start: eventDate.toISOString(),
|
||||||
end: new Date(eventDate.getTime() + 2 * 60 * 60 * 1000).toISOString(),
|
end: new Date(eventDate.getTime() + 2 * 60 * 60 * 1000).toISOString(),
|
||||||
location: '',
|
location: '',
|
||||||
planning: '', // Ne pas définir de valeur par défaut ici non plus
|
planning: selected?.id || '',
|
||||||
|
color: selected?.color || '',
|
||||||
recursionType: RecurrenceType.NONE,
|
recursionType: RecurrenceType.NONE,
|
||||||
selectedDays: [],
|
selectedDays: [],
|
||||||
recursionEnd: new Date(
|
recursionEnd: new Date(
|
||||||
|
|||||||
@ -36,6 +36,29 @@ export const PlanningModes = Object.freeze({
|
|||||||
PLANNING: 'planning'
|
PLANNING: 'planning'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const CLASS_SCHEDULE_COLORS = [
|
||||||
|
'#EF4444',
|
||||||
|
'#3B82F6',
|
||||||
|
'#F59E0B',
|
||||||
|
'#8B5CF6',
|
||||||
|
'#EC4899',
|
||||||
|
'#14B8A6',
|
||||||
|
'#F97316',
|
||||||
|
'#6366F1',
|
||||||
|
'#06B6D4',
|
||||||
|
'#84CC16',
|
||||||
|
];
|
||||||
|
|
||||||
|
const getClassScheduleColor = (schoolClassId) => {
|
||||||
|
const numericId = Number(schoolClassId);
|
||||||
|
if (!Number.isFinite(numericId) || numericId <= 0) {
|
||||||
|
return '#10b981';
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = (numericId - 1) % CLASS_SCHEDULE_COLORS.length;
|
||||||
|
return CLASS_SCHEDULE_COLORS[index];
|
||||||
|
};
|
||||||
|
|
||||||
export function PlanningProvider({
|
export function PlanningProvider({
|
||||||
children,
|
children,
|
||||||
modeSet = PlanningModes.PLANNING,
|
modeSet = PlanningModes.PLANNING,
|
||||||
@ -65,7 +88,15 @@ export function PlanningProvider({
|
|||||||
|
|
||||||
const reloadPlanning = () => {
|
const reloadPlanning = () => {
|
||||||
fetchPlannings(selectedEstablishmentId, planningMode).then((data) => {
|
fetchPlannings(selectedEstablishmentId, planningMode).then((data) => {
|
||||||
setSchedules(data);
|
const normalizedSchedules =
|
||||||
|
planningMode === PlanningModes.CLASS_SCHEDULE
|
||||||
|
? data.map((schedule) => ({
|
||||||
|
...schedule,
|
||||||
|
color: getClassScheduleColor(schedule.school_class),
|
||||||
|
}))
|
||||||
|
: data;
|
||||||
|
|
||||||
|
setSchedules(normalizedSchedules);
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
setSelectedSchedule(data[0].id);
|
setSelectedSchedule(data[0].id);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user