fix: Ajout d'un champ is_required pour les documents parents facultatifs

This commit is contained in:
N3WT DE COMPET
2025-05-09 09:38:47 +02:00
parent 6d805940fe
commit 5866427544
9 changed files with 61 additions and 21 deletions

View File

@ -291,6 +291,7 @@ class RegistrationParentFileMaster(models.Model):
groups = models.ManyToManyField(RegistrationFileGroup, related_name='parent_file_masters', blank=True) groups = models.ManyToManyField(RegistrationFileGroup, related_name='parent_file_masters', blank=True)
name = models.CharField(max_length=255, default="") name = models.CharField(max_length=255, default="")
description = models.CharField(blank=True, null=True) description = models.CharField(blank=True, null=True)
is_required = models.BooleanField(default=False)
############################################################ ############################################################
####################### CLONE FILES ######################## ####################### CLONE FILES ########################

View File

@ -46,6 +46,8 @@ class RegistrationParentFileTemplateSerializer(serializers.ModelSerializer):
file_url = serializers.SerializerMethodField() file_url = serializers.SerializerMethodField()
master_name = serializers.CharField(source='master.name', read_only=True) master_name = serializers.CharField(source='master.name', read_only=True)
master_description = serializers.CharField(source='master.description', read_only=True) master_description = serializers.CharField(source='master.description', read_only=True)
is_required = serializers.BooleanField(source='master.is_required', read_only=True)
class Meta: class Meta:
model = RegistrationParentFileTemplate model = RegistrationParentFileTemplate
fields = '__all__' fields = '__all__'

View File

