refactor: Transformation des requetes vers le back en action ajout des

erreurs 400 et refresh lors d'un envoie de formulaire
This commit is contained in:
Luc SORIGNET
2025-01-13 14:21:44 +01:00
parent c4d45426b5
commit 147a70135d
23 changed files with 2421 additions and 314 deletions

View File

@ -170,7 +170,7 @@ class RegistrationForm(models.Model):
def __str__(self): def __str__(self):
return "RF_" + self.student.last_name + "_" + self.student.first_name return "RF_" + self.student.last_name + "_" + self.student.first_name
class RegistrationFile(models.Model): class RegistrationFileTemplate(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
file = models.FileField(upload_to='registration_files/') file = models.FileField(upload_to='registration_files/')
date_added = models.DateTimeField(auto_now_add=True) date_added = models.DateTimeField(auto_now_add=True)

View File

@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from .models import RegistrationFile, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationFee from .models import RegistrationFileTemplate, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationFee
from School.models import SchoolClass from School.models import SchoolClass
from Auth.models import Profile from Auth.models import Profile
from Auth.serializers import ProfileSerializer from Auth.serializers import ProfileSerializer
@ -10,9 +10,9 @@ from django.utils import timezone
import pytz import pytz
from datetime import datetime from datetime import datetime
class RegistrationFileSerializer(serializers.ModelSerializer): class RegistrationFileTemplateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = RegistrationFile model = RegistrationFileTemplate
fields = '__all__' fields = '__all__'
class RegistrationFeeSerializer(serializers.ModelSerializer): class RegistrationFeeSerializer(serializers.ModelSerializer):

View File

@ -1,12 +1,12 @@
from django.urls import path, re_path from django.urls import path, re_path
from . import views from . import views
from Subscriptions.views import RegisterFileTemplateView, RegisterFormListView, RegisterFormView, StudentView, GuardianView, ChildrenListView, StudentListView, RegisterFeeView from Subscriptions.views import RegistrationFileTemplateView, RegisterFormListView, RegisterFormView, StudentView, GuardianView, ChildrenListView, StudentListView, RegistrationFeeView
urlpatterns = [ urlpatterns = [
re_path(r'^registerForms/([a-zA-z]+)$', RegisterFormListView.as_view(), name="listefichesInscriptions"), re_path(r'^registerForms/([a-zA-z]+)$', RegisterFormListView.as_view(), name="registerForms"),
re_path(r'^registerForm$', RegisterFormView.as_view(), name="registerForms"), re_path(r'^registerForm$', RegisterFormView.as_view(), name="registerForm"),
re_path(r'^registerForm/([0-9]+)$', RegisterFormView.as_view(), name="registerForms"), re_path(r'^registerForm/([0-9]+)$', RegisterFormView.as_view(), name="registerForm"),
# Page de formulaire d'inscription - ELEVE # Page de formulaire d'inscription - ELEVE
re_path(r'^student/([0-9]+)$', StudentView.as_view(), name="students"), re_path(r'^student/([0-9]+)$', StudentView.as_view(), name="students"),
@ -21,7 +21,7 @@ urlpatterns = [
re_path(r'^archive/([0-9]+)$', views.archive, name="archive"), re_path(r'^archive/([0-9]+)$', views.archive, name="archive"),
# 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="sendRelance"),
# Page PARENT - Liste des children # Page PARENT - Liste des children
re_path(r'^children/([0-9]+)$', ChildrenListView.as_view(), name="children"), re_path(r'^children/([0-9]+)$', ChildrenListView.as_view(), name="children"),
@ -30,7 +30,7 @@ urlpatterns = [
re_path(r'^students$', StudentListView.as_view(), name="students"), re_path(r'^students$', StudentListView.as_view(), name="students"),
# Frais d'inscription # Frais d'inscription
re_path(r'^registerFees$', RegisterFeeView.as_view(), name="registerFees"), re_path(r'^registrationFees$', RegistrationFeeView.as_view(), name="registrationFees"),
re_path(r'^registerFileTemplate$', RegisterFileTemplateView.as_view(), name='registerFileTemplate'), re_path(r'^registrationFileTemplates$', RegistrationFileTemplateView.as_view(), name='registrationFileTemplates'),
re_path(r'^registerFileTemplate/([0-9]+)$', RegisterFileTemplateView.as_view(), name="registerFileTemplate"), re_path(r'^registrationFileTemplates/([0-9]+)$', RegistrationFileTemplateView.as_view(), name="registrationFileTemplate"),
] ]

View File

@ -18,10 +18,10 @@ from io import BytesIO
import Subscriptions.mailManager as mailer import Subscriptions.mailManager as mailer
import Subscriptions.util as util import Subscriptions.util as util
from Subscriptions.serializers import RegistrationFormSerializer, RegistrationFileSerializer, StudentSerializer, RegistrationFormByParentSerializer, StudentByRFCreationSerializer, RegistrationFeeSerializer from Subscriptions.serializers import RegistrationFormSerializer, RegistrationFileTemplateSerializer, StudentSerializer, RegistrationFormByParentSerializer, StudentByRFCreationSerializer, RegistrationFeeSerializer
from Subscriptions.pagination import CustomPagination from Subscriptions.pagination import CustomPagination
from Subscriptions.signals import clear_cache from Subscriptions.signals import clear_cache
from .models import Student, Guardian, RegistrationForm, RegistrationFee, RegistrationFile from .models import Student, Guardian, RegistrationForm, RegistrationFee, RegistrationFileTemplate
from Subscriptions.automate import Automate_RF_Register, load_config, getStateMachineObjectState, updateStateMachine from Subscriptions.automate import Automate_RF_Register, load_config, getStateMachineObjectState, updateStateMachine
@ -137,7 +137,7 @@ class RegisterFormView(APIView):
return JsonResponse(studentForm_serializer.data, safe=False) return JsonResponse(studentForm_serializer.data, safe=False)
return JsonResponse(studentForm_serializer.errors, safe=False) return JsonResponse(studentForm_serializer.errors, safe=False, status=400)
def put(self, request, id): def put(self, request, id):
studentForm_data=JSONParser().parse(request) studentForm_data=JSONParser().parse(request)
@ -162,7 +162,7 @@ class RegisterFormView(APIView):
studentForm_serializer.save() studentForm_serializer.save()
return JsonResponse(studentForm_serializer.data, safe=False) return JsonResponse(studentForm_serializer.data, safe=False)
return JsonResponse(studentForm_serializer.errors, safe=False) return JsonResponse(studentForm_serializer.errors, safe=False, status=400)
def delete(self, request, id): def delete(self, request, id):
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id) register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
@ -175,7 +175,7 @@ class RegisterFormView(APIView):
return JsonResponse("La suppression du dossier a été effectuée avec succès", safe=False) return JsonResponse("La suppression du dossier a été effectuée avec succès", safe=False)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=400)
class StudentView(APIView): class StudentView(APIView):
def get(self, request, _id): def get(self, request, _id):
@ -200,9 +200,9 @@ def send(request, id):
# Mise à jour de l'automate # Mise à jour de l'automate
updateStateMachine(register_form, 'envoiDI') updateStateMachine(register_form, 'envoiDI')
return JsonResponse({"errorMessage":errorMessage}, safe=False) return JsonResponse({"errorMessage":errorMessage}, safe=False, status=400)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=400)
def archive(request, id): def archive(request, id):
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id) register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
@ -211,9 +211,9 @@ def archive(request, id):
# Mise à jour de l'automate # Mise à jour de l'automate
updateStateMachine(register_form, 'archiveDI') updateStateMachine(register_form, 'archiveDI')
return JsonResponse({"errorMessage":''}, safe=False) return JsonResponse({"errorMessage":''}, safe=False, status=400)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=400)
def relance(request, id): def relance(request, id):
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id) register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
@ -227,9 +227,9 @@ def relance(request, id):
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M') register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
register_form.save() register_form.save()
return JsonResponse({"errorMessage":errorMessage}, safe=False) return JsonResponse({"errorMessage":errorMessage}, safe=False, status=400)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=400)
# API utilisée pour la vue parent # API utilisée pour la vue parent
class ChildrenListView(APIView): class ChildrenListView(APIView):
@ -249,32 +249,32 @@ class StudentListView(APIView):
return JsonResponse(students_serializer.data, safe=False) return JsonResponse(students_serializer.data, safe=False)
# API utilisée pour la vue de personnalisation des frais d'inscription pour la structure # API utilisée pour la vue de personnalisation des frais d'inscription pour la structure
class RegisterFeeView(APIView): class RegistrationFeeView(APIView):
def get(self, request): def get(self, request):
tarifs = bdd.getAllObjects(RegistrationFee) tarifs = bdd.getAllObjects(RegistrationFee)
tarifs_serializer = RegistrationFeeSerializer(tarifs, many=True) tarifs_serializer = RegistrationFeeSerializer(tarifs, many=True)
return JsonResponse(tarifs_serializer.data, safe=False) return JsonResponse(tarifs_serializer.data, safe=False)
class RegisterFileTemplateView(APIView): class RegistrationFileTemplateView(APIView):
parser_classes = (MultiPartParser, FormParser) parser_classes = (MultiPartParser, FormParser)
def get(self, request): def get(self, request):
fichiers = RegistrationFile.objects.all() fichiers = RegistrationFileTemplate.objects.all()
serializer = RegistrationFormSerializer(fichiers, many=True) serializer = RegistrationFileTemplateSerializer(fichiers, many=True)
return Response(serializer.data) return Response(serializer.data)
def post(self, request): def post(self, request):
serializer = RegistrationFormSerializer(data=request.data) serializer = RegistrationFileTemplateSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, _id): def delete(self, request, _id):
fichierInscription = bdd.getObject(_objectName=RegistrationFile, _columnName='id', _value=_id) registrationFileTemplate = bdd.getObject(_objectName=RegistrationFileTemplate, _columnName='id', _value=_id)
if fichierInscription is not None: if registrationFileTemplate is not None:
fichierInscription.file.delete() # Supprimer le fichier uploadé registrationFileTemplate.file.delete() # Supprimer le fichier uploadé
fichierInscription.delete() registrationFileTemplate.delete()
return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False) return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False)
else: else:
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False) return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=400)

