espace-paie-odentas/hooks/useStaffOrgSelection.ts
odentas 266eb3598a feat: Implémenter store global Zustand + calcul total quantités + fix structure field + montants personnalisés virements
- Créer hook useStaffOrgSelection avec persistence localStorage
- Ajouter badge StaffOrgBadge dans Sidebar
- Synchroniser filtres org dans toutes les pages (contrats, cotisations, facturation, etc.)
- Fix calcul cachets: utiliser totalQuantities au lieu de dates.length
- Fix structure field bug: ne plus écraser avec production_name
- Ajouter création note lors modification contrat
- Implémenter montants personnalisés pour virements salaires
- Migrations SQL: custom_amount + fix_structure_field
- Réorganiser boutons ContractEditor en carte flottante droite
2025-12-01 21:51:57 +01:00

101 lines
3.2 KiB
TypeScript

'use client'
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
/**
* Interface pour l'état de sélection d'organisation du staff
*/
interface StaffOrgSelectionState {
/** ID de l'organisation sélectionnée (null = toutes les organisations) */
selectedOrgId: string | null
/** Nom de l'organisation sélectionnée (pour affichage dans le badge) */
selectedOrgName: string | null
/** Définir l'organisation sélectionnée */
setSelectedOrg: (id: string | null, name: string | null) => void
/** Réinitialiser la sélection (retour à "Toutes les organisations") */
clearSelection: () => void
}
/**
* Hook Zustand pour gérer la sélection d'organisation du staff
*
* Fonctionnalités :
* - État global accessible partout dans l'application
* - Persistence automatique dans localStorage
* - Synchronisation entre tous les composants
* - Validation UUID pour éviter les noms de structure
*
* Usage :
* ```tsx
* const { selectedOrgId, selectedOrgName, setSelectedOrg, clearSelection } = useStaffOrgSelection()
*
* // Sélectionner une orga
* setSelectedOrg("uuid-123", "Théâtre du Soleil")
*
* // Réinitialiser (toutes les orgas)
* clearSelection()
*
* // Filtrer des données
* const filtered = selectedOrgId
* ? data.filter(item => item.org_id === selectedOrgId)
* : data
* ```
*/
// Helper: vérifier si une string est un UUID valide
const isValidUUID = (str: string | null | undefined): boolean => {
if (!str) return false;
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
return uuidRegex.test(str);
};
export const useStaffOrgSelection = create<StaffOrgSelectionState>()(
persist(
(set, get) => ({
selectedOrgId: null,
selectedOrgName: null,
setSelectedOrg: (id, name) => {
// Valider que l'ID est bien un UUID (pas un nom de structure)
if (id && !isValidUUID(id)) {
console.warn('[useStaffOrgSelection] Invalid UUID provided:', id, '- Clearing selection');
set({ selectedOrgId: null, selectedOrgName: null });
return;
}
set({ selectedOrgId: id, selectedOrgName: name });
},
clearSelection: () => set({
selectedOrgId: null,
selectedOrgName: null
}),
}),
{
name: 'staff-org-selection', // Clé dans localStorage
// Ne persister que les données essentielles
partialize: (state) => ({
selectedOrgId: state.selectedOrgId,
selectedOrgName: state.selectedOrgName,
}),
// Migration : nettoyer les valeurs invalides
migrate: (persistedState: any, version: number) => {
if (persistedState && typeof persistedState === 'object') {
const { selectedOrgId } = persistedState;
// Si l'ID n'est pas un UUID valide, le nettoyer
if (selectedOrgId && !isValidUUID(selectedOrgId)) {
console.warn('[useStaffOrgSelection] Cleaning invalid UUID from localStorage:', selectedOrgId);
return {
selectedOrgId: null,
selectedOrgName: null,
};
}
}
return persistedState;
},
}
)
)