mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-04 04:01:27 +00:00
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
This commit is contained in:
@ -13,7 +13,7 @@ import {
|
||||
BASE_URL,
|
||||
} from '@/utils/Url';
|
||||
|
||||
const ProfileSelector = ({ onRoleChange, className = '' }) => {
|
||||
const ProfileSelector = ({ onRoleChange, className = '', compact = false }) => {
|
||||
const {
|
||||
establishments,
|
||||
selectedRoleId,
|
||||
@ -103,50 +103,72 @@ const ProfileSelector = ({ onRoleChange, className = '' }) => {
|
||||
// Suppression du tronquage JS, on utilise uniquement CSS
|
||||
const isSingleRole = establishments && establishments.length === 1;
|
||||
|
||||
const buttonContent = compact ? (
|
||||
/* Mode compact : avatar seul pour la topbar mobile */
|
||||
<div className="flex items-center gap-1 cursor-pointer px-2 py-1 rounded-md hover:bg-gray-100">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={selectedEstablishmentLogo ? `${BASE_URL}${selectedEstablishmentLogo}` : getGravatarUrl(user?.email)}
|
||||
alt="Profile"
|
||||
className="w-8 h-8 rounded-full object-cover shadow-md"
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<div
|
||||
className={`absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-white ${getStatusColor()}`}
|
||||
title={getStatusTitle()}
|
||||
/>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={`w-4 h-4 text-gray-500 transition-transform duration-200 ${dropdownOpen ? 'rotate-180' : 'rotate-0'}`}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
/* Mode normal : avatar + infos texte */
|
||||
<div className="flex items-center gap-2 cursor-pointer px-4 bg-white h-24">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={selectedEstablishmentLogo ? `${BASE_URL}${selectedEstablishmentLogo}` : getGravatarUrl(user?.email)}
|
||||
alt="Profile"
|
||||
className="w-16 h-16 rounded-full object-cover shadow-md"
|
||||
width={64}
|
||||
height={64}
|
||||
/>
|
||||
<div
|
||||
className={`absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full border-2 border-white ${getStatusColor()}`}
|
||||
title={getStatusTitle()}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div
|
||||
className="font-semibold text-base text-gray-900 text-left truncate max-w-full"
|
||||
title={user?.email}
|
||||
>
|
||||
{user?.email}
|
||||
</div>
|
||||
<div
|
||||
className="font-semibold text-base text-emerald-700 text-left truncate max-w-full"
|
||||
title={selectedEstablishment?.name || ''}
|
||||
>
|
||||
{selectedEstablishment?.name || ''}
|
||||
</div>
|
||||
<div
|
||||
className="italic text-sm text-emerald-600 text-left truncate max-w-full"
|
||||
title={getRightStr(selectedEstablishment?.role_type) || ''}
|
||||
>
|
||||
{getRightStr(selectedEstablishment?.role_type) || ''}
|
||||
</div>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={`w-5 h-5 transition-transform duration-200 ${dropdownOpen ? 'rotate-180' : 'rotate-0'}`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={`relative ${className}`}>
|
||||
<DropdownMenu
|
||||
buttonContent={
|
||||
<div className="h-16 flex items-center gap-2 cursor-pointer px-4 bg-white h-24">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={selectedEstablishmentLogo ? `${BASE_URL}${selectedEstablishmentLogo}` : getGravatarUrl(user?.email)}
|
||||
alt="Profile"
|
||||
className="w-16 h-16 rounded-full object-cover shadow-md"
|
||||
width={64}
|
||||
height={64}
|
||||
/>
|
||||
{/* Bulle de statut de connexion au chat */}
|
||||
<div
|
||||
className={`absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full border-2 border-white ${getStatusColor()}`}
|
||||
title={getStatusTitle()}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div
|
||||
className="font-semibold text-base text-gray-900 text-left truncate max-w-full"
|
||||
title={user?.email}
|
||||
>
|
||||
{user?.email}
|
||||
</div>
|
||||
<div
|
||||
className="font-semibold text-base text-emerald-700 text-left truncate max-w-full"
|
||||
title={selectedEstablishment?.name || ''}
|
||||
>
|
||||
{selectedEstablishment?.name || ''}
|
||||
</div>
|
||||
<div
|
||||
className="italic text-sm text-emerald-600 text-left truncate max-w-full"
|
||||
title={getRightStr(selectedEstablishment?.role_type) || ''}
|
||||
>
|
||||
{getRightStr(selectedEstablishment?.role_type) || ''}
|
||||
</div>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={`w-5 h-5 transition-transform duration-200 ${dropdownOpen ? 'rotate-180' : 'rotate-0'}`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
buttonContent={buttonContent}
|
||||
items={
|
||||
isSingleRole
|
||||
? [
|
||||
@ -190,7 +212,10 @@ const ProfileSelector = ({ onRoleChange, className = '' }) => {
|
||||
]
|
||||
}
|
||||
buttonClassName="w-full"
|
||||
menuClassName="absolute mt-2 w-full bg-white border border-gray-200 rounded shadow-lg z-10"
|
||||
menuClassName={compact
|
||||
? 'absolute right-0 mt-2 min-w-[200px] bg-white border border-gray-200 rounded shadow-lg z-50'
|
||||
: 'absolute mt-2 w-full bg-white border border-gray-200 rounded shadow-lg z-10'
|
||||
}
|
||||
dropdownOpen={dropdownOpen}
|
||||
setDropdownOpen={setDropdownOpen}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user