feat: Ajout de la gestion des fichier d'inscription [#1]

This commit is contained in:
Luc SORIGNET
2025-01-11 16:14:03 +01:00
parent fb5d485ce1
commit 3c27133cdb
16 changed files with 469 additions and 143 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ __pycache__/
node_modules/ node_modules/
Back-End/*/migrations/* Back-End/*/migrations/*
Back-End/documents Back-End/documents
Back-End/data
Back-End/*.dmp Back-End/*.dmp
Back-End/staticfiles Back-End/staticfiles
hardcoded-strings-report.md hardcoded-strings-report.md

View File

@ -61,7 +61,7 @@ class Eleve(models.Model):
NONE = 0, _('Sélection du genre') NONE = 0, _('Sélection du genre')
MALE = 1, _('Garçon') MALE = 1, _('Garçon')
FEMALE = 2, _('Fille') FEMALE = 2, _('Fille')
class NiveauEleve(models.IntegerChoices): class NiveauEleve(models.IntegerChoices):
NONE = 0, _('Sélection du niveau') NONE = 0, _('Sélection du niveau')
TPS = 1, _('TPS - Très Petite Section') TPS = 1, _('TPS - Très Petite Section')
@ -88,7 +88,7 @@ class Eleve(models.Model):
# Relation N-N # Relation N-N
profils = models.ManyToManyField(Profil, blank=True) profils = models.ManyToManyField(Profil, blank=True)
# Relation N-N # Relation N-N
responsables = models.ManyToManyField(Responsable, blank=True) responsables = models.ManyToManyField(Responsable, blank=True)
@ -141,10 +141,10 @@ class Eleve(models.Model):
return f"{years} ans" return f"{years} ans"
return None return None
@property @property
def dateNaissance_formattee(self): def dateNaissance_formattee(self):
if self.dateNaissance: if self.dateNaissance:
return self.dateNaissance.strftime('%d-%m-%Y') return self.dateNaissance.strftime('%d-%m-%Y')
return None return None
class FicheInscription(models.Model): class FicheInscription(models.Model):
@ -169,4 +169,11 @@ class FicheInscription(models.Model):
def __str__(self): def __str__(self):
return "FI_" + self.eleve.nom + "_" + self.eleve.prenom return "FI_" + self.eleve.nom + "_" + self.eleve.prenom
class FichierInscription(models.Model):
name = models.CharField(max_length=255)
file = models.FileField(upload_to='fichiers_inscription/')
date_ajout = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.nom

View File

@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from GestionInscriptions.models import FicheInscription, Eleve, Responsable, Frere, Langue, FraisInscription from GestionInscriptions.models import FichierInscription, FicheInscription, Eleve, Responsable, Frere, Langue, FraisInscription
from GestionEnseignants.models import Classe from GestionEnseignants.models import Classe
from GestionLogin.models import Profil from GestionLogin.models import Profil
from GestionLogin.serializers import ProfilSerializer from GestionLogin.serializers import ProfilSerializer
@ -10,6 +10,10 @@ from django.utils import timezone
import pytz import pytz
from datetime import datetime from datetime import datetime
class FichierInscriptionSerializer(serializers.ModelSerializer):
class Meta:
model = FichierInscription
fields = '__all__'
class FraisInscriptionSerializer(serializers.ModelSerializer): class FraisInscriptionSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
class Meta: class Meta:
@ -42,7 +46,7 @@ class EleveSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
responsables = ResponsableSerializer(many=True, required=False) responsables = ResponsableSerializer(many=True, required=False)
freres = FrereSerializer(many=True, required=False) freres = FrereSerializer(many=True, required=False)
langues = LanguesSerializer(many=True, required=False) langues = LanguesSerializer(many=True, required=False)
classeAssocie_id = serializers.PrimaryKeyRelatedField(queryset=Classe.objects.all(), source='classeAssociee', required=False, write_only=False, read_only=False) classeAssocie_id = serializers.PrimaryKeyRelatedField(queryset=Classe.objects.all(), source='classeAssociee', required=False, write_only=False, read_only=False)
age = serializers.SerializerMethodField() age = serializers.SerializerMethodField()
dateNaissance_formattee = serializers.SerializerMethodField() dateNaissance_formattee = serializers.SerializerMethodField()
@ -56,11 +60,11 @@ class EleveSerializer(serializers.ModelSerializer):
def get_or_create_packages(self, responsables_data): def get_or_create_packages(self, responsables_data):
responsables_ids = [] responsables_ids = []
for responsable_data in responsables_data: for responsable_data in responsables_data:
responsable_instance, created = Responsable.objects.get_or_create( id=responsable_data.get('id'), responsable_instance, created = Responsable.objects.get_or_create( id=responsable_data.get('id'),
defaults=responsable_data) defaults=responsable_data)
responsables_ids.append(responsable_instance.id) responsables_ids.append(responsable_instance.id)
return responsables_ids return responsables_ids
def create(self, validated_data): def create(self, validated_data):
responsables_data = validated_data.pop('responsables', []) responsables_data = validated_data.pop('responsables', [])
freres_data = validated_data.pop('freres', []) freres_data = validated_data.pop('freres', [])
@ -69,15 +73,15 @@ class EleveSerializer(serializers.ModelSerializer):
eleve.responsables.set(self.get_or_create_packages(responsables_data)) eleve.responsables.set(self.get_or_create_packages(responsables_data))
eleve.freres.set(self.get_or_create_packages(freres_data)) eleve.freres.set(self.get_or_create_packages(freres_data))
eleve.languesParlees.set(self.get_or_create_packages(langues_data)) eleve.languesParlees.set(self.get_or_create_packages(langues_data))
return eleve return eleve
def create_or_update_packages(self, responsables_data): def create_or_update_packages(self, responsables_data):
responsables_ids = [] responsables_ids = []
for responsable_data in responsables_data: for responsable_data in responsables_data:
responsable_instance, created = Responsable.objects.update_or_create( id=responsable_data.get('id'), responsable_instance, created = Responsable.objects.update_or_create( id=responsable_data.get('id'),
defaults=responsable_data) defaults=responsable_data)
responsables_ids.append(responsable_instance.id) responsables_ids.append(responsable_instance.id)
@ -103,13 +107,13 @@ class EleveSerializer(serializers.ModelSerializer):
return instance return instance
def get_age(self, obj): def get_age(self, obj):
return obj.age return obj.age
def get_dateNaissance_formattee(self, obj): def get_dateNaissance_formattee(self, obj):
return obj.dateNaissance_formattee return obj.dateNaissance_formattee
def get_classeAssocieeName(self, obj): def get_classeAssocieeName(self, obj):
return obj.classeAssociee.nom_ambiance if obj.classeAssociee else None return obj.classeAssociee.nom_ambiance if obj.classeAssociee else None
class FicheInscriptionSerializer(serializers.ModelSerializer): class FicheInscriptionSerializer(serializers.ModelSerializer):
@ -120,13 +124,13 @@ class FicheInscriptionSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = FicheInscription model = FicheInscription
fields = '__all__' fields = '__all__'
def create(self, validated_data): def create(self, validated_data):
eleve_data = validated_data.pop('eleve') eleve_data = validated_data.pop('eleve')
eleve = EleveSerializer.create(EleveSerializer(), eleve_data) eleve = EleveSerializer.create(EleveSerializer(), eleve_data)
ficheEleve = FicheInscription.objects.create(eleve=eleve, **validated_data) ficheEleve = FicheInscription.objects.create(eleve=eleve, **validated_data)
return ficheEleve return ficheEleve
def update(self, instance, validated_data): def update(self, instance, validated_data):
eleve_data = validated_data.pop('eleve') eleve_data = validated_data.pop('eleve')
eleve = instance.eleve eleve = instance.eleve
@ -138,10 +142,10 @@ class FicheInscriptionSerializer(serializers.ModelSerializer):
except KeyError: except KeyError:
pass pass
instance.save() instance.save()
return instance return instance
def get_etat_label(self, obj): def get_etat_label(self, obj):
return obj.get_etat_display() return obj.get_etat_display()
def get_dateMAJ_formattee(self, obj): def get_dateMAJ_formattee(self, obj):
@ -156,7 +160,7 @@ class EleveByParentSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Eleve model = Eleve
fields = ['id', 'nom', 'prenom'] fields = ['id', 'nom', 'prenom']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(EleveByParentSerializer , self).__init__(*args, **kwargs) super(EleveByParentSerializer , self).__init__(*args, **kwargs)
for field in self.fields: for field in self.fields:
@ -167,7 +171,7 @@ class FicheInscriptionByParentSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = FicheInscription model = FicheInscription
fields = ['eleve', 'etat'] fields = ['eleve', 'etat']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(FicheInscriptionByParentSerializer, self).__init__(*args, **kwargs) super(FicheInscriptionByParentSerializer, self).__init__(*args, **kwargs)
for field in self.fields: for field in self.fields:
@ -185,7 +189,7 @@ class EleveByDICreationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Eleve model = Eleve
fields = ['id', 'nom', 'prenom', 'responsables'] fields = ['id', 'nom', 'prenom', 'responsables']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(EleveByDICreationSerializer , self).__init__(*args, **kwargs) super(EleveByDICreationSerializer , self).__init__(*args, **kwargs)
for field in self.fields: for field in self.fields:
@ -196,4 +200,3 @@ class NotificationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Notification model = Notification
fields = '__all__' fields = '__all__'

View File

@ -1,7 +1,7 @@
from django.urls import path, re_path from django.urls import path, re_path
from . import views from . import views
from GestionInscriptions.views import ListFichesInscriptionView, FicheInscriptionView, EleveView, ResponsableView, ListeEnfantsView, ListeElevesView, FraisInscriptionView from GestionInscriptions.views import FichierInscriptionView, ListFichesInscriptionView, FicheInscriptionView, EleveView, ResponsableView, ListeEnfantsView, ListeElevesView, FraisInscriptionView
urlpatterns = [ urlpatterns = [
re_path(r'^fichesInscription/([a-zA-z]+)$', ListFichesInscriptionView.as_view(), name="listefichesInscriptions"), re_path(r'^fichesInscription/([a-zA-z]+)$', ListFichesInscriptionView.as_view(), name="listefichesInscriptions"),
@ -23,7 +23,7 @@ urlpatterns = [
# Envoi d'une relance de dossier d'inscription # Envoi d'une relance de dossier d'inscription
re_path(r'^sendRelance/([0-9]+)$', views.relance, name="relance"), re_path(r'^sendRelance/([0-9]+)$', views.relance, name="relance"),
# Page PARENT - Liste des enfants # Page PARENT - Liste des enfants
re_path(r'^enfants/([0-9]+)$', ListeEnfantsView.as_view(), name="enfants"), re_path(r'^enfants/([0-9]+)$', ListeEnfantsView.as_view(), name="enfants"),
# Page INSCRIPTION - Liste des élèves # Page INSCRIPTION - Liste des élèves
@ -31,4 +31,6 @@ urlpatterns = [
# Frais d'inscription # Frais d'inscription
re_path(r'^tarifsInscription$', FraisInscriptionView.as_view(), name="fraisInscription"), re_path(r'^tarifsInscription$', FraisInscriptionView.as_view(), name="fraisInscription"),
re_path(r'^fichiersInscription$', FichierInscriptionView.as_view(), name='fichiersInscription'),
re_path(r'^fichiersInscription/([0-9]+)$', FichierInscriptionView.as_view(), name="fichiersInscription"),
] ]

View File

@ -128,13 +128,13 @@ def toNewEleveJSONRequest(jsonOrigin):
etat=FicheInscription.EtatDossierInscription.DI_CREE etat=FicheInscription.EtatDossierInscription.DI_CREE
telephone = convertTelephone(_(jsonOrigin['telephoneResponsable'])) telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']))
finalJSON = { finalJSON = {
"eleve": "eleve":
{ {
"nom" : _(jsonOrigin['nomEleve']), "nom" : _(jsonOrigin['nomEleve']),
"prenom" : _(jsonOrigin['prenomEleve']), "prenom" : _(jsonOrigin['prenomEleve']),
"responsables" : [ "responsables" : [
{ {
"nom" : _(jsonOrigin['nomResponsable']), "nom" : _(jsonOrigin['nomResponsable']),
"prenom" : _(jsonOrigin['prenomResponsable']), "prenom" : _(jsonOrigin['prenomResponsable']),
"mail" : _(jsonOrigin['mailResponsable']), "mail" : _(jsonOrigin['mailResponsable']),
"telephone" : telephone "telephone" : telephone
@ -143,7 +143,7 @@ def toNewEleveJSONRequest(jsonOrigin):
"profils" : [ "profils" : [
], ],
}, },
"etat": str(etat), "etat": str(etat),
"dateMAJ": str(convertToStr(_now(), '%d-%m-%Y %H:%M')), "dateMAJ": str(convertToStr(_now(), '%d-%m-%Y %H:%M')),
} }
print(finalJSON) print(finalJSON)
@ -152,15 +152,15 @@ def toNewEleveJSONRequest(jsonOrigin):
def toEditEleveJSONRequest(jsonOrigin): def toEditEleveJSONRequest(jsonOrigin):
telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']), '.') telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']), '.')
finalJSON = { finalJSON = {
"eleve": "eleve":
{ {
"id" : _(jsonOrigin['fiche_id']), "id" : _(jsonOrigin['fiche_id']),
"nom" : _(jsonOrigin['nomEleve']), "nom" : _(jsonOrigin['nomEleve']),
"prenom" : _(jsonOrigin['prenomEleve']), "prenom" : _(jsonOrigin['prenomEleve']),
"responsables" : [ "responsables" : [
{ {
"id" : _(jsonOrigin['responsable_id']), "id" : _(jsonOrigin['responsable_id']),
"nom" : _(jsonOrigin['nomResponsable']), "nom" : _(jsonOrigin['nomResponsable']),
"prenom" : _(jsonOrigin['prenomResponsable']), "prenom" : _(jsonOrigin['prenomResponsable']),
"mail" : _(jsonOrigin['mailResponsable']), "mail" : _(jsonOrigin['mailResponsable']),
"telephone" : telephone "telephone" : telephone

View File

@ -6,7 +6,8 @@ from django.core.cache import cache
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.core.files import File from django.core.files import File
from django.db.models import Q # Ajout de cet import from django.db.models import Q # Ajout de cet import
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser,MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework import status from rest_framework import status
@ -17,10 +18,11 @@ from io import BytesIO
import GestionInscriptions.mailManager as mailer import GestionInscriptions.mailManager as mailer
import GestionInscriptions.util as util import GestionInscriptions.util as util
from GestionInscriptions.serializers import FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer, FraisInscriptionSerializer from GestionInscriptions.serializers import FichierInscriptionSerializer, FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer, FraisInscriptionSerializer
from GestionInscriptions.pagination import CustomPagination from GestionInscriptions.pagination import CustomPagination
from GestionInscriptions.signals import clear_cache from GestionInscriptions.signals import clear_cache
from .models import Eleve, Responsable, FicheInscription, FraisInscription from .models import Eleve, Responsable, FicheInscription, FraisInscription, FichierInscription
from GestionInscriptions.automate import Automate_DI_Inscription, load_config, getStateMachineObjectState, updateStateMachine from GestionInscriptions.automate import Automate_DI_Inscription, load_config, getStateMachineObjectState, updateStateMachine
from GestionLogin.models import Profil from GestionLogin.models import Profil
@ -57,7 +59,7 @@ class ListFichesInscriptionView(APIView):
page_size = int(page_size) page_size = int(page_size)
except ValueError: except ValueError:
page_size = settings.NB_RESULT_PER_PAGE page_size = settings.NB_RESULT_PER_PAGE
# Définir le cache_key en fonction du filtre # Définir le cache_key en fonction du filtre
page_number = request.GET.get('page', 1) page_number = request.GET.get('page', 1)
cache_key = f'N3WT_ficheInscriptions_{_filter}_page_{page_number}_search_{search if _filter == "pending" else ""}' cache_key = f'N3WT_ficheInscriptions_{_filter}_page_{page_number}_search_{search if _filter == "pending" else ""}'
@ -254,3 +256,27 @@ class FraisInscriptionView(APIView):
tarifs = bdd.getAllObjects(FraisInscription) tarifs = bdd.getAllObjects(FraisInscription)
tarifs_serializer = FraisInscriptionSerializer(tarifs, many=True) tarifs_serializer = FraisInscriptionSerializer(tarifs, many=True)
return JsonResponse(tarifs_serializer.data, safe=False) return JsonResponse(tarifs_serializer.data, safe=False)
class FichierInscriptionView(APIView):
parser_classes = (MultiPartParser, FormParser)
def get(self, request):
fichiers = FichierInscription.objects.all()
serializer = FichierInscriptionSerializer(fichiers, many=True)
return Response(serializer.data)
def post(self, request):
serializer = FichierInscriptionSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, _id):
fichierInscription = bdd.getObject(_objectName=FichierInscription, _columnName='id', _value=_id)
if fichierInscription is not None:
fichierInscription.file.delete() # Supprimer le fichier uploadé
fichierInscription.delete()
return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False)
else:
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False)

View File

@ -16,6 +16,8 @@ import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = '/data/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'data')
LOGIN_REDIRECT_URL = '/GestionInscriptions/fichesInscriptions' LOGIN_REDIRECT_URL = '/GestionInscriptions/fichesInscriptions'

View File

@ -16,6 +16,8 @@ Including another URLconf
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import include, path, re_path from django.urls import include, path, re_path
from django.conf import settings
from django.conf.urls.static import static
from rest_framework import permissions from rest_framework import permissions
from drf_yasg.views import get_schema_view from drf_yasg.views import get_schema_view
from drf_yasg import openapi from drf_yasg import openapi
@ -47,3 +49,6 @@ urlpatterns = [
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
] ]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -28,5 +28,6 @@
"lastUpdateDate":"Last update", "lastUpdateDate":"Last update",
"classe":"Class", "classe":"Class",
"registrationFileStatus":"Registration file status", "registrationFileStatus":"Registration file status",
"files":"Files" "files":"Files",
"subscribeFiles":"Subscribe files"
} }

View File

@ -28,5 +28,6 @@
"lastUpdateDate":"Dernière mise à jour", "lastUpdateDate":"Dernière mise à jour",
"classe":"Classe", "classe":"Classe",
"registrationFileStatus":"État du dossier d'inscription", "registrationFileStatus":"État du dossier d'inscription",
"files":"Fichiers" "files":"Fichiers",
"subscribeFiles":"Fichiers d'inscription"
} }

View File

@ -63,7 +63,7 @@ export default function Layout({
<Sidebar currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" /> <Sidebar currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
<div className="flex flex-col flex-1"> <div className="flex flex-col flex-1">
{/* Header - h-16 = 64px */} {/* Header - h-16 = 64px */}
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-10"> <header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
<div className="text-xl font-semibold">{headerTitle}</div> <div className="text-xl font-semibold">{headerTitle}</div>
<DropdownMenu <DropdownMenu
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />} buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}

