- 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
101 lines
3.2 KiB
TypeScript
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;
|
|
},
|
|
}
|
|
)
|
|
)
|