import Link from 'next/link'; import { Suspense } from 'react'; import { AddEmployeeDialog } from '@/app/(app)/equipe/AddEmployeeDialog'; import { DirectoryFilters } from '@/app/(app)/equipe/DirectoryFilters'; import { RegisterDialog } from '@/app/(app)/equipe/RegisterDialog'; import { listRegisterLocations } from '@/server/employees/rup'; import { PageBody, PageHeader } from '@/components/shell/PageHeader'; import { Badge, type Tone } from '@/components/ui/Badge'; import { EmptyState } from '@/components/ui/Card'; import { listContractLocations, listEmployees, } from '@/server/employees/queries'; export const metadata = { title: 'Équipe · PlanFlow' }; export const dynamic = 'force-dynamic'; const INVITATION_TONES: Record = { ACCEPTED: { label: 'Acceptée', tone: 'ok' }, PENDING: { label: 'En attente', tone: 'info' }, EXPIRED: { label: 'Expirée', tone: 'warn' }, REVOKED: { label: 'Révoquée', tone: 'neutral' }, }; const one = (value: string | string[] | undefined): string | undefined => Array.isArray(value) ? value[0] : value; export default async function EquipePage({ searchParams, }: { searchParams: Promise>; }) { const params = await searchParams; const presence = one(params.presence); const directory = await listEmployees({ ...(one(params.q) ? { q: one(params.q) as string } : {}), ...(one(params.etablissement) ? { locationId: one(params.etablissement) as string } : {}), ...(one(params.role) ? { roleId: one(params.role) as string } : {}), ...(one(params.contrat) ? { contractType: one(params.contrat) as string } : {}), ...(presence === 'archived' || presence === 'all' ? { presence } : { presence: 'active' as const }), ...(one(params.tri) === 'number' ? { sort: 'number' as const } : {}), }); // Sans la capacité d'ouvrir un contrat, la liste revient vide et le // formulaire s'en tient à l'identité. const hiringLocations = await listContractLocations().catch(() => []); // Sans `members.register.export`, le bouton du registre ne paraît pas. const registerLocations = await listRegisterLocations().catch(() => []); const filtered = directory.rows.length !== directory.total; return ( {registerLocations.length > 0 ? ( ) : null} } /> {/* `useSearchParams` impose une frontière de suspense : sans elle, la page entière serait rendue à la demande au lieu d'être servie puis hydratée. */} }> {directory.rows.length === 0 ? ( ) : (
{directory.rows.map((employee) => { const invitation = employee.invitationState ? INVITATION_TONES[employee.invitationState] : null; return ( ); })}
Collaborateur Rôle Email Mobile Rattachement Invitation
{employee.firstName.charAt(0)} {employee.lastName.charAt(0)} {employee.firstName} {employee.lastName} {/* Le matricule ne double la colonne « Email » que lorsqu'il n'y en a pas : c'est alors la seule adresse à laquelle on désigne ce salarié. */} {employee.email ? null : ( Matricule {employee.employeeNumber} )} {employee.roleName} {employee.email ?? ( Sans compte )} {employee.phone ?? ( Non renseigné )} {employee.locationName ? ( <> {employee.locationName} {employee.teamName ? ` / ${employee.teamName}` : ''} ) : ( Sans contrat )} {invitation ? ( {invitation.label} ) : ( — )}
)}
); }