feat: Ajout de la configuration des tarifs de l'école [#18]

This commit is contained in:
N3WT DE COMPET
2025-01-19 21:00:58 +01:00
committed by Luc SORIGNET
parent 147a70135d
commit 5a0e65bb75
45 changed files with 2089 additions and 376 deletions

View File

@ -5,8 +5,12 @@ import ResponsableInputFields from '@/components/Inscription/ResponsableInputFie
import Loader from '@/components/Loader';
import Button from '@/components/Button';
import DjangoCSRFToken from '@/components/DjangoCSRFToken';
import FileUpload from '@/app/[locale]/admin/subscriptions/components/FileUpload';
import Table from '@/components/Table';
import { fetchRegisterFormFileTemplate, createRegistrationFormFile } from '@/app/lib/subscriptionAction';
import { Download, Upload } from 'lucide-react';
import { BASE_URL } from '@/utils/Url';
import DraggableFileUpload from '@/app/[locale]/admin/subscriptions/components/DraggableFileUpload';
import Modal from '@/components/Modal';
const levels = [
{ value:'1', label: 'TPS - Très Petite Section'},
@ -20,7 +24,8 @@ export default function InscriptionFormShared({
csrfToken,
onSubmit,
cancelUrl,
isLoading = false
isLoading = false,
errors = {} // Nouvelle prop pour les erreurs
}) {
const [formData, setFormData] = useState(() => ({
@ -41,6 +46,11 @@ export default function InscriptionFormShared({
);
const [uploadedFiles, setUploadedFiles] = useState([]);
const [fileTemplates, setFileTemplates] = useState([]);
const [fileName, setFileName] = useState("");
const [file, setFile] = useState("");
const [showUploadModal, setShowUploadModal] = useState(false);
const [currentTemplateId, setCurrentTemplateId] = useState(null);
// Mettre à jour les données quand initialData change
useEffect(() => {
@ -58,6 +68,9 @@ export default function InscriptionFormShared({
level: initialData.level || ''
});
setGuardians(initialData.guardians || []);
fetchRegisterFormFileTemplate().then((data) => {
setFileTemplates(data);
});
}
}, [initialData]);
@ -65,8 +78,22 @@ export default function InscriptionFormShared({
setFormData(prev => ({...prev, [field]: value}));
};
const handleFileUpload = (file, fileName) => {
setUploadedFiles([...uploadedFiles, { file, fileName }]);
const handleFileUpload = async (file, fileName) => {
const data = new FormData();
data.append('file', file);
data.append('name',fileName);
data.append('template', currentTemplateId);
data.append('register_form', formData.id);
try {
await createRegistrationFormFile(data, csrfToken);
// Optionnellement, rafraîchir la liste des fichiers
fetchRegisterFormFileTemplate().then((data) => {
setFileTemplates(data);
});
} catch (error) {
console.error('Error uploading file:', error);
}
};
const handleSubmit = (e) => {
@ -80,12 +107,31 @@ export default function InscriptionFormShared({
onSubmit(data);
};
const getError = (field) => {
return errors?.student?.[field]?.[0];
};
const getGuardianError = (index, field) => {
return errors?.student?.guardians?.[index]?.[field]?.[0];
};
const columns = [
{ name: 'Nom du fichier', transform: (row) => row.last_name },
{ name: 'Nom du fichier', transform: (row) => row.name },
{ name: 'Fichier à Remplir', transform: (row) => row.is_required ? 'Oui' : 'Non' },
{ name: 'Fichier de référence', transform: (row) => row.file && <div className="flex items-center justify-center gap-2"> <a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
<Download size={16} />
</a> </div>},
{ name: 'Actions', transform: (row) => (
<a href={URL.createObjectURL(row.fichier)} target='_blank' className="text-blue-500 hover:text-blue-700">
Télécharger
</a>
<div className="flex items-center justify-center gap-2">
{row.is_required &&
<button className="text-emerald-500 hover:text-emerald-700" type="button" onClick={() => {
setCurrentTemplateId(row.id);
setShowUploadModal(true);
}}>
<Upload size={16} />
</button>
}
</div>
) },
];
@ -105,12 +151,14 @@ export default function InscriptionFormShared({
value={formData.last_name}
onChange={(e) => updateFormField('last_name', e.target.value)}
required
errorMsg={getError('last_name')}
/>
<InputText
name="first_name"
label="Prénom"
value={formData.first_name}
onChange={(e) => updateFormField('first_name', e.target.value)}
errorMsg={getError('first_name')}
required
/>
<InputText
@ -126,18 +174,22 @@ export default function InscriptionFormShared({
value={formData.birth_date}
onChange={(e) => updateFormField('birth_date', e.target.value)}
required
errorMsg={getError('birth_date')}
/>
<InputText
name="birth_place"
label="Lieu de Naissance"
value={formData.birth_place}
onChange={(e) => updateFormField('birth_place', e.target.value)}
errorMsg={getError('birth_place')}
/>
<InputText
name="birth_postal_code"
label="Code Postal de Naissance"
value={formData.birth_postal_code}
onChange={(e) => updateFormField('birth_postal_code', e.target.value)}
required
errorMsg={getError('birth_postal_code')}
/>
<div className="md:col-span-2">
<InputText
@ -145,6 +197,7 @@ export default function InscriptionFormShared({
label="Adresse"
value={formData.address}
onChange={(e) => updateFormField('address', e.target.value)}
errorMsg={getError('address')}
/>
</div>
<InputText
@ -152,14 +205,17 @@ export default function InscriptionFormShared({
label="Médecin Traitant"
value={formData.attending_physician}
onChange={(e) => updateFormField('attending_physician', e.target.value)}
errorMsg={getError('attending_physician')}
/>
<SelectChoice
name="level"
label="Niveau"
placeHolder="Sélectionner un niveau"
selected={formData.level}
callback={(e) => updateFormField('level', e.target.value)}
choices={levels}
required
errorMsg={getError('level')}
/>
</div>
</div>
@ -184,6 +240,7 @@ export default function InscriptionFormShared({
newArray.splice(index, 1);
setGuardians(newArray);
}}
errors={errors?.student?.guardians || []}
/>
</div>
@ -191,14 +248,13 @@ export default function InscriptionFormShared({
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<h2 className="text-xl font-bold mb-4 text-gray-800">Fichiers à remplir</h2>
<Table
data={uploadedFiles}
data={fileTemplates}
columns={columns}
itemsPerPage={5}
currentPage={1}
totalPages={1}
onPageChange={() => {}}
/>
<FileUpload onFileUpload={handleFileUpload} />
</div>
{/* Boutons de contrôle */}
@ -207,6 +263,44 @@ export default function InscriptionFormShared({
<Button type="submit" text="Valider" primary />
</div>
</form>
<Modal
isOpen={showUploadModal}
setIsOpen={setShowUploadModal}
title="Téléverser un fichier"
ContentComponent={() => (
<>
<DraggableFileUpload
className="w-full"
fileName={fileName}
onFileSelect={(selectedFile) => {
setFile(selectedFile);
setFileName(selectedFile.name);
}}
>
<input type="hidden" name="template" value={currentTemplateId} />
<input type="hidden" name="register_form" value={formData.id} />
</DraggableFileUpload>
<div className="mt-4 flex justify-center space-x-4">
<Button
text="Annuler"
onClick={() => {
setShowUploadModal(false);
setCurrentTemplateId(null);
}}
/>
<Button
text="Valider"
onClick={() => {
setShowUploadModal(false);
handleFileUpload(file, fileName);
setCurrentTemplateId(null);
}}
primary={true}
/>
</div>
</>
)}
/>
</div>
);
}