espace-paie-odentas/STAFF_GESTION_PRODUCTIONS.md

13 KiB

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.

const { data: staffCheck, isLoading } = useStaffCheck();
// Returns: { isStaff: boolean }

useOrganizations()

Récupère la liste de toutes les organisations.

const { data: organizations } = useOrganizations();
// Returns: Organization[]

useProductions(orgId?, searchQuery?)

Récupère les productions avec filtres optionnels.

const { data: productions, isLoading, error } = useProductions(orgId, searchQuery);
// Returns: Production[]

Types 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 :

{
  "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 :

{
  "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 :

{
  "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 :

{
  "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) :

{
  "name": "Nouveau nom",
  "reference": "NEW-REF",
  "declaration_date": "2025-02-01",
  "org_id": "autre-org-uuid"
}

Response :

{
  "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 :

{
  "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 :

<Link href="/staff/gestion-productions">
  <Clapperboard className="w-4 h-4" />
  Gestion des productions
</Link>

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

// 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