Files
planflow/src/app/(app)/reglages/emplois/page.tsx
T
MichaelandClaude Opus 5 527ea2e78a Ouvrir les référentiels au paramétrage
Emplois, étiquettes et types d'absence vivaient en base sans écran : le seed
les posait, et rien ne permettait ensuite d'en ajouter un. Ils s'éditent
désormais depuis les réglages.

Trois choix portent la conformité plutôt que le confort :

- Archiver, jamais supprimer. Un emploi figure au registre du personnel, une
  étiquette colore des semaines closes, un type d'absence justifie des
  écritures de compteur. Supprimer l'un des trois rendrait illisible un dossier
  dont la conservation court encore.
- Le code Silae manquant est signalé. Un type sans code fait échouer l'export
  de la période ; l'écran le dit avant l'échéance de paie plutôt qu'après.
- La convention se réédite, elle ne se modifie pas. Chaque enregistrement crée
  une version datée : une paie de mars doit rester reproductible après un
  changement de seuil en juin. L'origine de chaque valeur — ordre public,
  convention, accord d'entreprise — est affichée, parce que les trois ne se
  corrigent pas de la même main.

Les mutations de types d'absence passent par settings.agreement.manage : le
catalogue §5 ne déclare pas de code dédié, et ces drapeaux relèvent du
paramétrage légal. Inventer une capacité aurait créé un droit sans rien
protéger de neuf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 12:17:50 +02:00

104 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PageBody, PageHeader } from '@/components/shell/PageHeader';
import { Badge } from '@/components/ui/Badge';
import { Button } from '@/components/ui/Button';
import { Card, CardHeader, EmptyState } from '@/components/ui/Card';
import {
AddJobTitleForm,
RenameJobTitleForm,
} from '@/app/(app)/reglages/emplois/JobTitleForms';
import {
archiveJobTitleAction,
listJobTitles,
} from '@/server/settings/job-titles';
export const metadata = { title: 'Emplois · PlanFlow' };
export const dynamic = 'force-dynamic';
export default async function EmploisPage({
searchParams,
}: {
searchParams: Promise<{ archives?: string }>;
}) {
const { archives } = await searchParams;
const showArchived = archives === '1';
const titles = await listJobTitles(showArchived);
const active = titles.filter((title) => title.archivedAt === null);
return (
<PageBody>
<PageHeader
title="Emplois"
subtitle={`${active.length} emploi${active.length > 1 ? 's' : ''} en vigueur`}
/>
<Card>
<CardHeader
title="Référentiel"
badge={
<Badge tone="neutral">
{titles.length} affiché{titles.length > 1 ? 's' : ''}
</Badge>
}
action={
<a
href={showArchived ? '/reglages/emplois' : '/reglages/emplois?archives=1'}
className="text-xs text-ink-2 underline underline-offset-2 hover:text-ink-1"
>
{showArchived ? 'Masquer les archivés' : 'Voir les archivés'}
</a>
}
/>
{titles.length === 0 ? (
<EmptyState
title="Aucun emploi"
description="Un contrat porte une qualification ; créez d’abord les emplois de l’organisation."
/>
) : (
<ul className="divide-y divide-line-1">
{titles.map((title) => (
<li
key={title.id}
className="flex flex-wrap items-end gap-3 px-4 py-3"
>
<RenameJobTitleForm id={title.id} name={title.name} />
<div className="flex items-center gap-2">
<Badge tone="neutral">
{title.contractCount} contrat
{title.contractCount > 1 ? 's' : ''}
</Badge>
{title.archivedAt ? <Badge tone="warn">Archivé</Badge> : null}
</div>
<form action={archiveJobTitleAction}>
<input type="hidden" name="id" value={title.id} />
{title.archivedAt ? (
<input type="hidden" name="restore" value="1" />
) : null}
<Button size="sm" variant="ghost" type="submit">
{title.archivedAt ? 'Rétablir' : 'Archiver'}
</Button>
</form>
</li>
))}
</ul>
)}
</Card>
<Card>
<CardHeader title="Nouvel emploi" />
<div className="p-4">
<AddJobTitleForm />
</div>
</Card>
<p className="max-w-[70ch] text-xs leading-[var(--lh-prose)] text-ink-3">
Un emploi porté par un contrat est archivé, jamais supprimé : le registre
unique du personnel doit rester lisible pendant toute la durée de
conservation, y compris pour un salarié parti.
</p>
</PageBody>
);
}