View File

@ -3,6 +3,10 @@ import createNextIntlPlugin from 'next-intl/plugin';
const withNextIntl = createNextIntlPlugin(); const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = {}; const nextConfig = {
experimental: {
instrumentationHook: true,
},
};
export default withNextIntl(nextConfig); export default withNextIntl(nextConfig);

View File

@ -17,6 +17,8 @@
"lucide-react": "^0.453.0", "lucide-react": "^0.453.0",
"next": "14.2.11", "next": "14.2.11",
"next-intl": "^3.24.0", "next-intl": "^3.24.0",
"next-logger": "^5.0.1",
"pino": "^9.6.0",
"react": "^18", "react": "^18",
"react-cookie": "^7.2.0", "react-cookie": "^7.2.0",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
@ -175,6 +177,28 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@colors/colors": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"optional": true,
"peer": true,
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/@dabh/diagnostics": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
"optional": true,
"peer": true,
"dependencies": {
"colorspace": "1.1.x",
"enabled": "2.0.x",
"kuler": "^2.0.0"
}
},
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0", "version": "4.4.0",
"dev": true, "dev": true,
@ -1007,6 +1031,13 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/triple-beam": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
"optional": true,
"peer": true
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.2.0", "version": "7.2.0",
"dev": true, "dev": true,
@ -1472,6 +1503,21 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"optional": true,
"peer": true
},
"node_modules/atomic-sleep": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/autoprefixer": { "node_modules/autoprefixer": {
"version": "10.4.20", "version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
@ -1725,6 +1771,17 @@
"version": "0.0.1", "version": "0.0.1",
"license": "MIT" "license": "MIT"
}, },
"node_modules/color": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"optional": true,
"peer": true,
"dependencies": {
"color-convert": "^1.9.3",
"color-string": "^1.6.0"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"license": "MIT", "license": "MIT",
@ -1739,6 +1796,45 @@
"version": "1.1.4", "version": "1.1.4",
"license": "MIT" "license": "MIT"
}, },
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"optional": true,
"peer": true,
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/color/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"optional": true,
"peer": true,
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/color/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"optional": true,
"peer": true
},
"node_modules/colorspace": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"optional": true,
"peer": true,
"dependencies": {
"color": "^3.1.3",
"text-hex": "1.0.x"
}
},
"node_modules/commander": { "node_modules/commander": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@ -2006,6 +2102,13 @@
"version": "9.2.2", "version": "9.2.2",
"license": "MIT" "license": "MIT"
}, },
"node_modules/enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
"optional": true,
"peer": true
},
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.17.1", "version": "5.17.1",
"dev": true, "dev": true,
@ -2645,6 +2748,14 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-redact": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
"integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==",
"engines": {
"node": ">=6"
}
},
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.17.1", "version": "1.17.1",
"license": "ISC", "license": "ISC",
@ -2652,6 +2763,13 @@
"reusify": "^1.0.4" "reusify": "^1.0.4"
} }
}, },
"node_modules/fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
"optional": true,
"peer": true
},
"node_modules/file-entry-cache": { "node_modules/file-entry-cache": {
"version": "6.0.1", "version": "6.0.1",
"dev": true, "dev": true,
@ -2706,6 +2824,13 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
"optional": true,
"peer": true
},
"node_modules/for-each": { "node_modules/for-each": {
"version": "0.3.3", "version": "0.3.3",
"dev": true, "dev": true,
@ -3120,7 +3245,7 @@
}, },
"node_modules/inherits": { "node_modules/inherits": {
"version": "2.0.4", "version": "2.0.4",
"dev": true, "devOptional": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/input-format": { "node_modules/input-format": {
@ -3195,6 +3320,13 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"optional": true,
"peer": true
},
"node_modules/is-async-function": { "node_modules/is-async-function": {
"version": "2.0.0", "version": "2.0.0",
"dev": true, "dev": true,
@ -3446,6 +3578,19 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"optional": true,
"peer": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-string": { "node_modules/is-string": {
"version": "1.0.7", "version": "1.0.7",
"dev": true, "dev": true,
@ -3645,6 +3790,13 @@
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
}, },
"node_modules/kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
"optional": true,
"peer": true
},
"node_modules/language-subtag-registry": { "node_modules/language-subtag-registry": {
"version": "0.3.23", "version": "0.3.23",
"dev": true, "dev": true,
@ -3716,6 +3868,24 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/logform": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
"integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
"optional": true,
"peer": true,
"dependencies": {
"@colors/colors": "1.6.0",
"@types/triple-beam": "^1.3.2",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^2.3.1",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/loose-envify": { "node_modules/loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"license": "MIT", "license": "MIT",
@ -3793,7 +3963,7 @@
}, },
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/mz": { "node_modules/mz": {
@ -3905,6 +4075,38 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/next-logger": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/next-logger/-/next-logger-5.0.1.tgz",
"integrity": "sha512-zWTPtS0YwTB+4iSK4VxUVtCYt+zg8+Sx2Tjbtgmpd4SXsFnWdmCbXAeFZFKtEH8yNlucLCUaj0xqposMQ9rKRg==",
"dependencies": {
"lilconfig": "^3.1.2"
},
"peerDependencies": {
"next": ">=9.0.0",
"pino": "^8.0.0 || ^9.0.0",
"winston": "^3.0.0"
},
"peerDependenciesMeta": {
"pino": {
"optional": true
},
"winston": {
"optional": true
}
}
},
"node_modules/next-logger/node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/next/node_modules/postcss": { "node_modules/next/node_modules/postcss": {
"version": "8.4.31", "version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@ -4080,6 +4282,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/on-exit-leak-free": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/once": { "node_modules/once": {
"version": "1.4.0", "version": "1.4.0",
"dev": true, "dev": true,
@ -4088,6 +4298,16 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"node_modules/one-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
"optional": true,
"peer": true,
"dependencies": {
"fn.name": "1.x.x"
}
},
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.4", "version": "0.9.4",
"dev": true, "dev": true,
@ -4214,6 +4434,40 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/pino": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz",
"integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==",
"dependencies": {
"atomic-sleep": "^1.0.0",
"fast-redact": "^3.1.1",
"on-exit-leak-free": "^2.1.0",
"pino-abstract-transport": "^2.0.0",
"pino-std-serializers": "^7.0.0",
"process-warning": "^4.0.0",
"quick-format-unescaped": "^4.0.3",
"real-require": "^0.2.0",
"safe-stable-stringify": "^2.3.1",
"sonic-boom": "^4.0.1",
"thread-stream": "^3.0.0"
},
"bin": {
"pino": "bin.js"
}
},
"node_modules/pino-abstract-transport": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
"integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
"dependencies": {
"split2": "^4.0.0"
}
},
"node_modules/pino-std-serializers": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz",
"integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="
},
"node_modules/pirates": { "node_modules/pirates": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
@ -4385,6 +4639,21 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/process-warning": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz",
"integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
]
},
"node_modules/prop-types": { "node_modules/prop-types": {
"version": "15.8.1", "version": "15.8.1",
"license": "MIT", "license": "MIT",
@ -4425,6 +4694,11 @@
], ],
"license": "MIT" "license": "MIT"
}, },
"node_modules/quick-format-unescaped": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
},
"node_modules/react": { "node_modules/react": {
"version": "18.3.1", "version": "18.3.1",
"license": "MIT", "license": "MIT",
@ -4609,6 +4883,21 @@
"pify": "^2.3.0" "pify": "^2.3.0"
} }
}, },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"optional": true,
"peer": true,
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/readdirp": { "node_modules/readdirp": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@ -4620,6 +4909,14 @@
"node": ">=8.10.0" "node": ">=8.10.0"
} }
}, },
"node_modules/real-require": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
"engines": {
"node": ">= 12.13.0"
}
},
"node_modules/redux": { "node_modules/redux": {
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
@ -4787,6 +5084,27 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"optional": true,
"peer": true
},
"node_modules/safe-regex-test": { "node_modules/safe-regex-test": {
"version": "1.0.3", "version": "1.0.3",
"dev": true, "dev": true,
@ -4803,6 +5121,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"engines": {
"node": ">=10"
}
},
"node_modules/scheduler": { "node_modules/scheduler": {
"version": "0.23.2", "version": "0.23.2",
"license": "MIT", "license": "MIT",
@ -4895,6 +5221,16 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"optional": true,
"peer": true,
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/slash": { "node_modules/slash": {
"version": "3.0.0", "version": "3.0.0",
"dev": true, "dev": true,
@ -4903,6 +5239,14 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/sonic-boom": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
"integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
"dependencies": {
"atomic-sleep": "^1.0.0"
}
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@ -4910,6 +5254,24 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"optional": true,
"peer": true,
"engines": {
"node": "*"
}
},
"node_modules/stop-iteration-iterator": { "node_modules/stop-iteration-iterator": {
"version": "1.0.0", "version": "1.0.0",
"dev": true, "dev": true,
@ -4927,6 +5289,16 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"optional": true,
"peer": true,
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": { "node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"license": "MIT", "license": "MIT",
@ -5218,6 +5590,13 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/text-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
"optional": true,
"peer": true
},
"node_modules/text-table": { "node_modules/text-table": {
"version": "0.2.0", "version": "0.2.0",
"dev": true, "dev": true,
@ -5242,6 +5621,14 @@
"node": ">=0.8" "node": ">=0.8"
} }
}, },
"node_modules/thread-stream": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
"integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
"dependencies": {
"real-require": "^0.2.0"
}
},
"node_modules/tiny-case": { "node_modules/tiny-case": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
@ -5262,6 +5649,16 @@
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
}, },
"node_modules/triple-beam": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
"optional": true,
"peer": true,
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "1.3.0", "version": "1.3.0",
"dev": true, "dev": true,
@ -5608,6 +6005,44 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/winston": {
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
"integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
"optional": true,
"peer": true,
"dependencies": {
"@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
"logform": "^2.7.0",
"one-time": "^1.0.0",
"readable-stream": "^3.4.0",
"safe-stable-stringify": "^2.3.1",
"stack-trace": "0.0.x",
"triple-beam": "^1.3.0",
"winston-transport": "^4.9.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/winston-transport": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
"integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
"optional": true,
"peer": true,
"dependencies": {
"logform": "^2.7.0",
"readable-stream": "^3.6.2",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.5", "version": "1.2.5",
"dev": true, "dev": true,

View File

@ -19,6 +19,8 @@
"lucide-react": "^0.453.0", "lucide-react": "^0.453.0",
"next": "14.2.11", "next": "14.2.11",
"next-intl": "^3.24.0", "next-intl": "^3.24.0",
"next-logger": "^5.0.1",
"pino": "^9.6.0",
"react": "^18", "react": "^18",
"react-cookie": "^7.2.0", "react-cookie": "^7.2.0",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",

View File

@ -1,49 +0,0 @@
'use client'
import React, { useState, useEffect } from 'react';
import Table from '@/components/Table';
import Button from '@/components/Button';
const columns = [
{ name: 'Nom', transform: (row) => row.Nom },
{ name: 'Niveau', transform: (row) => row.Niveau },
{ name: 'Effectif', transform: (row) => row.Effectif },
];
export default function Page() {
const [classes, setClasses] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
useEffect(() => {
fetchClasses();
}, [currentPage]);
const fetchClasses = async () => {
const fakeData = {
classes: [
{ Nom: 'Classe A', Niveau: '1ère année', Effectif: 30 },
{ Nom: 'Classe B', Niveau: '2ème année', Effectif: 25 },
{ Nom: 'Classe C', Niveau: '3ème année', Effectif: 28 },
],
totalPages: 3
};
setClasses(fakeData.classes);
setTotalPages(fakeData.totalPages);
};
const handlePageChange = (page) => {
setCurrentPage(page);
};
const handleCreateClass = () => {
console.log('Créer une nouvelle classe');
};
return (
<div className='p-8'>
<h1 className='heading-section'>Gestion des Classes</h1>
<Button text="Créer une nouvelle classe" onClick={handleCreateClass} primary />
<Table data={classes} columns={columns} itemsPerPage={5} />
</div>
);
}

View File

@ -4,8 +4,8 @@ import React, { useState, useEffect } from 'react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react'; import { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react';
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';
import { BE_SCHOOL_SCHOOLCLASSES_URL } from '@/utils/Url';
import ClasseDetails from '@/components/ClasseDetails'; import ClasseDetails from '@/components/ClasseDetails';
import { fetchClasses } from '@/app/lib/schoolAction';
// Composant StatCard pour afficher une statistique // Composant StatCard pour afficher une statistique
const StatCard = ({ title, value, icon, change, color = "blue" }) => ( const StatCard = ({ title, value, icon, change, color = "blue" }) => (
@ -58,20 +58,15 @@ export default function DashboardPage() {
const [classes, setClasses] = useState([]); const [classes, setClasses] = useState([]);
const fetchClasses = () => {
fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`) useEffect(() => {
.then(response => response.json()) // Fetch data for classes
.then(data => { fetchClasses().then(data => {
setClasses(data); setClasses(data);
}) })
.catch(error => { .catch(error => {
console.error('Error fetching classes:', error); console.error('Error fetching classes:', error);
}); });
};
useEffect(() => {
// Fetch data for classes
fetchClasses();
// Simulation de chargement des données // Simulation de chargement des données
setTimeout(() => { setTimeout(() => {

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams, useRouter } from 'next/navigation';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url'; import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
@ -10,6 +10,7 @@ import { editRegisterForm, fetchRegisterForm } from '@/app/lib/subscriptionActio
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
export default function Page() { export default function Page() {
const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const idProfil = searchParams.get('id'); const idProfil = searchParams.get('id');
const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId
@ -21,50 +22,44 @@ export default function Page() {
useEffect(() => { useEffect(() => {
if (useFakeData) { if (useFakeData) {
setInitialData(mockStudent); setInitialData(mockStudent);
setIsLoading(false);
} else { } else {
fetchRegisterForm(studentId) fetchRegisterForm(studentId)
.then(data => { .then(data => {
console.log('Fetched data:', data); // Pour le débogage console.log('Fetched data:', data); // Pour le débogage
const formattedData = { const formattedData = {
id: data.id, ...data,
last_name: data.last_name,
first_name: data.first_name,
address: data.address,
birth_date: data.birth_date,
birth_place: data.birth_place,
birth_postal_code: data.birth_postal_code,
nationality: data.nationality,
attending_physician: data.attending_physician,
level: data.level,
guardians: data.guardians || [] guardians: data.guardians || []
}; };
setInitialData(formattedData); setInitialData(formattedData);
setIsLoading(false);
}) })
.catch(error => { .catch(error => {
console.error('Error fetching student data:', error); console.error('Error fetching student data:', error);
setIsLoading(false);
}); });
} }
setIsLoading(false);
}, [studentId]); // Dépendance changée à studentId }, [studentId]); // Dépendance changée à studentId
const handleSubmit = async (data) => { const handleSubmit = (data) => {
if (useFakeData) { if (useFakeData) {
console.log('Fake submit:', data); console.log('Fake submit:', data);
return; return;
} }
try { editRegisterForm(studentId, data, csrfToken)
const result = await editRegisterForm(studentId, data, csrfToken);
// Utilisation de studentId .then((result) => {
console.log('Success:', result); console.log('Success:', result);
// Redirection après succès router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
window.location.href = FE_ADMIN_SUBSCRIPTIONS_URL; })
} catch (error) { .catch((error) => {
console.error('Error:', error); console.error('Error:', error.message);
alert('Une erreur est survenue lors de la mise à jour des données'); if (error.details) {
console.error('Form errors:', error.details);
// Handle form errors (e.g., display them to the user)
} }
alert('Une erreur est survenue lors de la mise à jour des données');
});
}; };
return ( return (

View File

@ -27,6 +27,7 @@ import {
archiveRegisterForm, archiveRegisterForm,
fetchRegisterFormFileTemplate, fetchRegisterFormFileTemplate,
deleteRegisterFormFileTemplate, deleteRegisterFormFileTemplate,
createRegistrationFormFileTemplate,
fetchStudents, fetchStudents,
editRegisterForm } from "@/app/lib/subscriptionAction" editRegisterForm } from "@/app/lib/subscriptionAction"
@ -44,16 +45,14 @@ const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
export default function Page({ params: { locale } }) { export default function Page({ params: { locale } }) {
const t = useTranslations('subscriptions'); const t = useTranslations('subscriptions');
const [ficheInscriptions, setFicheInscriptions] = useState([]); const [registrationForms, setRegistrationForms] = useState([]);
const [fichesInscriptionsDataEnCours, setFichesInscriptionsDataEnCours] = useState([]); const [registrationFormsDataPending, setRegistrationFormsDataPending] = useState([]);
const [fichesInscriptionsDataInscrits, setFichesInscriptionsDataInscrits] = useState([]); const [registrationFormsDataSubscribed, setRegistrationFormsDataSubscribed] = useState([]);
const [fichesInscriptionsDataArchivees, setFichesInscriptionsDataArchivees] = useState([]); const [registrationFormsDataArchived, setRegistrationFormsDataArchived] = useState([]);
// const [filter, setFilter] = useState('*'); // const [filter, setFilter] = useState('*');
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [alertPage, setAlertPage] = useState(false); const [alertPage, setAlertPage] = useState(false);
const [mailSent, setMailSent] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [ficheArchivee, setFicheArchivee] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [popup, setPopup] = useState({ visible: false, message: '', onConfirm: null }); const [popup, setPopup] = useState({ visible: false, message: '', onConfirm: null });
const [activeTab, setActiveTab] = useState('pending'); const [activeTab, setActiveTab] = useState('pending');
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@ -64,13 +63,12 @@ export default function Page({ params: { locale } }) {
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 [fichiers, setFichiers] = useState([]);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false); const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false);
const [student, setStudent] = useState(''); const [student, setStudent] = useState('');
const [classes, setClasses] = useState([]); const [classes, setClasses] = useState([]);
const [students, setEleves] = useState([]); const [students, setEleves] = useState([]);
const [reloadFetch, setReloadFetch] = useState(false);
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
@ -80,6 +78,7 @@ export default function Page({ params: { locale } }) {
const closeModal = () => { const closeModal = () => {
setIsOpen(false); setIsOpen(false);
} }
const openModalAssociationEleve = (eleveSelected) => { const openModalAssociationEleve = (eleveSelected) => {
@ -88,58 +87,72 @@ export default function Page({ params: { locale } }) {
} }
const requestErrorHandler = (err)=>{ const requestErrorHandler = (err)=>{
setIsLoading(false); console.error('Error fetching data:', err);
} }
/**
* Handles the pending data for the registration form.
*
* @param {Object} data - The data object containing registration forms and count.
* @param {Array} data.registerForms - The array of registration forms.
* @param {number} data.count - The total count of registration forms.
*/
const registerFormPendingDataHandler = (data) => { const registerFormPendingDataHandler = (data) => {
setIsLoading(false);
if (data) { if (data) {
const { registerForms, count } = data; const { registerForms, count, page_size } = data;
if (registerForms) { if (registerForms) {
setFichesInscriptionsDataEnCours(registerForms); setRegistrationFormsDataPending(registerForms);
} }
const calculatedTotalPages = count === 0 ? 1 : Math.ceil(count / pageSize); const calculatedTotalPages = count === 0 ? 1 : Math.ceil(count / page_size);
setTotalPending(count); setTotalPending(count);
setTotalPages(calculatedTotalPages); setTotalPages(calculatedTotalPages);
} }
} }
/**
* Handles the data received from the subscription registration form.
*
* @param {Object} data - The data object received from the subscription registration form.
* @param {Array} data.registerForms - An array of registration forms.
* @param {number} data.count - The total count of subscribed forms.
*/
const registerFormSubscribedDataHandler = (data) => { const registerFormSubscribedDataHandler = (data) => {
setIsLoading(false);
if (data) { if (data) {
const { registerForms, count } = data; const { registerForms, count, page_size } = data;
setTotalSubscribed(count); setTotalSubscribed(count);
if (registerForms) { if (registerForms) {
setFichesInscriptionsDataInscrits(registerForms); setRegistrationFormsDataSubscribed(registerForms);
} }
} }
} }
/**
* Handles the archived data for the register form.
*
* @param {Object} data - The data object containing archived register forms and count.
* @param {Array} data.registerForms - The array of archived register forms.
* @param {number} data.count - The total count of archived register forms.
*/
const registerFormArchivedDataHandler = (data) => { const registerFormArchivedDataHandler = (data) => {
setIsLoading(false);
if (data) { if (data) {
const { registerForms, count } = data; const { registerForms, count, page_size } = data;
setTotalArchives(count); setTotalArchives(count);
if (registerForms) { if (registerForms) {
setFichesInscriptionsDataArchivees(registerForms); setRegistrationFormsDataArchived(registerForms);
} }
} }
} }
// TODO: revoir le système de pagination et de UseEffect
useEffect(() => {
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
}, []);
useEffect(() => { useEffect(() => {
fetchClasses() fetchClasses()
.then(data => { .then(data => {
setClasses(data); setClasses(data);
console.log("Success CLASSES : ", data) console.log('Success Classes:', data);
}) })
.catch(error => { .catch(error => {
console.error('Error fetching classes:', error); console.error('Error fetching classes:', error);
@ -154,10 +167,13 @@ const registerFormArchivedDataHandler = (data) => {
error = error.message; error = error.message;
console.log(error); console.log(error);
}); });
}, [fichesInscriptionsDataEnCours]); }, [registrationFormsDataPending]);
useEffect(() => { useEffect(() => {
const fetchDataAndSetState = () => { const fetchDataAndSetState = () => {
setIsLoading(true);
if (!useFakeData) { if (!useFakeData) {
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm) fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler) .then(registerFormPendingDataHandler)
@ -168,30 +184,73 @@ const registerFormArchivedDataHandler = (data) => {
fetchRegisterForms(ARCHIVED) fetchRegisterForms(ARCHIVED)
.then(registerFormArchivedDataHandler) .then(registerFormArchivedDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler)
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
} else { } else {
setTimeout(() => { setTimeout(() => {
setFichesInscriptionsDataEnCours(mockFicheInscription); setRegistrationFormsDataPending(mockFicheInscription);
setIsLoading(false);
}, 1000); }, 1000);
} }
setFicheArchivee(false); setIsLoading(false);
setMailSent(false); setReloadFetch(false);
}; };
fetchDataAndSetState();
}, [mailSent, ficheArchivee, currentPage, itemsPerPage]);
// Modifier le useEffect pour la recherche fetchDataAndSetState();
}, [reloadFetch, currentPage]);
useEffect(() => { useEffect(() => {
const timeoutId = setTimeout(() => { const fetchDataAndSetState = () => {
setIsLoading(true);
if (!useFakeData) {
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm) fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler) .then(registerFormPendingDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler)
fetchRegisterForms(SUBSCRIBED)
.then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler)
fetchRegisterForms(ARCHIVED)
.then(registerFormArchivedDataHandler)
.catch(requestErrorHandler)
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
} else {
setTimeout(() => {
setRegistrationFormsDataPending(mockFicheInscription);
}, 1000);
}
setIsLoading(false);
setReloadFetch(false);
};
const timeoutId = setTimeout(() => {
fetchDataAndSetState();
}, 500); // Debounce la recherche }, 500); // Debounce la recherche
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
}, [searchTerm, currentPage, itemsPerPage]); }, [searchTerm]);
/**
* UseEffect to update page count of tab
*/
useEffect(()=>{
if (activeTab === 'pending') {
setTotalPages(Math.ceil(totalPending / itemsPerPage));
} else if (activeTab === 'subscribed') {
setTotalPages(Math.ceil(totalSubscribed / itemsPerPage));
} else if (activeTab === 'archived') {
setTotalPages(Math.ceil(totalArchives / itemsPerPage));
}
},[currentPage]);
/**
* Archives a registration form after user confirmation.
*
* @param {number} id - The ID of the registration form to be archived.
* @param {string} nom - The last name of the person whose registration form is being archived.
* @param {string} prenom - The first name of the person whose registration form is being archived.
*/
const archiveFicheInscription = (id, nom, prenom) => { const archiveFicheInscription = (id, nom, prenom) => {
setPopup({ setPopup({
visible: true, visible: true,
@ -200,8 +259,8 @@ const registerFormArchivedDataHandler = (data) => {
archiveRegisterForm(id) archiveRegisterForm(id)
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFicheInscriptions(ficheInscriptions.filter(fiche => fiche.id !== id)); setRegistrationForms(registrationForms.filter(fiche => fiche.id !== id));
setFicheArchivee(true); setReloadFetch(true);
alert("Le dossier d'inscription a été correctement archivé"); alert("Le dossier d'inscription a été correctement archivé");
}) })
.catch(error => { .catch(error => {
@ -219,7 +278,7 @@ const registerFormArchivedDataHandler = (data) => {
onConfirm: () => { onConfirm: () => {
sendRegisterForm(id).then(data => { sendRegisterForm(id).then(data => {
console.log('Success:', data); console.log('Success:', data);
setMailSent(true); setReloadFetch(true);
}) })
.catch(error => { .catch(error => {
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
@ -227,15 +286,18 @@ const registerFormArchivedDataHandler = (data) => {
} }
}); });
}; };
const affectationClassFormSubmitHandler = (formdata)=> { const affectationClassFormSubmitHandler = (formdata)=> {
editRegisterForm(student.id,formData, csrfToken) editRegisterForm(student.id,formData, csrfToken)
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setReloadFetch(true);
}) })
.catch(error => { .catch(error => {
console.error('Error :', error); console.error('Error :', error);
}); });
} }
const updateStatusAction = (id, newStatus) => { const updateStatusAction = (id, newStatus) => {
console.log('Edit fiche inscription with id:', id); console.log('Edit fiche inscription with id:', id);
}; };
@ -246,11 +308,11 @@ const registerFormArchivedDataHandler = (data) => {
const handlePageChange = (newPage) => { const handlePageChange = (newPage) => {
setCurrentPage(newPage); setCurrentPage(newPage);
fetchData(newPage, itemsPerPage); // Appeler fetchData directement ici
}; };
const createRF = (updatedData) => { const createRF = (updatedData) => {
console.log("updateDATA",updatedData); console.log('createRF updatedData:', updatedData);
if (updatedData.selectedGuardians.length !== 0) { if (updatedData.selectedGuardians.length !== 0) {
const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId) const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId)
@ -263,10 +325,9 @@ const registerFormArchivedDataHandler = (data) => {
}; };
createRegisterForm(data,csrfToken) createRegisterForm(data,csrfToken)
.then(response => response.json())
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => { setRegistrationFormsDataPending(prevState => {
if (prevState) { if (prevState) {
return [...prevState, data]; return [...prevState, data];
} }
@ -315,7 +376,7 @@ const registerFormArchivedDataHandler = (data) => {
createRegisterForm(data,csrfToken) createRegisterForm(data,csrfToken)
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => { setRegistrationFormsDataPending(prevState => {
if (prevState && prevState.length > 0) { if (prevState && prevState.length > 0) {
return [...prevState, data]; return [...prevState, data];
} }
@ -338,6 +399,7 @@ const registerFormArchivedDataHandler = (data) => {
}); });
} }
closeModal(); closeModal();
setReloadFetch(true);
} }
@ -350,7 +412,7 @@ const columns = [
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update}, { name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
{ name: t('registrationFileStatus'), transform: (row) => ( { name: t('registrationFileStatus'), transform: (row) => (
<div className="flex justify-center items-center h-full"> <div className="flex justify-center items-center h-full">
<StatusLabel etat={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} /> <StatusLabel status={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
</div> </div>
) )
}, },
@ -431,7 +493,7 @@ const columnsSubscribed = [
{ name: t('registrationFileStatus'), transform: (row) => { name: t('registrationFileStatus'), transform: (row) =>
( (
<div className="flex justify-center items-center h-full"> <div className="flex justify-center items-center h-full">
<StatusLabel etat={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} /> <StatusLabel status={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
</div> </div>
) )
}, },
@ -513,10 +575,10 @@ const handleFileUpload = (file, fileName) => {
const formData = new FormData(); const formData = new FormData();
if(file){ if(file){
formData.append('fichier', file); formData.append('file', file);
} }
formData.append('nom', fileName); formData.append('name', fileName);
createRegisterFormFileTemplate(formData,csrfToken) createRegistrationFormFileTemplate(formData,csrfToken)
.then(data => { .then(data => {
console.log('Success:', data); console.log('Success:', data);
setFichiers([...fichiers, data]); setFichiers([...fichiers, data]);
@ -530,7 +592,7 @@ const handleFileUpload = (file, fileName) => {
if (isLoading) { if (isLoading) {
return <Loader />; return <Loader />;
} else { } else {
if (ficheInscriptions.length === 0 && fichesInscriptionsDataArchivees.length === 0 && alertPage) { if (registrationForms.length === 0 && registrationFormsDataArchived.length === 0 && alertPage) {
return ( return (
<div className='p-8'> <div className='p-8'>
<AlertWithModal <AlertWithModal
@ -616,10 +678,10 @@ const handleFileUpload = (file, fileName) => {
key={`${currentPage}-${searchTerm}`} key={`${currentPage}-${searchTerm}`}
data={ data={
activeTab === 'pending' activeTab === 'pending'
? fichesInscriptionsDataEnCours ? registrationFormsDataPending
: activeTab === 'subscribed' : activeTab === 'subscribed'
? fichesInscriptionsDataInscrits ? registrationFormsDataSubscribed
: fichesInscriptionsDataArchivees : registrationFormsDataArchived
} }
columns={ columns={
activeTab === 'subscribed' activeTab === 'subscribed'

View File

@ -1,23 +0,0 @@
'use client'
import React, { useState, useEffect } from 'react';
import Button from '@/components/Button';
import { MoreVertical, Send, Edit, Trash2, FileText, ChevronUp, UserPlus } from 'lucide-react';
import Modal from '@/components/Modal';
export default function Page() {
const [isOpen, setIsOpen] = useState(false);
const openModal = () => {
setIsOpen(true);
}
return (
<div className='p-8'>
<Button text={"addTeacher"} primary onClick={openModal} icon={<UserPlus size={20} />} />
<Modal isOpen={isOpen} setIsOpen={setIsOpen} />
</div>
);
}

View File

@ -3,11 +3,9 @@ import React, { useState, useEffect } from 'react';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared'; import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { useSearchParams, redirect, useRouter } from 'next/navigation'; import { useSearchParams, redirect, useRouter } from 'next/navigation';
import useCsrfToken from '@/hooks/useCsrfToken'; import useCsrfToken from '@/hooks/useCsrfToken';
import { FE_PARENTS_HOME_URL, import { FE_PARENTS_HOME_URL} from '@/utils/Url';
BE_SUBSCRIPTION_STUDENT_URL,
BE_SUBSCRIPTION_REGISTERFORM_URL,
BE_SUBSCRIPTION_LAST_GUARDIAN_URL } from '@/utils/Url';
import { mockStudent } from '@/data/mockStudent'; import { mockStudent } from '@/data/mockStudent';
import { fetchLastGuardian, fetchRegisterForm } from '@/app/lib/subscriptionAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -21,7 +19,7 @@ export default function Page() {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
const [currentProfil, setCurrentProfil] = useState(""); const [currentProfil, setCurrentProfil] = useState("");
const [lastIdResponsable, setLastIdResponsable] = useState(1); const [lastGuardianId, setLastGuardianId] = useState(1);
useEffect(() => { useEffect(() => {
if (!studentId || !idProfil) { if (!studentId || !idProfil) {
@ -31,37 +29,25 @@ export default function Page() {
if (useFakeData) { if (useFakeData) {
setInitialData(mockStudent); setInitialData(mockStudent);
setLastIdResponsable(999); setLastGuardianId(999);
setIsLoading(false); setIsLoading(false);
} else { } else {
Promise.all([ Promise.all([
// Fetch eleve data // Fetch eleve data
fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${studentId}`), fetchRegisterForm(studentId),
// Fetch last responsable ID // Fetch last guardian ID
fetch(BE_SUBSCRIPTION_LAST_GUARDIAN_URL) fetchLastGuardian()
]) ])
.then(async ([eleveResponse, responsableResponse]) => { .then(async ([studentData, guardianData]) => {
const eleveData = await eleveResponse.json();
const responsableData = await responsableResponse.json();
const formattedData = { const formattedData = {
id: eleveData.id, ...studentData,
nom: eleveData.nom, guardians: studentData.guardians || []
prenom: eleveData.prenom,
adresse: eleveData.adresse,
dateNaissance: eleveData.dateNaissance,
lieuNaissance: eleveData.lieuNaissance,
codePostalNaissance: eleveData.codePostalNaissance,
nationalite: eleveData.nationalite,
medecinTraitant: eleveData.medecinTraitant,
niveau: eleveData.niveau,
responsables: eleveData.responsables || []
}; };
setInitialData(formattedData); setInitialData(formattedData);
setLastIdResponsable(responsableData.lastid); setLastGuardianId(guardianData.lastid);
let profils = eleveData.profils; let profils = studentData.profils;
const currentProf = profils.find(profil => profil.id === idProfil); const currentProf = profils.find(profil => profil.id === idProfil);
if (currentProf) { if (currentProf) {
setCurrentProfil(currentProf); setCurrentProfil(currentProf);
@ -83,17 +69,8 @@ export default function Page() {
} }
try { try {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORM_URL}/${studentId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
credentials: 'include',
body: JSON.stringify(data),
});
const result = await response.json(); const result = await editRegisterForm(studentId, data, csrfToken);
console.log('Success:', result); console.log('Success:', result);
router.push(FE_PARENTS_HOME_URL); router.push(FE_PARENTS_HOME_URL);
} catch (error) { } catch (error) {

View File

@ -67,7 +67,7 @@ export default function ParentHomePage() {
<h3 className="text-lg font-semibold">{child.student.last_name} {child.student.first_name}</h3> <h3 className="text-lg font-semibold">{child.student.last_name} {child.student.first_name}</h3>
<Edit className="cursor-pointer" onClick={() => handleEdit(child.student.id)} /> <Edit className="cursor-pointer" onClick={() => handleEdit(child.student.id)} />
</div> </div>
<StatusLabel etat={child.status } showDropdown={false}/> <StatusLabel status={child.status } showDropdown={false}/>
</div> </div>
))} ))}
</div> </div>

View File

@ -12,6 +12,20 @@ import {mockUser} from "@/data/mockUsersData";
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
const requestResponseHandler = async (response) => {
const body = await response.json();
if (response.ok) {
return body;
}
// Throw an error with the JSON body containing the form errors
const error = new Error('Form submission error');
error.details = body;
throw error;
}
export const login = (data, csrfToken) => { export const login = (data, csrfToken) => {
const request = new Request( const request = new Request(
`${BE_AUTH_LOGIN_URL}`, `${BE_AUTH_LOGIN_URL}`,
@ -25,7 +39,7 @@ export const login = (data, csrfToken) => {
credentials: 'include', credentials: 'include',
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
/** /**
@ -64,7 +78,7 @@ const request = new Request(
body: JSON.stringify(data), body: JSON.stringify(data),
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
export const updateProfile = (id, data, csrfToken) => { export const updateProfile = (id, data, csrfToken) => {
@ -80,7 +94,7 @@ export const updateProfile = (id, data, csrfToken) => {
body: JSON.stringify(data), body: JSON.stringify(data),
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
export const sendNewPassword = (data, csrfToken) => { export const sendNewPassword = (data, csrfToken) => {
@ -97,7 +111,7 @@ export const sendNewPassword = (data, csrfToken) => {
body: JSON.stringify(data), body: JSON.stringify(data),
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
export const subscribe = (data,csrfToken) =>{ export const subscribe = (data,csrfToken) =>{
@ -113,7 +127,7 @@ export const subscribe = (data,csrfToken) =>{
body: JSON.stringify( data), body: JSON.stringify( data),
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
export const resetPassword = (uuid, data, csrfToken) => { export const resetPassword = (uuid, data, csrfToken) => {
@ -129,7 +143,7 @@ export const resetPassword = (uuid, data, csrfToken) => {
body: JSON.stringify(data), body: JSON.stringify(data),
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }
export const getResetPassword = (uuid) => { export const getResetPassword = (uuid) => {
@ -138,5 +152,5 @@ export const getResetPassword = (uuid) => {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}).then(response => response.json()) }).then(requestResponseHandler)
} }

View File

@ -5,22 +5,35 @@ import {
BE_SCHOOL_PLANNINGS_URL BE_SCHOOL_PLANNINGS_URL
} from '@/utils/Url'; } from '@/utils/Url';
const requestResponseHandler = async (response) => {
const body = await response.json();
if (response.ok) {
return body;
}
// Throw an error with the JSON body containing the form errors
const error = new Error('Form submission error');
error.details = body;
throw error;
}
export const fetchSpecialities = () => { export const fetchSpecialities = () => {
return fetch(`${BE_SCHOOL_SPECIALITIES_URL}`) return fetch(`${BE_SCHOOL_SPECIALITIES_URL}`)
.then(response => response.json()) .then(requestResponseHandler)
}; };
export const fetchTeachers = () => { export const fetchTeachers = () => {
return fetch(`${BE_SCHOOL_TEACHERS_URL}`) return fetch(`${BE_SCHOOL_TEACHERS_URL}`)
.then(response => response.json()) .then(requestResponseHandler)
}; };
export const fetchClasses = () => { export const fetchClasses = () => {
return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`) return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json()) .then(requestResponseHandler)
}; };
export const fetchSchedules = () => { export const fetchSchedules = () => {
return fetch(`${BE_SCHOOL_PLANNINGS_URL}`) return fetch(`${BE_SCHOOL_PLANNINGS_URL}`)
.then(response => response.json()) .then(requestResponseHandler)
}; };

View File

@ -6,7 +6,8 @@ import {
BE_SUBSCRIPTION_CHILDRENS_URL, BE_SUBSCRIPTION_CHILDRENS_URL,
BE_SUBSCRIPTION_REGISTERFORM_URL, BE_SUBSCRIPTION_REGISTERFORM_URL,
BE_SUBSCRIPTION_REGISTERFORMS_URL, BE_SUBSCRIPTION_REGISTERFORMS_URL,
BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL,
BE_SUBSCRIPTION_LAST_GUARDIAN_URL
} from '@/utils/Url'; } from '@/utils/Url';
export const PENDING = 'pending'; export const PENDING = 'pending';
@ -14,6 +15,18 @@ export const SUBSCRIBED = 'subscribed';
export const ARCHIVED = 'archived'; export const ARCHIVED = 'archived';
const requestResponseHandler = async (response) => {
const body = await response.json();
if (response.ok) {
return body;
}
// Throw an error with the JSON body containing the form errors
const error = new Error('Form submission error');
error.details = body;
throw error;
}
export const fetchRegisterForms = (type=PENDING, page='', pageSize='', search = '') => { export const fetchRegisterForms = (type=PENDING, page='', pageSize='', search = '') => {
let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${type}`; let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${type}`;
if (page !== '' && pageSize !== '') { if (page !== '' && pageSize !== '') {
@ -23,12 +36,16 @@ export const fetchRegisterForms = (type=PENDING, page='', pageSize='', search =
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}).then(response => response.json()) }).then(requestResponseHandler)
}; };
export const fetchRegisterForm = (id) =>{ export const fetchRegisterForm = (id) =>{
return fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${id}`) // Utilisation de studentId au lieu de codeDI return fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${id}`) // Utilisation de studentId au lieu de codeDI
.then(response => response.json()) .then(requestResponseHandler)
}
export const fetchLastGuardian = () =>{
return fetch(`${BE_SUBSCRIPTION_LAST_GUARDIAN_URL}`)
.then(requestResponseHandler)
} }
export const editRegisterForm=(id, data, csrfToken)=>{ export const editRegisterForm=(id, data, csrfToken)=>{
@ -42,7 +59,7 @@ export const editRegisterForm=(id, data, csrfToken)=>{
body: JSON.stringify(data), body: JSON.stringify(data),
credentials: 'include' credentials: 'include'
}) })
.then(response => response.json()) .then(requestResponseHandler)
}; };
@ -57,7 +74,7 @@ export const createRegisterForm=(data, csrfToken)=>{
body: JSON.stringify(data), body: JSON.stringify(data),
credentials: 'include' credentials: 'include'
}) })
.then(response => response.json()) .then(requestResponseHandler)
} }
export const archiveRegisterForm = (id) => { export const archiveRegisterForm = (id) => {
@ -67,7 +84,7 @@ export const archiveRegisterForm = (id) => {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}).then(response => response.json()) }).then(requestResponseHandler)
} }
export const sendRegisterForm = (id) => { export const sendRegisterForm = (id) => {
@ -76,13 +93,13 @@ export const sendRegisterForm = (id) => {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}).then(response => response.json()) }).then(requestResponseHandler)
} }
export const fetchRegisterFormFileTemplate = () => { export const fetchRegisterFormFileTemplate = () => {
const request = new Request( const request = new Request(
`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}`, `${BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL}`,
{ {
method:'GET', method:'GET',
headers: { headers: {
@ -90,12 +107,12 @@ export const fetchRegisterFormFileTemplate = () => {
}, },
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
}; };
export const createRegisterFormFileTemplate = (data,csrfToken) => { export const createRegistrationFormFileTemplate = (data,csrfToken) => {
fetch(`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}`, { return fetch(`${BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL}`, {
method: 'POST', method: 'POST',
body: data, body: data,
headers: { headers: {
@ -103,11 +120,11 @@ export const createRegisterFormFileTemplate = (data,csrfToken) => {
}, },
credentials: 'include', credentials: 'include',
}) })
.then(response => response.json()) .then(requestResponseHandler)
} }
export const deleteRegisterFormFileTemplate = (fileId,csrfToken) => { export const deleteRegisterFormFileTemplate = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}/${fileId}`, { return fetch(`${BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL}/${fileId}`, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
@ -125,7 +142,7 @@ export const fetchStudents = () => {
}, },
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
}; };
@ -139,5 +156,5 @@ export const fetchChildren = (id) =>{
}, },
} }
); );
return fetch(request).then(response => response.json()) return fetch(request).then(requestResponseHandler)
} }

View File

@ -2,7 +2,7 @@ import { useState } from 'react';
import { ChevronUp } from 'lucide-react'; import { ChevronUp } from 'lucide-react';
import DropdownMenu from './DropdownMenu'; import DropdownMenu from './DropdownMenu';
const StatusLabel = ({ etat, onChange, showDropdown = true }) => { const StatusLabel = ({ status, onChange, showDropdown = true }) => {
const [dropdownOpen, setDropdownOpen] = useState(false); const [dropdownOpen, setDropdownOpen] = useState(false);
const statusOptions = [ const statusOptions = [
{ value: 1, label: 'Créé' }, { value: 1, label: 'Créé' },
@ -13,7 +13,7 @@ const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
{ value: 6, label: 'Archivé' }, { value: 6, label: 'Archivé' },
]; ];
const currentStatus = statusOptions.find(option => option.value === etat); const currentStatus = statusOptions.find(option => option.value === status);
return ( return (
<> <>
{showDropdown ? ( {showDropdown ? (
@ -29,12 +29,12 @@ const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
onClick: () => onChange(option.value), onClick: () => onChange(option.value),
}))} }))}
buttonClassName={`w-[150px] flex items-center justify-center gap-2 px-2 py-2 rounded-md text-sm text-center font-medium ${ buttonClassName={`w-[150px] flex items-center justify-center gap-2 px-2 py-2 rounded-md text-sm text-center font-medium ${
etat === 1 && 'bg-blue-50 text-blue-600' || status === 1 && 'bg-blue-50 text-blue-600' ||
etat === 2 && 'bg-orange-50 text-orange-600' || status === 2 && 'bg-orange-50 text-orange-600' ||
etat === 3 && 'bg-purple-50 text-purple-600' || status === 3 && 'bg-purple-50 text-purple-600' ||
etat === 4 && 'bg-red-50 text-red-600' || status === 4 && 'bg-red-50 text-red-600' ||
etat === 5 && 'bg-green-50 text-green-600' || status === 5 && 'bg-green-50 text-green-600' ||
etat === 6 && 'bg-red-50 text-red-600' status === 6 && 'bg-red-50 text-red-600'
}`} }`}
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg z-10" menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg z-10"
dropdownOpen={dropdownOpen} dropdownOpen={dropdownOpen}
@ -42,12 +42,12 @@ const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
/> />
) : ( ) : (
<div className={`w-[150px] flex items-center justify-center gap-2 px-2 py-2 rounded-md text-sm text-center font-medium ${ <div className={`w-[150px] flex items-center justify-center gap-2 px-2 py-2 rounded-md text-sm text-center font-medium ${
etat === 1 && 'bg-blue-50 text-blue-600' || status === 1 && 'bg-blue-50 text-blue-600' ||
etat === 2 && 'bg-orange-50 text-orange-600' || status === 2 && 'bg-orange-50 text-orange-600' ||
etat === 3 && 'bg-purple-50 text-purple-600' || status === 3 && 'bg-purple-50 text-purple-600' ||
etat === 4 && 'bg-red-50 text-red-600' || status === 4 && 'bg-red-50 text-red-600' ||
etat === 5 && 'bg-green-50 text-green-600' || status === 5 && 'bg-green-50 text-green-600' ||
etat === 6 && 'bg-red-50 text-red-600' status === 6 && 'bg-red-50 text-red-600'
}`}> }`}>
{currentStatus ? currentStatus.label : 'Statut inconnu'} {currentStatus ? currentStatus.label : 'Statut inconnu'}
</div> </div>

View File

@ -0,0 +1,7 @@
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await require('pino')
await require('next-logger')
}
}

View File

@ -1,7 +1,6 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import createMiddleware from 'next-intl/middleware'; import createMiddleware from 'next-intl/middleware';
import { routing } from '@/i18n/routing'; import { routing } from '@/i18n/routing';
const middleware = createMiddleware(routing); const middleware = createMiddleware(routing);
export default function handler(req) { export default function handler(req) {

View File

@ -0,0 +1,28 @@
const pino = require('pino')
const PinoLevelToSeverityLookup = {
trace: 'DEBUG',
debug: 'DEBUG',
info: 'INFO',
warn: 'WARNING',
error: 'ERROR',
fatal: 'CRITICAL',
};
const logger = defaultConfig =>
pino({
...defaultConfig,
messageKey: 'message',
formatters: {
level(label, number) {
return {
severity: PinoLevelToSeverityLookup[label] || PinoLevelToSeverityLookup['info'],
level: number,
}
},},
mixin: () => ({ name: 'custom-pino-instance' }),
})
module.exports = {
logger,
}

View File

@ -22,7 +22,7 @@ export const BE_SUBSCRIPTION_SEND_URL = `${BASE_URL}/Subscriptions/send`
export const BE_SUBSCRIPTION_ARCHIVE_URL = `${BASE_URL}/Subscriptions/archive` export const BE_SUBSCRIPTION_ARCHIVE_URL = `${BASE_URL}/Subscriptions/archive`
export const BE_SUBSCRIPTION_REGISTERFORM_URL = `${BASE_URL}/Subscriptions/registerForm` export const BE_SUBSCRIPTION_REGISTERFORM_URL = `${BASE_URL}/Subscriptions/registerForm`
export const BE_SUBSCRIPTION_REGISTERFORMS_URL = `${BASE_URL}/Subscriptions/registerForms` export const BE_SUBSCRIPTION_REGISTERFORMS_URL = `${BASE_URL}/Subscriptions/registerForms`
export const BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL = `${BASE_URL}/Subscriptions/registerFormFileTemplate` export const BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL = `${BASE_URL}/Subscriptions/registrationFileTemplates`
export const BE_SUBSCRIPTION_LAST_GUARDIAN_URL = `${BASE_URL}/Subscriptions/lastGuardian` export const BE_SUBSCRIPTION_LAST_GUARDIAN_URL = `${BASE_URL}/Subscriptions/lastGuardian`
//GESTION ENSEIGNANT //GESTION ENSEIGNANT

1685
package-lock.json generated

File diff suppressed because it is too large Load Diff