mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Formulaire de création RF sur une seule pag
This commit is contained in:
@ -44,6 +44,8 @@ from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
|
||||
from Establishment.serializers import EstablishmentSerializer
|
||||
from Subscriptions.serializers import RegistrationFormSerializer, StudentSerializer
|
||||
|
||||
from Subscriptions.util import getCurrentSchoolYear, getNextSchoolYear # Import des fonctions nécessaires
|
||||
|
||||
# Définir le chemin vers le dossier mock_datas
|
||||
MOCK_DATAS_PATH = os.path.join(settings.BASE_DIR, 'School', 'management', 'mock_datas')
|
||||
|
||||
@ -403,11 +405,15 @@ class Command(BaseCommand):
|
||||
fees = Fee.objects.filter(id__in=[1, 2, 3, 4])
|
||||
discounts = Discount.objects.filter(id__in=[1])
|
||||
|
||||
# Déterminer l'année scolaire (soit l'année en cours, soit l'année prochaine)
|
||||
school_year = random.choice([getCurrentSchoolYear(), getNextSchoolYear()])
|
||||
|
||||
# Créer les données du formulaire d'inscription
|
||||
register_form_data = {
|
||||
"fileGroup": RegistrationFileGroup.objects.get(id=fake.random_int(min=1, max=file_group_count)),
|
||||
"establishment": profile_role.establishment,
|
||||
"status": fake.random_int(min=1, max=3)
|
||||
"status": fake.random_int(min=1, max=3),
|
||||
"school_year": school_year # Ajouter l'année scolaire
|
||||
}
|
||||
|
||||
# Créer ou mettre à jour le formulaire d'inscription
|
||||
@ -420,7 +426,7 @@ class Command(BaseCommand):
|
||||
if created:
|
||||
register_form.fees.set(fees)
|
||||
register_form.discounts.set(discounts)
|
||||
self.stdout.write(self.style.SUCCESS(f'RegistrationForm for student {student.last_name} created successfully'))
|
||||
self.stdout.write(self.style.SUCCESS(f'RegistrationForm for student {student.last_name} created successfully with school year {school_year}'))
|
||||
else:
|
||||
self.stdout.write(self.style.SUCCESS(f'RegistrationForm for student {student.last_name} already exists'))
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ class Guardian(models.Model):
|
||||
"""
|
||||
Représente un responsable légal (parent/tuteur) d’un élève.
|
||||
"""
|
||||
last_name = models.CharField(max_length=200, default="")
|
||||
first_name = models.CharField(max_length=200, default="")
|
||||
last_name = models.CharField(max_length=200, null=True, blank=True)
|
||||
first_name = models.CharField(max_length=200, null=True, blank=True)
|
||||
birth_date = models.DateField(null=True, blank=True)
|
||||
address = models.CharField(max_length=200, default="", blank=True)
|
||||
phone = models.CharField(max_length=200, default="", blank=True)
|
||||
@ -49,8 +49,8 @@ class Sibling(models.Model):
|
||||
"""
|
||||
Représente un frère ou une sœur d’un élève.
|
||||
"""
|
||||
last_name = models.CharField(max_length=200, default="")
|
||||
first_name = models.CharField(max_length=200, default="")
|
||||
last_name = models.CharField(max_length=200, null=True, blank=True)
|
||||
first_name = models.CharField(max_length=200, null=True, blank=True)
|
||||
birth_date = models.DateField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
@ -218,6 +218,7 @@ class RegistrationForm(models.Model):
|
||||
student = models.OneToOneField(Student, on_delete=models.CASCADE, primary_key=True)
|
||||
status = models.IntegerField(choices=RegistrationFormStatus, default=RegistrationFormStatus.RF_IDLE)
|
||||
last_update = models.DateTimeField(auto_now=True)
|
||||
school_year = models.CharField(max_length=9, default="", blank=True)
|
||||
notes = models.CharField(max_length=200, blank=True)
|
||||
registration_link_code = models.CharField(max_length=200, default="", blank=True)
|
||||
registration_file = models.FileField(
|
||||
|
||||
@ -343,7 +343,7 @@ class GuardianByDICreationSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Guardian
|
||||
fields = ['id', 'last_name', 'first_name', 'associated_profile_email']
|
||||
fields = ['id', 'last_name', 'first_name', 'associated_profile_email', 'phone']
|
||||
|
||||
def get_associated_profile_email(self, obj):
|
||||
if obj.profile_role and obj.profile_role.profile:
|
||||
@ -356,7 +356,7 @@ class StudentByRFCreationSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Student
|
||||
fields = ['id', 'last_name', 'first_name', 'guardians']
|
||||
fields = ['id', 'last_name', 'first_name', 'guardians', 'level']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StudentByRFCreationSerializer, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -175,3 +175,44 @@ def delete_registration_files(registerForm):
|
||||
|
||||
if os.path.exists(base_dir):
|
||||
shutil.rmtree(base_dir)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
def getCurrentSchoolYear():
|
||||
"""
|
||||
Retourne l'année scolaire en cours au format "YYYY-YYYY".
|
||||
Exemple : Si nous sommes en octobre 2023, retourne "2023-2024".
|
||||
"""
|
||||
now = datetime.now()
|
||||
current_year = now.year
|
||||
current_month = now.month
|
||||
|
||||
# Si nous sommes avant septembre, l'année scolaire a commencé l'année précédente
|
||||
start_year = current_year if current_month >= 9 else current_year - 1
|
||||
return f"{start_year}-{start_year + 1}"
|
||||
|
||||
def getNextSchoolYear():
|
||||
"""
|
||||
Retourne l'année scolaire suivante au format "YYYY-YYYY".
|
||||
Exemple : Si nous sommes en octobre 2023, retourne "2024-2025".
|
||||
"""
|
||||
current_school_year = getCurrentSchoolYear()
|
||||
start_year, end_year = map(int, current_school_year.split('-'))
|
||||
return f"{start_year + 1}-{end_year + 1}"
|
||||
|
||||
|
||||
def getHistoricalYears(count=5):
|
||||
"""
|
||||
Retourne un tableau des années scolaires passées au format "YYYY-YYYY".
|
||||
Exemple : ["2022-2023", "2021-2022", "2020-2021"].
|
||||
:param count: Le nombre d'années scolaires passées à inclure.
|
||||
"""
|
||||
current_school_year = getCurrentSchoolYear()
|
||||
start_year = int(current_school_year.split('-')[0])
|
||||
|
||||
historical_years = []
|
||||
for i in range(1, count + 1):
|
||||
historical_start_year = start_year - i
|
||||
historical_years.append(f"{historical_start_year}-{historical_start_year + 1}")
|
||||
|
||||
return historical_years
|
||||
@ -33,7 +33,7 @@ class RegisterFormView(APIView):
|
||||
|
||||
@swagger_auto_schema(
|
||||
manual_parameters=[
|
||||
openapi.Parameter('filter', openapi.IN_QUERY, description="filtre", type=openapi.TYPE_STRING, enum=['pending', 'archived', 'subscribed'], required=True),
|
||||
openapi.Parameter('filter', openapi.IN_QUERY, description="filtre", type=openapi.TYPE_STRING, enum=['current_year', 'next_year', 'historical'], required=True),
|
||||
openapi.Parameter('search', openapi.IN_QUERY, description="search", type=openapi.TYPE_STRING, required=False),
|
||||
openapi.Parameter('page_size', openapi.IN_QUERY, description="limite de page lors de la pagination", type=openapi.TYPE_INTEGER, required=False),
|
||||
openapi.Parameter('establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True),
|
||||
@ -51,7 +51,7 @@ class RegisterFormView(APIView):
|
||||
"last_name": "Doe",
|
||||
"date_of_birth": "2010-01-01"
|
||||
},
|
||||
"status": "pending",
|
||||
"status": "current_year",
|
||||
"last_update": "10-02-2025 10:00"
|
||||
},
|
||||
{
|
||||
@ -62,7 +62,7 @@ class RegisterFormView(APIView):
|
||||
"last_name": "Doe",
|
||||
"date_of_birth": "2011-02-02"
|
||||
},
|
||||
"status": "archived",
|
||||
"status": "historical",
|
||||
"last_update": "09-02-2025 09:00"
|
||||
}
|
||||
]
|
||||
@ -85,14 +85,19 @@ class RegisterFormView(APIView):
|
||||
except ValueError:
|
||||
page_size = settings.NB_RESULT_PER_PAGE
|
||||
|
||||
# Récupérer les dossier d'inscriptions en fonction du filtre
|
||||
# Récupérer les années scolaires
|
||||
current_year = util.getCurrentSchoolYear()
|
||||
next_year = util.getNextSchoolYear()
|
||||
historical_years = util.getHistoricalYears()
|
||||
|
||||
# Récupérer les dossiers d'inscriptions en fonction du filtre
|
||||
registerForms_List = None
|
||||
if filter == 'pending':
|
||||
exclude_states = [RegistrationForm.RegistrationFormStatus.RF_VALIDATED, RegistrationForm.RegistrationFormStatus.RF_ARCHIVED]
|
||||
registerForms_List = bdd.searchObjects(RegistrationForm, search, _excludeStates=exclude_states)
|
||||
elif filter == 'archived':
|
||||
registerForms_List = bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_ARCHIVED)
|
||||
elif filter == 'subscribed':
|
||||
if filter == 'current_year':
|
||||
registerForms_List = RegistrationForm.objects.filter(school_year=current_year)
|
||||
elif filter == 'next_year':
|
||||
registerForms_List = RegistrationForm.objects.filter(school_year=next_year)
|
||||
elif filter == 'historical':
|
||||
registerForms_List = RegistrationForm.objects.filter(school_year__in=historical_years)
|
||||
registerForms_List = bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_VALIDATED)
|
||||
else:
|
||||
registerForms_List = None
|
||||
@ -126,7 +131,7 @@ class RegisterFormView(APIView):
|
||||
"last_name": "Doe",
|
||||
"date_of_birth": "2010-01-01"
|
||||
},
|
||||
"status": "pending",
|
||||
"status": "current_year",
|
||||
"last_update": "10-02-2025 10:00",
|
||||
"codeLienInscription": "ABC123XYZ456"
|
||||
}
|
||||
@ -515,3 +520,4 @@ def get_parent_file_templates_by_rf(request, id):
|
||||
return JsonResponse(serializer.data, safe=False)
|
||||
except RegistrationParentFileTemplate.DoesNotExist:
|
||||
return JsonResponse({'error': 'Aucune pièce à fournir trouvée pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
@ -30,5 +30,6 @@
|
||||
"classe": "Class",
|
||||
"registrationFileStatus": "Registration file status",
|
||||
"files": "Files",
|
||||
"subscribeFiles": "Subscribe files"
|
||||
"subscribeFiles": "Subscribe files",
|
||||
"historical": "Historical"
|
||||
}
|
||||
|
||||
@ -30,5 +30,6 @@
|
||||
"classe": "Classe",
|
||||
"registrationFileStatus": "État du dossier d'inscription",
|
||||
"files": "Fichiers",
|
||||
"subscribeFiles": "Fichiers d'inscription"
|
||||
"subscribeFiles": "Fichiers d'inscription",
|
||||
"historical": "Historique"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -25,40 +25,24 @@ import InscriptionForm from '@/components/Inscription/InscriptionForm';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
|
||||
import {
|
||||
PENDING,
|
||||
SUBSCRIBED,
|
||||
ARCHIVED,
|
||||
CURRENT_YEAR,
|
||||
NEXT_YEAR,
|
||||
HISTORICAL,
|
||||
fetchRegisterForms,
|
||||
createRegisterForm,
|
||||
sendRegisterForm,
|
||||
archiveRegisterForm,
|
||||
fetchStudents,
|
||||
editRegisterForm,
|
||||
editRegisterFormWithBinaryFile,
|
||||
} from '@/app/actions/subscriptionAction';
|
||||
|
||||
import {
|
||||
fetchRegistrationSchoolFileMasters,
|
||||
fetchRegistrationParentFileMasters,
|
||||
createRegistrationSchoolFileTemplate,
|
||||
createRegistrationParentFileTemplate,
|
||||
fetchRegistrationFileGroups,
|
||||
cloneTemplate,
|
||||
} from '@/app/actions/registerFileGroupAction';
|
||||
|
||||
import {
|
||||
fetchClasses,
|
||||
fetchRegistrationDiscounts,
|
||||
fetchTuitionDiscounts,
|
||||
fetchRegistrationFees,
|
||||
fetchTuitionFees,
|
||||
} from '@/app/actions/schoolAction';
|
||||
import { fetchClasses, updateDatas } from '@/app/actions/schoolAction';
|
||||
|
||||
import { fetchProfiles } from '@/app/actions/authAction';
|
||||
|
||||
import {
|
||||
FE_ADMIN_SUBSCRIPTIONS_EDIT_URL,
|
||||
FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL,
|
||||
FE_ADMIN_SUBSCRIPTIONS_CREATE_URL,
|
||||
BASE_URL,
|
||||
} from '@/utils/Url';
|
||||
|
||||
@ -68,41 +52,41 @@ import logger from '@/utils/logger';
|
||||
import { PhoneLabel } from '@/components/PhoneLabel';
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
import FilesModal from '@/components/Inscription/FilesModal';
|
||||
import {
|
||||
getCurrentSchoolYear,
|
||||
getNextSchoolYear,
|
||||
getHistoricalYears,
|
||||
} from '@/utils/Date';
|
||||
|
||||
export default function Page({ params: { locale } }) {
|
||||
const t = useTranslations('subscriptions');
|
||||
const [registrationForms, setRegistrationForms] = useState([]);
|
||||
const [registrationFormsDataPending, setRegistrationFormsDataPending] =
|
||||
const [
|
||||
registrationFormsDataCurrentYear,
|
||||
setRegistrationFormsDataCurrentYear,
|
||||
] = useState([]);
|
||||
const [registrationFormsDataNextYear, setRegistrationFormsDataNextYear] =
|
||||
useState([]);
|
||||
const [registrationFormsDataSubscribed, setRegistrationFormsDataSubscribed] =
|
||||
const [registrationFormsDataHistorical, setRegistrationFormsDataHistorical] =
|
||||
useState([]);
|
||||
const [registrationFormsDataArchived, setRegistrationFormsDataArchived] =
|
||||
useState([]);
|
||||
// const [filter, setFilter] = useState('*');
|
||||
const currentSchoolYear = getCurrentSchoolYear(); // Exemple : "2024-2025"
|
||||
const nextSchoolYear = getNextSchoolYear(); // Exemple : "2025-2026"
|
||||
const historicalYears = getHistoricalYears();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [alertPage, setAlertPage] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState('pending');
|
||||
const [activeTab, setActiveTab] = useState('currentYear');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [totalPages, setTotalPages] = useState(1);
|
||||
const [totalPending, setTotalPending] = useState(0);
|
||||
const [totalSubscribed, setTotalSubscribed] = useState(0);
|
||||
const [totalArchives, setTotalArchives] = useState(0);
|
||||
const [totalCurrentYear, setTotalCurrentYear] = useState(0);
|
||||
const [totalSubscribed, setTotalNextYear] = useState(0);
|
||||
const [totalHistorical, setTotalHistorical] = useState(0);
|
||||
const [itemsPerPage, setItemsPerPage] = useState(10); // Définir le nombre d'éléments par page
|
||||
|
||||
const [schoolFileMasters, setSchoolFileMasters] = useState([]);
|
||||
const [parentFileMasters, setParentFileMasters] = useState([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [student, setStudent] = useState('');
|
||||
const [classes, setClasses] = useState([]);
|
||||
const [students, setEleves] = useState([]);
|
||||
const [reloadFetch, setReloadFetch] = useState(false);
|
||||
|
||||
const [registrationDiscounts, setRegistrationDiscounts] = useState([]);
|
||||
const [tuitionDiscounts, setTuitionDiscounts] = useState([]);
|
||||
const [registrationFees, setRegistrationFees] = useState([]);
|
||||
const [tuitionFees, setTuitionFees] = useState([]);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [profiles, setProfiles] = useState([]);
|
||||
const [isOpenAddGuardian, setIsOpenAddGuardian] = useState(false);
|
||||
|
||||
@ -132,14 +116,6 @@ export default function Page({ params: { locale } }) {
|
||||
setIsSepaUploadModalOpen(false);
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const openFilesModal = (row) => {
|
||||
setSelectedRegisterForm(row || []);
|
||||
setIsFilesModalOpen(true);
|
||||
@ -160,11 +136,11 @@ export default function Page({ params: { locale } }) {
|
||||
if (data) {
|
||||
const { registerForms, count, page_size } = data;
|
||||
if (registerForms) {
|
||||
setRegistrationFormsDataPending(registerForms);
|
||||
setRegistrationFormsDataCurrentYear(registerForms);
|
||||
}
|
||||
const calculatedTotalPages =
|
||||
count === 0 ? 1 : Math.ceil(count / page_size);
|
||||
setTotalPending(count);
|
||||
setTotalCurrentYear(count);
|
||||
setTotalPages(calculatedTotalPages);
|
||||
}
|
||||
};
|
||||
@ -179,9 +155,9 @@ export default function Page({ params: { locale } }) {
|
||||
const registerFormSubscribedDataHandler = (data) => {
|
||||
if (data) {
|
||||
const { registerForms, count, page_size } = data;
|
||||
setTotalSubscribed(count);
|
||||
setTotalNextYear(count);
|
||||
if (registerForms) {
|
||||
setRegistrationFormsDataSubscribed(registerForms);
|
||||
setRegistrationFormsDataNextYear(registerForms);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -197,9 +173,9 @@ export default function Page({ params: { locale } }) {
|
||||
if (data) {
|
||||
const { registerForms, count, page_size } = data;
|
||||
|
||||
setTotalArchives(count);
|
||||
setTotalHistorical(count);
|
||||
if (registerForms) {
|
||||
setRegistrationFormsDataArchived(registerForms);
|
||||
setRegistrationFormsDataHistorical(registerForms);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -211,7 +187,7 @@ export default function Page({ params: { locale } }) {
|
||||
Promise.all([
|
||||
fetchRegisterForms(
|
||||
selectedEstablishmentId,
|
||||
PENDING,
|
||||
CURRENT_YEAR,
|
||||
currentPage,
|
||||
itemsPerPage,
|
||||
searchTerm
|
||||
@ -225,59 +201,12 @@ export default function Page({ params: { locale } }) {
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
|
||||
fetchStudents(selectedEstablishmentId)
|
||||
.then((studentsData) => {
|
||||
setEleves(studentsData);
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
|
||||
fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED)
|
||||
fetchRegisterForms(selectedEstablishmentId, NEXT_YEAR)
|
||||
.then(registerFormSubscribedDataHandler)
|
||||
.catch(requestErrorHandler),
|
||||
fetchRegisterForms(selectedEstablishmentId, ARCHIVED)
|
||||
fetchRegisterForms(selectedEstablishmentId, HISTORICAL)
|
||||
.then(registerFormArchivedDataHandler)
|
||||
.catch(requestErrorHandler),
|
||||
fetchRegistrationSchoolFileMasters()
|
||||
.then((data) => {
|
||||
setSchoolFileMasters(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.debug(err.message);
|
||||
}),
|
||||
fetchRegistrationParentFileMasters()
|
||||
.then((data) => {
|
||||
setParentFileMasters(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.debug(err.message);
|
||||
}),
|
||||
fetchRegistrationDiscounts(selectedEstablishmentId)
|
||||
.then((data) => {
|
||||
setRegistrationDiscounts(data);
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
fetchTuitionDiscounts(selectedEstablishmentId)
|
||||
.then((data) => {
|
||||
setTuitionDiscounts(data);
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
fetchRegistrationFees(selectedEstablishmentId)
|
||||
.then((data) => {
|
||||
setRegistrationFees(data);
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
fetchTuitionFees(selectedEstablishmentId)
|
||||
.then((data) => {
|
||||
setTuitionFees(data);
|
||||
})
|
||||
.catch(requestErrorHandler),
|
||||
fetchRegistrationFileGroups(selectedEstablishmentId)
|
||||
.then((data) => {
|
||||
setGroups(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Error fetching file groups:', error);
|
||||
}),
|
||||
fetchProfiles()
|
||||
.then((data) => {
|
||||
setProfiles(data);
|
||||
@ -307,27 +236,19 @@ export default function Page({ params: { locale } }) {
|
||||
setIsLoading(true);
|
||||
fetchRegisterForms(
|
||||
selectedEstablishmentId,
|
||||
PENDING,
|
||||
CURRENT_YEAR,
|
||||
currentPage,
|
||||
itemsPerPage,
|
||||
searchTerm
|
||||
)
|
||||
.then(registerFormPendingDataHandler)
|
||||
.catch(requestErrorHandler);
|
||||
fetchRegisterForms(selectedEstablishmentId, SUBSCRIBED)
|
||||
fetchRegisterForms(selectedEstablishmentId, NEXT_YEAR)
|
||||
.then(registerFormSubscribedDataHandler)
|
||||
.catch(requestErrorHandler);
|
||||
fetchRegisterForms(selectedEstablishmentId, ARCHIVED)
|
||||
fetchRegisterForms(selectedEstablishmentId, HISTORICAL)
|
||||
.then(registerFormArchivedDataHandler)
|
||||
.catch(requestErrorHandler);
|
||||
fetchRegistrationSchoolFileMasters()
|
||||
.then((data) => {
|
||||
setSchoolFileMasters(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
err = err.message;
|
||||
logger.debug(err);
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
setReloadFetch(false);
|
||||
@ -344,12 +265,12 @@ export default function Page({ params: { locale } }) {
|
||||
* UseEffect to update page count of tab
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (activeTab === 'pending') {
|
||||
setTotalPages(Math.ceil(totalPending / itemsPerPage));
|
||||
} else if (activeTab === 'subscribed') {
|
||||
if (activeTab === 'currentYear') {
|
||||
setTotalPages(Math.ceil(totalCurrentYear / itemsPerPage));
|
||||
} else if (activeTab === 'nextYear') {
|
||||
setTotalPages(Math.ceil(totalSubscribed / itemsPerPage));
|
||||
} else if (activeTab === 'archived') {
|
||||
setTotalPages(Math.ceil(totalArchives / itemsPerPage));
|
||||
} else if (activeTab === 'historical') {
|
||||
setTotalPages(Math.ceil(totalHistorical / itemsPerPage));
|
||||
}
|
||||
}, [currentPage]);
|
||||
|
||||
@ -460,187 +381,6 @@ export default function Page({ params: { locale } }) {
|
||||
setCurrentPage(newPage);
|
||||
};
|
||||
|
||||
const createRF = (updatedData) => {
|
||||
logger.debug('createRF updatedData:', updatedData);
|
||||
|
||||
const selectedRegistrationFeesIds =
|
||||
updatedData.selectedRegistrationFees.map((feeId) => feeId);
|
||||
const selectedRegistrationDiscountsIds =
|
||||
updatedData.selectedRegistrationDiscounts.map((discountId) => discountId);
|
||||
const selectedTuitionFeesIds = updatedData.selectedTuitionFees.map(
|
||||
(feeId) => feeId
|
||||
);
|
||||
const selectedTuitionDiscountsIds =
|
||||
updatedData.selectedTuitionDiscounts.map((discountId) => discountId);
|
||||
const selectedFileGroup = updatedData.selectedFileGroup;
|
||||
const allFeesIds = [
|
||||
...selectedRegistrationFeesIds,
|
||||
...selectedTuitionFeesIds,
|
||||
];
|
||||
const allDiscountsds = [
|
||||
...selectedRegistrationDiscountsIds,
|
||||
...selectedTuitionDiscountsIds,
|
||||
];
|
||||
|
||||
const data = {
|
||||
student: {
|
||||
last_name: updatedData.studentLastName,
|
||||
first_name: updatedData.studentFirstName,
|
||||
guardians:
|
||||
updatedData.selectedGuardians.length !== 0
|
||||
? updatedData.selectedGuardians.map((guardianId) => ({
|
||||
id: guardianId,
|
||||
}))
|
||||
: (() => {
|
||||
if (updatedData.isExistingParentProfile) {
|
||||
return [
|
||||
{
|
||||
profile_role_data: {
|
||||
establishment: selectedEstablishmentId,
|
||||
role_type: 2,
|
||||
is_active: false,
|
||||
profile: updatedData.existingProfileId, // Associer au profil existant
|
||||
},
|
||||
last_name: updatedData.guardianLastName,
|
||||
first_name: updatedData.guardianFirstName,
|
||||
birth_date: updatedData.guardianBirthDate,
|
||||
address: updatedData.guardianAddress,
|
||||
phone: updatedData.guardianPhone,
|
||||
profession: updatedData.guardianProfession,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
||||
return [
|
||||
{
|
||||
profile_role_data: {
|
||||
establishment: selectedEstablishmentId,
|
||||
role_type: 2,
|
||||
is_active: false,
|
||||
profile_data: {
|
||||
email: updatedData.guardianEmail,
|
||||
password: 'Provisoire01!',
|
||||
username: updatedData.guardianEmail,
|
||||
},
|
||||
},
|
||||
last_name: updatedData.guardianLastName,
|
||||
first_name: updatedData.guardianFirstName,
|
||||
birth_date: updatedData.guardianBirthDate,
|
||||
address: updatedData.guardianAddress,
|
||||
phone: updatedData.guardianPhone,
|
||||
profession: updatedData.guardianProfession,
|
||||
},
|
||||
];
|
||||
})(),
|
||||
sibling: [],
|
||||
},
|
||||
fees: allFeesIds,
|
||||
discounts: allDiscountsds,
|
||||
fileGroup: selectedFileGroup,
|
||||
establishment: selectedEstablishmentId,
|
||||
};
|
||||
|
||||
setIsLoading(true);
|
||||
createRegisterForm(data, csrfToken)
|
||||
.then((data) => {
|
||||
// Cloner les schoolFileTemplates pour chaque templateMaster du fileGroup
|
||||
const masters = schoolFileMasters.filter((file) =>
|
||||
file.groups.includes(selectedFileGroup)
|
||||
);
|
||||
const parent_masters = parentFileMasters.filter((file) =>
|
||||
file.groups.includes(selectedFileGroup)
|
||||
);
|
||||
|
||||
const clonePromises = masters.map((templateMaster) => {
|
||||
return cloneTemplate(
|
||||
templateMaster.id,
|
||||
updatedData.guardianEmail,
|
||||
templateMaster.is_required
|
||||
)
|
||||
.then((clonedDocument) => {
|
||||
// Sauvegarde des schoolFileTemplates clonés dans la base de données
|
||||
const cloneData = {
|
||||
name: `${templateMaster.name}_${updatedData.studentFirstName}_${updatedData.studentLastName}`,
|
||||
slug: clonedDocument.slug,
|
||||
id: clonedDocument.id,
|
||||
master: templateMaster.id,
|
||||
registration_form: data.student.id,
|
||||
};
|
||||
|
||||
return createRegistrationSchoolFileTemplate(cloneData, csrfToken)
|
||||
.then((response) => {
|
||||
logger.debug('Template enregistré avec succès:', response);
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false);
|
||||
logger.error(
|
||||
"Erreur lors de l'enregistrement du template:",
|
||||
error
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false);
|
||||
logger.error('Error during cloning or sending:', error);
|
||||
});
|
||||
});
|
||||
|
||||
// Créer les parentFileTemplates pour chaque parentMaster
|
||||
const parentClonePromises = parent_masters.map((parentMaster) => {
|
||||
const parentTemplateData = {
|
||||
master: parentMaster.id,
|
||||
registration_form: data.student.id,
|
||||
};
|
||||
|
||||
return createRegistrationParentFileTemplate(
|
||||
parentTemplateData,
|
||||
csrfToken
|
||||
)
|
||||
.then((response) => {
|
||||
logger.debug('Parent template enregistré avec succès:', response);
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false);
|
||||
logger.error(
|
||||
"Erreur lors de l'enregistrement du parent template:",
|
||||
error
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Attendre que tous les clones (school et parent) soient créés
|
||||
Promise.all([...clonePromises, ...parentClonePromises])
|
||||
.then(() => {
|
||||
// Mise à jour immédiate des données
|
||||
setRegistrationFormsDataPending((prevState) => [
|
||||
...(prevState || []),
|
||||
data,
|
||||
]);
|
||||
setTotalPending((prev) => prev + 1);
|
||||
if (updatedData.autoMail) {
|
||||
sendConfirmRegisterForm(
|
||||
data.student.id,
|
||||
updatedData.studentLastName,
|
||||
updatedData.studentFirstName
|
||||
);
|
||||
}
|
||||
closeModal(); // Appeler closeModal ici après que tout soit terminé
|
||||
// Forcer le rechargement complet des données
|
||||
setReloadFetch(true);
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false);
|
||||
logger.error('Error during cloning or sending:', error);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false);
|
||||
logger.error('Error:', error);
|
||||
});
|
||||
};
|
||||
|
||||
const updateRF = (updatedData) => {
|
||||
logger.debug('updateRF updatedData:', updatedData);
|
||||
|
||||
@ -700,11 +440,11 @@ export default function Page({ params: { locale } }) {
|
||||
editRegisterForm(student.id, data, csrfToken)
|
||||
.then((data) => {
|
||||
// Mise à jour immédiate des données
|
||||
setRegistrationFormsDataPending((prevState) => [
|
||||
setRegistrationFormsDataCurrentYear((prevState) => [
|
||||
...(prevState || []),
|
||||
data,
|
||||
]);
|
||||
setTotalPending((prev) => prev + 1);
|
||||
setTotalCurrentYear((prev) => prev + 1);
|
||||
if (updatedData.autoMail) {
|
||||
sendConfirmRegisterForm(
|
||||
data.student.id,
|
||||
@ -980,7 +720,7 @@ export default function Page({ params: { locale } }) {
|
||||
} else {
|
||||
if (
|
||||
registrationForms.length === 0 &&
|
||||
registrationFormsDataArchived.length === 0 &&
|
||||
registrationFormsDataHistorical.length === 0 &&
|
||||
alertPage
|
||||
) {
|
||||
return (
|
||||
@ -997,49 +737,54 @@ export default function Page({ params: { locale } }) {
|
||||
<div className="p-8">
|
||||
<div className="border-b border-gray-200 mb-6">
|
||||
<div className="flex items-center gap-8">
|
||||
{/* Tab pour l'année scolaire en cours */}
|
||||
<Tab
|
||||
text={
|
||||
<>
|
||||
{t('pending')}
|
||||
{currentSchoolYear}
|
||||
<span className="ml-2 text-sm text-gray-400">
|
||||
({totalPending})
|
||||
({totalCurrentYear})
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
active={activeTab === 'pending'}
|
||||
onClick={() => setActiveTab('pending')}
|
||||
active={activeTab === 'currentYear'}
|
||||
onClick={() => setActiveTab('currentYear')}
|
||||
/>
|
||||
|
||||
{/* Tab pour l'année scolaire prochaine */}
|
||||
<Tab
|
||||
text={
|
||||
<>
|
||||
{t('subscribed')}
|
||||
{nextSchoolYear}
|
||||
<span className="ml-2 text-sm text-gray-400">
|
||||
({totalSubscribed})
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
active={activeTab === 'subscribed'}
|
||||
onClick={() => setActiveTab('subscribed')}
|
||||
active={activeTab === 'nextYear'}
|
||||
onClick={() => setActiveTab('nextYear')}
|
||||
/>
|
||||
|
||||
{/* Tab pour l'historique */}
|
||||
<Tab
|
||||
text={
|
||||
<>
|
||||
{t('archived')}
|
||||
{t('historical')}
|
||||
<span className="ml-2 text-sm text-gray-400">
|
||||
({totalArchives})
|
||||
({totalHistorical})
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
active={activeTab === 'archived'}
|
||||
onClick={() => setActiveTab('archived')}
|
||||
active={activeTab === 'historical'}
|
||||
onClick={() => setActiveTab('historical')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-b border-gray-200 mb-6 w-full">
|
||||
{/*SI STATE == pending || subscribe || archived */}
|
||||
{activeTab === 'pending' ||
|
||||
activeTab === 'subscribed' ||
|
||||
activeTab === 'archived' ? (
|
||||
{activeTab === 'currentYear' ||
|
||||
activeTab === 'nextYear' ||
|
||||
activeTab === 'historical' ? (
|
||||
<React.Fragment>
|
||||
<div className="flex justify-between items-center mb-4 w-full">
|
||||
<div className="relative flex-grow">
|
||||
@ -1056,7 +801,10 @@ export default function Page({ params: { locale } }) {
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={openModal}
|
||||
onClick={() => {
|
||||
const url = `${FE_ADMIN_SUBSCRIPTIONS_CREATE_URL}`;
|
||||
router.push(url);
|
||||
}}
|
||||
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-900 transition duration-200 ml-4"
|
||||
>
|
||||
<Plus className="w-5 h-5" />
|
||||
@ -1068,18 +816,13 @@ export default function Page({ params: { locale } }) {
|
||||
<Table
|
||||
key={`${currentPage}-${searchTerm}`}
|
||||
data={
|
||||
activeTab === 'pending'
|
||||
? [
|
||||
...registrationFormsDataPending,
|
||||
...registrationFormsDataSubscribed,
|
||||
]
|
||||
: activeTab === 'subscribed'
|
||||
? registrationFormsDataSubscribed
|
||||
: registrationFormsDataArchived
|
||||
}
|
||||
columns={
|
||||
activeTab === 'subscribed' ? columnsSubscribed : columns
|
||||
activeTab === 'currentYear'
|
||||
? registrationFormsDataCurrentYear
|
||||
: activeTab === 'nextYear'
|
||||
? registrationFormsDataNextYear
|
||||
: registrationFormsDataHistorical
|
||||
}
|
||||
columns={columns}
|
||||
itemsPerPage={itemsPerPage}
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
@ -1102,27 +845,6 @@ export default function Page({ params: { locale } }) {
|
||||
onCancel={() => setConfirmPopupVisible(false)}
|
||||
/>
|
||||
|
||||
{isOpen && (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
setIsOpen={setIsOpen}
|
||||
title={"Nouveau dossier d'inscription"}
|
||||
ContentComponent={() => (
|
||||
<InscriptionForm
|
||||
students={students}
|
||||
registrationDiscounts={registrationDiscounts}
|
||||
tuitionDiscounts={tuitionDiscounts}
|
||||
registrationFees={registrationFees.filter(
|
||||
(fee) => fee.is_active
|
||||
)}
|
||||
tuitionFees={tuitionFees.filter((fee) => fee.is_active)}
|
||||
groups={groups}
|
||||
profiles={profiles}
|
||||
onSubmit={createRF}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isSepaUploadModalOpen && (
|
||||
<Modal
|
||||
isOpen={isSepaUploadModalOpen}
|
||||
|
||||
@ -6,9 +6,9 @@ import {
|
||||
BE_SUBSCRIPTION_ABSENCES_URL,
|
||||
} from '@/utils/Url';
|
||||
|
||||
export const PENDING = 'pending';
|
||||
export const SUBSCRIBED = 'subscribed';
|
||||
export const ARCHIVED = 'archived';
|
||||
export const CURRENT_YEAR = 'current_year';
|
||||
export const NEXT_YEAR = 'next_year';
|
||||
export const HISTORICAL = 'historical';
|
||||
|
||||
const requestResponseHandler = async (response) => {
|
||||
const body = await response.json();
|
||||
@ -23,7 +23,7 @@ const requestResponseHandler = async (response) => {
|
||||
|
||||
export const fetchRegisterForms = (
|
||||
establishment,
|
||||
filter = PENDING,
|
||||
filter = CURRENT_YEAR,
|
||||
page = '',
|
||||
pageSize = '',
|
||||
search = ''
|
||||
|
||||
@ -6,8 +6,11 @@ export default function InputTextIcon({
|
||||
value,
|
||||
onChange,
|
||||
errorMsg,
|
||||
errorLocalMsg,
|
||||
placeholder,
|
||||
className,
|
||||
required,
|
||||
enable = true, // Nouvelle prop pour activer/désactiver le champ
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
@ -17,9 +20,16 @@ export default function InputTextIcon({
|
||||
className="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
{label}
|
||||
{required && <span className="text-red-500 ml-1">*</span>}
|
||||
</label>
|
||||
<div
|
||||
className={`mt-1 flex items-stretch border border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} hover:border-gray-400 focus-within:border-gray-500`}
|
||||
className={`mt-1 flex items-center border rounded-md ${
|
||||
errorMsg || errorLocalMsg
|
||||
? 'border-red-500 hover:border-red-700'
|
||||
: 'border-gray-200 hover:border-gray-400'
|
||||
} ${!errorMsg && !errorLocalMsg ? 'focus-within:border-gray-500' : ''} ${
|
||||
!enable ? 'bg-gray-100 cursor-not-allowed' : ''
|
||||
}`}
|
||||
>
|
||||
<span className="inline-flex items-center px-3 rounded-l-md bg-gray-50 text-gray-500 text-sm">
|
||||
{IconItem && <IconItem />}
|
||||
@ -30,8 +40,12 @@ export default function InputTextIcon({
|
||||
placeholder={placeholder}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="flex-1 px-3 py-2 block w-full rounded-r-md sm:text-sm border-none focus:ring-0 outline-none"
|
||||
onChange={enable ? onChange : undefined}
|
||||
className={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md ${
|
||||
!enable ? 'bg-gray-100 cursor-not-allowed' : ''
|
||||
}`}
|
||||
required={required}
|
||||
readOnly={!enable ? 'readOnly' : ''}
|
||||
/>
|
||||
</div>
|
||||
{errorMsg && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>}
|
||||
|
||||
@ -14,6 +14,8 @@ import InputPhone from '../InputPhone';
|
||||
import { PhoneLabel } from '../PhoneLabel';
|
||||
import CheckBox from '@/components/CheckBox';
|
||||
import RadioList from '@/components/RadioList';
|
||||
import SelectChoice from '@/components/SelectChoice';
|
||||
import { getCurrentSchoolYear, getNextSchoolYear } from '@/utils/Date';
|
||||
|
||||
const InscriptionForm = ({
|
||||
students,
|
||||
@ -52,6 +54,7 @@ const InscriptionForm = ({
|
||||
selectedTuitionDiscounts: [],
|
||||
selectedTuitionFees: [],
|
||||
selectedFileGroup: null, // Ajout du groupe de fichiers sélectionné
|
||||
schoolYear: getCurrentSchoolYear(),
|
||||
};
|
||||
});
|
||||
|
||||
@ -390,6 +393,24 @@ const InscriptionForm = ({
|
||||
|
||||
{step === 1 && (
|
||||
<div className="mt-6">
|
||||
{/* Sélection de l'année scolaire */}
|
||||
<SelectChoice
|
||||
name="schoolYear"
|
||||
label="Année scolaire"
|
||||
placeHolder="Sélectionnez une année scolaire"
|
||||
choices={[
|
||||
{ value: getCurrentSchoolYear(), label: getCurrentSchoolYear() },
|
||||
{ value: getNextSchoolYear(), label: getNextSchoolYear() },
|
||||
]}
|
||||
selected={formData.schoolYear || getCurrentSchoolYear()}
|
||||
callback={(e) =>
|
||||
setFormData((prevData) => ({
|
||||
...prevData,
|
||||
schoolYear: e.target.value,
|
||||
}))
|
||||
}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="studentLastName"
|
||||
type="text"
|
||||
|
||||
@ -8,23 +8,7 @@ import SectionHeader from '@/components/SectionHeader';
|
||||
import { User } from 'lucide-react';
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
import { BASE_URL } from '@/utils/Url';
|
||||
|
||||
const levels = [
|
||||
{ value: '1', label: 'TPS - Très Petite Section' },
|
||||
{ value: '2', label: 'PS - Petite Section' },
|
||||
{ value: '3', label: 'MS - Moyenne Section' },
|
||||
{ value: '4', label: 'GS - Grande Section' },
|
||||
{ value: '5', label: 'CP' },
|
||||
{ value: '6', label: 'CE1' },
|
||||
{ value: '7', label: 'CE2' },
|
||||
{ value: '8', label: 'CM1' },
|
||||
{ value: '9', label: 'CM2' },
|
||||
];
|
||||
|
||||
const genders = [
|
||||
{ value: '1', label: 'Garçon' },
|
||||
{ value: '2', label: 'Fille' },
|
||||
];
|
||||
import { levels, genders } from '@/utils/constants';
|
||||
|
||||
export default function StudentInfoForm({
|
||||
studentId,
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
const SectionTitle = ({ title }) => {
|
||||
const SectionTitle = ({ title, children }) => {
|
||||
return (
|
||||
<div className="relative mb-4">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-gray-300"></div>
|
||||
<div className="relative flex">
|
||||
{/* Liseré vertical */}
|
||||
<div className="w-1 bg-emerald-400"></div>
|
||||
|
||||
{/* Contenu de la section */}
|
||||
<div className="flex-1 pl-6">
|
||||
{/* Titre avec liseré horizontal */}
|
||||
<div className="flex items-center mb-4">
|
||||
<h2 className="text-emerald-700 font-bold text-xl">{title}</h2>
|
||||
<div className="flex-1 h-0.5 bg-emerald-200 ml-4"></div>
|
||||
</div>
|
||||
<div className="relative flex justify-center">
|
||||
<div className="px-4 bg-white text-gray-500">{title}</div>
|
||||
{/* Contenu passé en children */}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -345,15 +345,17 @@ const DiscountsSection = ({
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="space-y-4 mt-8">
|
||||
<div className="space-y-4">
|
||||
{!subscriptionMode && (
|
||||
<SectionHeader
|
||||
icon={Tag}
|
||||
discountStyle={true}
|
||||
title={`${type == 0 ? "Liste des réductions sur les frais d'inscription" : 'Liste des réductions sur les frais de scolarité'}`}
|
||||
description={`${subscriptionMode ? 'Sélectionnez' : 'Gérez'} ${type == 0 ? " vos réductions sur les frais d'inscription" : ' vos réductions sur les frais de scolarité'}`}
|
||||
description={`'Gérez' ${type == 0 ? " vos réductions sur les frais d'inscription" : ' vos réductions sur les frais de scolarité'}`}
|
||||
button={!subscriptionMode}
|
||||
onClick={handleAddDiscount}
|
||||
/>
|
||||
)}
|
||||
<Table
|
||||
data={newDiscount ? [newDiscount, ...discounts] : discounts}
|
||||
columns={columns}
|
||||
|
||||
@ -321,13 +321,15 @@ const FeesSection = ({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{!subscriptionMode && (
|
||||
<SectionHeader
|
||||
icon={CreditCard}
|
||||
title={`${type == 0 ? "Liste des frais d'inscription" : 'Liste des frais de scolarité'}`}
|
||||
description={`${subscriptionMode ? 'Sélectionnez' : 'Gérez'} ${type == 0 ? " vos frais d'inscription" : ' vos frais de scolarité'}`}
|
||||
description={`'Gérez'${type == 0 ? " vos frais d'inscription" : ' vos frais de scolarité'}`}
|
||||
button={!subscriptionMode}
|
||||
onClick={handleAddFee}
|
||||
/>
|
||||
)}
|
||||
<Table
|
||||
data={newFee ? [newFee, ...fees] : fees}
|
||||
columns={columns}
|
||||
|
||||
@ -99,3 +99,45 @@ export const isWeekend = (date) => {
|
||||
const day = date.getDay();
|
||||
return day === 0 || day === 6;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retourne l'année scolaire en cours au format "YYYY-YYYY".
|
||||
* Exemple : Si nous sommes en octobre 2023, retourne "2023-2024".
|
||||
*/
|
||||
export function getCurrentSchoolYear() {
|
||||
const now = new Date();
|
||||
const currentYear = now.getFullYear();
|
||||
const currentMonth = now.getMonth() + 1; // Les mois sont indexés à partir de 0
|
||||
|
||||
// Si nous sommes avant septembre, l'année scolaire a commencé l'année précédente
|
||||
const startYear = currentMonth >= 9 ? currentYear : currentYear - 1;
|
||||
return `${startYear}-${startYear + 1}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'année scolaire suivante au format "YYYY-YYYY".
|
||||
* Exemple : Si nous sommes en octobre 2023, retourne "2024-2025".
|
||||
*/
|
||||
export function getNextSchoolYear() {
|
||||
const currentSchoolYear = getCurrentSchoolYear();
|
||||
const [startYear, endYear] = currentSchoolYear.split('-').map(Number);
|
||||
return `${startYear + 1}-${endYear + 1}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne un tableau des années scolaires passées au format "YYYY-YYYY".
|
||||
* Exemple : ["2022-2023", "2021-2022", "2020-2021"].
|
||||
* @param {number} count - Le nombre d'années scolaires passées à inclure.
|
||||
*/
|
||||
export function getHistoricalYears(count = 5) {
|
||||
const currentSchoolYear = getCurrentSchoolYear();
|
||||
const [startYear] = currentSchoolYear.split('-').map(Number);
|
||||
|
||||
const historicalYears = [];
|
||||
for (let i = 1; i <= count; i++) {
|
||||
const historicalStartYear = startYear - i;
|
||||
historicalYears.push(`${historicalStartYear}-${historicalStartYear + 1}`);
|
||||
}
|
||||
|
||||
return historicalYears;
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ export const FE_ADMIN_HOME_URL = `/admin`;
|
||||
|
||||
// ADMIN/SUBSCRIPTIONS URL
|
||||
export const FE_ADMIN_SUBSCRIPTIONS_URL = `/admin/subscriptions`;
|
||||
export const FE_ADMIN_SUBSCRIPTIONS_CREATE_URL = `/admin/subscriptions/createSubscription`;
|
||||
export const FE_ADMIN_SUBSCRIPTIONS_EDIT_URL = `/admin/subscriptions/editInscription`;
|
||||
export const FE_ADMIN_SUBSCRIPTIONS_VALIDATE_URL = `/admin/subscriptions/validateSubscription`;
|
||||
|
||||
|
||||
16
Front-End/src/utils/constants.js
Normal file
16
Front-End/src/utils/constants.js
Normal file
@ -0,0 +1,16 @@
|
||||
export const levels = [
|
||||
{ value: '1', label: 'TPS - Très Petite Section' },
|
||||
{ value: '2', label: 'PS - Petite Section' },
|
||||
{ value: '3', label: 'MS - Moyenne Section' },
|
||||
{ value: '4', label: 'GS - Grande Section' },
|
||||
{ value: '5', label: 'CP' },
|
||||
{ value: '6', label: 'CE1' },
|
||||
{ value: '7', label: 'CE2' },
|
||||
{ value: '8', label: 'CM1' },
|
||||
{ value: '9', label: 'CM2' },
|
||||
];
|
||||
|
||||
export const genders = [
|
||||
{ value: '1', label: 'Garçon' },
|
||||
{ value: '2', label: 'Fille' },
|
||||
];
|
||||
Reference in New Issue
Block a user