View File

@ -0,0 +1,77 @@
import React, { useState } from 'react';
import { Upload } from 'lucide-react';
export default function FileUpload({ onFileUpload }) {
const [dragActive, setDragActive] = useState(false);
const [fileName, setFileName] = useState('');
const [file, setFile] = useState(null);
const handleDragOver = (event) => {
event.preventDefault();
setDragActive(true);
};
const handleDragLeave = () => {
setDragActive(false);
};
const handleDrop = (event) => {
event.preventDefault();
setDragActive(false);
const droppedFile = event.dataTransfer.files[0];
setFile(droppedFile);
setFileName(droppedFile.name.replace(/\.[^/.]+$/, ""));
};
const handleFileChange = (event) => {
const selectedFile = event.target.files[0];
setFile(selectedFile);
setFileName(selectedFile.name.replace(/\.[^/.]+$/, ""));
};
const handleFileNameChange = (event) => {
setFileName(event.target.value);
};
const handleUpload = () => {
if (file) {
onFileUpload(file, fileName);
setFile(null);
setFileName('');
}
};
return (
<div>
<div
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={`border-2 border-dashed p-8 rounded-md ${dragActive ? 'border-blue-500' : 'border-gray-300'} flex flex-col items-center justify-center`}
style={{ height: '200px' }}
>
<input type="file" onChange={handleFileChange} className="hidden" id="fileInput" />
<label htmlFor="fileInput" className="cursor-pointer flex flex-col items-center">
<Upload size={48} className="text-gray-400 mb-2" />
<p className="text-center">{fileName || 'Glissez et déposez un fichier ici ou cliquez ici pour sélectionner un fichier'}</p>
</label>
</div>
<div className="flex mt-2">
<input
type="text"
placeholder="Nom du fichier"
value={fileName}
onChange={handleFileNameChange}
className="flex-grow p-2 border border-gray-200 rounded-md"
/>
<button
onClick={handleUpload}
className={`p-2 rounded-md shadow transition duration-200 ml-2 ${file ? 'bg-emerald-600 text-white hover:bg-emerald-900' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}`}
disabled={!file}
>
Ajouter
</button>
</div>
</div>
);
}

