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):
return "RF_" + self.student.last_name + "_" + self.student.first_name
class RegistrationFile(models.Model):
class RegistrationFileTemplate(models.Model):
name = models.CharField(max_length=255)
file = models.FileField(upload_to='registration_files/')
date_added = models.DateTimeField(auto_now_add=True)

View File

@ -1,5 +1,5 @@
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 Auth.models import Profile
from Auth.serializers import ProfileSerializer
@ -10,9 +10,9 @@ from django.utils import timezone
import pytz
from datetime import datetime
class RegistrationFileSerializer(serializers.ModelSerializer):
class RegistrationFileTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = RegistrationFile
model = RegistrationFileTemplate
fields = '__all__'
class RegistrationFeeSerializer(serializers.ModelSerializer):

View File

@ -1,12 +1,12 @@
from django.urls import path, re_path
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 = [
re_path(r'^registerForms/([a-zA-z]+)$', RegisterFormListView.as_view(), name="listefichesInscriptions"),
re_path(r'^registerForm$', RegisterFormView.as_view(), name="registerForms"),
re_path(r'^registerForm/([0-9]+)$', RegisterFormView.as_view(), name="registerForms"),
re_path(r'^registerForms/([a-zA-z]+)$', RegisterFormListView.as_view(), name="registerForms"),
re_path(r'^registerForm$', RegisterFormView.as_view(), name="registerForm"),
re_path(r'^registerForm/([0-9]+)$', RegisterFormView.as_view(), name="registerForm"),
# Page de formulaire d'inscription - ELEVE
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"),
# 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
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"),
# Frais d'inscription
re_path(r'^registerFees$', RegisterFeeView.as_view(), name="registerFees"),
re_path(r'^registerFileTemplate$', RegisterFileTemplateView.as_view(), name='registerFileTemplate'),
re_path(r'^registerFileTemplate/([0-9]+)$', RegisterFileTemplateView.as_view(), name="registerFileTemplate"),
re_path(r'^registrationFees$', RegistrationFeeView.as_view(), name="registrationFees"),
re_path(r'^registrationFileTemplates$', RegistrationFileTemplateView.as_view(), name='registrationFileTemplates'),
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.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.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
@ -137,7 +137,7 @@ class RegisterFormView(APIView):
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):
studentForm_data=JSONParser().parse(request)
@ -162,7 +162,7 @@ class RegisterFormView(APIView):
studentForm_serializer.save()
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):
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({"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):
def get(self, request, _id):
@ -200,9 +200,9 @@ def send(request, id):
# Mise à jour de l'automate
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):
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
@ -211,9 +211,9 @@ def archive(request, id):
# Mise à jour de l'automate
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):
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.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
class ChildrenListView(APIView):
@ -249,32 +249,32 @@ class StudentListView(APIView):
return JsonResponse(students_serializer.data, safe=False)
# 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):
tarifs = bdd.getAllObjects(RegistrationFee)
tarifs_serializer = RegistrationFeeSerializer(tarifs, many=True)
return JsonResponse(tarifs_serializer.data, safe=False)
class RegisterFileTemplateView(APIView):
class RegistrationFileTemplateView(APIView):
parser_classes = (MultiPartParser, FormParser)
def get(self, request):
fichiers = RegistrationFile.objects.all()
serializer = RegistrationFormSerializer(fichiers, many=True)
fichiers = RegistrationFileTemplate.objects.all()
serializer = RegistrationFileTemplateSerializer(fichiers, many=True)
return Response(serializer.data)
def post(self, request):
serializer = RegistrationFormSerializer(data=request.data)
serializer = RegistrationFileTemplateSerializer(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=RegistrationFile, _columnName='id', _value=_id)
if fichierInscription is not None:
fichierInscription.file.delete() # Supprimer le fichier uploadé
fichierInscription.delete()
registrationFileTemplate = bdd.getObject(_objectName=RegistrationFileTemplate, _columnName='id', _value=_id)
if registrationFileTemplate is not None:
registrationFileTemplate.file.delete() # Supprimer le fichier uploadé
registrationFileTemplate.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)
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();
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
experimental: {
instrumentationHook: true,
},
};
export default withNextIntl(nextConfig);

View File

