diff --git a/.gitignore b/.gitignore index a37a203..1770d0d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ __pycache__/ node_modules/ Back-End/*/migrations/* Back-End/documents +Back-End/data Back-End/*.dmp Back-End/staticfiles hardcoded-strings-report.md \ No newline at end of file diff --git a/Back-End/GestionInscriptions/models.py b/Back-End/GestionInscriptions/models.py index 4404b81..e8a9d00 100644 --- a/Back-End/GestionInscriptions/models.py +++ b/Back-End/GestionInscriptions/models.py @@ -61,7 +61,7 @@ class Eleve(models.Model): NONE = 0, _('Sélection du genre') MALE = 1, _('Garçon') FEMALE = 2, _('Fille') - + class NiveauEleve(models.IntegerChoices): NONE = 0, _('Sélection du niveau') TPS = 1, _('TPS - Très Petite Section') @@ -88,7 +88,7 @@ class Eleve(models.Model): # Relation N-N profils = models.ManyToManyField(Profil, blank=True) - + # Relation N-N responsables = models.ManyToManyField(Responsable, blank=True) @@ -141,10 +141,10 @@ class Eleve(models.Model): return f"{years} ans" return None - @property - def dateNaissance_formattee(self): - if self.dateNaissance: - return self.dateNaissance.strftime('%d-%m-%Y') + @property + def dateNaissance_formattee(self): + if self.dateNaissance: + return self.dateNaissance.strftime('%d-%m-%Y') return None class FicheInscription(models.Model): @@ -169,4 +169,11 @@ class FicheInscription(models.Model): def __str__(self): return "FI_" + self.eleve.nom + "_" + self.eleve.prenom - \ No newline at end of file + +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 \ No newline at end of file diff --git a/Back-End/GestionInscriptions/serializers.py b/Back-End/GestionInscriptions/serializers.py index f3954db..90121fe 100644 --- a/Back-End/GestionInscriptions/serializers.py +++ b/Back-End/GestionInscriptions/serializers.py @@ -1,5 +1,5 @@ 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 GestionLogin.models import Profil from GestionLogin.serializers import ProfilSerializer @@ -10,6 +10,10 @@ from django.utils import timezone import pytz from datetime import datetime +class FichierInscriptionSerializer(serializers.ModelSerializer): + class Meta: + model = FichierInscription + fields = '__all__' class FraisInscriptionSerializer(serializers.ModelSerializer): id = serializers.IntegerField(required=False) class Meta: @@ -42,7 +46,7 @@ class EleveSerializer(serializers.ModelSerializer): id = serializers.IntegerField(required=False) responsables = ResponsableSerializer(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) age = serializers.SerializerMethodField() dateNaissance_formattee = serializers.SerializerMethodField() @@ -56,11 +60,11 @@ class EleveSerializer(serializers.ModelSerializer): def get_or_create_packages(self, responsables_data): responsables_ids = [] 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) responsables_ids.append(responsable_instance.id) return responsables_ids - + def create(self, validated_data): responsables_data = validated_data.pop('responsables', []) 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.freres.set(self.get_or_create_packages(freres_data)) eleve.languesParlees.set(self.get_or_create_packages(langues_data)) - + return eleve def create_or_update_packages(self, responsables_data): responsables_ids = [] - + 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) responsables_ids.append(responsable_instance.id) @@ -103,13 +107,13 @@ class EleveSerializer(serializers.ModelSerializer): return instance - def get_age(self, obj): + def get_age(self, obj): return obj.age def get_dateNaissance_formattee(self, obj): return obj.dateNaissance_formattee - def get_classeAssocieeName(self, obj): + def get_classeAssocieeName(self, obj): return obj.classeAssociee.nom_ambiance if obj.classeAssociee else None class FicheInscriptionSerializer(serializers.ModelSerializer): @@ -120,13 +124,13 @@ class FicheInscriptionSerializer(serializers.ModelSerializer): class Meta: model = FicheInscription fields = '__all__' - + def create(self, validated_data): eleve_data = validated_data.pop('eleve') eleve = EleveSerializer.create(EleveSerializer(), eleve_data) ficheEleve = FicheInscription.objects.create(eleve=eleve, **validated_data) return ficheEleve - + def update(self, instance, validated_data): eleve_data = validated_data.pop('eleve') eleve = instance.eleve @@ -138,10 +142,10 @@ class FicheInscriptionSerializer(serializers.ModelSerializer): except KeyError: pass instance.save() - + return instance - - def get_etat_label(self, obj): + + def get_etat_label(self, obj): return obj.get_etat_display() def get_dateMAJ_formattee(self, obj): @@ -156,7 +160,7 @@ class EleveByParentSerializer(serializers.ModelSerializer): class Meta: model = Eleve fields = ['id', 'nom', 'prenom'] - + def __init__(self, *args, **kwargs): super(EleveByParentSerializer , self).__init__(*args, **kwargs) for field in self.fields: @@ -167,7 +171,7 @@ class FicheInscriptionByParentSerializer(serializers.ModelSerializer): class Meta: model = FicheInscription fields = ['eleve', 'etat'] - + def __init__(self, *args, **kwargs): super(FicheInscriptionByParentSerializer, self).__init__(*args, **kwargs) for field in self.fields: @@ -185,7 +189,7 @@ class EleveByDICreationSerializer(serializers.ModelSerializer): class Meta: model = Eleve fields = ['id', 'nom', 'prenom', 'responsables'] - + def __init__(self, *args, **kwargs): super(EleveByDICreationSerializer , self).__init__(*args, **kwargs) for field in self.fields: @@ -196,4 +200,3 @@ class NotificationSerializer(serializers.ModelSerializer): class Meta: model = Notification fields = '__all__' - \ No newline at end of file diff --git a/Back-End/GestionInscriptions/urls.py b/Back-End/GestionInscriptions/urls.py index 1b09589..924cad1 100644 --- a/Back-End/GestionInscriptions/urls.py +++ b/Back-End/GestionInscriptions/urls.py @@ -1,7 +1,7 @@ from django.urls import path, re_path 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 = [ 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 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"), # Page INSCRIPTION - Liste des élèves @@ -31,4 +31,6 @@ urlpatterns = [ # Frais d'inscription 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"), ] \ No newline at end of file diff --git a/Back-End/GestionInscriptions/util.py b/Back-End/GestionInscriptions/util.py index 9dd556c..8196240 100644 --- a/Back-End/GestionInscriptions/util.py +++ b/Back-End/GestionInscriptions/util.py @@ -128,13 +128,13 @@ def toNewEleveJSONRequest(jsonOrigin): etat=FicheInscription.EtatDossierInscription.DI_CREE telephone = convertTelephone(_(jsonOrigin['telephoneResponsable'])) finalJSON = { - "eleve": + "eleve": { - "nom" : _(jsonOrigin['nomEleve']), - "prenom" : _(jsonOrigin['prenomEleve']), + "nom" : _(jsonOrigin['nomEleve']), + "prenom" : _(jsonOrigin['prenomEleve']), "responsables" : [ { - "nom" : _(jsonOrigin['nomResponsable']), + "nom" : _(jsonOrigin['nomResponsable']), "prenom" : _(jsonOrigin['prenomResponsable']), "mail" : _(jsonOrigin['mailResponsable']), "telephone" : telephone @@ -143,7 +143,7 @@ def toNewEleveJSONRequest(jsonOrigin): "profils" : [ ], }, - "etat": str(etat), + "etat": str(etat), "dateMAJ": str(convertToStr(_now(), '%d-%m-%Y %H:%M')), } print(finalJSON) @@ -152,15 +152,15 @@ def toNewEleveJSONRequest(jsonOrigin): def toEditEleveJSONRequest(jsonOrigin): telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']), '.') finalJSON = { - "eleve": + "eleve": { - "id" : _(jsonOrigin['fiche_id']), - "nom" : _(jsonOrigin['nomEleve']), - "prenom" : _(jsonOrigin['prenomEleve']), + "id" : _(jsonOrigin['fiche_id']), + "nom" : _(jsonOrigin['nomEleve']), + "prenom" : _(jsonOrigin['prenomEleve']), "responsables" : [ { - "id" : _(jsonOrigin['responsable_id']), - "nom" : _(jsonOrigin['nomResponsable']), + "id" : _(jsonOrigin['responsable_id']), + "nom" : _(jsonOrigin['nomResponsable']), "prenom" : _(jsonOrigin['prenomResponsable']), "mail" : _(jsonOrigin['mailResponsable']), "telephone" : telephone diff --git a/Back-End/GestionInscriptions/views.py b/Back-End/GestionInscriptions/views.py index f7251d4..c488b3e 100644 --- a/Back-End/GestionInscriptions/views.py +++ b/Back-End/GestionInscriptions/views.py @@ -6,7 +6,8 @@ from django.core.cache import cache from django.core.paginator import Paginator from django.core.files import File 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 import status @@ -17,10 +18,11 @@ from io import BytesIO import GestionInscriptions.mailManager as mailer 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.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 GestionLogin.models import Profil @@ -57,7 +59,7 @@ class ListFichesInscriptionView(APIView): page_size = int(page_size) except ValueError: page_size = settings.NB_RESULT_PER_PAGE - + # Définir le cache_key en fonction du filtre page_number = request.GET.get('page', 1) 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_serializer = FraisInscriptionSerializer(tarifs, many=True) 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) diff --git a/Back-End/N3wtSchool/settings.py b/Back-End/N3wtSchool/settings.py index 75c2b88..695dc20 100644 --- a/Back-End/N3wtSchool/settings.py +++ b/Back-End/N3wtSchool/settings.py @@ -16,6 +16,8 @@ import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent +MEDIA_URL = '/data/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'data') LOGIN_REDIRECT_URL = '/GestionInscriptions/fichesInscriptions' diff --git a/Back-End/N3wtSchool/urls.py b/Back-End/N3wtSchool/urls.py index 639494f..3ebef11 100644 --- a/Back-End/N3wtSchool/urls.py +++ b/Back-End/N3wtSchool/urls.py @@ -16,6 +16,8 @@ Including another URLconf """ from django.contrib import admin 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 drf_yasg.views import get_schema_view 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('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) \ No newline at end of file diff --git a/Front-End/messages/en/subscriptions.json b/Front-End/messages/en/subscriptions.json index 8bfa08b..ffde89a 100644 --- a/Front-End/messages/en/subscriptions.json +++ b/Front-End/messages/en/subscriptions.json @@ -28,5 +28,6 @@ "lastUpdateDate":"Last update", "classe":"Class", "registrationFileStatus":"Registration file status", - "files":"Files" + "files":"Files", + "subscribeFiles":"Subscribe files" } \ No newline at end of file diff --git a/Front-End/messages/fr/subscriptions.json b/Front-End/messages/fr/subscriptions.json index 0b0d6df..eb1f509 100644 --- a/Front-End/messages/fr/subscriptions.json +++ b/Front-End/messages/fr/subscriptions.json @@ -28,5 +28,6 @@ "lastUpdateDate":"Dernière mise à jour", "classe":"Classe", "registrationFileStatus":"État du dossier d'inscription", - "files":"Fichiers" + "files":"Fichiers", + "subscribeFiles":"Fichiers d'inscription" } \ No newline at end of file diff --git a/Front-End/src/app/[locale]/admin/layout.js b/Front-End/src/app/[locale]/admin/layout.js index ba0ec67..b30edd1 100644 --- a/Front-End/src/app/[locale]/admin/layout.js +++ b/Front-End/src/app/[locale]/admin/layout.js @@ -63,7 +63,7 @@ export default function Layout({
{/* Header - h-16 = 64px */} -
+
{headerTitle}
} diff --git a/Front-End/src/app/[locale]/admin/subscriptions/components/FileUpload.js b/Front-End/src/app/[locale]/admin/subscriptions/components/FileUpload.js new file mode 100644 index 0000000..beab467 --- /dev/null +++ b/Front-End/src/app/[locale]/admin/subscriptions/components/FileUpload.js @@ -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 ( +
+
+ + +
+
+ + +
+
+ ); +} \ No newline at end of file diff --git a/Front-End/src/app/[locale]/admin/subscriptions/page.js b/Front-End/src/app/[locale]/admin/subscriptions/page.js index 63fbe6c..cc94eec 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/page.js @@ -13,17 +13,19 @@ import Button from '@/components/Button'; import DropdownMenu from "@/components/DropdownMenu"; import { swapFormatDate } from '@/utils/Date'; 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 InscriptionForm from '@/components/Inscription/InscriptionForm' import AffectationClasseForm from '@/components/AffectationClasseForm' +import FileUpload from './components/FileUpload'; -import { BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL, - BK_GESTIONINSCRIPTION_SEND_URL, - FR_ADMIN_SUBSCRIPTIONS_EDIT_URL, - BK_GESTIONINSCRIPTION_ARCHIVE_URL, - BK_GESTIONENSEIGNANTS_CLASSES_URL, +import { BASE_URL, BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL, + BK_GESTIONINSCRIPTION_SEND_URL, + FR_ADMIN_SUBSCRIPTIONS_EDIT_URL, + BK_GESTIONINSCRIPTION_ARCHIVE_URL, + BK_GESTIONENSEIGNANTS_CLASSES_URL, BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL, + BK_GESTIONINSCRIPTION_FICHERSINSCRIPTION_URL , BK_GESTIONINSCRIPTION_ELEVES_URL, BK_PROFILE_URL } from '@/utils/Url'; @@ -53,6 +55,10 @@ export default function Page({ params: { locale } }) { const [totalArchives, setTotalArchives] = useState(0); 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 [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false); 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(() => { fetchClasses(); fetchStudents(); @@ -326,7 +358,7 @@ export default function Page({ params: { locale } }) { { method:'POST', headers: { - 'Content-Type':'application/json', + 'Content-Type':'application/json', 'X-CSRFToken': csrfToken }, credentials: 'include', @@ -371,7 +403,7 @@ export default function Page({ params: { locale } }) { }) .then(response => response.json()) .then(data => { - console.log('Success:', data); + console.log('Success:', data); setFichesInscriptionsDataEnCours(prevState => { if (prevState && prevState.length > 0) { return [...prevState, data]; @@ -429,13 +461,11 @@ const columns = [ ) }, { name: t('files'), transform: (row) => ( -
) }, - { name: t('files'), transform: (row) => ( + { name: t('files'), 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) => ( +
+ + + + +
+ ) }, +]; + +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) { return ; } else { @@ -593,16 +714,23 @@ const columnsSubscribed = [ active={activeTab === 'archived'} onClick={() => setActiveTab('archived')} /> + + {t('subscribeFiles')} + ({totalSubscribed}) + + )} + active={activeTab === 'subscribeFiles'} + onClick={() => setActiveTab('subscribeFiles')} + />
+ {/*SI STATE == pending || subscribe || archived */} + {activeTab === 'pending' || activeTab === 'subscribed' || activeTab === 'archived' ? ( +
-
+
+
+ + ) : null} + {/*SI STATE == subscribeFiles */} + {activeTab === 'subscribeFiles' && ( +
+ +
+
+ + + )} ( - - )} + + )} /> )} {isOpenAffectationClasse && ( @@ -674,6 +828,17 @@ const columnsSubscribed = [ )} /> )} + {isUploadModalOpen && ( + ( + + )} + /> + )} ); } diff --git a/Front-End/src/components/Inscription/InscriptionForm.js b/Front-End/src/components/Inscription/InscriptionForm.js index ed7d8cc..79d8edb 100644 --- a/Front-End/src/components/Inscription/InscriptionForm.js +++ b/Front-End/src/components/Inscription/InscriptionForm.js @@ -70,21 +70,21 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
{step === 1 && (
-

Nouvel élève

- Nouvel élève + - { {step === 2 && (
-

Responsable(s)

+

Responsable(s)

{formData.responsableType === 'new' && ( - )} - + {formData.responsableType === 'existing' && (
@@ -161,10 +161,10 @@ const InscriptionForm = ( { eleves, onSubmit }) => { {existingResponsables.map((responsable) => (
+ + + + + + + + + + + + +
NomPrénom
{formData.eleveNom}{formData.elevePrenom}
+ +
+

Responsable(s)

{formData.responsableType === 'new' && ( -
-

Responsable

-

Email : {formData.responsableEmail}

-

Téléphone : {formData.responsableTel}

-
+ + + + + + + + + + + + + +
EmailTéléphone
{formData.responsableEmail}{formData.responsableTel}
)} {formData.responsableType === 'existing' && selectedEleve && (
-

Responsable(s)

Associé(s) à : {selectedEleve.nom} {selectedEleve.prenom}

-
    - {existingResponsables.filter(responsable => formData.selectedResponsables.includes(responsable.id)).map((responsable) => ( -
  • - {responsable.nom && responsable.prenom ? `${responsable.nom} ${responsable.prenom}` : responsable.mail} -
  • - ))} -
+ + + + + + + + + + {existingResponsables.filter(responsable => formData.selectedResponsables.includes(responsable.id)).map((responsable) => ( + + + + + + ))} + +
NomPrénomEmail
{responsable.nom}{responsable.prenom}{responsable.mail}
)} -
-
+ +
- @@ -271,7 +297,7 @@ const InscriptionForm = ( { eleves, onSubmit }) => {
diff --git a/Front-End/src/components/Modal.js b/Front-End/src/components/Modal.js index b6a4cd3..509aaa5 100644 --- a/Front-End/src/components/Modal.js +++ b/Front-End/src/components/Modal.js @@ -7,23 +7,26 @@ const Modal = ({ isOpen, setIsOpen, title, ContentComponent, size }) => { -
- - {title} - +
+
+ + {title} + + + + +
-
- -
diff --git a/Front-End/src/utils/Url.js b/Front-End/src/utils/Url.js index 48fa8c8..e366544 100644 --- a/Front-End/src/utils/Url.js +++ b/Front-End/src/utils/Url.js @@ -4,12 +4,17 @@ export const BASE_URL = process.env.NEXT_PUBLIC_API_URL; //URL-Back-End + +// GESTION LOGIN export const BK_NEW_PASSWORD_URL = `${BASE_URL}/GestionLogin/newPassword` export const BK_REGISTER_URL = `${BASE_URL}/GestionLogin/subscribe` export const BK_RESET_PASSWORD_URL = `${BASE_URL}/GestionLogin/resetPassword` export const BK_LOGIN_URL = `${BASE_URL}/GestionLogin/login` export const BK_LOGOUT_URL = `${BASE_URL}/GestionLogin/logout` 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_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 @@ -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_FICHESINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichesInscription` 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_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie` + +//GESTION ENSEIGNANT export const BK_GESTIONENSEIGNANTS_SPECIALITES_URL = `${BASE_URL}/GestionEnseignants/specialites` export const BK_GESTIONENSEIGNANTS_SPECIALITE_URL = `${BASE_URL}//GestionEnseignants/specialite` 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_PLANNING_URL = `${BASE_URL}/GestionEnseignants/planning` -export const BK_GET_CSRF = `${BASE_URL}/GestionLogin/csrf` // URL FRONT-END