feat: Améliorer accessibilité des voyants d'urgence (rouge/bleu)
This commit is contained in:
parent
839190fa8f
commit
605d55f4e6
1 changed files with 71 additions and 2 deletions
|
|
@ -32,6 +32,44 @@ function classNames(...arr: Array<string | false | null | undefined>) {
|
|||
return arr.filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
// Fonction pour calculer l'urgence basée sur la date de début
|
||||
function getUrgencyIndicator(startDate: string | null): { color: string; show: boolean; label: string } {
|
||||
if (!startDate) return { color: '', show: false, label: '' };
|
||||
|
||||
const start = new Date(startDate);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
start.setHours(0, 0, 0, 0);
|
||||
|
||||
const diffTime = start.getTime() - today.getTime();
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
// Rouge si contrat démarre aujourd'hui ou dans le passé
|
||||
if (diffDays <= 0) {
|
||||
return { color: 'bg-red-600', show: true, label: 'Urgent - Début aujourd\'hui ou passé' };
|
||||
}
|
||||
// Bleu si moins de 48 heures (moins de 2 jours)
|
||||
if (diffDays < 2) {
|
||||
return { color: 'bg-blue-500', show: true, label: 'Urgent - Début dans moins de 48h' };
|
||||
}
|
||||
// Pas de voyant si plus de 48 heures
|
||||
return { color: '', show: false, label: '' };
|
||||
}
|
||||
|
||||
// Fonction pour trier les enregistrements par date de début (ordre croissant)
|
||||
function sortByStartDate(records: AirtableRecord[]): AirtableRecord[] {
|
||||
return [...records].sort((a, b) => {
|
||||
const dateA = a.fields?.start_date || a.fields?.['Date de début'];
|
||||
const dateB = b.fields?.start_date || b.fields?.['Date de début'];
|
||||
|
||||
if (!dateA && !dateB) return 0;
|
||||
if (!dateA) return 1;
|
||||
if (!dateB) return -1;
|
||||
|
||||
return new Date(dateA).getTime() - new Date(dateB).getTime();
|
||||
});
|
||||
}
|
||||
|
||||
// Composant pour un bouton désactivé avec tooltip
|
||||
function DisabledButton({ label, className }: { label: string; className?: string }) {
|
||||
const btnRef = useRef<HTMLButtonElement | null>(null);
|
||||
|
|
@ -1217,6 +1255,23 @@ export default function SignaturesElectroniques() {
|
|||
<div className="text-slate-500">Aucun document à signer.</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Légende des voyants d'urgence */}
|
||||
<div className="mb-4 p-3 rounded-lg bg-slate-50 border border-slate-200">
|
||||
<div className="flex items-center gap-6 text-xs">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-semibold text-slate-700">Légende :</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-3 h-3 rounded-full bg-red-600" />
|
||||
<span className="text-slate-600">Début aujourd'hui ou passé</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-3 h-3 rounded-full bg-blue-500" />
|
||||
<span className="text-slate-600">Début dans moins de 48h</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Table 1: employeur pending (contrats + avenants) */}
|
||||
<div className="rounded-xl border overflow-hidden shadow-sm">
|
||||
<div className="flex items-center justify-between gap-3 px-3 py-2 border-b bg-white/60 backdrop-blur supports-[backdrop-filter]:bg-white/60[backdrop-filter]:bg-slate-900/60">
|
||||
|
|
@ -1227,6 +1282,7 @@ export default function SignaturesElectroniques() {
|
|||
<table className="min-w-full text-sm">
|
||||
<thead>
|
||||
<tr className="text-left text-slate-500 border-b bg-slate-50/60">
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap w-8"></th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Type</th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Référence</th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Salarié</th>
|
||||
|
|
@ -1237,7 +1293,7 @@ export default function SignaturesElectroniques() {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[...recordsEmployeur, ...avenantsEmployeur].map((rec, idx) => {
|
||||
{sortByStartDate([...recordsEmployeur, ...avenantsEmployeur]).map((rec, idx) => {
|
||||
const f = rec.fields || {};
|
||||
const isAvenant = f.is_avenant === true;
|
||||
const isSigned = String(f['Contrat signé par employeur'] || '').toLowerCase() === 'oui';
|
||||
|
|
@ -1249,9 +1305,15 @@ export default function SignaturesElectroniques() {
|
|||
const docType = isAvenant ? 'Avenant' : 'Contrat';
|
||||
const urlPath = isAvenant ? `/staff/avenants/${rec.id}` : `/contrats/${rec.id}`;
|
||||
const docLabel = isAvenant ? `Avenant · ${ref}` : `Contrat · ${ref}`;
|
||||
const urgency = getUrgencyIndicator(dateDebut);
|
||||
|
||||
return (
|
||||
<tr key={rec.id} className={classNames(idx % 2 ? 'bg-white' : 'bg-slate-50/30', 'hover:bg-slate-50 transition-colors')}>
|
||||
<td className="px-3 py-2 text-center">
|
||||
{urgency.show && (
|
||||
<span className={`inline-block w-3 h-3 rounded-full ${urgency.color}`} title={urgency.label} />
|
||||
)}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-slate-700 whitespace-nowrap">
|
||||
<span className={classNames(
|
||||
'inline-flex items-center gap-1 text-xs px-2 py-1 rounded-full border font-medium',
|
||||
|
|
@ -1313,6 +1375,7 @@ export default function SignaturesElectroniques() {
|
|||
<table className="min-w-full text-sm">
|
||||
<thead>
|
||||
<tr className="text-left text-slate-500 border-b bg-slate-50/60">
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap w-8"></th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Type</th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Référence</th>
|
||||
<th className="px-3 py-2 font-medium whitespace-nowrap">Salarié</th>
|
||||
|
|
@ -1323,7 +1386,7 @@ export default function SignaturesElectroniques() {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[...recordsSalarie, ...avenantsSalarie].map((rec, idx) => {
|
||||
{sortByStartDate([...recordsSalarie, ...avenantsSalarie]).map((rec, idx) => {
|
||||
const f = rec.fields || {};
|
||||
const isAvenant = f.is_avenant === true;
|
||||
const mat = f.employee_matricule || f['Matricule API'] || f.Matricule || '—';
|
||||
|
|
@ -1334,9 +1397,15 @@ export default function SignaturesElectroniques() {
|
|||
const docType = isAvenant ? 'Avenant' : 'Contrat';
|
||||
const urlPath = isAvenant ? `/staff/avenants/${rec.id}` : `/contrats/${rec.id}`;
|
||||
const docLabel = isAvenant ? `Avenant · ${ref}` : `Contrat · ${ref}`;
|
||||
const urgency = getUrgencyIndicator(dateDebut);
|
||||
|
||||
return (
|
||||
<tr key={rec.id} className={classNames(idx % 2 ? 'bg-white' : 'bg-slate-50/30', 'hover:bg-slate-50 transition-colors')}>
|
||||
<td className="px-3 py-2 text-center">
|
||||
{urgency.show && (
|
||||
<span className={`inline-block w-3 h-3 rounded-full ${urgency.color}`} title={urgency.label} />
|
||||
)}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-slate-700 whitespace-nowrap">
|
||||
<span className={classNames(
|
||||
'inline-flex items-center gap-1 text-xs px-2 py-1 rounded-full border font-medium',
|
||||
|
|
|
|||
Loading…
Reference in a new issue