espace-paie-odentas/hooks/useContrats.ts

244 lines
7.6 KiB
TypeScript

"use client";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/fetcher";
// --- Types partagés
export type Contrat = {
id: string;
reference: string;
salarie_nom: string; // "LOMPO Mariam"
production: string; // "Les Vies Dansent" / "KB HARMONY"
profession: string; // code + libellé
date_debut: string; // ISO yyyy-mm-dd
date_fin: string; // ISO
etat: "pre-demande" | "Reçue" | "envoye" | "signe" | "modification" | "traitee" | "en_cours";
is_multi_mois?: boolean; // drapeau listé par l'API
regime?: "CDDU_MONO" | "CDDU_MULTI" | "RG" | string; // si l'API renvoie directement le régime
};
export type ContratsQueryParams = {
regime?: "CDDU" | "RG" | "ALL"; // Rendre regime optionnel et ajouter "ALL"
status: "en_cours" | "termines";
page: number;
limit: number;
q?: string;
month?: number;
year?: number;
period?: string; // ex: "Y", "S1", "Q3", "M12"
};
export type ContratsResponse = {
items: Contrat[];
page: number;
limit: number;
hasMore: boolean;
total?: number;
totalPages?: number;
};
type ClientInfo = {
id: string;
name: string;
api_name?: string;
} | null;
/**
* Hook partagé pour récupérer les contrats.
* Utilise le helper `api()` (qui gère cookies/headers) et React Query pour cache/chargement/erreurs.
*/
export function useContrats(params: ContratsQueryParams){
const { regime, status, page, limit, q, month, year, period } = params;
// 🎭 Détection directe du mode démo
const isDemoMode = typeof window !== 'undefined' && window.location.hostname === 'demo.odentas.fr';
console.log('🔍 useContrats (hook) debug:', {
isDemoMode,
hostname: typeof window !== 'undefined' ? window.location.hostname : 'server',
regime,
status
});
// 🎭 Mode démo : utiliser les données fictives DIRECTEMENT
if (isDemoMode) {
console.log('🎭 Demo mode detected, loading demo contracts from hook...');
// Import direct des données de demo
const DEMO_CONTRACTS: Contrat[] = [
{
id: "demo-cont-001",
reference: "DEMO-2024-001",
salarie_nom: "MARTIN Alice",
production: "Les Misérables - Tournée 2024",
profession: "04201 - Comédien",
date_debut: "2024-01-15",
date_fin: "2024-06-30",
etat: "en_cours",
regime: "CDDU_MULTI",
is_multi_mois: true
},
{
id: "demo-cont-002",
reference: "DEMO-2024-002",
salarie_nom: "DUBOIS Pierre",
production: "Le Cid - Avignon 2024",
profession: "04202 - Metteur en scène",
date_debut: "2024-07-05",
date_fin: "2024-07-28",
etat: "signe",
regime: "CDDU_MONO"
},
{
id: "demo-cont-003",
reference: "DEMO-2024-003",
salarie_nom: "LEROY Sophie",
production: "Ballet Moderne - Saison 2024",
profession: "04301 - Danseur",
date_debut: "2024-09-01",
date_fin: "2024-12-20",
etat: "en_cours",
regime: "CDDU_MULTI",
is_multi_mois: true
},
{
id: "demo-cont-004",
reference: "DEMO-2024-004",
salarie_nom: "BERNARD Marc",
production: "Festival d'été - Son",
profession: "04501 - Technicien son",
date_debut: "2024-06-01",
date_fin: "2024-08-31",
etat: "en_cours",
regime: "CDDU_MULTI",
is_multi_mois: true
},
{
id: "demo-cont-005",
reference: "DEMO-2024-005",
salarie_nom: "GARCIA Elena",
production: "Atelier Costumes",
profession: "04401 - Costumière",
date_debut: "2024-03-01",
date_fin: "2024-05-15",
etat: "signe",
regime: "CDDU_MONO"
}
];
const filteredContracts = DEMO_CONTRACTS
.filter(contract => {
// Filtrer par régime si nécessaire
if (regime === "CDDU" && (contract.regime === "CDDU_MONO" || contract.regime === "CDDU_MULTI")) return true;
if (regime === "RG" && contract.regime === "RG") return true;
if (regime === "ALL" || !regime) return true; // Pas de filtre de régime
return false;
})
.filter(contract => {
// Filtrer par recherche
if (q) {
const searchTerm = q.toLowerCase();
return contract.salarie_nom.toLowerCase().includes(searchTerm) ||
contract.production.toLowerCase().includes(searchTerm) ||
contract.reference.toLowerCase().includes(searchTerm);
}
return true;
});
console.log('✅ Filtered demo contracts (hook):', filteredContracts.length, 'contracts');
return {
data: {
items: filteredContracts,
page,
limit,
hasMore: false, // Pas de pagination pour les données de démo
total: filteredContracts.length,
totalPages: Math.ceil(filteredContracts.length / limit),
} as ContratsResponse,
isLoading: false,
error: null,
isError: false,
isFetching: false
};
}
// Mode normal : récupération via API
// Récupération dynamique des infos client via /api/me
const { data: clientInfo } = useQuery({
queryKey: ["client-info"],
queryFn: async () => {
try {
const res = await fetch("/api/me", {
cache: "no-store",
headers: { Accept: "application/json" },
credentials: "include"
});
if (!res.ok) return null;
const me = await res.json();
return {
id: me.active_org_id || null,
name: me.active_org_name || "Organisation",
api_name: me.active_org_api_name
} as ClientInfo;
} catch {
return null;
}
},
staleTime: 30_000, // Cache 30s
});
return useQuery<ContratsResponse>({
queryKey: [
"contrats",
regime,
status,
page,
limit,
q,
status === "termines" ? (period || "Y") : undefined,
status === "termines" ? year : undefined,
clientInfo?.id, // Inclure l'ID client dans la queryKey
],
queryFn: () => {
// Construire l'URL de base - inclure regime seulement s'il est défini et différent de "ALL"
let base = `/contrats?status=${status}&page=${page}&limit=${limit}`;
if (regime && regime !== "ALL") {
base = `/contrats?regime=${encodeURIComponent(regime)}&status=${status}&page=${page}&limit=${limit}`;
}
const parts: string[] = [];
if (q) parts.push(`q=${encodeURIComponent(q)}`);
if (status === "termines") {
// priorité au paramètre explicite si fourni
if (typeof month === "number") {
parts.push(`year=${year ?? new Date().getFullYear()}`);
parts.push(`month=${month}`);
} else if (year) {
parts.push(`year=${year}`);
const p = period || "Y";
if (p.startsWith("M")) {
const m = parseInt(p.slice(1), 10);
if (!Number.isNaN(m)) parts.push(`month=${m}`);
} else if (p.startsWith("Q")) {
const qv = parseInt(p.slice(1), 10);
if (!Number.isNaN(qv)) parts.push(`quarter=${qv}`);
} else if (p.startsWith("S")) {
const sv = parseInt(p.slice(1), 10);
if (!Number.isNaN(sv)) parts.push(`semester=${sv}`);
} else {
// "Y" → année entière
}
}
}
const qs = parts.length ? `&${parts.join("&")}` : "";
return api<ContratsResponse>(base + qs, {}, clientInfo); // Passer clientInfo au helper api()
},
staleTime: 15_000,
placeholderData: (prev) => prev,
enabled: !!clientInfo, // Ne pas exécuter si pas d'infos client
});
}