feat: Ajout des Bundles de fichiers [#24]

This commit is contained in:
Luc SORIGNET
2025-02-10 18:35:24 +01:00
parent fb7fbaf839
commit ffc6ce8de8
25 changed files with 1736 additions and 743 deletions

View File

@ -11,11 +11,10 @@ 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, Download } from 'lucide-react';
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 FileUpload from './components/FileUpload';
import {
PENDING,
@ -26,17 +25,14 @@ import {
sendRegisterForm,
archiveRegisterForm,
fetchRegisterFormFileTemplate,
deleteRegisterFormFileTemplate,
createRegistrationFormFileTemplate,
editRegistrationFormFileTemplate,
fetchStudents,
editRegisterForm } from "@/app/lib/subscriptionAction"
import {
import {
fetchClasses,
fetchRegistrationDiscounts,
fetchTuitionDiscounts,
fetchRegistrationFees,
fetchRegistrationDiscounts,
fetchTuitionDiscounts,
fetchRegistrationFees,
fetchTuitionFees } from '@/app/lib/schoolAction';
import { createProfile } from '@/app/lib/authAction';
@ -47,7 +43,7 @@ import {
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
import useCsrfToken from '@/hooks/useCsrfToken';
import { formatDate } from '@/utils/Date';
import { fetchRegistrationFileGroups } from '@/app/lib/registerFileGroupAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@ -77,14 +73,13 @@ export default function Page({ params: { locale } }) {
const [classes, setClasses] = useState([]);
const [students, setEleves] = useState([]);
const [reloadFetch, setReloadFetch] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditing, setIsEditing] = useState(false);
const [fileToEdit, setFileToEdit] = useState(null);
const [registrationDiscounts, setRegistrationDiscounts] = useState([]);
const [tuitionDiscounts, setTuitionDiscounts] = useState([]);
const [registrationFees, setRegistrationFees] = useState([]);
const [tuitionFees, setTuitionFees] = useState([]);
const [groups, setGroups] = useState([]);
const csrfToken = useCsrfToken();
@ -228,6 +223,11 @@ const registerFormArchivedDataHandler = (data) => {
setTuitionFees(data);
})
.catch(requestErrorHandler);
fetchRegistrationFileGroups()
.then(data => {
setGroups(data);
})
.catch(error => console.error('Error fetching file groups:', error));
} else {
setTimeout(() => {
setRegistrationFormsDataPending(mockFicheInscription);
@ -357,7 +357,7 @@ useEffect(()=>{
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];
@ -370,7 +370,8 @@ useEffect(()=>{
},
idGuardians: selectedGuardiansIds,
fees: allFeesIds,
discounts: allDiscountsds
discounts: allDiscountsds,
fileGroup: selectedFileGroup
};
createRegisterForm(data, csrfToken)
@ -567,89 +568,23 @@ const columnsSubscribed = [
];
const handleFileDelete = (fileId) => {
deleteRegisterFormFileTemplate(fileId,csrfToken)
.then(response => {
if (response.ok) {
setFichiers(fichiers.filter(fichier => fichier.id !== fileId));
alert('Fichier supprimé avec succès.');
} else {
alert('Erreur lors de la suppression du fichier.');
}
})
.catch(error => {
console.error('Error deleting file:', error);
alert('Erreur lors de la suppression du fichier.');
});
};
const handleFileEdit = (file) => {
setIsEditing(true);
setFileToEdit(file);
setIsModalOpen(true);
};
const columnsFiles = [
{ name: 'Nom du fichier', transform: (row) => row.name },
{ name: 'Date de création', transform: (row) => formatDate(new Date (row.date_added),"DD/MM/YYYY hh:mm:ss") },
{ name: 'Fichier Obligatoire', transform: (row) => row.is_required ? 'Oui' : 'Non' },
{ name: 'Ordre de fusion', transform: (row) => row.order },
{ name: 'Actions', transform: (row) => (
<div className="flex items-center justify-center gap-2">
{
row.file && (
<a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
<Download size={16} />
</a>)
}
<button onClick={() => handleFileEdit(row)} className="text-blue-500 hover:text-blue-700">
<Edit size={16} />
</button>
<button onClick={() => handleFileDelete(row.id)} className="text-red-500 hover:text-red-700">
<Trash2 size={16} />
</button>
</div>
) },
];
const handleFileUpload = ({file, name, is_required, order}) => {
if (!name) {
alert('Veuillez entrer un nom de fichier.');
return;
}
const formData = new FormData();
if(file){
formData.append('file', file);
}
formData.append('name', name);
formData.append('is_required', is_required);
formData.append('order', order);
if (isEditing && fileToEdit) {
editRegistrationFormFileTemplate(fileToEdit.id, formData, csrfToken)
.then(data => {
setFichiers(prevFichiers =>
prevFichiers.map(f => f.id === fileToEdit.id ? data : f)
);
setIsModalOpen(false);
setFileToEdit(null);
setIsEditing(false);
})
.catch(error => {
console.error('Error editing file:', error);
});
} else {
createRegistrationFormFileTemplate(formData, csrfToken)
.then(data => {
setFichiers([...fichiers, data]);
setIsModalOpen(false);
})
.catch(error => {
console.error('Error uploading file:', error);
});
}
};
const tabs = [
{
id: 'pending',
label: t('pending'),
count: totalPending
},
{
id: 'subscribed',
label: t('subscribed'),
count: totalSubscribed
},
{
id: 'archived',
label: t('archived'),
count: totalArchives
}
];
if (isLoading) {
return <Loader />;
@ -699,16 +634,6 @@ const handleFileUpload = ({file, name, is_required, order}) => {
active={activeTab === 'archived'}
onClick={() => setActiveTab('archived')}
/>
<Tab
text={(
<>
{t('subscribeFiles')}
<span className="ml-2 text-sm text-gray-400">({fichiers.length})</span>
</>
)}
active={activeTab === 'subscribeFiles'}
onClick={() => setActiveTab('subscribeFiles')}
/>
</div>
</div>
<div className="border-b border-gray-200 mb-6 w-full">
@ -758,41 +683,6 @@ const handleFileUpload = ({file, name, is_required, order}) => {
</div>
</React.Fragment>
) : null}
{/*SI STATE == subscribeFiles */}
{activeTab === 'subscribeFiles' && (
<div>
<div className="flex justify-end mb-4">
<button
onClick={() => { setIsModalOpen(true); setIsEditing(false); }}
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-900 transition duration-200"
>
<Plus className="w-5 h-5" />
</button>
</div>
<Modal
isOpen={isModalOpen}
setIsOpen={setIsModalOpen}
title={isEditing ? 'Modifier un fichier' : 'Ajouter un fichier'}
ContentComponent={() => (
<FileUpload
onFileUpload={handleFileUpload}
fileToEdit={fileToEdit}
/>
)}
/>
<div className="mt-8">
<Table
data={fichiers}
columns={columnsFiles}
itemsPerPage={itemsPerPage}
currentPage={currentPage}
totalPages={totalPages}
onPageChange={handlePageChange}
className="mt-8"
/>
</div>
</div>
)}
</div>
<Popup
visible={popup.visible}
@ -815,6 +705,7 @@ const handleFileUpload = ({file, name, is_required, order}) => {
tuitionDiscounts={tuitionDiscounts}
registrationFees={registrationFees.filter(fee => fee.is_active)}
tuitionFees={tuitionFees.filter(fee => fee.is_active)}
groups={groups}
onSubmit={createRF}
/>
)}