View File

@ -13,17 +13,19 @@ import Button from '@/components/Button';
import DropdownMenu from "@/components/DropdownMenu"; import DropdownMenu from "@/components/DropdownMenu";
import { swapFormatDate } from '@/utils/Date'; import { swapFormatDate } from '@/utils/Date';
import { formatPhoneNumber } from '@/utils/Telephone'; import { formatPhoneNumber } from '@/utils/Telephone';
import { MoreVertical, Send, Edit, Trash2, FileText, ChevronUp, UserPlus, CheckCircle, Plus} from 'lucide-react'; import { MoreVertical, Send, Edit, Trash2, FileText, ChevronUp, UserPlus, CheckCircle, Plus, Download } from 'lucide-react';
import Modal from '@/components/Modal'; import Modal from '@/components/Modal';
import InscriptionForm from '@/components/Inscription/InscriptionForm' import InscriptionForm from '@/components/Inscription/InscriptionForm'
import AffectationClasseForm from '@/components/AffectationClasseForm' import AffectationClasseForm from '@/components/AffectationClasseForm'
import FileUpload from './components/FileUpload';
import { BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL, import { BASE_URL, BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL,
BK_GESTIONINSCRIPTION_SEND_URL, BK_GESTIONINSCRIPTION_SEND_URL,
FR_ADMIN_SUBSCRIPTIONS_EDIT_URL, FR_ADMIN_SUBSCRIPTIONS_EDIT_URL,
BK_GESTIONINSCRIPTION_ARCHIVE_URL, BK_GESTIONINSCRIPTION_ARCHIVE_URL,
BK_GESTIONENSEIGNANTS_CLASSES_URL, BK_GESTIONENSEIGNANTS_CLASSES_URL,
BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL, BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL,
BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL ,
BK_GESTIONINSCRIPTION_ELEVES_URL, BK_GESTIONINSCRIPTION_ELEVES_URL,
BK_PROFILE_URL } from '@/utils/Url'; BK_PROFILE_URL } from '@/utils/Url';
@ -53,6 +55,10 @@ export default function Page({ params: { locale } }) {
const [totalArchives, setTotalArchives] = useState(0); const [totalArchives, setTotalArchives] = useState(0);
const [itemsPerPage, setItemsPerPage] = useState(5); // Définir le nombre d'éléments par page const [itemsPerPage, setItemsPerPage] = useState(5); // Définir le nombre d'éléments par page
const [fichiers, setFichiers] = useState([]);
const [nomFichier, setNomFichier] = useState('');
const [fichier, setFichier] = useState(null);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false); const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false);
const [eleve, setEleve] = useState(''); const [eleve, setEleve] = useState('');
@ -180,6 +186,32 @@ export default function Page({ params: { locale } }) {
}); });
}; };
useEffect(() => {
const fetchFichiers = () => {
const request = new Request(
`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
fetch(request).then(response => response.json())
.then(data => {
console.log('Success FILES:', data);
setFichiers(data);
})
.catch(error => {
console.error('Error fetching data:', error);
error = error.message;
console.log(error);
});
};
fetchFichiers();
}, []);
useEffect(() => { useEffect(() => {
fetchClasses(); fetchClasses();
fetchStudents(); fetchStudents();
@ -326,7 +358,7 @@ export default function Page({ params: { locale } }) {
{ {
method:'POST', method:'POST',
headers: { headers: {
'Content-Type':'application/json', 'Content-Type':'application/json',
'X-CSRFToken': csrfToken 'X-CSRFToken': csrfToken
}, },
credentials: 'include', credentials: 'include',
@ -371,7 +403,7 @@ export default function Page({ params: { locale } }) {
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => { setFichesInscriptionsDataEnCours(prevState => {
if (prevState && prevState.length > 0) { if (prevState && prevState.length > 0) {
return [...prevState, data]; return [...prevState, data];
@ -429,13 +461,11 @@ const columns = [
) )
}, },
{ name: t('files'), transform: (row) => ( { name: t('files'), transform: (row) => (
<ul> <ul>
{row.fichiers?.map((fichier, fileIndex) => ( <li className="flex items-center gap-2">
<li key={fileIndex} className="flex items-center gap-2">
<FileText size={16} /> <FileText size={16} />
<a href={fichier.url}>{fichier.nom}</a> <a href={ `${BASE_URL}${row.fichierInscription}`} target='_blank'>{row.fichierInscription.split('/').pop()}</a>
</li> </li>
))}
</ul> </ul>
) }, ) },
{ name: 'Actions', transform: (row) => ( { name: 'Actions', transform: (row) => (
@ -509,14 +539,13 @@ const columnsSubscribed = [
</div> </div>
) )
}, },
{ name: t('files'), transform: (row) => ( { name: t('files'), transform: (row) =>
(
<ul> <ul>
{row.fichiers?.map((fichier, fileIndex) => ( <li className="flex items-center gap-2">
<li key={fileIndex} className="flex items-center gap-2">
<FileText size={16} /> <FileText size={16} />
<a href={fichier.url}>{fichier.nom}</a> <a href={ `${BASE_URL}${row.fichierInscription}`} target='_blank'>{row.fichierInscription.split('/').pop()}</a>
</li> </li>
))}
</ul> </ul>
) }, ) },
{ name: 'Actions', transform: (row) => ( { name: 'Actions', transform: (row) => (
@ -545,6 +574,98 @@ const columnsSubscribed = [
]; ];
const handleFileDelete = (fileId) => {
fetch(`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(response => {
if (response.ok) {
setFichiers(fichiers.filter(fichier => fichier.id !== fileId));
alert('Fichier supprimé avec succès.');
} else {
alert('Erreur lors de la suppression du fichier.');
}
})
.catch(error => {
console.error('Error deleting file:', error);
alert('Erreur lors de la suppression du fichier.');
});
};
const columnsFiles = [
{ name: 'Nom du fichier', transform: (row) => row.name },
{ name: 'Date de création', transform: (row) => row.date_ajout },
{ name: 'Actions', transform: (row) => (
<div className="flex items-center justify-center gap-2">
<a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
<Download size={16} />
</a>
<button onClick={() => handleFileDelete(row.id)} className="text-red-500 hover:text-red-700">
<Trash2 size={16} />
</button>
</div>
) },
];
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
const [uploadFile, setUploadFile] = useState(null);
const [uploadFileName, setUploadFileName] = useState('');
const [fileName, setFileName] = useState('');
const openUploadModal = () => {
setIsUploadModalOpen(true);
};
const closeUploadModal = () => {
setIsUploadModalOpen(false);
setUploadFile(null);
setUploadFileName('');
setFileName('');
};
const handleFileChange = (event) => {
const file = event.target.files[0];
setUploadFile(file);
setUploadFileName(file ? file.name : '');
};
const handleFileNameChange = (event) => {
setFileName(event.target.value);
};
const handleFileUpload = (file, fileName) => {
if (!file || !fileName) {
alert('Veuillez sélectionner un fichier et entrer un nom de fichier.');
return;
}
const formData = new FormData();
formData.append('file', file);
formData.append('name', fileName);
fetch(`${BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL}`, {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
setFichiers([...fichiers, data]);
closeUploadModal();
})
.catch(error => {
console.error('Error uploading file:', error);
});
};
if (isLoading) { if (isLoading) {
return <Loader />; return <Loader />;
} else { } else {
@ -593,16 +714,23 @@ const columnsSubscribed = [
active={activeTab === 'archived'} active={activeTab === 'archived'}
onClick={() => setActiveTab('archived')} onClick={() => setActiveTab('archived')}
/> />
<Tab
text={(
<>
{t('subscribeFiles')}
<span className="ml-2 text-sm text-gray-400">({totalSubscribed})</span>
</>
)}
active={activeTab === 'subscribeFiles'}
onClick={() => setActiveTab('subscribeFiles')}
/>
</div> </div>
</div> </div>
<div className="border-b border-gray-200 mb-6 w-full"> <div className="border-b border-gray-200 mb-6 w-full">
{/*SI STATE == pending || subscribe || archived */}
{activeTab === 'pending' || activeTab === 'subscribed' || activeTab === 'archived' ? (
<React.Fragment>
<div className="flex justify-between items-center mb-4 w-full"> <div className="flex justify-between items-center mb-4 w-full">
<button
onClick={openModal}
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-900 transition duration-200 mr-4"
>
<Plus className="w-5 h-5" />
</button>
<div className="relative flex-grow"> <div className="relative flex-grow">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" size={20} /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" size={20} />
<input <input
@ -613,7 +741,14 @@ const columnsSubscribed = [
onChange={handleSearchChange} onChange={handleSearchChange}
/> />
</div> </div>
<button
onClick={openModal}
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-900 transition duration-200 ml-4"
>
<Plus className="w-5 h-5" />
</button>
</div> </div>
<div className="w-full"> <div className="w-full">
<DjangoCSRFToken csrfToken={csrfToken} /> <DjangoCSRFToken csrfToken={csrfToken} />
<Table <Table
@ -636,6 +771,25 @@ const columnsSubscribed = [
onPageChange={handlePageChange} onPageChange={handlePageChange}
/> />
</div> </div>
</React.Fragment>
) : null}
{/*SI STATE == subscribeFiles */}
{activeTab === 'subscribeFiles' && (
<div>
<FileUpload onFileUpload={handleFileUpload} className="mb-4" />
<div className="mt-8">
<Table
data={fichiers}
columns={columnsFiles}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
totalPages={totalPages}
onPageChange={handlePageChange}
className="mt-8"
/>
</div>
</div>
)}
</div> </div>
<Popup <Popup
visible={popup.visible} visible={popup.visible}
@ -654,10 +808,10 @@ const columnsSubscribed = [
title={"Création d'un nouveau dossier d'inscription"} title={"Création d'un nouveau dossier d'inscription"}
size='sm:w-1/4' size='sm:w-1/4'
ContentComponent={() => ( ContentComponent={() => (
<InscriptionForm eleves={eleves} <InscriptionForm eleves={eleves}
onSubmit={createDI} onSubmit={createDI}
/> />
)} )}
/> />
)} )}
{isOpenAffectationClasse && ( {isOpenAffectationClasse && (
@ -674,6 +828,17 @@ const columnsSubscribed = [
)} )}
/> />
)} )}
{isUploadModalOpen && (
<Modal
isOpen={isUploadModalOpen}
setIsOpen={setIsUploadModalOpen}
title="Uploader un nouveau fichier"
size='sm:w-1/4'
ContentComponent={() => (
<FileUpload onFileUpload={handleFileUpload} />
)}
/>
)}
</div> </div>
); );
} }

