mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
feat: planning events
This commit is contained in:
@ -13,7 +13,7 @@ export default function Page() {
|
||||
start: '',
|
||||
end: '',
|
||||
location: '',
|
||||
scheduleId: '', // Enlever la valeur par défaut ici
|
||||
planning: '', // Enlever la valeur par défaut ici
|
||||
recurrence: 'none',
|
||||
selectedDays: [],
|
||||
recurrenceEnd: '',
|
||||
@ -32,7 +32,7 @@ export default function Page() {
|
||||
start: eventDate.toISOString(),
|
||||
end: new Date(eventDate.getTime() + 2 * 60 * 60 * 1000).toISOString(),
|
||||
location: '',
|
||||
scheduleId: '', // Ne pas définir de valeur par défaut ici non plus
|
||||
planning: '', // Ne pas définir de valeur par défaut ici non plus
|
||||
recurrence: 'none',
|
||||
selectedDays: [],
|
||||
recurrenceEnd: '',
|
||||
|
||||
108
Front-End/src/app/actions/planningAction.js
Normal file
108
Front-End/src/app/actions/planningAction.js
Normal file
@ -0,0 +1,108 @@
|
||||
import { BE_PLANNING_PLANNINGS_URL,
|
||||
BE_PLANNING_EVENTS_URL
|
||||
} from '@/utils/Url';
|
||||
|
||||
|
||||
|
||||
const requestResponseHandler = async (response) => {
|
||||
const body = response.status !== 204 ? await response?.json() : {};
|
||||
console.log(response)
|
||||
if (response.ok) {
|
||||
return body;
|
||||
}
|
||||
// Throw an error with the JSON body containing the form errors
|
||||
const error = new Error(body?.errorMessage || "Une erreur est survenue");
|
||||
error.details = body;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const getData = (url) => {
|
||||
return fetch(`${url}`).then(requestResponseHandler);
|
||||
}
|
||||
|
||||
const createDatas = (url, newData, csrfToken) => {
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify(newData),
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
};
|
||||
|
||||
const updateDatas = (url, updatedData, csrfToken) => {
|
||||
return fetch(`${url}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify(updatedData),
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
};
|
||||
|
||||
const removeDatas = (url, csrfToken) => {
|
||||
return fetch(`${url}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
export const fetchPlannings = () => {
|
||||
return getData(`${BE_PLANNING_PLANNINGS_URL}`)
|
||||
};
|
||||
|
||||
|
||||
export const getPlanning = (id) => {
|
||||
return getData(`${BE_PLANNING_PLANNINGS_URL}/${id}`)
|
||||
};
|
||||
|
||||
export const createPlanning = (newData, csrfToken) => {
|
||||
return createDatas(`${BE_PLANNING_PLANNINGS_URL}`, newData, csrfToken)
|
||||
}
|
||||
|
||||
export const updatePlanning = (id,newData, csrfToken) => {
|
||||
return updateDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, newData, csrfToken)
|
||||
}
|
||||
|
||||
export const deletePlanning = (id, csrfToken) => {
|
||||
return removeDatas(`${BE_PLANNING_PLANNINGS_URL}/${id}`, csrfToken)
|
||||
}
|
||||
|
||||
|
||||
export const fetchEvents = () => {
|
||||
return getData(`${BE_PLANNING_EVENTS_URL}`)
|
||||
};
|
||||
|
||||
|
||||
export const getEvent = (id) => {
|
||||
return getData(`${BE_PLANNING_EVENTS_URL}/${id}`)
|
||||
};
|
||||
|
||||
export const createEvent = (newData, csrfToken) => {
|
||||
return createDatas(`${BE_PLANNING_EVENTS_URL}`, newData, csrfToken)
|
||||
}
|
||||
|
||||
export const updateEvent = (id,newData, csrfToken) => {
|
||||
return updateDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, newData, csrfToken)
|
||||
}
|
||||
|
||||
export const deleteEvent = (id, csrfToken) => {
|
||||
return removeDatas(`${BE_PLANNING_EVENTS_URL}/${id}`, csrfToken)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ const Calendar = ({ onDateClick, onEventClick }) => {
|
||||
|
||||
useEffect(() => {
|
||||
// S'assurer que le filtrage est fait au niveau parent
|
||||
const filtered = events.filter(event => !hiddenSchedules.includes(event.scheduleId));
|
||||
const filtered = events?.filter(event => !hiddenSchedules.includes(event.planning));
|
||||
setVisibleEvents(filtered);
|
||||
logger.debug('Events filtrés:', filtered); // Debug
|
||||
}, [events, hiddenSchedules]);
|
||||
|
||||
@ -3,18 +3,18 @@ import { format } from 'date-fns';
|
||||
import React from 'react';
|
||||
|
||||
export default function EventModal({ isOpen, onClose, eventData, setEventData }) {
|
||||
const { addEvent, updateEvent, deleteEvent, schedules } = usePlanning();
|
||||
const { addEvent, handleUpdateEvent, handleDeleteEvent, schedules } = usePlanning();
|
||||
|
||||
// S'assurer que scheduleId est défini lors du premier rendu
|
||||
// S'assurer que planning est défini lors du premier rendu
|
||||
React.useEffect(() => {
|
||||
if (!eventData.scheduleId && schedules.length > 0) {
|
||||
if (!eventData.planning && schedules.length > 0) {
|
||||
setEventData(prev => ({
|
||||
...prev,
|
||||
scheduleId: schedules[0].id,
|
||||
planning: schedules[0].id,
|
||||
color: schedules[0].color
|
||||
}));
|
||||
}
|
||||
}, [schedules, eventData.scheduleId]);
|
||||
}, [schedules, eventData.planning]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
@ -39,24 +39,24 @@ export default function EventModal({ isOpen, onClose, eventData, setEventData })
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!eventData.scheduleId) {
|
||||
if (!eventData.planning) {
|
||||
alert('Veuillez sélectionner un planning');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedSchedule = schedules.find(s => s.id === eventData.scheduleId);
|
||||
const selectedSchedule = schedules.find(s => s.id === eventData.planning);
|
||||
|
||||
if (eventData.id) {
|
||||
updateEvent(eventData.id, {
|
||||
handleUpdateEvent(eventData.id, {
|
||||
...eventData,
|
||||
scheduleId: eventData.scheduleId, // S'assurer que scheduleId est bien défini
|
||||
planning: eventData.planning, // S'assurer que planning est bien défini
|
||||
color: eventData.color || selectedSchedule?.color
|
||||
});
|
||||
} else {
|
||||
addEvent({
|
||||
...eventData,
|
||||
id: `event-${Date.now()}`,
|
||||
scheduleId: eventData.scheduleId, // S'assurer que scheduleId est bien défini
|
||||
planning: eventData.planning, // S'assurer que planning est bien défini
|
||||
color: eventData.color || selectedSchedule?.color
|
||||
});
|
||||
}
|
||||
@ -65,7 +65,7 @@ export default function EventModal({ isOpen, onClose, eventData, setEventData })
|
||||
|
||||
const handleDelete = () => {
|
||||
if (eventData.id && confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')) {
|
||||
deleteEvent(eventData.id);
|
||||
handleDeleteEvent(eventData.id);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
@ -111,12 +111,12 @@ export default function EventModal({ isOpen, onClose, eventData, setEventData })
|
||||
Planning
|
||||
</label>
|
||||
<select
|
||||
value={eventData.scheduleId || schedules[0]?.id}
|
||||
value={eventData.planning || schedules[0]?.id}
|
||||
onChange={(e) => {
|
||||
const selectedSchedule = schedules.find(s => s.id === e.target.value);
|
||||
setEventData({
|
||||
...eventData,
|
||||
scheduleId: e.target.value,
|
||||
planning: e.target.value,
|
||||
color: selectedSchedule?.color || '#10b981'
|
||||
});
|
||||
}}
|
||||
@ -138,7 +138,7 @@ export default function EventModal({ isOpen, onClose, eventData, setEventData })
|
||||
</label>
|
||||
<input
|
||||
type="color"
|
||||
value={eventData.color || schedules.find(s => s.id === eventData.scheduleId)?.color || '#10b981'}
|
||||
value={eventData.color || schedules.find(s => s.id === eventData.planning)?.color || '#10b981'}
|
||||
onChange={(e) => setEventData({ ...eventData, color: e.target.value })}
|
||||
className="w-full h-10 p-1 rounded border"
|
||||
/>
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
import { createContext, useContext, useState } from 'react';
|
||||
import { mockEvents, mockSchedules } from '@/data/mockData';
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { createPlanning, fetchEvents, fetchPlannings, updatePlanning, createEvent, deleteEvent, updateEvent } from '@/app/actions/planningAction';
|
||||
import { useCsrfToken } from './CsrfContext';
|
||||
import { ESTABLISHMENT_ID } from '@/utils/Url';
|
||||
import logger from '@/utils/logger';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contexte de planification pour gérer l'état global du planning
|
||||
@ -16,51 +21,90 @@ export function PlanningProvider({ children }) {
|
||||
// const [events, setEvents] = useState([]);
|
||||
// const [schedules, setSchedules] = useState([]);
|
||||
// const [selectedSchedule, setSelectedSchedule] = useState(null);
|
||||
const [events, setEvents] = useState(mockEvents);
|
||||
const [schedules, setSchedules] = useState(mockSchedules);
|
||||
const [selectedSchedule, setSelectedSchedule] = useState(mockSchedules[0].id);
|
||||
const [events, setEvents] = useState([]);
|
||||
const [schedules, setSchedules] = useState([]);
|
||||
const [selectedSchedule, setSelectedSchedule] = useState(0);
|
||||
const [currentDate, setCurrentDate] = useState(new Date());
|
||||
const [viewType, setViewType] = useState('week'); // Changer 'month' en 'week'
|
||||
const [hiddenSchedules, setHiddenSchedules] = useState([]);
|
||||
|
||||
const csrfToken = useCsrfToken();
|
||||
useEffect(()=>{
|
||||
|
||||
fetchPlannings().then((data) => {
|
||||
setSchedules(data)
|
||||
setSelectedSchedule(data[0].id);
|
||||
});
|
||||
fetchEvents().then((data)=>{
|
||||
setEvents(data);
|
||||
});
|
||||
},[]);
|
||||
|
||||
|
||||
|
||||
|
||||
const addEvent = (newEvent) => {
|
||||
setEvents((prevEvents) => [...prevEvents, newEvent]);
|
||||
createEvent(newEvent).then((data) => {
|
||||
setEvents((prevEvents) => [...prevEvents, data]);
|
||||
});
|
||||
console.log('newEvent',newEvent);
|
||||
|
||||
//dssetEvents((prevEvents) => [...prevEvents, newEvent]);
|
||||
};
|
||||
|
||||
const updateEvent = (id, updatedEvent) => {
|
||||
setEvents((prevEvents) =>
|
||||
prevEvents.map((event) => (event.id === id ? updatedEvent : event))
|
||||
);
|
||||
const handleUpdateEvent = (id, updatedEvent) => {
|
||||
updateEvent(id,updatedEvent,csrfToken).then((data) => {
|
||||
setEvents((prevEvents) =>
|
||||
prevEvents.map((event) => (event.id === id ? updatedEvent : event))
|
||||
);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const deleteEvent = (id) => {
|
||||
setEvents((prevEvents) => prevEvents.filter((event) => event.id !== id));
|
||||
const handleDeleteEvent = (id) => {
|
||||
deleteEvent(id,csrfToken).then((data) => {
|
||||
setEvents((prevEvents) => prevEvents.filter((event) => event.id !== id));
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const addSchedule = (newSchedule) => {
|
||||
setSchedules((prevSchedules) => [...prevSchedules, newSchedule]);
|
||||
//FIXME:Gerenr lestablshment
|
||||
logger.debug('newSchedule',newSchedule);
|
||||
newSchedule.establishment = ESTABLISHMENT_ID;
|
||||
|
||||
createPlanning(newSchedule,csrfToken).then((data) => {
|
||||
setSchedules((prevSchedules) => [...prevSchedules, data]);
|
||||
});
|
||||
};
|
||||
|
||||
const updateSchedule = (id, updatedSchedule) => {
|
||||
setSchedules((prevSchedules) =>
|
||||
prevSchedules.map((schedule) =>
|
||||
schedule.id === id ? updatedSchedule : schedule
|
||||
)
|
||||
);
|
||||
|
||||
updatePlanning(id,updatedSchedule,csrfToken).then((data) => {
|
||||
setSchedules((prevSchedules) =>
|
||||
prevSchedules.map((schedule) =>
|
||||
schedule.id === id ? updatedSchedule : schedule
|
||||
)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const deleteSchedule = (id) => {
|
||||
setSchedules((prevSchedules) =>
|
||||
prevSchedules.filter((schedule) => schedule.id !== id)
|
||||
deletePlanning(id,csrfToken).then((data) => {
|
||||
setSchedules((prevSchedules) =>
|
||||
prevSchedules.filter((schedule) => schedule.id !== id)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
const toggleScheduleVisibility = (scheduleId) => {
|
||||
const toggleScheduleVisibility = (planning) => {
|
||||
setHiddenSchedules((prev) => {
|
||||
const isHidden = prev.includes(scheduleId);
|
||||
const isHidden = prev.includes(planning);
|
||||
const newHiddenSchedules = isHidden
|
||||
? prev.filter((id) => id !== scheduleId)
|
||||
: [...prev, scheduleId];
|
||||
? prev.filter((id) => id !== planning)
|
||||
: [...prev, planning];
|
||||
return newHiddenSchedules;
|
||||
});
|
||||
};
|
||||
@ -73,8 +117,8 @@ export function PlanningProvider({ children }) {
|
||||
selectedSchedule,
|
||||
setSelectedSchedule,
|
||||
addEvent,
|
||||
updateEvent,
|
||||
deleteEvent,
|
||||
handleUpdateEvent,
|
||||
handleDeleteEvent,
|
||||
addSchedule,
|
||||
updateSchedule,
|
||||
deleteSchedule,
|
||||
|
||||
@ -12,7 +12,7 @@ export const mockEvents = [
|
||||
description: 'Cours de mathématiques avancées',
|
||||
start: '2024-02-20T08:00:00',
|
||||
end: '2024-02-20T10:00:00',
|
||||
scheduleId: 'default',
|
||||
planning: 'default',
|
||||
location: 'Salle A101',
|
||||
color: '#10b981'
|
||||
},
|
||||
@ -22,7 +22,7 @@ export const mockEvents = [
|
||||
description: 'Examen final de physique',
|
||||
start: '2024-02-21T14:00:00',
|
||||
end: '2024-02-21T16:00:00',
|
||||
scheduleId: 'exam',
|
||||
planning: 'exam',
|
||||
location: 'Amphithéâtre B',
|
||||
color: '#f59e0b'
|
||||
}
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
export function useSchedules() {
|
||||
const [schedules, setSchedules] = useState([
|
||||
{ id: 'default', name: 'Planning principal', color: '#10b981' },
|
||||
{ id: 'secondary', name: 'Planning secondaire', color: '#3b82f6' },
|
||||
{ id: 'special', name: 'Événements spéciaux', color: '#ef4444' },
|
||||
{ id: 'exam', name: 'Planning examens', color: '#f59e0b' }
|
||||
]);
|
||||
|
||||
const addSchedule = (newSchedule) => {
|
||||
setSchedules(prev => [...prev, {
|
||||
...newSchedule,
|
||||
id: `schedule-${Date.now()}`
|
||||
}]);
|
||||
};
|
||||
|
||||
const updateSchedule = (id, updates) => {
|
||||
setSchedules(prev => prev.map(schedule =>
|
||||
schedule.id === id ? { ...schedule, ...updates } : schedule
|
||||
));
|
||||
};
|
||||
|
||||
const deleteSchedule = (id) => {
|
||||
setSchedules(prev => prev.filter(schedule => schedule.id !== id));
|
||||
};
|
||||
|
||||
return {
|
||||
schedules,
|
||||
addSchedule,
|
||||
updateSchedule,
|
||||
deleteSchedule
|
||||
};
|
||||
}
|
||||
|
||||
export function useEvents(initialEvents = []) {
|
||||
const [events, setEvents] = useState(initialEvents);
|
||||
|
||||
const addEvent = (newEvent) => {
|
||||
setEvents(prev => [...prev, {
|
||||
...newEvent,
|
||||
id: `event-${Date.now()}`
|
||||
}]);
|
||||
};
|
||||
|
||||
const updateEvent = (id, updates) => {
|
||||
setEvents(prev => prev.map(event =>
|
||||
event.id === id ? { ...event, ...updates } : event
|
||||
));
|
||||
};
|
||||
|
||||
const deleteEvent = (id) => {
|
||||
setEvents(prev => prev.filter(event => event.id !== id));
|
||||
};
|
||||
|
||||
return {
|
||||
events,
|
||||
setEvents,
|
||||
addEvent,
|
||||
updateEvent,
|
||||
deleteEvent
|
||||
};
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { mockEvents, mockSchedules } from '@/data/mockData';
|
||||
|
||||
export default function useSchedules() {
|
||||
const [schedules, setSchedules] = useState(mockSchedules);
|
||||
const [events, setEvents] = useState(mockEvents);
|
||||
const [selectedSchedule, setSelectedSchedule] = useState(mockSchedules[0].id);
|
||||
|
||||
const addEvent = async (eventData) => {
|
||||
const newEvent = {
|
||||
...eventData,
|
||||
id: `event-${Date.now()}`,
|
||||
color: schedules.find(s => s.id === eventData.scheduleId)?.color || '#10b981'
|
||||
};
|
||||
setEvents(prev => [...prev, newEvent]);
|
||||
return newEvent;
|
||||
};
|
||||
|
||||
const updateEvent = async (eventId, updates) => {
|
||||
setEvents(prev => prev.map(event =>
|
||||
event.id === eventId ? { ...event, ...updates } : event
|
||||
));
|
||||
return updates;
|
||||
};
|
||||
|
||||
const deleteEvent = async (eventId) => {
|
||||
setEvents(prev => prev.filter(event => event.id !== eventId));
|
||||
return eventId;
|
||||
};
|
||||
|
||||
const addSchedule = (newSchedule) => {
|
||||
setSchedules(prev => [...prev, {
|
||||
...newSchedule,
|
||||
id: `schedule-${Date.now()}`
|
||||
}]);
|
||||
};
|
||||
|
||||
const updateSchedule = (id, updates) => {
|
||||
setSchedules(prev => prev.map(schedule =>
|
||||
schedule.id === id ? { ...schedule, ...updates } : schedule
|
||||
));
|
||||
};
|
||||
|
||||
const deleteSchedule = (id) => {
|
||||
setSchedules(prev => prev.filter(schedule => schedule.id !== id));
|
||||
};
|
||||
|
||||
return {
|
||||
events,
|
||||
schedules,
|
||||
selectedSchedule,
|
||||
setSelectedSchedule,
|
||||
addEvent,
|
||||
updateEvent,
|
||||
deleteEvent,
|
||||
addSchedule,
|
||||
updateSchedule,
|
||||
deleteSchedule
|
||||
};
|
||||
}
|
||||
@ -42,7 +42,13 @@ export const BE_SCHOOL_PAYMENT_PLANS_URL = `${BASE_URL}/School/paymentPlans`;
|
||||
export const BE_SCHOOL_PAYMENT_MODES_URL = `${BASE_URL}/School/paymentModes`;
|
||||
export const BE_SCHOOL_ESTABLISHMENT_URL = `${BASE_URL}/School/establishments`;
|
||||
|
||||
// En attendant la gestion des sessions
|
||||
|
||||
// GESTION PLANNING
|
||||
export const BE_PLANNING_PLANNINGS_URL = `${BASE_URL}/Planning/plannings`
|
||||
export const BE_PLANNING_EVENTS_URL = `${BASE_URL}/Planning/events`
|
||||
|
||||
|
||||
// FIXME : En attendant la gestion des sessions
|
||||
export const ESTABLISHMENT_ID = 1;
|
||||
|
||||
// GESTION MESSAGERIE
|
||||
|
||||
@ -14,7 +14,7 @@ export const DEFAULT_EVENT = {
|
||||
start: '',
|
||||
end: '',
|
||||
location: '',
|
||||
scheduleId: 'default',
|
||||
planning: 'default',
|
||||
color: '#10b981',
|
||||
recurrence: 'none',
|
||||
selectedDays: [],
|
||||
|
||||
@ -85,7 +85,7 @@ export const getWeekEvents = (day, events) => {
|
||||
const start = startOfDay(day);
|
||||
const end = endOfDay(day);
|
||||
|
||||
return events.filter(event => {
|
||||
return events?.filter(event => {
|
||||
const eventStart = new Date(event.start);
|
||||
const eventEnd = new Date(event.end);
|
||||
|
||||
@ -106,5 +106,5 @@ export const getWeekEvents = (day, events) => {
|
||||
* @returns {Array<Object>} Liste des événements filtrés
|
||||
*/
|
||||
export const filterEventsByVisibleSchedules = (events, hiddenSchedules) => {
|
||||
return events.filter(event => !hiddenSchedules.includes(event.scheduleId));
|
||||
return events.filter(event => !hiddenSchedules.includes(event.planning));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user