Files
n3wt-school/Front-End/src/components/Calendar/MonthView.js
Luc SORIGNET 4248a589c5 feat(frontend): refonte mobile planning et ameliorations suivi pedagogique [#NEWTS-4]
Fonction PWA et ajout du responsive design

Planning mobile :
- Nouvelle vue DayView avec bandeau semaine scrollable, date picker natif et navigation integree
- ScheduleNavigation converti en drawer overlay sur mobile, sidebar fixe sur desktop
- Suppression double barre navigation mobile, controles deplaces dans DayView
- Date picker natif via label+input sur mobile

Suivi pedagogique :
- Refactorisation page grades avec composant Table partage
- Colonnes stats par periode, absences, actions (Fiche + Evaluer)
- Lien cliquable sur la classe vers SchoolClassManagement

feat(backend): ajout associated_class_id dans StudentByRFCreationSerializer [#NEWTS-4]

UI global :
- Remplacement fleches texte par icones Lucide ChevronDown/ChevronRight
- Pagination conditionnelle sur tous les tableaux plats
- Layout responsive mobile : cartes separees fond transparent
- Table.js : pagination optionnelle, wrapper md uniquement
2026-03-16 12:27:06 +01:00

113 lines
3.5 KiB
JavaScript

import React from 'react';
import { usePlanning } from '@/context/PlanningContext';
import {
format,
startOfWeek,
endOfWeek,
eachDayOfInterval,
startOfMonth,
endOfMonth,
isSameMonth,
isToday,
} from 'date-fns';
import { fr } from 'date-fns/locale';
import { getEventsForDate } from '@/utils/events';
const MonthView = ({ onDateClick, onEventClick }) => {
const { currentDate, setViewType, setCurrentDate, events } = usePlanning();
// Obtenir tous les jours du mois actuel
const monthStart = startOfMonth(currentDate);
const monthEnd = endOfMonth(currentDate);
const startDate = startOfWeek(monthStart, { locale: fr, weekStartsOn: 1 });
const endDate = endOfWeek(monthEnd, { locale: fr, weekStartsOn: 1 });
const days = eachDayOfInterval({ start: startDate, end: endDate });
const handleDayClick = (day) => {
setCurrentDate(day); // Met à jour la date courante
setViewType('week'); // Change la vue en mode semaine
};
const renderDay = (day) => {
const isCurrentMonth = isSameMonth(day, currentDate);
const dayEvents = getEventsForDate(day, events);
const isCurrentDay = isToday(day);
return (
<div
key={day.toString()}
className={`p-2 overflow-y-auto relative flex flex-col
${!isCurrentMonth ? 'bg-gray-100 text-gray-400' : ''}
${isCurrentDay ? 'bg-emerald-50' : ''}
hover:bg-gray-100 cursor-pointer border-b border-r`}
onClick={() => handleDayClick(day)}
>
<div className="flex justify-between items-center mb-1">
<span
className={`text-sm font-medium rounded-full w-7 h-7 flex items-center justify-center
${isCurrentDay ? 'bg-emerald-500 text-white' : ''}
${!isCurrentMonth ? 'text-gray-400' : ''}`}
>
{format(day, 'd')}
</span>
</div>
<div className="space-y-1 flex-1">
{dayEvents.map((event, index) => (
<div
key={event.id}
className="text-xs p-1 rounded truncate cursor-pointer"
style={{
backgroundColor: `${event.color}15`,
color: event.color,
borderLeft: `2px solid ${event.color}`,
}}
onClick={(e) => {
e.stopPropagation();
onEventClick(event);
}}
>
{event.title}
</div>
))}
</div>
</div>
);
};
const dayLabels = [
{ short: 'L', long: 'Lun' },
{ short: 'M', long: 'Mar' },
{ short: 'M', long: 'Mer' },
{ short: 'J', long: 'Jeu' },
{ short: 'V', long: 'Ven' },
{ short: 'S', long: 'Sam' },
{ short: 'D', long: 'Dim' },
];
return (
<div className="h-full flex flex-col border border-gray-200 rounded-lg bg-white overflow-x-auto">
<div className="min-w-[280px]">
{/* En-tête des jours de la semaine */}
<div className="grid grid-cols-7 border-b">
{dayLabels.map((day, i) => (
<div
key={i}
className="p-1 sm:p-2 text-center text-xs sm:text-sm font-medium text-gray-500"
>
<span className="sm:hidden">{day.short}</span>
<span className="hidden sm:inline">{day.long}</span>
</div>
))}
</div>
{/* Grille des jours */}
<div className="grid grid-cols-7 grid-rows-[repeat(6,1fr)]">
{days.map((day) => renderDay(day))}
</div>
</div>
</div>
);
};
export default MonthView;