'use client' import React, { useState, useEffect } from 'react'; import Table from '@/components/Table'; import {mockFicheInscription} from '@/data/mockFicheInscription'; import Tab from '@/components/Tab'; import { useTranslations } from 'next-intl'; import StatusLabel from '@/components/StatusLabel'; import { Search } from 'lucide-react'; import Popup from '@/components/Popup'; import Loader from '@/components/Loader'; import AlertWithModal from '@/components/AlertWithModal'; import DropdownMenu from "@/components/DropdownMenu"; import { formatPhoneNumber } from '@/utils/Telephone'; import { MoreVertical, Send, Edit, Trash2, FileText, CheckCircle, Plus } from 'lucide-react'; import Modal from '@/components/Modal'; import InscriptionForm from '@/components/Inscription/InscriptionForm' import AffectationClasseForm from '@/components/AffectationClasseForm' import { PENDING, SUBSCRIBED, ARCHIVED, fetchRegisterForms, createRegisterForm, sendRegisterForm, archiveRegisterForm, fetchRegisterFormFileTemplate, fetchStudents, editRegisterForm } from "@/app/actions/subscriptionAction" import { fetchClasses, fetchRegistrationDiscounts, fetchTuitionDiscounts, fetchRegistrationFees, fetchTuitionFees } from '@/app/actions/schoolAction'; import { createProfile } from '@/app/actions/authAction'; import { BASE_URL, FE_ADMIN_SUBSCRIPTIONS_EDIT_URL } from '@/utils/Url'; import DjangoCSRFToken from '@/components/DjangoCSRFToken' import { useCsrfToken } from '@/context/CsrfContext'; import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction'; import { ESTABLISHMENT_ID } from '@/utils/Url'; import logger from '@/utils/logger'; const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true'; export default function Page({ params: { locale } }) { const t = useTranslations('subscriptions'); 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 [isLoading, setIsLoading] = useState(false); const [popup, setPopup] = useState({ visible: false, message: '', onConfirm: null }); const [activeTab, setActiveTab] = useState('pending'); 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 [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 [registrationDiscounts, setRegistrationDiscounts] = useState([]); const [tuitionDiscounts, setTuitionDiscounts] = useState([]); const [registrationFees, setRegistrationFees] = useState([]); const [tuitionFees, setTuitionFees] = useState([]); const [groups, setGroups] = useState([]); const csrfToken = useCsrfToken(); const openModal = () => { setIsOpen(true); } const closeModal = () => { setIsOpen(false); } const openModalAssociationEleve = (eleveSelected) => { setIsOpenAffectationClasse(true); setStudent(eleveSelected); } const requestErrorHandler = (err)=>{ logger.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) => { if (data) { const { registerForms, count, page_size } = data; if (registerForms) { setRegistrationFormsDataPending(registerForms); } 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) => { if (data) { const { registerForms, count, page_size } = data; setTotalSubscribed(count); if (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) => { if (data) { const { registerForms, count, page_size } = data; setTotalArchives(count); if (registerForms) { setRegistrationFormsDataArchived(registerForms); } } } useEffect(() => { const fetchInitialData = async () => { try { const [classesData, studentsData] = await Promise.all([ fetchClasses(), fetchStudents() ]); setClasses(classesData); setEleves(studentsData); logger.debug('Success - Classes:', classesData); logger.debug('Success - Students:', studentsData); } catch (error) { logger.error('Error fetching initial data:', error); } }; fetchInitialData(); }, []); 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)=> { logger.debug(data); setFichiers(data) }) .catch((err)=>{ err = err.message; logger.debug(err);}) fetchRegistrationDiscounts() .then(data => { setRegistrationDiscounts(data); }) .catch(requestErrorHandler) fetchTuitionDiscounts() .then(data => { setTuitionDiscounts(data); }) .catch(requestErrorHandler) fetchRegistrationFees() .then(data => { setRegistrationFees(data); }) .catch(requestErrorHandler) fetchTuitionFees() .then(data => { setTuitionFees(data); }) .catch(requestErrorHandler); fetchRegistrationFileGroups() .then(data => { setGroups(data); }) .catch(error => logger.error('Error fetching file groups:', error)); } else { setTimeout(() => { setRegistrationFormsDataPending(mockFicheInscription); }, 1000); } setIsLoading(false); setReloadFetch(false); }; fetchDataAndSetState(); }, [reloadFetch, currentPage]); 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; logger.debug(err);}); } else { setTimeout(() => { setRegistrationFormsDataPending(mockFicheInscription); }, 1000); } setIsLoading(false); setReloadFetch(false); }; const timeoutId = setTimeout(() => { fetchDataAndSetState(); }, 500); // Debounce la recherche return () => clearTimeout(timeoutId); }, [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, message: `Attentions ! \nVous êtes sur le point d'archiver le dossier d'inscription de ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`, onConfirm: () => { archiveRegisterForm(id) .then(data => { logger.debug('Success:', data); setRegistrationForms(registrationForms.filter(fiche => fiche.id !== id)); setReloadFetch(true); alert("Le dossier d'inscription a été correctement archivé"); }) .catch(error => { logger.error('Error archiving data:', error); alert("Erreur lors de l'archivage du dossier d'inscription.\nContactez l'administrateur."); }); } }); }; const sendConfirmRegisterForm = (id, nom, prenom) => { setPopup({ visible: true, message: `Avertissement ! \nVous êtes sur le point d'envoyer un dossier d'inscription à ${nom} ${prenom}\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`, onConfirm: () => { sendRegisterForm(id).then(data => { logger.debug('Success:', data); setReloadFetch(true); }) .catch(error => { logger.error('Error fetching data:', error); }); } }); }; const affectationClassFormSubmitHandler = (formdata)=> { editRegisterForm(student.id,formData, csrfToken) .then(data => { logger.debug('Success:', data); setReloadFetch(true); }) .catch(error => { logger.error('Error :', error); }); } const updateStatusAction = (id, newStatus) => { logger.debug('Edit fiche inscription with id:', id); }; const handleSearchChange = (event) => { setSearchTerm(event.target.value); }; const handlePageChange = (newPage) => { 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]; if (updatedData.selectedGuardians.length !== 0) { const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId) const data = { student: { last_name: updatedData.studentLastName, first_name: updatedData.studentFirstName, }, idGuardians: selectedGuardiansIds, fees: allFeesIds, discounts: allDiscountsds, fileGroup: selectedFileGroup, establishment: ESTABLISHMENT_ID }; createRegisterForm(data, csrfToken) .then(data => { // 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(); // Forcer le rechargement complet des données setReloadFetch(true); }) .catch((error) => { logger.error('Error:', error); }); } else { const data = { email: updatedData.guardianEmail, password: 'Provisoire01!', username: updatedData.guardianEmail, is_active: 0, droit: 2 } createProfile(data, csrfToken) .then(response => { if (response.id) { const data = { student: { last_name: updatedData.studentLastName, first_name: updatedData.studentFirstName, guardians: [{ email: updatedData.guardianEmail, phone: updatedData.guardianPhone, associated_profile: response.id }], sibling: [] }, fees: allFeesIds, discounts: allDiscountsds, establishment: ESTABLISHMENT_ID }; createRegisterForm(data, csrfToken) .then(data => { // 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(); logger.debug('Success:', data); // Forcer le rechargement complet des données setReloadFetch(true); }) .catch((error) => { logger.error('Error:', error); }); } }) .catch(error => { logger.error('Error:', error); }); } } const columns = [ { name: t('studentName'), transform: (row) => row.student.last_name }, { name: t('studentFistName'), transform: (row) => row.student.first_name }, { name: t('mainContactMail'), transform: (row) => row.student.guardians[0].email }, { 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) => (