@ -17,14 +17,15 @@ export default function EmailSender({ csrfToken }) {
message, message,
}; };
sendMessage(data); sendMessage(data);
}; };
return ( return (
<div className="p-4 bg-white rounded shadow"> <div className="p-4 bg-white rounded shadow">
<h2 className="text-xl font-bold mb-4">Envoyer un Email</h2> <h2 className="text-xl font-bold mb-4">Envoyer un Email</h2>
<div className="mb-4"> <div className="mb-4">
<label className="block font-medium">Destinataires (séparés par des virgules)</label> <label className="block font-medium">
Destinataires (séparés par des virgules)
</label>
<input <input
type="text" type="text"
value={recipients} value={recipients}

View File

@ -8,6 +8,7 @@ const CheckBox = ({
itemLabelFunc = () => null, itemLabelFunc = () => null,
horizontal, horizontal,
}) => { }) => {
console.log(formData);
const isChecked = formData[fieldName].includes(parseInt(item.id)); const isChecked = formData[fieldName].includes(parseInt(item.id));
return ( return (
<div <div

View File

@ -73,7 +73,7 @@ export default function InscriptionFormShared({
const [uploadedFiles, setUploadedFiles] = useState([]); const [uploadedFiles, setUploadedFiles] = useState([]);
const [schoolFileTemplates, setSchoolFileTemplates] = useState([]); const [schoolFileTemplates, setSchoolFileTemplates] = useState([]);
const [parentFileTemplates, setParentFileTemplates] = useState([]); const [parentFileTemplates, setParentFileTemplates] = useState([]);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(6);
const [isPage1Valid, setIsPage1Valid] = useState(false); const [isPage1Valid, setIsPage1Valid] = useState(false);
const [isPage2Valid, setIsPage2Valid] = useState(false); const [isPage2Valid, setIsPage2Valid] = useState(false);
@ -131,13 +131,14 @@ export default function InscriptionFormShared({
}, [schoolFileTemplates]); }, [schoolFileTemplates]);
useEffect(() => { useEffect(() => {
// Vérifier si tous les parentFileTemplates ont leur champ "file" différent de null // Vérifier si tous les documents avec is_required = true ont leur champ "file" différent de null
const allUploaded = parentFileTemplates.every( const allRequiredUploaded = parentFileTemplates
(template) => template.file !== null .filter((template) => template.is_required) // Ne garder que les documents requis
); .every((template) => template.file !== null); // Vérifier que chaque fichier requis est uploadé
// Mettre à jour isPage6Valid en fonction de cette condition // Mettre à jour isPage6Valid en fonction de cette condition
setIsPage6Valid(allUploaded); setIsPage6Valid(allRequiredUploaded);
console.log(allRequiredUploaded);
}, [parentFileTemplates]); }, [parentFileTemplates]);
const handleTemplateSigned = (index) => { const handleTemplateSigned = (index) => {
@ -659,8 +660,7 @@ export default function InscriptionFormShared({
(currentPage === 2 && !isPage2Valid) || (currentPage === 2 && !isPage2Valid) ||
(currentPage === 3 && !isPage3Valid) || (currentPage === 3 && !isPage3Valid) ||
(currentPage === 4 && !isPage4Valid) || (currentPage === 4 && !isPage4Valid) ||
(currentPage === 5 && !isPage5Valid) || (currentPage === 5 && !isPage5Valid)
(currentPage === 6 && !isPage6Valid)
? 'bg-gray-300 text-gray-700 cursor-not-allowed' ? 'bg-gray-300 text-gray-700 cursor-not-allowed'
: 'bg-emerald-500 text-white hover:bg-emerald-600' : 'bg-emerald-500 text-white hover:bg-emerald-600'
}`} }`}
@ -669,8 +669,7 @@ export default function InscriptionFormShared({
(currentPage === 2 && !isPage2Valid) || (currentPage === 2 && !isPage2Valid) ||
(currentPage === 3 && !isPage3Valid) || (currentPage === 3 && !isPage3Valid) ||
(currentPage === 4 && !isPage4Valid) || (currentPage === 4 && !isPage4Valid) ||
(currentPage === 5 && !isPage5Valid) || (currentPage === 5 && !isPage5Valid)
(currentPage === 6 && !isPage6Valid)
} }
primary primary
name="Next" name="Next"
@ -682,7 +681,12 @@ export default function InscriptionFormShared({
e.preventDefault(); e.preventDefault();
handleSubmit(e); handleSubmit(e);
}} }}
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none" className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
currentPage === 6 && !isPage6Valid
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
: 'bg-emerald-500 text-white hover:bg-emerald-600'
}`}
disabled={currentPage === 6 && !isPage6Valid}
primary primary
/> />
)} )}

View File

@ -8,6 +8,7 @@ import logger from '@/utils/logger';
import { createRegistrationParentFileTemplate } from '@/app/actions/registerFileGroupAction'; import { createRegistrationParentFileTemplate } from '@/app/actions/registerFileGroupAction';
import { useCsrfToken } from '@/context/CsrfContext'; import { useCsrfToken } from '@/context/CsrfContext';
import SectionHeader from '@/components/SectionHeader'; import SectionHeader from '@/components/SectionHeader';
import ToggleSwitch from '@/components/ToggleSwitch';
export default function ParentFilesSection({ export default function ParentFilesSection({
parentFiles, parentFiles,
@ -32,7 +33,7 @@ export default function ParentFilesSection({
const handleAddEmptyRequiredDocument = () => { const handleAddEmptyRequiredDocument = () => {
setEditingDocumentId('new'); setEditingDocumentId('new');
setFormData({ name: '', description: '', groups: [] }); setFormData({ name: '', description: '', groups: [], is_required: false }); // Add is_required
setSelectedGroups([]); // Réinitialiser les groupes sélectionnés setSelectedGroups([]); // Réinitialiser les groupes sélectionnés
}; };
@ -58,7 +59,6 @@ export default function ParentFilesSection({
"Attention !\nVeuillez sélectionner au moins un dossier d'inscription pour valider l'opération" "Attention !\nVeuillez sélectionner au moins un dossier d'inscription pour valider l'opération"
); );
setPopupVisible(true); setPopupVisible(true);
setPopupVisible(true);
return; return;
} }
@ -73,13 +73,12 @@ export default function ParentFilesSection({
setFormData(null); setFormData(null);
setSelectedGroups([]); setSelectedGroups([]);
guardianDetails.forEach((guardian, index) => { guardianDetails.forEach((guardian) => {
// Création des templates // Création des templates
const data = { const data = {
master: createdDocument?.id, master: createdDocument?.id,
registration_form: guardian.registration_form, registration_form: guardian.registration_form,
}; };
console.log(guardian);
createRegistrationParentFileTemplate(data, csrfToken) createRegistrationParentFileTemplate(data, csrfToken)
.then((response) => { .then((response) => {
logger.debug('Template enregistré avec succès:', response); logger.debug('Template enregistré avec succès:', response);
@ -178,6 +177,22 @@ export default function ParentFilesSection({
errorMsg={null} errorMsg={null}
/> />
); );
case 'Obligatoire':
return (
<div className="flex justify-center items-center">
<ToggleSwitch
name="is_required"
checked={formData.is_required} // Utilise la valeur booléenne de is_required
onChange={(e) => {
const { checked } = e.target; // Récupère l'état du toggle
setFormData((prevData) => ({
...prevData,
is_required: checked, // Met à jour directement le champ is_required
}));
}}
/>
</div>
);
case 'Actions': case 'Actions':
return ( return (
<div className="flex justify-center space-x-2"> <div className="flex justify-center space-x-2">
@ -218,6 +233,18 @@ export default function ParentFilesSection({
.join(', ')} .join(', ')}
</span> </span>
); );
case 'Obligatoire':
return (
<span
className={`px-3 py-1 rounded-full text-sm font-semibold ${
document.is_required
? 'bg-green-100 text-green-600'
: 'bg-gray-100 text-gray-600'
}`}
>
{document.is_required ? 'Oui' : 'Non'}
</span>
);
case 'Actions': case 'Actions':
return ( return (
<div className="flex justify-center space-x-2"> <div className="flex justify-center space-x-2">
@ -283,6 +310,10 @@ export default function ParentFilesSection({
transform: (row) => transform: (row) =>
renderRequiredDocumentCell(row, "Dossiers d'inscription"), renderRequiredDocumentCell(row, "Dossiers d'inscription"),
}, },
{
name: 'Obligatoire',
transform: (row) => renderRequiredDocumentCell(row, 'Obligatoire'),
},
{ {
name: 'Actions', name: 'Actions',
transform: (row) => renderRequiredDocumentCell(row, 'Actions'), transform: (row) => renderRequiredDocumentCell(row, 'Actions'),