336 lines
15 KiB
TypeScript
336 lines
15 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useState, useEffect } from "react";
|
|
import { AlertCircle, Calendar, Euro, FileSignature } from "lucide-react";
|
|
import ContractsGrid, { ContractsGridHandle } from "./ContractsGrid";
|
|
|
|
export default function StaffContractsPageClient({ initialData, activeOrgId }: { initialData: any[]; activeOrgId?: string | null }) {
|
|
const gridRef = useRef<ContractsGridHandle | null>(null);
|
|
const [activeFilter, setActiveFilter] = useState<string | null>(null);
|
|
const [counts, setCounts] = useState({
|
|
dpaeAFaire: null as number | null,
|
|
contratsAFaireMois: null as number | null,
|
|
paieATraiterMoisDernier: null as number | null,
|
|
paieATraiterToutes: null as number | null,
|
|
nonSignesDateProche: null as number | null,
|
|
});
|
|
|
|
// Check localStorage to detect which filter is active
|
|
useEffect(() => {
|
|
try {
|
|
const saved = localStorage.getItem('staff-contracts-filters');
|
|
if (saved) {
|
|
const filters = JSON.parse(saved);
|
|
|
|
// Check for DPAE à faire filter
|
|
if (filters.dpaeFilter === 'À faire') {
|
|
const today = new Date();
|
|
const in7 = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
|
|
const y = in7.getFullYear();
|
|
const m = String(in7.getMonth() + 1).padStart(2, '0');
|
|
const day = String(in7.getDate()).padStart(2, '0');
|
|
const expectedEndDate = `${y}-${m}-${day}`;
|
|
|
|
if (filters.startTo === expectedEndDate && filters.sortField === 'start_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('dpae-a-faire');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for Contrats à faire mois filter
|
|
if (filters.etatContratFilters?.length > 0 && filters.etatContratFilters.includes('Reçue')) {
|
|
const today = new Date();
|
|
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
const y1 = firstDay.getFullYear();
|
|
const m1 = String(firstDay.getMonth() + 1).padStart(2, '0');
|
|
const day1 = String(firstDay.getDate()).padStart(2, '0');
|
|
const expectedStartDate = `${y1}-${m1}-${day1}`;
|
|
|
|
const y2 = lastDay.getFullYear();
|
|
const m2 = String(lastDay.getMonth() + 1).padStart(2, '0');
|
|
const day2 = String(lastDay.getDate()).padStart(2, '0');
|
|
const expectedEndDate = `${y2}-${m2}-${day2}`;
|
|
|
|
if (filters.startFrom === expectedStartDate && filters.startTo === expectedEndDate && filters.sortField === 'start_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('contrats-a-faire-mois');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for Paie à traiter mois dernier filter
|
|
if (filters.etatPaieFilter === 'À traiter') {
|
|
const today = new Date();
|
|
const firstDayThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
const lastDayLastMonth = new Date(firstDayThisMonth.getFullYear(), firstDayThisMonth.getMonth(), 0);
|
|
const firstDayLastMonth = new Date(lastDayLastMonth.getFullYear(), lastDayLastMonth.getMonth(), 1);
|
|
|
|
const y1 = firstDayLastMonth.getFullYear();
|
|
const m1 = String(firstDayLastMonth.getMonth() + 1).padStart(2, '0');
|
|
const day1 = String(firstDayLastMonth.getDate()).padStart(2, '0');
|
|
const expectedStartDate = `${y1}-${m1}-${day1}`;
|
|
|
|
const y2 = lastDayLastMonth.getFullYear();
|
|
const m2 = String(lastDayLastMonth.getMonth() + 1).padStart(2, '0');
|
|
const day2 = String(lastDayLastMonth.getDate()).padStart(2, '0');
|
|
const expectedEndDate = `${y2}-${m2}-${day2}`;
|
|
|
|
if (filters.endFrom === expectedStartDate && filters.endTo === expectedEndDate && filters.sortField === 'end_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('paie-a-traiter-mois-dernier');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for Paie à traiter toutes les périodes filter
|
|
if (filters.etatPaieFilter === 'À traiter' && filters.etatContratFilters?.includes('Traitée')) {
|
|
const today = new Date();
|
|
const y = today.getFullYear();
|
|
const m = String(today.getMonth() + 1).padStart(2, '0');
|
|
const day = String(today.getDate()).padStart(2, '0');
|
|
const expectedEndDate = `${y}-${m}-${day}`;
|
|
|
|
if (filters.endTo === expectedEndDate && filters.startFrom === null && filters.startTo === null && filters.sortField === 'end_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('paie-a-traiter-toutes');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for Non signés date proche filter
|
|
if (filters.signatureFilter === 'non_signe') {
|
|
const today = new Date();
|
|
const tomorrow = new Date(today);
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
const y = tomorrow.getFullYear();
|
|
const m = String(tomorrow.getMonth() + 1).padStart(2, '0');
|
|
const day = String(tomorrow.getDate()).padStart(2, '0');
|
|
const expectedEndDate = `${y}-${m}-${day}`;
|
|
|
|
if (filters.startTo === expectedEndDate && filters.startFrom === null && filters.sortField === 'start_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('non-signes-date-proche');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check for Contrats en cours filter
|
|
// start_to = aujourd'hui, end_from = aujourd'hui, sort by end_date asc
|
|
const today = new Date();
|
|
const y = today.getFullYear();
|
|
const m = String(today.getMonth() + 1).padStart(2, '0');
|
|
const day = String(today.getDate()).padStart(2, '0');
|
|
const todayStr = `${y}-${m}-${day}`;
|
|
|
|
if (filters.startTo === todayStr && filters.endFrom === todayStr &&
|
|
filters.startFrom === null && filters.endTo === null &&
|
|
filters.sortField === 'end_date' && filters.sortOrder === 'asc') {
|
|
setActiveFilter('contrats-en-cours');
|
|
return;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// ignore
|
|
}
|
|
}, []);
|
|
|
|
// Update counts from grid when they change
|
|
useEffect(() => {
|
|
const updateCounts = () => {
|
|
setCounts({
|
|
dpaeAFaire: gridRef.current?.getCountDpaeAFaire() ?? null,
|
|
contratsAFaireMois: gridRef.current?.getCountContratsAFaireMois() ?? null,
|
|
paieATraiterMoisDernier: gridRef.current?.getCountPaieATraiterMoisDernier() ?? null,
|
|
paieATraiterToutes: gridRef.current?.getCountPaieATraiterToutes() ?? null,
|
|
nonSignesDateProche: gridRef.current?.getCountNonSignesDateProche() ?? null,
|
|
});
|
|
};
|
|
|
|
updateCounts();
|
|
const interval = setInterval(updateCounts, 500); // Update counts every 500ms
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
const handleDpaeAFaire = () => {
|
|
gridRef.current?.quickFilterDpaeAFaire();
|
|
setActiveFilter('dpae-a-faire');
|
|
};
|
|
|
|
const handleContratsAFaireMois = () => {
|
|
gridRef.current?.quickFilterContratsAFaireMois();
|
|
setActiveFilter('contrats-a-faire-mois');
|
|
};
|
|
|
|
const handlePaieATraiterMoisDernier = () => {
|
|
gridRef.current?.quickFilterPaieATraiterMoisDernier();
|
|
setActiveFilter('paie-a-traiter-mois-dernier');
|
|
};
|
|
|
|
const handlePaieATraiterToutes = () => {
|
|
gridRef.current?.quickFilterPaieATraiterToutes();
|
|
setActiveFilter('paie-a-traiter-toutes');
|
|
};
|
|
|
|
const handleNonSignesDateProche = () => {
|
|
gridRef.current?.quickFilterNonSignesDateProche();
|
|
setActiveFilter('non-signes-date-proche');
|
|
};
|
|
|
|
const handleContratsEnCours = () => {
|
|
gridRef.current?.quickFilterContratsEnCours();
|
|
setActiveFilter('contrats-en-cours');
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-3">
|
|
<div className="flex items-center justify-between gap-4">
|
|
<h1 className="text-lg font-semibold">Contrats (Staff)</h1>
|
|
|
|
{/* Card de raccourcis à droite du titre */}
|
|
<div className="flex items-center gap-3 rounded-xl border border-slate-200 bg-gradient-to-r from-slate-50 to-slate-100 p-3">
|
|
<div className="flex flex-col gap-1">
|
|
<span className="text-xs text-slate-600 font-medium">Filtres contrats:</span>
|
|
<div className="flex items-center gap-2">
|
|
{/* Bouton DPAE à faire */}
|
|
<button
|
|
onClick={handleDpaeAFaire}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'dpae-a-faire'
|
|
? 'bg-gradient-to-r from-orange-500 to-orange-600 text-white shadow-md'
|
|
: 'bg-white text-orange-700 border border-orange-300 hover:border-orange-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher les contrats avec DPAE à faire dont la date de début est passée ou dans les 7 jours"
|
|
>
|
|
<AlertCircle size={16} />
|
|
DPAE à faire
|
|
{counts.dpaeAFaire !== null && (
|
|
<span className={`ml-1 inline-flex items-center justify-center w-5 h-5 rounded-full text-xs font-bold ${
|
|
activeFilter === 'dpae-a-faire'
|
|
? 'bg-orange-300 text-orange-900'
|
|
: 'bg-orange-200 text-orange-800'
|
|
}`}>
|
|
{counts.dpaeAFaire}
|
|
</span>
|
|
)}
|
|
</button>
|
|
|
|
{/* Bouton Contrats à faire mois */}
|
|
<button
|
|
onClick={handleContratsAFaireMois}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'contrats-a-faire-mois'
|
|
? 'bg-gradient-to-r from-blue-500 to-blue-600 text-white shadow-md'
|
|
: 'bg-white text-blue-700 border border-blue-300 hover:border-blue-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher les contrats reçus ou en cours dont la date de début est dans le mois courant"
|
|
>
|
|
<Calendar size={16} />
|
|
Contrats à faire mois
|
|
{counts.contratsAFaireMois !== null && (
|
|
<span className={`ml-1 inline-flex items-center justify-center w-5 h-5 rounded-full text-xs font-bold ${
|
|
activeFilter === 'contrats-a-faire-mois'
|
|
? 'bg-blue-300 text-blue-900'
|
|
: 'bg-blue-200 text-blue-800'
|
|
}`}>
|
|
{counts.contratsAFaireMois}
|
|
</span>
|
|
)}
|
|
</button>
|
|
|
|
{/* Bouton Contrats non signés date proche */}
|
|
<button
|
|
onClick={handleNonSignesDateProche}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'non-signes-date-proche'
|
|
? 'bg-gradient-to-r from-red-500 to-red-600 text-white shadow-md'
|
|
: 'bg-white text-red-700 border border-red-300 hover:border-red-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher les contrats non signés dont la date de début est passée, aujourd'hui ou demain"
|
|
>
|
|
<FileSignature size={16} />
|
|
Non signés
|
|
{counts.nonSignesDateProche !== null && (
|
|
<span className={`ml-1 inline-flex items-center justify-center w-5 h-5 rounded-full text-xs font-bold ${
|
|
activeFilter === 'non-signes-date-proche'
|
|
? 'bg-red-300 text-red-900'
|
|
: 'bg-red-200 text-red-800'
|
|
}`}>
|
|
{counts.nonSignesDateProche}
|
|
</span>
|
|
)}
|
|
</button>
|
|
|
|
{/* Bouton Contrats en cours */}
|
|
<button
|
|
onClick={handleContratsEnCours}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'contrats-en-cours'
|
|
? 'bg-gradient-to-r from-green-500 to-green-600 text-white shadow-md'
|
|
: 'bg-white text-green-700 border border-green-300 hover:border-green-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher les contrats en cours (date de début passée et date de fin future)"
|
|
>
|
|
<Calendar size={16} />
|
|
En cours
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Séparateur vertical */}
|
|
<div className="border-l border-slate-300 h-12"></div>
|
|
|
|
{/* Sous-card Paies à traiter */}
|
|
<div className="flex flex-col gap-1">
|
|
<span className="text-xs text-slate-600 font-medium">Paies à traiter:</span>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={handlePaieATraiterMoisDernier}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'paie-a-traiter-mois-dernier'
|
|
? 'bg-gradient-to-r from-green-500 to-green-600 text-white shadow-md'
|
|
: 'bg-white text-green-700 border border-green-300 hover:border-green-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher les contrats avec paie à traiter dont la date de fin est au mois dernier"
|
|
>
|
|
<Euro size={16} />
|
|
Mois dernier
|
|
{counts.paieATraiterMoisDernier !== null && (
|
|
<span className={`ml-1 inline-flex items-center justify-center w-5 h-5 rounded-full text-xs font-bold ${
|
|
activeFilter === 'paie-a-traiter-mois-dernier'
|
|
? 'bg-green-300 text-green-900'
|
|
: 'bg-green-200 text-green-800'
|
|
}`}>
|
|
{counts.paieATraiterMoisDernier}
|
|
</span>
|
|
)}
|
|
</button>
|
|
|
|
<button
|
|
onClick={handlePaieATraiterToutes}
|
|
className={`inline-flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-lg font-medium transition-all relative ${
|
|
activeFilter === 'paie-a-traiter-toutes'
|
|
? 'bg-gradient-to-r from-green-500 to-green-600 text-white shadow-md'
|
|
: 'bg-white text-green-700 border border-green-300 hover:border-green-500 hover:shadow-sm'
|
|
}`}
|
|
title="Afficher tous les contrats avec paie à traiter, toutes périodes confondues"
|
|
>
|
|
<Euro size={16} />
|
|
Toutes
|
|
{counts.paieATraiterToutes !== null && (
|
|
<span className={`ml-1 inline-flex items-center justify-center w-5 h-5 rounded-full text-xs font-bold ${
|
|
activeFilter === 'paie-a-traiter-toutes'
|
|
? 'bg-green-300 text-green-900'
|
|
: 'bg-green-200 text-green-800'
|
|
}`}>
|
|
{counts.paieATraiterToutes}
|
|
</span>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="rounded-2xl border bg-white p-4">
|
|
<ContractsGrid ref={gridRef} initialData={initialData} activeOrgId={activeOrgId} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|