diff --git a/Back-End/N3wtSchool/settings.py b/Back-End/N3wtSchool/settings.py index bc75281..b17dd31 100644 --- a/Back-End/N3wtSchool/settings.py +++ b/Back-End/N3wtSchool/settings.py @@ -43,6 +43,7 @@ INSTALLED_APPS = [ 'GestionMessagerie.apps.GestionMessagerieConfig', 'GestionNotification.apps.GestionNotificationConfig', 'School.apps.SchoolConfig', + 'Planning.apps.PlanningConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', diff --git a/Back-End/N3wtSchool/urls.py b/Back-End/N3wtSchool/urls.py index e336cac..8a90e6f 100644 --- a/Back-End/N3wtSchool/urls.py +++ b/Back-End/N3wtSchool/urls.py @@ -45,6 +45,7 @@ urlpatterns = [ path("GestionNotification/", include(("GestionNotification.urls", 'GestionNotification'), namespace='GestionNotification')), path("School/", include(("School.urls", 'School'), namespace='School')), path("DocuSeal/", include(("DocuSeal.urls", 'DocuSeal'), namespace='DocuSeal')), + path("Planning/", include(("Planning.urls", 'Planning'), namespace='Planning')), # Documentation Api re_path(r'^swagger(?P\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), diff --git a/Back-End/Planning/__init__.py b/Back-End/Planning/__init__.py new file mode 100644 index 0000000..d3fd592 --- /dev/null +++ b/Back-End/Planning/__init__.py @@ -0,0 +1 @@ +default_app_config = 'Planning.apps.PlanningConfig' diff --git a/Back-End/Planning/admin.py b/Back-End/Planning/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/Back-End/Planning/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/Back-End/Planning/apps.py b/Back-End/Planning/apps.py new file mode 100644 index 0000000..43ec794 --- /dev/null +++ b/Back-End/Planning/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +class PlanningConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Planning' + + diff --git a/Back-End/Planning/models.py b/Back-End/Planning/models.py new file mode 100644 index 0000000..1ee967f --- /dev/null +++ b/Back-End/Planning/models.py @@ -0,0 +1,38 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models +from django.utils.translation import gettext_lazy as _ +from django.conf import settings + +from School.models import Establishment + +class RecursionType(models.IntegerChoices): + RECURSION_NONE = 0, _('Aucune') + RECURSION_DAILY = 1, _('Quotidienne') + RECURSION_WEEKLY = 2, _('Hebdomadaire') + RECURSION_MONTHLY = 3, _('Mensuel') + RECURSION_CUSTOM = 4, _('Personnalisé') + +class Planning(models.Model): + establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT) + name = models.CharField(max_length=255) + description = models.TextField(default="", blank=True, null=True) + color= models.CharField(max_length=255, default="#000000") + + def __str__(self): + return f'Planning for {self.user.username}' + + +class Events(models.Model): + planning = models.ForeignKey(Planning, on_delete=models.PROTECT) + title = models.CharField(max_length=255) + description = models.TextField() + start = models.DateTimeField() + end = models.DateTimeField() + recursionType = models.IntegerField(choices=RecursionType, default=0) + color= models.CharField(max_length=255) + location = models.CharField(max_length=255, default="", blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) + + + def __str__(self): + return f'Event for {self.user.username}' \ No newline at end of file diff --git a/Back-End/Planning/serializers.py b/Back-End/Planning/serializers.py new file mode 100644 index 0000000..b3467f1 --- /dev/null +++ b/Back-End/Planning/serializers.py @@ -0,0 +1,13 @@ +from rest_framework import serializers + +from .models import Planning, Events + + +class PlanningSerializer(serializers.ModelSerializer): + class Meta: + model = Planning + fields = '__all__' +class EventsSerializer(serializers.ModelSerializer): + class Meta: + model = Events + fields = '__all__' \ No newline at end of file diff --git a/Back-End/Planning/urls.py b/Back-End/Planning/urls.py new file mode 100644 index 0000000..f796b1d --- /dev/null +++ b/Back-End/Planning/urls.py @@ -0,0 +1,10 @@ +from django.urls import path, re_path + +from Planning.views import PlanningView,PlanningWithIdView,EventsView,EventsWithIdView + +urlpatterns = [ + re_path(r'^plannings$', PlanningView.as_view(), name="planning"), + re_path(r'^plannings/(?P[0-9]+)$', PlanningWithIdView.as_view(), name="planning"), + re_path(r'^events$', EventsView.as_view(), name="events"), + re_path(r'^events/(?P[0-9]+)$', EventsWithIdView.as_view(), name="events"), +] \ No newline at end of file diff --git a/Back-End/Planning/views.py b/Back-End/Planning/views.py new file mode 100644 index 0000000..6bb4e7b --- /dev/null +++ b/Back-End/Planning/views.py @@ -0,0 +1,89 @@ +from django.http.response import JsonResponse +from rest_framework.views import APIView + +from .models import Planning, Events + +from .serializers import PlanningSerializer, EventsSerializer + +from N3wtSchool import bdd + +class PlanningView(APIView): + def get(self, request): + plannings=bdd.getAllObjects(Planning) + planning_serializer=PlanningSerializer(plannings, many=True) + + return JsonResponse(planning_serializer.data, safe=False) + + def post(self, request): + planning_serializer = PlanningSerializer(data=request.data) + if planning_serializer.is_valid(): + planning_serializer.save() + return JsonResponse(planning_serializer.data, status=201) + return JsonResponse(planning_serializer.errors, status=400) + + + +class PlanningWithIdView(APIView): + def get(self, request,id): + planning = Planning.objects.get(pk=id) + if planning is None: + return JsonResponse({"errorMessage":'Le dossier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) + planning_serializer=PlanningSerializer(planning) + + return JsonResponse(planning_serializer.data, safe=False) + + def put(self, request, id): + try: + planning = Planning.objects.get(pk=id) + except Planning.DoesNotExist: + return JsonResponse({'error': 'Planning not found'}, status=404) + + planning_serializer = PlanningSerializer(planning, data=request.data) + if planning_serializer.is_valid(): + planning_serializer.save() + return JsonResponse(planning_serializer.data) + return JsonResponse(planning_serializer.errors, status=400) + + def delete(self, request, id): + try: + planning = Planning.objects.get(pk=id) + except Planning.DoesNotExist: + return JsonResponse({'error': 'Planning not found'}, status=404) + + planning.delete() + return JsonResponse({'message': 'Planning deleted'}, status=204) + +class EventsView(APIView): + def get(self, request): + events = bdd.getAllObjects(Events) + events_serializer = EventsSerializer(events, many=True) + return JsonResponse(events_serializer.data, safe=False) + + def post(self, request): + events_serializer = EventsSerializer(data=request.data) + if events_serializer.is_valid(): + events_serializer.save() + return JsonResponse(events_serializer.data, status=201) + return JsonResponse(events_serializer.errors, status=400) + +class EventsWithIdView(APIView): + def put(self, request, id): + try: + event = Events.objects.get(pk=id) + except Events.DoesNotExist: + return JsonResponse({'error': 'Event not found'}, status=404) + + events_serializer = EventsSerializer(event, data=request.data) + if events_serializer.is_valid(): + events_serializer.save() + return JsonResponse(events_serializer.data) + return JsonResponse(events_serializer.errors, status=400) + + def delete(self, request, id): + try: + event = Events.objects.get(pk=id) + except Events.DoesNotExist: + return JsonResponse({'error': 'Event not found'}, status=404) + + event.delete() + return JsonResponse({'message': 'Event deleted'}, status=204) \ No newline at end of file diff --git a/Back-End/start.py b/Back-End/start.py index ca1d961..c11e339 100644 --- a/Back-End/start.py +++ b/Back-End/start.py @@ -16,6 +16,7 @@ commands = [ ["python", "manage.py", "collectstatic", "--noinput"], ["python", "manage.py", "flush", "--noinput"], ["python", "manage.py", "makemigrations", "Subscriptions", "--noinput"], + ["python", "manage.py", "makemigrations", "Planning", "--noinput"], ["python", "manage.py", "makemigrations", "GestionNotification", "--noinput"], ["python", "manage.py", "makemigrations", "GestionMessagerie", "--noinput"], ["python", "manage.py", "makemigrations", "Auth", "--noinput"], diff --git a/Front-End/src/app/[locale]/admin/planning/page.js b/Front-End/src/app/[locale]/admin/planning/page.js index 346d223..a09e2a8 100644 --- a/Front-End/src/app/[locale]/admin/planning/page.js +++ b/Front-End/src/app/[locale]/admin/planning/page.js @@ -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: '', diff --git a/Front-End/src/app/actions/planningAction.js b/Front-End/src/app/actions/planningAction.js new file mode 100644 index 0000000..035d057 --- /dev/null +++ b/Front-End/src/app/actions/planningAction.js @@ -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) +} + + + diff --git a/Front-End/src/components/Calendar.js b/Front-End/src/components/Calendar.js index 06afcd3..4ffdb1c 100644 --- a/Front-End/src/components/Calendar.js +++ b/Front-End/src/components/Calendar.js @@ -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]); diff --git a/Front-End/src/components/EventModal.js b/Front-End/src/components/EventModal.js index fa2051f..823f88d 100644 --- a/Front-End/src/components/EventModal.js +++ b/Front-End/src/components/EventModal.js @@ -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 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" /> diff --git a/Front-End/src/context/PlanningContext.js b/Front-End/src/context/PlanningContext.js index ebf53e9..9010871 100644 --- a/Front-End/src/context/PlanningContext.js +++ b/Front-End/src/context/PlanningContext.js @@ -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, diff --git a/Front-End/src/data/mockData.js b/Front-End/src/data/mockData.js index efea860..fd0609a 100644 --- a/Front-End/src/data/mockData.js +++ b/Front-End/src/data/mockData.js @@ -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' } diff --git a/Front-End/src/hooks/useEvents.js b/Front-End/src/hooks/useEvents.js deleted file mode 100644 index 5d37b84..0000000 --- a/Front-End/src/hooks/useEvents.js +++ /dev/null @@ -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 - }; -} \ No newline at end of file diff --git a/Front-End/src/hooks/useSchedules.js b/Front-End/src/hooks/useSchedules.js deleted file mode 100644 index 6d926f8..0000000 --- a/Front-End/src/hooks/useSchedules.js +++ /dev/null @@ -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 - }; -} \ No newline at end of file diff --git a/Front-End/src/utils/Url.js b/Front-End/src/utils/Url.js index c690d1e..9c1fc4b 100644 --- a/Front-End/src/utils/Url.js +++ b/Front-End/src/utils/Url.js @@ -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 diff --git a/Front-End/src/utils/constants.js b/Front-End/src/utils/constants.js index 6bb0e80..6229242 100644 --- a/Front-End/src/utils/constants.js +++ b/Front-End/src/utils/constants.js @@ -14,7 +14,7 @@ export const DEFAULT_EVENT = { start: '', end: '', location: '', - scheduleId: 'default', + planning: 'default', color: '#10b981', recurrence: 'none', selectedDays: [], diff --git a/Front-End/src/utils/events.js b/Front-End/src/utils/events.js index 5d09c88..126b257 100644 --- a/Front-End/src/utils/events.js +++ b/Front-End/src/utils/events.js @@ -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} 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)); };