mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: planning events
This commit is contained in:
@ -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',
|
||||
|
||||
@ -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<format>\.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'),
|
||||
|
||||
1
Back-End/Planning/__init__.py
Normal file
1
Back-End/Planning/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
default_app_config = 'Planning.apps.PlanningConfig'
|
||||
3
Back-End/Planning/admin.py
Normal file
3
Back-End/Planning/admin.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
7
Back-End/Planning/apps.py
Normal file
7
Back-End/Planning/apps.py
Normal file
@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
class PlanningConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'Planning'
|
||||
|
||||
|
||||
38
Back-End/Planning/models.py
Normal file
38
Back-End/Planning/models.py
Normal file
@ -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}'
|
||||
13
Back-End/Planning/serializers.py
Normal file
13
Back-End/Planning/serializers.py
Normal file
@ -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__'
|
||||
10
Back-End/Planning/urls.py
Normal file
10
Back-End/Planning/urls.py
Normal file
@ -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<id>[0-9]+)$', PlanningWithIdView.as_view(), name="planning"),
|
||||
re_path(r'^events$', EventsView.as_view(), name="events"),
|
||||
re_path(r'^events/(?P<id>[0-9]+)$', EventsWithIdView.as_view(), name="events"),
|
||||
]
|
||||
89
Back-End/Planning/views.py
Normal file
89
Back-End/Planning/views.py
Normal file
@ -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)
|
||||
@ -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"],
|
||||
|
||||
@ -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