244 lines
7.6 KiB
TypeScript
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
|
|
});
|
|
}
|