View File

@ -70,21 +70,21 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
<div className="space-y-4 mt-8"> <div className="space-y-4 mt-8">
{step === 1 && ( {step === 1 && (
<div> <div>
<h2 className="text-2xl font-bold mb-4">Nouvel élève</h2> <h2 className="text-l font-bold mb-4">Nouvel élève</h2>
<InputTextIcon <InputTextIcon
name="eleveNom" name="eleveNom"
type="text" type="text"
IconItem={User} IconItem={User}
placeholder="Nom de l'élève" placeholder="Nom de l'élève"
value={formData.eleveNom} value={formData.eleveNom}
onChange={handleChange} onChange={handleChange}
className="w-full" className="w-full"
/> />
<InputTextIcon <InputTextIcon
name="elevePrenom" name="elevePrenom"
type="text" type="text"
IconItem={User} IconItem={User}
placeholder="Prénom de l'élève" placeholder="Prénom de l'élève"
value={formData.elevePrenom} value={formData.elevePrenom}
onChange={handleChange} onChange={handleChange}
className="w-full" className="w-full"
@ -94,7 +94,7 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
{step === 2 && ( {step === 2 && (
<div className="mt-6"> <div className="mt-6">
<h2 className="text-2xl font-bold mb-4">Responsable(s)</h2> <h2 className="text-l font-bold mb-4">Responsable(s)</h2>
<div className="flex flex-col space-y-4"> <div className="flex flex-col space-y-4">
<label className="flex items-center space-x-3"> <label className="flex items-center space-x-3">
<input <input
@ -120,17 +120,17 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
</label> </label>
</div> </div>
{formData.responsableType === 'new' && ( {formData.responsableType === 'new' && (
<InputTextIcon <InputTextIcon
name="responsableEmail" name="responsableEmail"
type="email" type="email"
IconItem={Mail} IconItem={Mail}
placeholder="Email du responsable" placeholder="Email du responsable"
value={formData.responsableEmail} value={formData.responsableEmail}
onChange={handleChange} onChange={handleChange}
className="w-full mt-4" className="w-full mt-4"
/> />
)} )}
{formData.responsableType === 'existing' && ( {formData.responsableType === 'existing' && (
<div className="mt-4"> <div className="mt-4">
<div className="mt-4" style={{ maxHeight: '300px', overflowY: 'auto' }}> <div className="mt-4" style={{ maxHeight: '300px', overflowY: 'auto' }}>
@ -161,10 +161,10 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
{existingResponsables.map((responsable) => ( {existingResponsables.map((responsable) => (
<div key={responsable.id}> <div key={responsable.id}>
<label className="flex items-center space-x-3 mt-2"> <label className="flex items-center space-x-3 mt-2">
<input <input
type="checkbox" type="checkbox"
checked={formData.selectedResponsables.includes(responsable.id)} checked={formData.selectedResponsables.includes(responsable.id)}
className="form-checkbox h-5 w-5 text-emerald-600" className="form-checkbox h-5 w-5 text-emerald-600"
onChange={() => handleResponsableSelection(responsable.id)} onChange={() => handleResponsableSelection(responsable.id)}
/> />
<span className="text-gray-900"> <span className="text-gray-900">
@ -182,12 +182,12 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
{step === 3 && ( {step === 3 && (
<div className="mt-6"> <div className="mt-6">
<h2 className="text-2xl font-bold mb-4">Téléphone (optionnel)</h2> <h2 className="text-l font-bold mb-4">Téléphone (optionnel)</h2>
<InputTextIcon <InputTextIcon
name="responsableTel" name="responsableTel"
type="tel" type="tel"
IconItem={Phone} IconItem={Phone}
placeholder="Numéro de téléphone" placeholder="Numéro de téléphone"
value={formData.responsableTel} value={formData.responsableTel}
onChange={handleChange} onChange={handleChange}
className="w-full mt-4" className="w-full mt-4"
@ -197,45 +197,71 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
{step === maxStep && ( {step === maxStep && (
<div> <div>
<h2 className="text-2xl font-bold mb-4">Récapitulatif</h2> <h2 className="text-l font-bold mb-4">Récapitulatif</h2>
<div className="flex items-center justify-between space-x-4"> <div className="space-y-4">
<div className="bg-gray-100 p-3 rounded-lg shadow-md flex items-center w-1/2 mb-4"> <section>
<User className="w-10 h-10 text-gray-300 mr-4" /> <h3 className="font-bold">Élève</h3>
<div> <table className="min-w-full bg-white border">
<p className="italic text-gray-600">Élève</p> <thead>
<p>Nom : {formData.eleveNom}</p> <tr>
<p>Prénom : {formData.elevePrenom}</p> <th className="px-4 py-2 border">Nom</th>
</div> <th className="px-4 py-2 border">Prénom</th>
</div> </tr>
</div> </thead>
<div className="flex items-center justify-between space-x-4"> <tbody>
<div className="bg-gray-100 p-3 rounded-lg shadow-md flex items-center w-1/2"> <tr>
<UserCheck className="w-10 h-10 text-gray-300 mr-4" /> <td className="px-4 py-2 border">{formData.eleveNom}</td>
<td className="px-4 py-2 border">{formData.elevePrenom}</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 className="font-bold">Responsable(s)</h3>
{formData.responsableType === 'new' && ( {formData.responsableType === 'new' && (
<div> <table className="min-w-full bg-white border">
<p className="italic text-gray-600">Responsable</p> <thead>
<p>Email : {formData.responsableEmail}</p> <tr>
<p>Téléphone : {formData.responsableTel}</p> <th className="px-4 py-2 border">Email</th>
</div> <th className="px-4 py-2 border">Téléphone</th>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">{formData.responsableEmail}</td>
<td className="px-4 py-2 border">{formData.responsableTel}</td>
</tr>
</tbody>
</table>
)} )}
{formData.responsableType === 'existing' && selectedEleve && ( {formData.responsableType === 'existing' && selectedEleve && (
<div> <div>
<p className="italic text-gray-600">Responsable(s)</p>
<p>Associé(s) à : {selectedEleve.nom} {selectedEleve.prenom}</p> <p>Associé(s) à : {selectedEleve.nom} {selectedEleve.prenom}</p>
<ul className="list-disc ml-6"> <table className="min-w-full bg-white border">
{existingResponsables.filter(responsable => formData.selectedResponsables.includes(responsable.id)).map((responsable) => ( <thead>
<li key={responsable.id}> <tr>
{responsable.nom && responsable.prenom ? `${responsable.nom} ${responsable.prenom}` : responsable.mail} <th className="px-4 py-2 border">Nom</th>
</li> <th className="px-4 py-2 border">Prénom</th>
))} <th className="px-4 py-2 border">Email</th>
</ul> </tr>
</thead>
<tbody>
{existingResponsables.filter(responsable => formData.selectedResponsables.includes(responsable.id)).map((responsable) => (
<tr key={responsable.id}>
<td className="px-4 py-2 border">{responsable.nom}</td>
<td className="px-4 py-2 border">{responsable.prenom}</td>
<td className="px-4 py-2 border">{responsable.mail}</td>
</tr>
))}
</tbody>
</table>
</div> </div>
)} )}
</div> </section>
</div> </div>
<div className='mt-4'> <div className='mt-4'>
<ToggleSwitch <ToggleSwitch
label="Envoi automatique" label="Envoi automatique"
checked={formData.autoMail} checked={formData.autoMail}
onChange={handleToggleChange} onChange={handleToggleChange}
/> />
@ -271,7 +297,7 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
<Button text="Créer" <Button text="Créer"
onClick={submit} onClick={submit}
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none" className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none"
primary primary
name="Create" /> name="Create" />
)} )}
</div> </div>

View File

@ -7,23 +7,26 @@ const Modal = ({ isOpen, setIsOpen, title, ContentComponent, size }) => {
<Dialog.Portal> <Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" /> <Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
<Dialog.Content className="fixed inset-0 flex items-center justify-center"> <Dialog.Content className="fixed inset-0 flex items-center justify-center">
<div className={`inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:p-6 ${size ? size : 'sm:w-full' }`}> <div className={`inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:p-6 ${size ? size : 'sm:w-full' }`} style={{ minWidth: '300px', width: 'auto' }}>
<Dialog.Title className="text-lg font-medium text-gray-900"> <div className="flex justify-between items-start">
{title} <Dialog.Title className="text-xl font-medium text-gray-900">
</Dialog.Title> {title}
</Dialog.Title>
<Dialog.Close asChild>
<button
onClick={() => setIsOpen(false)}
className="text-gray-400 hover:text-gray-500 ml-4 focus:outline-none"
>
<span className="sr-only">Fermer</span>
<svg className="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</Dialog.Close>
</div>
<div className="mt-2"> <div className="mt-2">
<ContentComponent /> <ContentComponent />
</div> </div>
<div className="mt-4 flex justify-end space-x-4">
<Dialog.Close asChild>
<Button text="Fermer"
onClick={() => setIsOpen(false)}
className="px-4 py-2 rounded-md shadow-sm focus:outline-none bg-gray-300 text-gray-700 hover:bg-gray-400"
secondary
type="submit"
name="Create" />
</Dialog.Close>
</div>
</div> </div>
</Dialog.Content> </Dialog.Content>
</Dialog.Portal> </Dialog.Portal>

View File

@ -4,12 +4,17 @@ export const BASE_URL = process.env.NEXT_PUBLIC_API_URL;
//URL-Back-End //URL-Back-End
// GESTION LOGIN
export const BK_NEW_PASSWORD_URL = `${BASE_URL}/GestionLogin/newPassword` export const BK_NEW_PASSWORD_URL = `${BASE_URL}/GestionLogin/newPassword`
export const BK_REGISTER_URL = `${BASE_URL}/GestionLogin/subscribe` export const BK_REGISTER_URL = `${BASE_URL}/GestionLogin/subscribe`
export const BK_RESET_PASSWORD_URL = `${BASE_URL}/GestionLogin/resetPassword` export const BK_RESET_PASSWORD_URL = `${BASE_URL}/GestionLogin/resetPassword`
export const BK_LOGIN_URL = `${BASE_URL}/GestionLogin/login` export const BK_LOGIN_URL = `${BASE_URL}/GestionLogin/login`
export const BK_LOGOUT_URL = `${BASE_URL}/GestionLogin/logout` export const BK_LOGOUT_URL = `${BASE_URL}/GestionLogin/logout`
export const BK_PROFILE_URL = `${BASE_URL}/GestionLogin/profil` export const BK_PROFILE_URL = `${BASE_URL}/GestionLogin/profil`
export const BK_GET_CSRF = `${BASE_URL}/GestionLogin/csrf`
// GESTION INSCRIPTION
export const BK_GESTIONINSCRIPTION_ELEVE_URL = `${BASE_URL}/GestionInscriptions/eleve` export const BK_GESTIONINSCRIPTION_ELEVE_URL = `${BASE_URL}/GestionInscriptions/eleve`
export const BK_GESTIONINSCRIPTION_ENFANTS_URL = `${BASE_URL}/GestionInscriptions/enfants` // Récupère la liste des élèves d'un profil export const BK_GESTIONINSCRIPTION_ENFANTS_URL = `${BASE_URL}/GestionInscriptions/enfants` // Récupère la liste des élèves d'un profil
export const BK_GESTIONINSCRIPTION_ELEVES_URL = `${BASE_URL}/GestionInscriptions/eleves` // Récupère la liste des élèves inscrits ou en cours d'inscriptions export const BK_GESTIONINSCRIPTION_ELEVES_URL = `${BASE_URL}/GestionInscriptions/eleves` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
@ -17,8 +22,11 @@ export const BK_GESTIONINSCRIPTION_SEND_URL = `${BASE_URL}/GestionInscriptions/s
export const BK_GESTIONINSCRIPTION_ARCHIVE_URL = `${BASE_URL}/GestionInscriptions/archive` export const BK_GESTIONINSCRIPTION_ARCHIVE_URL = `${BASE_URL}/GestionInscriptions/archive`
export const BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichesInscription` export const BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichesInscription`
export const BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/ficheInscription` export const BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/ficheInscription`
export const BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichiersInscription`
export const BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL = `${BASE_URL}/GestionInscriptions/recupereDernierResponsable` export const BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL = `${BASE_URL}/GestionInscriptions/recupereDernierResponsable`
export const BK_GESTIONINSCRIPTION_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie` export const BK_GESTIONINSCRIPTION_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
//GESTION ENSEIGNANT
export const BK_GESTIONENSEIGNANTS_SPECIALITES_URL = `${BASE_URL}/GestionEnseignants/specialites` export const BK_GESTIONENSEIGNANTS_SPECIALITES_URL = `${BASE_URL}/GestionEnseignants/specialites`
export const BK_GESTIONENSEIGNANTS_SPECIALITE_URL = `${BASE_URL}//GestionEnseignants/specialite` export const BK_GESTIONENSEIGNANTS_SPECIALITE_URL = `${BASE_URL}//GestionEnseignants/specialite`
export const BK_GESTIONENSEIGNANTS_CLASSES_URL = `${BASE_URL}/GestionEnseignants/classes` export const BK_GESTIONENSEIGNANTS_CLASSES_URL = `${BASE_URL}/GestionEnseignants/classes`
@ -28,7 +36,6 @@ export const BK_GESTIONENSEIGNANTS_TEACHER_URL = `${BASE_URL}/GestionEnseignants
export const BK_GESTIONENSEIGNANTS_PLANNINGS_URL = `${BASE_URL}/GestionEnseignants/plannings` export const BK_GESTIONENSEIGNANTS_PLANNINGS_URL = `${BASE_URL}/GestionEnseignants/plannings`
export const BK_GESTIONENSEIGNANTS_PLANNING_URL = `${BASE_URL}/GestionEnseignants/planning` export const BK_GESTIONENSEIGNANTS_PLANNING_URL = `${BASE_URL}/GestionEnseignants/planning`
export const BK_GET_CSRF = `${BASE_URL}/GestionLogin/csrf`
// URL FRONT-END // URL FRONT-END