mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
fix: application des recommandations linter es pour générer un build de prod
This commit is contained in:
@ -5,12 +5,31 @@ const withNextIntl = createNextIntlPlugin();
|
|||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
output: 'standalone',
|
||||||
|
webpack: (config, { isServer }) => {
|
||||||
|
// Configuration pour améliorer le hot reload dans Docker
|
||||||
|
config.watchOptions = {
|
||||||
|
poll: 1000,
|
||||||
|
aggregateTimeout: 300,
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
instrumentationHook: true,
|
instrumentationHook: true,
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
NEXT_PUBLIC_APP_VERSION: pkg.version,
|
NEXT_PUBLIC_APP_VERSION: pkg.version,
|
||||||
},
|
},
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: 'https',
|
||||||
|
hostname: 'i.pravatar.cc',
|
||||||
|
port: '',
|
||||||
|
pathname: '/**',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withNextIntl(nextConfig);
|
export default withNextIntl(nextConfig);
|
||||||
@ -26,6 +26,7 @@ import {
|
|||||||
|
|
||||||
import { disconnect } from '@/app/lib/authAction';
|
import { disconnect } from '@/app/lib/authAction';
|
||||||
import { fetchEstablishment } from '@/app/lib/schoolAction';
|
import { fetchEstablishment } from '@/app/lib/schoolAction';
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
export default function Layout({
|
export default function Layout({
|
||||||
children,
|
children,
|
||||||
@ -75,13 +76,13 @@ export default function Layout({
|
|||||||
<>
|
<>
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<div className="flex min-h-screen bg-gray-50">
|
<div className="flex min-h-screen bg-gray-50">
|
||||||
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
||||||
<div className="flex flex-col flex-1">
|
<div className="flex flex-col flex-1">
|
||||||
{/* Header - h-16 = 64px */}
|
{/* Header - h-16 = 64px */}
|
||||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
buttonContent={<Image src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" width={150} height={150} />}
|
||||||
items={dropdownItems}
|
items={dropdownItems}
|
||||||
buttonClassName=""
|
buttonClassName=""
|
||||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||||
|
|||||||
@ -154,8 +154,8 @@ export default function DashboardPage() {
|
|||||||
|
|
||||||
<div className="flex flex-wrap">
|
<div className="flex flex-wrap">
|
||||||
{classes.map((classe) => (
|
{classes.map((classe) => (
|
||||||
<div className="lg:col-span-2 bg-white p-6 rounded-lg shadow-sm border border-gray-100 mr-4">
|
<div key={classe.id} className="lg:col-span-2 bg-white p-6 rounded-lg shadow-sm border border-gray-100 mr-4">
|
||||||
<ClasseDetails key={classe.id} classe={classe} />
|
<ClasseDetails classe={classe} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -239,7 +239,7 @@ const registerFormArchivedDataHandler = (data) => {
|
|||||||
|
|
||||||
|
|
||||||
fetchDataAndSetState();
|
fetchDataAndSetState();
|
||||||
}, [reloadFetch, currentPage]);
|
}, [reloadFetch, itemsPerPage, currentPage,activeTab, searchTerm]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchDataAndSetState = () => {
|
const fetchDataAndSetState = () => {
|
||||||
@ -271,7 +271,7 @@ const timeoutId = setTimeout(() => {
|
|||||||
fetchDataAndSetState();
|
fetchDataAndSetState();
|
||||||
}, 500); // Debounce la recherche
|
}, 500); // Debounce la recherche
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
}, [searchTerm]);
|
}, [currentPage,itemsPerPage,searchTerm]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UseEffect to update page count of tab
|
* UseEffect to update page count of tab
|
||||||
@ -284,7 +284,7 @@ useEffect(()=>{
|
|||||||
} else if (activeTab === 'archived') {
|
} else if (activeTab === 'archived') {
|
||||||
setTotalPages(Math.ceil(totalArchives / itemsPerPage));
|
setTotalPages(Math.ceil(totalArchives / itemsPerPage));
|
||||||
}
|
}
|
||||||
},[currentPage]);
|
},[currentPage,activeTab,itemsPerPage,totalPending,totalSubscribed,totalArchives]);
|
||||||
/**
|
/**
|
||||||
* Archives a registration form after user confirmation.
|
* Archives a registration form after user confirmation.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export default function Layout({
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, [userId]);
|
}, [setUserId, userId]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
import { SendHorizontal } from 'lucide-react';
|
import { SendHorizontal } from 'lucide-react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
const contacts = [
|
const contacts = [
|
||||||
{ id: 1, name: 'Facturation', profilePic: 'https://i.pravatar.cc/32' },
|
{ id: 1, name: 'Facturation', profilePic: 'https://i.pravatar.cc/32' },
|
||||||
@ -61,7 +62,7 @@ export default function MessageriePage() {
|
|||||||
className={`p-2 cursor-pointer ${selectedContact?.id === contact.id ? 'bg-gray-200' : ''}`}
|
className={`p-2 cursor-pointer ${selectedContact?.id === contact.id ? 'bg-gray-200' : ''}`}
|
||||||
onClick={() => setSelectedContact(contact)}
|
onClick={() => setSelectedContact(contact)}
|
||||||
>
|
>
|
||||||
<img src={contact.profilePic} alt={`${contact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" />
|
<Image src={contact.profilePic} alt={`${contact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150} />
|
||||||
{contact.name}
|
{contact.name}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -75,7 +76,7 @@ export default function MessageriePage() {
|
|||||||
style={{ borderRadius: message.isResponse ? '20px 20px 0 20px' : '20px 20px 20px 0', minWidth: '25%' }}
|
style={{ borderRadius: message.isResponse ? '20px 20px 0 20px' : '20px 20px 20px 0', minWidth: '25%' }}
|
||||||
>
|
>
|
||||||
<div className="flex items-center mb-1">
|
<div className="flex items-center mb-1">
|
||||||
<img src={selectedContact.profilePic} alt={`${selectedContact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" />
|
<Image src={selectedContact.profilePic} alt={`${selectedContact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150}/>
|
||||||
<span className="text-xs text-gray-600">{selectedContact.name}</span>
|
<span className="text-xs text-gray-600">{selectedContact.name}</span>
|
||||||
<span className="text-xs text-gray-400 ml-2">{new Date(message.date).toLocaleTimeString()}</span>
|
<span className="text-xs text-gray-400 ml-2">{new Date(message.date).toLocaleTimeString()}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export default function Page() {
|
|||||||
console.error('Error fetching data:', error);
|
console.error('Error fetching data:', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, [uuid]);
|
||||||
|
|
||||||
function validate(formData) {
|
function validate(formData) {
|
||||||
if (useFakeData) {
|
if (useFakeData) {
|
||||||
|
|||||||
17
Front-End/src/app/_error/page.js
Normal file
17
Front-End/src/app/_error/page.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Logo from '@/components/Logo';
|
||||||
|
|
||||||
|
export default function Error() {
|
||||||
|
return (
|
||||||
|
<div className='flex items-center justify-center min-h-screen bg-emerald-500'>
|
||||||
|
<div className='text-center p-6'>
|
||||||
|
<Logo className="w-32 h-32 mx-auto mb-4" />
|
||||||
|
<h2 className='text-2xl font-bold text-emerald-900 mb-4'>Une erreur est survenue</h2>
|
||||||
|
<p className='text-emerald-900 mb-4'>Désolé, une erreur s'est produite.</p>
|
||||||
|
<Link className="text-gray-900 hover:underline" href="/">Retour Accueil</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,15 +1,17 @@
|
|||||||
import Link from 'next/link'
|
'use client';
|
||||||
import Logo from '../components/Logo'
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Logo from '@/components/Logo';
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound() {
|
||||||
return (
|
return (
|
||||||
<div className='flex items-center justify-center min-h-screen bg-emerald-500'>
|
<div className='flex items-center justify-center min-h-screen bg-emerald-500'>
|
||||||
<div className='text-center p-6 '>
|
<div className='text-center p-6'>
|
||||||
<Logo className="w-32 h-32 mx-auto mb-4" />
|
<Logo className="w-32 h-32 mx-auto mb-4" />
|
||||||
<h2 className='text-2xl font-bold text-emerald-900 mb-4'>404 | Page non trouvée</h2>
|
<h2 className='text-2xl font-bold text-emerald-900 mb-4'>404 | Page non trouvée</h2>
|
||||||
<p className='text-emerald-900 mb-4'>La ressource que vous souhaitez consulter n'existe pas ou plus.</p>
|
<p className='text-emerald-900 mb-4'>La ressource que vous souhaitez consulter n'existe pas ou plus.</p>
|
||||||
<Link className="text-gray-900 hover:underline" href="/">Retour Accueil</Link>
|
<Link className="text-gray-900 hover:underline" href="/">Retour Accueil</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
|
|
||||||
import {getMessages} from 'next-intl/server';
|
import {getMessages} from 'next-intl/server';
|
||||||
import "@/css/tailwind.css";
|
import "@/css/tailwind.css";
|
||||||
|
|
||||||
@ -22,12 +21,13 @@ export const metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function RootLayout({ children, params: { locale } }) {
|
export default async function RootLayout({ children, params: { locale } }) {
|
||||||
const messages = await getMessages();
|
|
||||||
|
const messages = await getMessages(locale);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={locale}>
|
<html lang={locale}>
|
||||||
<body>
|
<body>
|
||||||
<NextIntlClientProvider messages={messages}>
|
<NextIntlClientProvider messages={messages} locale={locale}>
|
||||||
{children}
|
{children}
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -75,7 +75,7 @@ const Calendar = ({ onDateClick, onEventClick }) => {
|
|||||||
onClick={() => setCurrentDate(new Date())}
|
onClick={() => setCurrentDate(new Date())}
|
||||||
className="px-3 py-1.5 text-sm font-medium text-gray-700 hover:text-gray-900 bg-gray-100 hover:bg-gray-200 rounded-md transition-colors"
|
className="px-3 py-1.5 text-sm font-medium text-gray-700 hover:text-gray-900 bg-gray-100 hover:bg-gray-200 rounded-md transition-colors"
|
||||||
>
|
>
|
||||||
Aujourd'hui
|
Aujourd'hui
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => navigateDate('prev')} className="p-2 hover:bg-gray-100 rounded-full">
|
<button onClick={() => navigateDate('prev')} className="p-2 hover:bg-gray-100 rounded-full">
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
|
|||||||
@ -11,18 +11,20 @@ const DropdownMenu = ({ buttonContent, items, buttonClassName, menuClassName, dr
|
|||||||
const actualSetDropdownOpen = isControlled ? propSetDropdownOpen : setDropdownOpen;
|
const actualSetDropdownOpen = isControlled ? propSetDropdownOpen : setDropdownOpen;
|
||||||
|
|
||||||
|
|
||||||
const handleClickOutside = (event) => {
|
|
||||||
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
||||||
actualSetDropdownOpen(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (event) => {
|
||||||
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||||
|
actualSetDropdownOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('mousedown', handleClickOutside);
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [actualSetDropdownOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative" ref={menuRef}>
|
<div className="relative" ref={menuRef}>
|
||||||
<button className={buttonClassName} onClick={() => actualSetDropdownOpen(!actualDropdownOpen)}>
|
<button className={buttonClassName} onClick={() => actualSetDropdownOpen(!actualDropdownOpen)}>
|
||||||
@ -33,7 +35,7 @@ const DropdownMenu = ({ buttonContent, items, buttonClassName, menuClassName, dr
|
|||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2"
|
className="w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
item.onClick();
|
item.onClick();
|
||||||
actualSetDropdownOpen(false);
|
actualSetDropdownOpen(false);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default function EventModal({ isOpen, onClose, eventData, setEventData })
|
|||||||
color: schedules[0].color
|
color: schedules[0].color
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}, [schedules, eventData.scheduleId]);
|
}, [schedules, eventData.scheduleId,setEventData]);
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
selectedTuitionDiscounts: [],
|
selectedTuitionDiscounts: [],
|
||||||
selectedTuitionFees: [],
|
selectedTuitionFees: [],
|
||||||
selectedFileGroup: null // Ajout du groupe de fichiers sélectionné
|
selectedFileGroup: null // Ajout du groupe de fichiers sélectionné
|
||||||
});
|
}, [registrationFees, registrationDiscounts]);
|
||||||
|
|
||||||
const [step, setStep] = useState(currentStep || 1);
|
const [step, setStep] = useState(currentStep || 1);
|
||||||
const [selectedStudent, setSelectedEleve] = useState('');
|
const [selectedStudent, setSelectedEleve] = useState('');
|
||||||
@ -79,7 +79,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
);
|
);
|
||||||
setTotalRegistrationAmount(initialTotalRegistrationAmount);
|
setTotalRegistrationAmount(initialTotalRegistrationAmount);
|
||||||
|
|
||||||
}, [registrationDiscounts, registrationFees]);
|
}, [registrationDiscounts, registrationFees,calculateFinalRegistrationAmount]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setStep(currentStep || 1);
|
setStep(currentStep || 1);
|
||||||
@ -176,7 +176,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateFinalRegistrationAmount = (selectedRegistrationFees, selectedRegistrationDiscounts) => {
|
const calculateFinalRegistrationAmount = useCallback((selectedRegistrationFees, selectedRegistrationDiscounts) => {
|
||||||
const totalFees = selectedRegistrationFees.reduce((sum, feeId) => {
|
const totalFees = selectedRegistrationFees.reduce((sum, feeId) => {
|
||||||
const fee = registrationFees.find(f => f.id === feeId);
|
const fee = registrationFees.find(f => f.id === feeId);
|
||||||
if (fee && !isNaN(parseFloat(fee.base_amount))) {
|
if (fee && !isNaN(parseFloat(fee.base_amount))) {
|
||||||
@ -200,7 +200,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
const finalAmount = totalFees - totalDiscounts;
|
const finalAmount = totalFees - totalDiscounts;
|
||||||
|
|
||||||
return finalAmount.toFixed(2);
|
return finalAmount.toFixed(2);
|
||||||
};
|
},[registrationDiscounts, registrationFees]);
|
||||||
|
|
||||||
const calculateFinalTuitionAmount = (selectedTuitionFees, selectedTuitionDiscounts) => {
|
const calculateFinalTuitionAmount = (selectedTuitionFees, selectedTuitionDiscounts) => {
|
||||||
const totalFees = selectedTuitionFees.reduce((sum, feeId) => {
|
const totalFees = selectedTuitionFees.reduce((sum, feeId) => {
|
||||||
@ -385,7 +385,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
) : (
|
) : (
|
||||||
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
|
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
|
||||||
<strong className="font-bold">Information</strong>
|
<strong className="font-bold">Information</strong>
|
||||||
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais d'inscription.</span>
|
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais d'inscription.</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -408,7 +408,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
) : (
|
) : (
|
||||||
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||||
<strong className="font-bold">Attention!</strong>
|
<strong className="font-bold">Attention!</strong>
|
||||||
<span className="block sm:inline"> Aucun frais d'inscription n'a été créé.</span>
|
<span className="block sm:inline"> Aucun frais d'inscription n'a été créé.</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -440,7 +440,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
) : (
|
) : (
|
||||||
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
|
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
|
||||||
<strong className="font-bold">Information</strong>
|
<strong className="font-bold">Information</strong>
|
||||||
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais de scolarité.</span>
|
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais de scolarité.</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -463,7 +463,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
) : (
|
) : (
|
||||||
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||||
<strong className="font-bold">Attention!</strong>
|
<strong className="font-bold">Attention!</strong>
|
||||||
<span className="block sm:inline"> Aucun frais de scolarité n'a été créé.</span>
|
<span className="block sm:inline"> Aucun frais de scolarité n'a été créé.</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -501,7 +501,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
) : (
|
) : (
|
||||||
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
|
||||||
<strong className="font-bold">Attention!</strong>
|
<strong className="font-bold">Attention!</strong>
|
||||||
<span className="block sm:inline"> Aucun groupe de documents n'a été créé.</span>
|
<span className="block sm:inline"> Aucun groupe de documents n'a été créé.</span>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -249,7 +249,7 @@ export default function InscriptionFormShared({
|
|||||||
<DjangoCSRFToken csrfToken={csrfToken}/>
|
<DjangoCSRFToken csrfToken={csrfToken}/>
|
||||||
{/* Section Élève */}
|
{/* Section Élève */}
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
<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">Informations de l'élève</h2>
|
<h2 className="text-xl font-bold mb-4 text-gray-800">Informations de l'élève</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<InputText
|
<InputText
|
||||||
name="last_name"
|
name="last_name"
|
||||||
|
|||||||
@ -49,24 +49,24 @@ const PaymentPlanSelector = ({ paymentPlans, setPaymentPlans, handleEdit, type }
|
|||||||
}, [paymentPlans]);
|
}, [paymentPlans]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateDefaultDay();
|
const updateDefaultDay = () => {
|
||||||
}, [dates, selectedFrequency]);
|
const currentDates = dates[selectedFrequency];
|
||||||
|
if (currentDates && currentDates.length > 0) {
|
||||||
const updateDefaultDay = () => {
|
const days = currentDates.map(date => new Date(date).getDate());
|
||||||
const currentDates = dates[selectedFrequency];
|
const allSameDay = days.every(day => day === days[0]);
|
||||||
if (currentDates && currentDates.length > 0) {
|
if (allSameDay) {
|
||||||
const days = currentDates.map(date => new Date(date).getDate());
|
setDefaultDay(days[0]);
|
||||||
const allSameDay = days.every(day => day === days[0]);
|
} else {
|
||||||
if (allSameDay) {
|
setDefaultDay('-');
|
||||||
setDefaultDay(days[0]);
|
setIsDefaultDayModified(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setDefaultDay('-');
|
setDefaultDay('-');
|
||||||
setIsDefaultDayModified(false);
|
|
||||||
}
|
}
|
||||||
} else {
|
};
|
||||||
setDefaultDay('-');
|
|
||||||
}
|
updateDefaultDay();
|
||||||
};
|
}, [dates, selectedFrequency]);
|
||||||
|
|
||||||
const handleActivationChange = (value) => {
|
const handleActivationChange = (value) => {
|
||||||
const selectedPlan = paymentPlans.find(plan => plan.frequency === paymentPlansOptions.find(p => p.id === value)?.frequency);
|
const selectedPlan = paymentPlans.find(plan => plan.frequency === paymentPlansOptions.find(p => p.id === value)?.frequency);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export default function RegistrationFileGroupList() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Groupes de fichiers d'inscription</h2>
|
<h2>Groupes de fichiers d'inscription</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{groups.map(group => (
|
{groups.map(group => (
|
||||||
<li key={group.id}>{group.name}</li>
|
<li key={group.id}>{group.name}</li>
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import SelectChoice from '@/components/SelectChoice';
|
|||||||
import TeacherItem from '@/components/Structure/Configuration/TeacherItem';
|
import TeacherItem from '@/components/Structure/Configuration/TeacherItem';
|
||||||
import MultiSelect from '@/components/MultiSelect';
|
import MultiSelect from '@/components/MultiSelect';
|
||||||
import LevelLabel from '@/components/CustomLabels/LevelLabel';
|
import LevelLabel from '@/components/CustomLabels/LevelLabel';
|
||||||
import { DndProvider, HTML5Backend, useDrop } from 'react-dnd';
|
import { DndProvider, useDrop } from 'react-dnd';
|
||||||
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import { ESTABLISHMENT_ID } from '@/utils/Url';
|
import { ESTABLISHMENT_ID } from '@/utils/Url';
|
||||||
|
|
||||||
const ItemTypes = {
|
const ItemTypes = {
|
||||||
@ -17,16 +18,13 @@ const ItemTypes = {
|
|||||||
const TeachersDropZone = ({ classe, handleTeachersChange, teachers, isEditing }) => {
|
const TeachersDropZone = ({ classe, handleTeachersChange, teachers, isEditing }) => {
|
||||||
const [localTeachers, setLocalTeachers] = useState(classe.teachers_details || []);
|
const [localTeachers, setLocalTeachers] = useState(classe.teachers_details || []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
}, [teachers]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLocalTeachers(classe.teachers_details || []);
|
setLocalTeachers(classe.teachers_details || []);
|
||||||
}, [classe.teachers_details]);
|
}, [classe.teachers_details]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleTeachersChange(localTeachers.map(teacher => teacher.id));
|
handleTeachersChange(localTeachers.map(teacher => teacher.id));
|
||||||
}, [localTeachers]);
|
}, [handleTeachersChange, localTeachers]);
|
||||||
|
|
||||||
const [{ isOver, canDrop }, drop] = useDrop({
|
const [{ isOver, canDrop }, drop] = useDrop({
|
||||||
accept: ItemTypes.TEACHER,
|
accept: ItemTypes.TEACHER,
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const SpecialitiesDropZone = ({ teacher, handleSpecialitiesChange, specialities,
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleSpecialitiesChange(localSpecialities.map(speciality => speciality.id));
|
handleSpecialitiesChange(localSpecialities.map(speciality => speciality.id));
|
||||||
}, [localSpecialities]);
|
}, [localSpecialities,handleSpecialitiesChange]);
|
||||||
|
|
||||||
const [{ isOver, canDrop }, drop] = useDrop({
|
const [{ isOver, canDrop }, drop] = useDrop({
|
||||||
accept: ItemTypes.SPECIALITY,
|
accept: ItemTypes.SPECIALITY,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const PlanningClassView = ({ schedule, onDrop, selectedLevel, handleUpdatePlanni
|
|||||||
if (schedule?.emploiDuTemps) {
|
if (schedule?.emploiDuTemps) {
|
||||||
setCurrentPeriod(determineInitialPeriod(schedule.emploiDuTemps));
|
setCurrentPeriod(determineInitialPeriod(schedule.emploiDuTemps));
|
||||||
}
|
}
|
||||||
}, [schedule]);
|
}, [schedule, determineInitialPeriod]);
|
||||||
|
|
||||||
if (!schedule || !schedule.emploiDuTemps) {
|
if (!schedule || !schedule.emploiDuTemps) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
|
|||||||
const [schedule, setSchedule] = useState(null);
|
const [schedule, setSchedule] = useState(null);
|
||||||
|
|
||||||
const { getNiveauxTabs } = useClasses();
|
const { getNiveauxTabs } = useClasses();
|
||||||
const niveauxLabels = Array.isArray(selectedClass?.levels) ? getNiveauxTabs(selectedClass.levels) : [];
|
const niveauxLabels = useMemo(() => Array.isArray(selectedClass?.levels) ? getNiveauxTabs(selectedClass.levels) : [], [selectedClass, getNiveauxTabs]);
|
||||||
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const handleOpenModal = () => setIsModalOpen(true);
|
const handleOpenModal = () => setIsModalOpen(true);
|
||||||
@ -38,7 +38,7 @@ const ScheduleManagement = ({ handleUpdatePlanning, classes }) => {
|
|||||||
const currentPlanning = selectedClass.plannings_read?.find(planning => planning.niveau === niveau);
|
const currentPlanning = selectedClass.plannings_read?.find(planning => planning.niveau === niveau);
|
||||||
setSchedule(currentPlanning ? currentPlanning.planning : {});
|
setSchedule(currentPlanning ? currentPlanning.planning : {});
|
||||||
}
|
}
|
||||||
}, [selectedClass, niveauxLabels]);
|
}, [selectedClass, niveauxLabels, selectedLevel]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedClass && selectedLevel) {
|
if (selectedClass && selectedLevel) {
|
||||||
|
|||||||
@ -47,7 +47,7 @@ const FeesManagement = ({ registrationDiscounts,
|
|||||||
return (
|
return (
|
||||||
<div className="w-full mx-auto p-2 mt-6 space-y-6">
|
<div className="w-full mx-auto p-2 mt-6 space-y-6">
|
||||||
<div className="bg-white p-2 rounded-lg shadow-md">
|
<div className="bg-white p-2 rounded-lg shadow-md">
|
||||||
<h2 className="text-2xl font-semibold mb-4">Frais d'inscription</h2>
|
<h2 className="text-2xl font-semibold mb-4">Frais d'inscription</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<div className="col-span-1 p-6 rounded-lg shadow-inner mt-4">
|
<div className="col-span-1 p-6 rounded-lg shadow-inner mt-4">
|
||||||
<FeesSection
|
<FeesSection
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const useCsrfToken = () => {
|
|||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error fetching CSRF token:', error);
|
console.error('Error fetching CSRF token:', error);
|
||||||
});
|
});
|
||||||
}, []);
|
}, [token]);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user