@ -17,6 +17,8 @@
"lucide-react": "^0.453.0",
"next": "14.2.11",
"next-intl": "^3.24.0",
"next-logger": "^5.0.1",
"pino": "^9.6.0",
"react": "^18",
"react-cookie": "^7.2.0",
"react-dnd": "^16.0.1",
@ -175,6 +177,28 @@
"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": {
"version": "4.4.0",
"dev": true,
@ -1007,6 +1031,13 @@
"dev": true,
"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": {
"version": "7.2.0",
"dev": true,
@ -1472,6 +1503,21 @@
"dev": true,
"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": {
"version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
@ -1725,6 +1771,17 @@
"version": "0.0.1",
"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": {
"version": "2.0.1",
"license": "MIT",
@ -1739,6 +1796,45 @@
"version": "1.1.4",
"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": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@ -2006,6 +2102,13 @@
"version": "9.2.2",
"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": {
"version": "5.17.1",
"dev": true,
@ -2645,6 +2748,14 @@
"dev": true,
"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": {
"version": "1.17.1",
"license": "ISC",
@ -2652,6 +2763,13 @@
"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": {
"version": "6.0.1",
"dev": true,
@ -2706,6 +2824,13 @@
"dev": true,
"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": {
"version": "0.3.3",
"dev": true,
@ -3120,7 +3245,7 @@
},
"node_modules/inherits": {
"version": "2.0.4",
"dev": true,
"devOptional": true,
"license": "ISC"
},
"node_modules/input-format": {
@ -3195,6 +3320,13 @@
"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": {
"version": "2.0.0",
"dev": true,
@ -3446,6 +3578,19 @@
"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": {
"version": "1.0.7",
"dev": true,
@ -3645,6 +3790,13 @@
"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": {
"version": "0.3.23",
"dev": true,
@ -3716,6 +3868,24 @@
"dev": true,
"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": {
"version": "1.4.0",
"license": "MIT",
@ -3793,7 +3963,7 @@
},
"node_modules/ms": {
"version": "2.1.3",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/mz": {
@ -3905,6 +4075,38 @@
"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": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@ -4080,6 +4282,14 @@
"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": {
"version": "1.4.0",
"dev": true,
@ -4088,6 +4298,16 @@
"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": {
"version": "0.9.4",
"dev": true,
@ -4214,6 +4434,40 @@
"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": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
@ -4385,6 +4639,21 @@
"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": {
"version": "15.8.1",
"license": "MIT",
@ -4425,6 +4694,11 @@
],
"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": {
"version": "18.3.1",
"license": "MIT",
@ -4609,6 +4883,21 @@
"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": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@ -4620,6 +4909,14 @@
"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": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
@ -4787,6 +5084,27 @@
"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": {
"version": "1.0.3",
"dev": true,
@ -4803,6 +5121,14 @@
"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": {
"version": "0.23.2",
"license": "MIT",
@ -4895,6 +5221,16 @@
"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": {
"version": "3.0.0",
"dev": true,
@ -4903,6 +5239,14 @@
"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": {
"version": "1.2.1",
"license": "BSD-3-Clause",
@ -4910,6 +5254,24 @@
"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": {
"version": "1.0.0",
"dev": true,
@ -4927,6 +5289,16 @@
"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": {
"version": "5.1.2",
"license": "MIT",
@ -5218,6 +5590,13 @@
"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": {
"version": "0.2.0",
"dev": true,
@ -5242,6 +5621,14 @@
"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": {
"version": "1.0.3",
"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",
"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": {
"version": "1.3.0",
"dev": true,
@ -5608,6 +6005,44 @@
"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": {
"version": "1.2.5",
"dev": true,

View File

@ -19,6 +19,8 @@
"lucide-react": "^0.453.0",
"next": "14.2.11",
"next-intl": "^3.24.0",
"next-logger": "^5.0.1",
"pino": "^9.6.0",
"react": "^18",
"react-cookie": "^7.2.0",
"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 { Users, Clock, CalendarCheck, School, TrendingUp, UserCheck } from 'lucide-react';
import Loader from '@/components/Loader';
import { BE_SCHOOL_SCHOOLCLASSES_URL } from '@/utils/Url';
import ClasseDetails from '@/components/ClasseDetails';
import { fetchClasses } from '@/app/lib/schoolAction';
// Composant StatCard pour afficher une statistique
const StatCard = ({ title, value, icon, change, color = "blue" }) => (
@ -58,20 +58,15 @@ export default function DashboardPage() {
const [classes, setClasses] = useState([]);
const fetchClasses = () => {
fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json())
.then(data => {
useEffect(() => {
// Fetch data for classes
fetchClasses().then(data => {
setClasses(data);
})
.catch(error => {
console.error('Error fetching classes:', error);
});
};
useEffect(() => {
// Fetch data for classes
fetchClasses();
// Simulation de chargement des données
setTimeout(() => {

View File

@ -1,6 +1,6 @@
'use client'
import React, { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
import { useSearchParams, useRouter } from 'next/navigation';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url';
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';
export default function Page() {
const router = useRouter();
const searchParams = useSearchParams();
const idProfil = searchParams.get('id');
const studentId = searchParams.get('studentId'); // Changé de codeDI à studentId
@ -21,50 +22,44 @@ export default function Page() {
useEffect(() => {
if (useFakeData) {
setInitialData(mockStudent);
setIsLoading(false);
} else {
fetchRegisterForm(studentId)
.then(data => {
console.log('Fetched data:', data); // Pour le débogage
const formattedData = {
id: data.id,
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,
...data,
guardians: data.guardians || []
};
setInitialData(formattedData);
setIsLoading(false);
})
.catch(error => {
console.error('Error fetching student data:', error);
setIsLoading(false);
});
}
setIsLoading(false);
}, [studentId]); // Dépendance changée à studentId
const handleSubmit = async (data) => {
const handleSubmit = (data) => {
if (useFakeData) {
console.log('Fake submit:', data);
return;
}
try {
const result = await editRegisterForm(studentId, data, csrfToken);
// Utilisation de studentId
editRegisterForm(studentId, data, csrfToken)
.then((result) => {
console.log('Success:', result);
// Redirection après succès
window.location.href = FE_ADMIN_SUBSCRIPTIONS_URL;
} catch (error) {
console.error('Error:', error);
router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
})
.catch((error) => {
console.error('Error:', error.message);
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 (

View File

@ -27,6 +27,7 @@ import {
archiveRegisterForm,
fetchRegisterFormFileTemplate,
deleteRegisterFormFileTemplate,
createRegistrationFormFileTemplate,
fetchStudents,
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 } }) {
const t = useTranslations('subscriptions');
const [ficheInscriptions, setFicheInscriptions] = useState([]);
const [fichesInscriptionsDataEnCours, setFichesInscriptionsDataEnCours] = useState([]);
const [fichesInscriptionsDataInscrits, setFichesInscriptionsDataInscrits] = useState([]);
const [fichesInscriptionsDataArchivees, setFichesInscriptionsDataArchivees] = useState([]);
const [registrationForms, setRegistrationForms] = useState([]);
const [registrationFormsDataPending, setRegistrationFormsDataPending] = useState([]);
const [registrationFormsDataSubscribed, setRegistrationFormsDataSubscribed] = useState([]);
const [registrationFormsDataArchived, setRegistrationFormsDataArchived] = useState([]);
// const [filter, setFilter] = useState('*');
const [searchTerm, setSearchTerm] = useState('');
const [alertPage, setAlertPage] = useState(false);
const [mailSent, setMailSent] = useState(false);
const [ficheArchivee, setFicheArchivee] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [popup, setPopup] = useState({ visible: false, message: '', onConfirm: null });
const [activeTab, setActiveTab] = useState('pending');
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 [fichiers, setFichiers] = useState([]);
const [isOpen, setIsOpen] = useState(false);
const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false);
const [student, setStudent] = useState('');
const [classes, setClasses] = useState([]);
const [students, setEleves] = useState([]);
const [reloadFetch, setReloadFetch] = useState(false);
const csrfToken = useCsrfToken();
@ -80,6 +78,7 @@ export default function Page({ params: { locale } }) {
const closeModal = () => {
setIsOpen(false);
}
const openModalAssociationEleve = (eleveSelected) => {
@ -88,58 +87,72 @@ export default function Page({ params: { locale } }) {
}
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) => {
setIsLoading(false);
if (data) {
const { registerForms, count } = data;
const { registerForms, count, page_size } = data;
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);
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) => {
setIsLoading(false);
if (data) {
const { registerForms, count } = data;
const { registerForms, count, page_size } = data;
setTotalSubscribed(count);
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) => {
setIsLoading(false);
if (data) {
const { registerForms, count } = data;
const { registerForms, count, page_size } = data;
setTotalArchives(count);
if (registerForms) {
setFichesInscriptionsDataArchivees(registerForms);
setRegistrationFormsDataArchived(registerForms);
}
}
}
useEffect(() => {
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
}, []);
// TODO: revoir le système de pagination et de UseEffect
useEffect(() => {
fetchClasses()
.then(data => {
setClasses(data);
console.log("Success CLASSES : ", data)
console.log('Success Classes:', data);
})
.catch(error => {
console.error('Error fetching classes:', error);
@ -154,10 +167,13 @@ const registerFormArchivedDataHandler = (data) => {
error = error.message;
console.log(error);
});
}, [fichesInscriptionsDataEnCours]);
}, [registrationFormsDataPending]);
useEffect(() => {
const fetchDataAndSetState = () => {
setIsLoading(true);
if (!useFakeData) {
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
@ -168,30 +184,73 @@ const registerFormArchivedDataHandler = (data) => {
fetchRegisterForms(ARCHIVED)
.then(registerFormArchivedDataHandler)
.catch(requestErrorHandler)
fetchRegisterFormFileTemplate()
.then((data)=> {setFichiers(data)})
.catch((err)=>{ err = err.message; console.log(err);});
} else {
setTimeout(() => {
setFichesInscriptionsDataEnCours(mockFicheInscription);
setIsLoading(false);
setRegistrationFormsDataPending(mockFicheInscription);
}, 1000);
}
setFicheArchivee(false);
setMailSent(false);
setIsLoading(false);
setReloadFetch(false);
};
fetchDataAndSetState();
}, [mailSent, ficheArchivee, currentPage, itemsPerPage]);
}, [reloadFetch, currentPage]);
// Modifier le useEffect pour la recherche
useEffect(() => {
const timeoutId = setTimeout(() => {
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
.catch(requestErrorHandler)
useEffect(() => {
const fetchDataAndSetState = () => {
setIsLoading(true);
if (!useFakeData) {
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler)
.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
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) => {
setPopup({
visible: true,
@ -200,8 +259,8 @@ const registerFormArchivedDataHandler = (data) => {
archiveRegisterForm(id)
.then(data => {
console.log('Success:', data);
setFicheInscriptions(ficheInscriptions.filter(fiche => fiche.id !== id));
setFicheArchivee(true);
setRegistrationForms(registrationForms.filter(fiche => fiche.id !== id));
setReloadFetch(true);
alert("Le dossier d'inscription a été correctement archivé");
})
.catch(error => {
@ -219,7 +278,7 @@ const registerFormArchivedDataHandler = (data) => {
onConfirm: () => {
sendRegisterForm(id).then(data => {
console.log('Success:', data);
setMailSent(true);
setReloadFetch(true);
})
.catch(error => {
console.error('Error fetching data:', error);
@ -227,15 +286,18 @@ const registerFormArchivedDataHandler = (data) => {
}
});
};
const affectationClassFormSubmitHandler = (formdata)=> {
editRegisterForm(student.id,formData, csrfToken)
.then(data => {
console.log('Success:', data);
setReloadFetch(true);
})
.catch(error => {
console.error('Error :', error);
});
}
const updateStatusAction = (id, newStatus) => {
console.log('Edit fiche inscription with id:', id);
};
@ -246,11 +308,11 @@ const registerFormArchivedDataHandler = (data) => {
const handlePageChange = (newPage) => {
setCurrentPage(newPage);
fetchData(newPage, itemsPerPage); // Appeler fetchData directement ici
};
const createRF = (updatedData) => {
console.log("updateDATA",updatedData);
console.log('createRF updatedData:', updatedData);
if (updatedData.selectedGuardians.length !== 0) {
const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId)
@ -263,10 +325,9 @@ const registerFormArchivedDataHandler = (data) => {
};
createRegisterForm(data,csrfToken)
.then(response => response.json())
.then(data => {
console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => {
setRegistrationFormsDataPending(prevState => {
if (prevState) {
return [...prevState, data];
}
@ -291,7 +352,7 @@ const registerFormArchivedDataHandler = (data) => {
is_active: 0, // On rend le profil inactif : impossible de s'y connecter dans la fenêtre du login tant qu'il ne s'est pas inscrit
droit:2 // Profil PARENT
}
createProfile(data,csrfToken)
createProfile(data,csrfToken)
.then(response => {
console.log('Success:', response);
if (response.id) {
@ -315,7 +376,7 @@ const registerFormArchivedDataHandler = (data) => {
createRegisterForm(data,csrfToken)
.then(data => {
console.log('Success:', data);
setFichesInscriptionsDataEnCours(prevState => {
setRegistrationFormsDataPending(prevState => {
if (prevState && prevState.length > 0) {
return [...prevState, data];
}
@ -338,6 +399,7 @@ const registerFormArchivedDataHandler = (data) => {
});
}
closeModal();
setReloadFetch(true);
}
@ -349,10 +411,10 @@ const columns = [
{ name: t('phone'), transform: (row) => formatPhoneNumber(row.student.guardians[0].phone) },
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
{ name: t('registrationFileStatus'), transform: (row) => (
<div className="flex justify-center items-center h-full">
<StatusLabel etat={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
</div>
)
<div className="flex justify-center items-center h-full">
<StatusLabel status={row.status} onChange={(newStatus) => updateStatusAction(row.student.id, newStatus)} showDropdown={false} />
</div>
)
},
{ name: t('files'), transform: (row) =>
(row.registerForms != null) &&(
@ -431,7 +493,7 @@ const columnsSubscribed = [
{ name: t('registrationFileStatus'), transform: (row) =>
(
<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>
)
},
@ -513,10 +575,10 @@ const handleFileUpload = (file, fileName) => {
const formData = new FormData();
if(file){
formData.append('fichier', file);
formData.append('file', file);
}
formData.append('nom', fileName);
createRegisterFormFileTemplate(formData,csrfToken)
formData.append('name', fileName);
createRegistrationFormFileTemplate(formData,csrfToken)
.then(data => {
console.log('Success:', data);
setFichiers([...fichiers, data]);
@ -530,7 +592,7 @@ const handleFileUpload = (file, fileName) => {
if (isLoading) {
return <Loader />;
} else {
if (ficheInscriptions.length === 0 && fichesInscriptionsDataArchivees.length === 0 && alertPage) {
if (registrationForms.length === 0 && registrationFormsDataArchived.length === 0 && alertPage) {
return (
<div className='p-8'>
<AlertWithModal
@ -616,10 +678,10 @@ const handleFileUpload = (file, fileName) => {
key={`${currentPage}-${searchTerm}`}
data={
activeTab === 'pending'
? fichesInscriptionsDataEnCours
? registrationFormsDataPending
: activeTab === 'subscribed'
? fichesInscriptionsDataInscrits
: fichesInscriptionsDataArchivees
? registrationFormsDataSubscribed
: registrationFormsDataArchived
}
columns={
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 { useSearchParams, redirect, useRouter } from 'next/navigation';
import useCsrfToken from '@/hooks/useCsrfToken';
import { FE_PARENTS_HOME_URL,
BE_SUBSCRIPTION_STUDENT_URL,
BE_SUBSCRIPTION_REGISTERFORM_URL,
BE_SUBSCRIPTION_LAST_GUARDIAN_URL } from '@/utils/Url';
import { FE_PARENTS_HOME_URL} from '@/utils/Url';
import { mockStudent } from '@/data/mockStudent';
import { fetchLastGuardian, fetchRegisterForm } from '@/app/lib/subscriptionAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -21,7 +19,7 @@ export default function Page() {
const [isLoading, setIsLoading] = useState(true);
const csrfToken = useCsrfToken();
const [currentProfil, setCurrentProfil] = useState("");
const [lastIdResponsable, setLastIdResponsable] = useState(1);
const [lastGuardianId, setLastGuardianId] = useState(1);
useEffect(() => {
if (!studentId || !idProfil) {
@ -31,37 +29,25 @@ export default function Page() {
if (useFakeData) {
setInitialData(mockStudent);
setLastIdResponsable(999);
setLastGuardianId(999);
setIsLoading(false);
} else {
Promise.all([
// Fetch eleve data
fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${studentId}`),
// Fetch last responsable ID
fetch(BE_SUBSCRIPTION_LAST_GUARDIAN_URL)
fetchRegisterForm(studentId),
// Fetch last guardian ID
fetchLastGuardian()
])
.then(async ([eleveResponse, responsableResponse]) => {
const eleveData = await eleveResponse.json();
const responsableData = await responsableResponse.json();
const formattedData = {
id: eleveData.id,
nom: eleveData.nom,
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 || []
.then(async ([studentData, guardianData]) => {
const formattedData = {
...studentData,
guardians: studentData.guardians || []
};
setInitialData(formattedData);
setLastIdResponsable(responsableData.lastid);
setLastGuardianId(guardianData.lastid);
let profils = eleveData.profils;
let profils = studentData.profils;
const currentProf = profils.find(profil => profil.id === idProfil);
if (currentProf) {
setCurrentProfil(currentProf);
@ -83,17 +69,8 @@ export default function Page() {
}
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);
router.push(FE_PARENTS_HOME_URL);
} 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>
<Edit className="cursor-pointer" onClick={() => handleEdit(child.student.id)} />
</div>
<StatusLabel etat={child.status } showDropdown={false}/>
<StatusLabel status={child.status } showDropdown={false}/>
</div>
))}
</div>

View File

@ -12,6 +12,20 @@ import {mockUser} from "@/data/mockUsersData";
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) => {
const request = new Request(
`${BE_AUTH_LOGIN_URL}`,
@ -25,7 +39,7 @@ export const login = (data, csrfToken) => {
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),
}
);
return fetch(request).then(response => response.json())
return fetch(request).then(requestResponseHandler)
}
export const updateProfile = (id, data, csrfToken) => {
@ -80,7 +94,7 @@ export const updateProfile = (id, data, csrfToken) => {
body: JSON.stringify(data),
}
);
return fetch(request).then(response => response.json())
return fetch(request).then(requestResponseHandler)
}
export const sendNewPassword = (data, csrfToken) => {
@ -97,7 +111,7 @@ export const sendNewPassword = (data, csrfToken) => {
body: JSON.stringify(data),
}
);
return fetch(request).then(response => response.json())
return fetch(request).then(requestResponseHandler)
}
export const subscribe = (data,csrfToken) =>{
@ -113,7 +127,7 @@ export const subscribe = (data,csrfToken) =>{
body: JSON.stringify( data),
}
);
return fetch(request).then(response => response.json())
return fetch(request).then(requestResponseHandler)
}
export const resetPassword = (uuid, data, csrfToken) => {
@ -129,7 +143,7 @@ export const resetPassword = (uuid, data, csrfToken) => {
body: JSON.stringify(data),
}
);
return fetch(request).then(response => response.json())
return fetch(request).then(requestResponseHandler)
}
export const getResetPassword = (uuid) => {
@ -138,5 +152,5 @@ export const getResetPassword = (uuid) => {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}).then(requestResponseHandler)
}

View File

@ -5,22 +5,35 @@ import {
BE_SCHOOL_PLANNINGS_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 = () => {
return fetch(`${BE_SCHOOL_SPECIALITIES_URL}`)
.then(response => response.json())
.then(requestResponseHandler)
};
export const fetchTeachers = () => {
return fetch(`${BE_SCHOOL_TEACHERS_URL}`)
.then(response => response.json())
.then(requestResponseHandler)
};
export const fetchClasses = () => {
return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}`)
.then(response => response.json())
.then(requestResponseHandler)
};
export const fetchSchedules = () => {
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_REGISTERFORM_URL,
BE_SUBSCRIPTION_REGISTERFORMS_URL,
BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL
BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL,
BE_SUBSCRIPTION_LAST_GUARDIAN_URL
} from '@/utils/Url';
export const PENDING = 'pending';
@ -14,6 +15,18 @@ export const SUBSCRIBED = 'subscribed';
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 = '') => {
let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${type}`;
if (page !== '' && pageSize !== '') {
@ -23,12 +36,16 @@ export const fetchRegisterForms = (type=PENDING, page='', pageSize='', search =
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}).then(requestResponseHandler)
};
export const fetchRegisterForm = (id) =>{
return fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${id}`) // Utilisation de studentId au lieu de codeDI
.then(response => response.json())
return fetch(`${BE_SUBSCRIPTION_STUDENT_URL}/${id}`) // Utilisation de studentId au lieu de codeDI
.then(requestResponseHandler)
}
export const fetchLastGuardian = () =>{
return fetch(`${BE_SUBSCRIPTION_LAST_GUARDIAN_URL}`)
.then(requestResponseHandler)
}
export const editRegisterForm=(id, data, csrfToken)=>{
@ -42,7 +59,7 @@ export const editRegisterForm=(id, data, csrfToken)=>{
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json())
.then(requestResponseHandler)
};
@ -57,7 +74,7 @@ export const createRegisterForm=(data, csrfToken)=>{
body: JSON.stringify(data),
credentials: 'include'
})
.then(response => response.json())
.then(requestResponseHandler)
}
export const archiveRegisterForm = (id) => {
@ -67,7 +84,7 @@ export const archiveRegisterForm = (id) => {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}).then(requestResponseHandler)
}
export const sendRegisterForm = (id) => {
@ -76,13 +93,13 @@ export const sendRegisterForm = (id) => {
headers: {
'Content-Type': 'application/json',
},
}).then(response => response.json())
}).then(requestResponseHandler)
}
export const fetchRegisterFormFileTemplate = () => {
const request = new Request(
`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}`,
`${BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL}`,
{
method:'GET',
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',
body: data,
headers: {
@ -103,11 +120,11 @@ export const createRegisterFormFileTemplate = (data,csrfToken) => {
},
credentials: 'include',
})
.then(response => response.json())
.then(requestResponseHandler)
}
export const deleteRegisterFormFileTemplate = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMFILE_TEMPLATE_URL}/${fileId}`, {
return fetch(`${BE_SUBSCRIPTION_REGISTRATIONFORMFILE_TEMPLATE_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'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 DropdownMenu from './DropdownMenu';
const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
const StatusLabel = ({ status, onChange, showDropdown = true }) => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const statusOptions = [
{ value: 1, label: 'Créé' },
@ -13,7 +13,7 @@ const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
{ value: 6, label: 'Archivé' },
];
const currentStatus = statusOptions.find(option => option.value === etat);
const currentStatus = statusOptions.find(option => option.value === status);
return (
<>
{showDropdown ? (
@ -29,12 +29,12 @@ const StatusLabel = ({ etat, onChange, showDropdown = true }) => {
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 ${
etat === 1 && 'bg-blue-50 text-blue-600' ||
etat === 2 && 'bg-orange-50 text-orange-600' ||
etat === 3 && 'bg-purple-50 text-purple-600' ||
etat === 4 && 'bg-red-50 text-red-600' ||
etat === 5 && 'bg-green-50 text-green-600' ||
etat === 6 && 'bg-red-50 text-red-600'
status === 1 && 'bg-blue-50 text-blue-600' ||
status === 2 && 'bg-orange-50 text-orange-600' ||
status === 3 && 'bg-purple-50 text-purple-600' ||
status === 4 && 'bg-red-50 text-red-600' ||
status === 5 && 'bg-green-50 text-green-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"
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 ${
etat === 1 && 'bg-blue-50 text-blue-600' ||
etat === 2 && 'bg-orange-50 text-orange-600' ||
etat === 3 && 'bg-purple-50 text-purple-600' ||
etat === 4 && 'bg-red-50 text-red-600' ||
etat === 5 && 'bg-green-50 text-green-600' ||
etat === 6 && 'bg-red-50 text-red-600'
status === 1 && 'bg-blue-50 text-blue-600' ||
status === 2 && 'bg-orange-50 text-orange-600' ||
status === 3 && 'bg-purple-50 text-purple-600' ||
status === 4 && 'bg-red-50 text-red-600' ||
status === 5 && 'bg-green-50 text-green-600' ||
status === 6 && 'bg-red-50 text-red-600'
}`}>
{currentStatus ? currentStatus.label : 'Statut inconnu'}
</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 createMiddleware from 'next-intl/middleware';
import { routing } from '@/i18n/routing';
const middleware = createMiddleware(routing);
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_REGISTERFORM_URL = `${BASE_URL}/Subscriptions/registerForm`
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`
//GESTION ENSEIGNANT

1685
package-lock.json generated

File diff suppressed because it is too large Load Diff