# Gestion des Productions - Documentation Staff ## 📋 Vue d'ensemble La page **Gestion des Productions** (`/staff/gestion-productions`) est une interface complète permettant aux membres du staff de gérer l'ensemble des productions et spectacles de toutes les organisations. ## ✨ Fonctionnalités ### 🎬 CRUD Complet - **Créer** : Ajouter de nouvelles productions avec nom, référence, date de déclaration et organisation - **Lire** : Visualiser toutes les productions dans un tableau moderne avec filtres - **Mettre à jour** : Modifier les informations d'une production existante - **Supprimer** : Supprimer une production (avec vérification d'utilisation dans les contrats) ### 🔍 Recherche et Filtrage - **Recherche textuelle** : Recherche en temps réel par nom ou référence - **Filtre par organisation** : Filtrer les productions d'une organisation spécifique - **Effacement rapide** : Bouton pour réinitialiser tous les filtres ### 📊 Interface Moderne - **Design ultra-moderne** : Interface avec gradients, ombres et animations fluides - **Modales élégantes** : Modales avec backdrop blur et animations d'entrée - **Badges et icônes** : Affichage visuel clair avec icônes Lucide - **Responsive** : Adaptation automatique mobile/tablette/desktop - **États de chargement** : Spinners et messages informatifs ## 🎨 Interface Utilisateur ### Header ``` ┌────────────────────────────────────────────────────┐ │ Gestion des productions [+ Nouvelle] │ │ Gérez les productions et spectacles... │ └────────────────────────────────────────────────────┘ ``` ### Barre de Filtres - **Recherche** : Input avec icône de recherche et bouton de réinitialisation - **Filtres** : Bouton avec badge indiquant le nombre de filtres actifs - **Organisation** : Dropdown pour filtrer par organisation ### Tableau des Productions | Colonne | Description | Type | |---------|-------------|------| | Nom | Nom de la production | Texte | | Référence | Numéro d'objet/référence | Badge avec icône Hash | | Date déclaration | Date de déclaration | Date avec icône Calendar | | Organisation | Organisation liée | Texte | | Actions | Éditer / Supprimer | Boutons icônes | ### Modales #### Modal Création/Édition ``` ┌──────────────────────────────────────┐ │ 🏢 Nouvelle production ✕ │ ├──────────────────────────────────────┤ │ │ │ 📄 Nom de la production * │ │ [Ex: Festival d'Avignon 2025] │ │ │ │ # Numéro d'objet / Référence │ │ [Ex: PROD-2025-001] │ │ │ │ 📅 Date de déclaration │ │ [Date picker] │ │ │ │ 🏢 Organisation * │ │ [Dropdown] │ │ │ │ [Annuler] [Créer ⟳] │ └──────────────────────────────────────┘ ``` #### Modal Suppression ``` ┌──────────────────────────────────────┐ │ 🗑️ Confirmer la suppression │ │ Cette action est irréversible │ ├──────────────────────────────────────┤ │ │ │ Voulez-vous vraiment supprimer │ │ la production "Festival 2025" ? │ │ Référence : PROD-001 │ │ │ │ [Annuler] [Supprimer ⟳] │ └──────────────────────────────────────┘ ``` ## 🔧 Implémentation Technique ### Architecture ``` app/(app)/staff/gestion-productions/ └── page.tsx (Client Component) app/api/staff/productions/ ├── route.ts (GET, POST) └── [id]/ └── route.ts (GET, PATCH, DELETE) components/ └── Sidebar.tsx (+ lien navigation) ``` ### Hooks React Query #### `useStaffCheck()` Vérifie si l'utilisateur connecté est staff. ```typescript const { data: staffCheck, isLoading } = useStaffCheck(); // Returns: { isStaff: boolean } ``` #### `useOrganizations()` Récupère la liste de toutes les organisations. ```typescript const { data: organizations } = useOrganizations(); // Returns: Organization[] ``` #### `useProductions(orgId?, searchQuery?)` Récupère les productions avec filtres optionnels. ```typescript const { data: productions, isLoading, error } = useProductions(orgId, searchQuery); // Returns: Production[] ``` ### Types TypeScript ```typescript type Production = { id: string; name: string; reference: string | null; declaration_date: string | null; org_id: string; created_at?: string; updated_at?: string; }; type Organization = { id: string; name: string; structure_api: string; }; ``` ## 🌐 Routes API ### GET `/api/staff/productions` **Description** : Liste toutes les productions avec filtres optionnels **Query Parameters** : - `org_id` (optional) : Filtrer par organisation - `q` (optional) : Recherche textuelle (nom ou référence) **Response** : ```json { "productions": [ { "id": "uuid", "name": "Festival d'Avignon 2025", "reference": "PROD-2025-001", "declaration_date": "2025-01-15", "org_id": "org-uuid", "created_at": "2025-01-10T10:00:00Z", "updated_at": "2025-01-10T10:00:00Z" } ] } ``` **Codes d'erreur** : - `401` : Non authentifié - `403` : Accès refusé (non-staff) - `500` : Erreur serveur ### POST `/api/staff/productions` **Description** : Créer une nouvelle production **Body** : ```json { "name": "Festival d'Avignon 2025", "reference": "PROD-2025-001", "declaration_date": "2025-01-15", "org_id": "org-uuid" } ``` **Validation** : - `name` : Requis, non vide - `org_id` : Requis, doit exister dans `organizations` - `reference` : Optionnel - `declaration_date` : Optionnel **Response** : ```json { "production": { /* Production créée */ } } ``` **Codes d'erreur** : - `400` : Validation échouée - `401` : Non authentifié - `403` : Accès refusé (non-staff) - `500` : Erreur serveur ### GET `/api/staff/productions/[id]` **Description** : Récupérer une production spécifique **Response** : ```json { "production": { /* Production */ } } ``` **Codes d'erreur** : - `401` : Non authentifié - `403` : Accès refusé (non-staff) - `404` : Production introuvable - `500` : Erreur serveur ### PATCH `/api/staff/productions/[id]` **Description** : Mettre à jour une production **Body** (tous les champs optionnels) : ```json { "name": "Nouveau nom", "reference": "NEW-REF", "declaration_date": "2025-02-01", "org_id": "autre-org-uuid" } ``` **Response** : ```json { "production": { /* Production mise à jour */ } } ``` **Codes d'erreur** : - `400` : Validation échouée - `401` : Non authentifié - `403` : Accès refusé (non-staff) - `404` : Production introuvable - `500` : Erreur serveur ### DELETE `/api/staff/productions/[id]` **Description** : Supprimer une production **Vérifications** : - La production existe - La production n'est pas utilisée dans des contrats CDDU **Response** : ```json { "message": "Production supprimée avec succès", "deleted_id": "uuid" } ``` **Codes d'erreur** : - `400` : Production utilisée dans des contrats - `401` : Non authentifié - `403` : Accès refusé (non-staff) - `404` : Production introuvable - `500` : Erreur serveur ## 🔐 Sécurité ### Vérifications - **Authentification** : Session Supabase requise - **Autorisation** : Vérification `staff_users.is_staff = true` - **Validation** : Toutes les entrées utilisateur sont validées - **Protection suppression** : Vérification des dépendances (contrats) ### Permissions - **Staff uniquement** : Toutes les opérations réservées au staff - **Aucune restriction par organisation** : Le staff peut gérer toutes les organisations ## 📱 Responsive Design ### Desktop (≥1024px) - Tableau pleine largeur - Filtres sur une ligne - Modales centrées (max-width: 640px) ### Tablet (768px - 1023px) - Tableau scrollable horizontal - Filtres sur deux lignes - Modales adaptées ### Mobile (<768px) - Tableau scrollable - Filtres empilés verticalement - Modales plein écran avec padding ## 🎨 Design System ### Couleurs - **Primary Gradient** : `from-indigo-600 to-purple-600` - **Hover Gradient** : `from-indigo-700 to-purple-700` - **Background** : `bg-white`, `bg-slate-50` - **Border** : `border-slate-200` - **Text** : `text-slate-900`, `text-slate-600` ### Animations - **Modal entrée** : `animate-in fade-in zoom-in-95 duration-200` - **Backdrop** : `backdrop-blur-sm` - **Transitions** : `transition-all`, `transition-colors` ### Icônes (Lucide React) - `Building2` : Organisations - `FileText` : Nom de production - `Hash` : Référence - `Calendar` : Date de déclaration - `Plus` : Créer - `Edit2` : Éditer - `Trash2` : Supprimer - `Filter` : Filtres - `Search` : Recherche - `Loader2` : Chargement - `Clapperboard` : Icône sidebar ## 🚀 Utilisation ### Créer une production 1. Cliquer sur **"+ Nouvelle production"** 2. Remplir le formulaire : - Nom (requis) - Référence (optionnel) - Date de déclaration (optionnel) - Organisation (requis) 3. Cliquer sur **"Créer"** ### Modifier une production 1. Cliquer sur l'icône ✏️ dans la colonne Actions 2. Modifier les champs souhaités 3. Cliquer sur **"Enregistrer"** ### Supprimer une production 1. Cliquer sur l'icône 🗑️ dans la colonne Actions 2. Confirmer la suppression dans le modal 3. La production est supprimée si elle n'est pas utilisée ### Filtrer les productions 1. Cliquer sur **"Filtres"** 2. Sélectionner une organisation 3. Les résultats sont filtrés automatiquement ### Rechercher une production 1. Saisir du texte dans la barre de recherche 2. Les résultats sont filtrés en temps réel 3. La recherche porte sur le nom et la référence ## 🐛 Gestion des Erreurs ### Messages utilisateur - **Champ requis** : "Le nom est requis" - **Organisation requise** : "L'organisation est requise" - **Production utilisée** : "Cette production est utilisée dans des contrats..." - **Erreur réseau** : "Erreur lors du chargement des productions" ### États - **Loading** : Spinner avec message "Chargement..." - **Empty** : Message "Aucune production trouvée" - **Error** : Message d'erreur en rouge avec détails ## 📊 Performances ### Optimisations - **React Query** : Cache des requêtes API (15s) - **useMemo** : Mémoïsation du filtrage local - **Invalidation sélective** : Rafraîchissement uniquement des données modifiées - **Debouncing** : Pas de debounce nécessaire (filtrage instant) ### Stale Time - `useStaffCheck()` : 30 secondes - `useOrganizations()` : 60 secondes - `useProductions()` : 15 secondes ## 🔗 Intégration ### Sidebar La page est accessible via la sidebar staff : ```tsx Gestion des productions ``` ### Navigation - URL : `/staff/gestion-productions` - Position : Entre "Virements salaires" et "Gestion des utilisateurs" - Icône : 🎬 Clapperboard ## 🧪 Tests ### Scénarios de test 1. **Accès non-staff** : Vérifier refus d'accès 2. **Création** : Créer une production valide 3. **Création invalide** : Vérifier validation (nom vide, org manquante) 4. **Modification** : Éditer une production existante 5. **Suppression** : Supprimer une production non utilisée 6. **Suppression protection** : Tenter de supprimer une production utilisée 7. **Filtres** : Vérifier filtrage par organisation 8. **Recherche** : Vérifier recherche textuelle 9. **Responsive** : Tester sur mobile/tablet/desktop ### Console logs ```javascript // Vérifier les requêtes API // Réseau > Fetch/XHR // GET /api/staff/productions // POST /api/staff/productions // PATCH /api/staff/productions/[id] // DELETE /api/staff/productions/[id] ``` ## 📝 Todo / Améliorations futures - [ ] Export CSV/Excel des productions - [ ] Tri des colonnes du tableau - [ ] Pagination (si + de 100 productions) - [ ] Filtre par date de déclaration (plage) - [ ] Import CSV de productions en masse - [ ] Historique des modifications - [ ] Duplication de production - [ ] Statistiques (nb productions par org, par période) - [ ] Champ description/notes - [ ] Tags/catégories de productions - [ ] Lien direct vers les contrats associés ## 📚 Références - [Lucide Icons](https://lucide.dev/) - [TanStack Query (React Query)](https://tanstack.com/query/latest) - [Tailwind CSS](https://tailwindcss.com/) - [Next.js App Router](https://nextjs.org/docs/app) - [Supabase Client](https://supabase.com/docs/reference/javascript)