# 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)