Aller au contenu principal

Implémentation frontend — Assistant publication DMV (état mai 2026)

Statut

Document d'état réel — décrit le code déployé en production.
Mis à jour le 2026-05-23. À faire valider avant toute extension.


Vue d'ensemble

L'IA est intégrée dans dmv-public (Next.js 14, App Router, TypeScript).
Le seul point d'entrée utilisateur livré est le panneau IA dans la modale de publication (PubModal), accessible depuis l'espace acteur.

Page Mon Espace Acteur
└── PubModal (création / édition publication)
└── Panneau IA (toggle)
├── Mode "Générer" → génère titre + texte depuis une idée brute
└── Mode "Améliorer" → améliore un texte existant avec un ton choisi

Authentification : échange de token

Problème : dmv-public utilise Supabase Auth (JWT) mais l'API Laravel utilise Sanctum (Bearer token).
Solution : un client API centralisé qui fait l'échange au premier appel, puis met en cache le token Sanctum en sessionStorage.

Fichier : dmv-public/lib/apiClient.ts

Flux :

  1. Au premier appel IA, récupère la session Supabase (supabase.auth.getSession()).
  2. Échange le JWT Supabase contre un token Sanctum via POST /auth/exchange avec X-App-Source: dmv.
  3. Stocke le token Sanctum et son expiry (Date.now() + 3 600 000 ms) en sessionStorage.
  4. Pour les appels suivants : si le token stocké expire dans plus de 5 minutes, il est réutilisé.
  5. Tous les appels API ajoutent automatiquement les headers Authorization: Bearer <token> et X-App-Source: dmv.

Fonctions exportées :

apiGet<T>(path: string): Promise<T>
apiPost<T>(path: string, body: unknown): Promise<T>

Hooks React

Fichier : dmv-public/hooks/useAIPublication.ts

Quatre hooks, un par action IA. Chacun encapsule son état loading / error / result.

useAIImprove

const { loading, error, result, improve, reset } = useAIImprove()
await improve(texte, ton, actorId?)
// result: { texte_ameliore: string; suggestions: string[] }

Appelle POST /ai/publication/improve.

useAIGenerate

const { loading, error, result, generate, reset } = useAIGenerate()
await generate(idee, actorId?)
// result: { titre: string; texte: string }

Appelle POST /ai/publication/generate.

useAIVariants

const { loading, error, result, variants, reset } = useAIVariants()
await variants(texte, actorId?)
// result: { version_dmv, version_facebook, version_push, titre_seo }

Appelle POST /ai/publication/variants. Non exposé dans l'UI actuellement.

useAITags

const { loading, error, result, tags, reset } = useAITags()
await tags(texte, titre?)
// result: { tags: string[]; categories: string[] }

Appelle POST /ai/publication/tags. Non exposé dans l'UI actuellement.


Hook quota

Fichier : dmv-public/hooks/useAIQuota.ts

const { quota, loading, canUseAI } = useAIQuota(actorId?)
// quota: { monthly_limit, monthly_used, bonus_credits, available, reset_at }
// canUseAI: boolean (available > 0)

Appelle GET /ai/quota?actor_id=<id> au montage du composant.
Utilisé dans PubModal pour décider si le panneau IA est accessible ou verrouillé.


Interface utilisateur — PubModal

Fichier : dmv-public/app/mon-espace/acteur/MonEspaceActeurClient.tsx

Le panneau IA s'ouvre en bas de la modale de publication par un toggle.

État : quota insuffisant (plan gratuit ou quota épuisé)

  • Affiche un cadenas (🔒).
  • Message : "Assistant IA disponible dès l'offre Standard".
  • Lien vers /mon-espace/tarifs?slug=<actor.slug> pour upgrader.

État : quota disponible

Toggle Générer / Améliorer pour choisir le mode.

Mode Générer

  1. Champ texte : l'acteur écrit une idée brute (ex : "Je cherche un développeur pour mon application").
  2. Bouton "Générer".
  3. L'IA retourne un titre et un texte complets.
  4. Bouton "Utiliser" → remplit automatiquement les champs titre et texte de la publication.

Mode Améliorer

  1. Sélecteur de ton : chaleureux, professionnel, informatif, engageant.
  2. Bouton "Améliorer le texte".
  3. L'IA retourne un texte_ameliore + tableau de suggestions.
  4. Bouton "Utiliser ce texte" → remplace le texte de la publication.
  5. Les suggestions sont affichées en dessous à titre informatif.

Paramètres transmis à l'API

Dans les deux modes, l'actor_id est systématiquement transmis :

  • Permet à l'API d'utiliser le quota par acteur (et non par user).
  • Permet de logguer l'usage à l'acteur.
  • La commune n'est pas encore transmise (le prompt prévoie {{commune}} mais il est laissé vide).

Quota vu côté utilisateur

Le quota est vérifié côté API avant chaque appel. En cas de dépassement, l'API retourne une erreur HTTP 429. Le hook affiche alors l'erreur dans le panneau IA (champ error). Il n'y a pas encore de feedback UX spécifique pour le 429 (message générique).


Ce qui n'est pas encore exposé dans l'UI

FonctionnalitéCode présentUI
Variantes multi-canal (DMV, Facebook, push, SEO)Oui — useAIVariantsNon
Génération de tagsOui — useAITagsNon
Suggestion onboarding acteurOui — endpoint backendNon
Affichage du solde de crédits dans l'UIOui — useAIQuotaPartiel (verrouillage uniquement)
Compteur crédits restants visibleNonNon
Message UX dédié quota épuisé (429)NonNon
Transmission de la commune au promptNonNon

Suivi des modifications de plan — Admin backoffice

Fichier : dmv-backoffice/src/pages/Souscriptions.jsx

Deux onglets dans la page Souscriptions :

  • Abonnements — liste existante de toutes les souscriptions acteurs avec actions (changer plan, offrir, boost, facturer, historique).
  • Changements de plan — liste paginée de tous les upgraded, downgraded et admin_grant enregistrés dans subscription_logs, avec filtres par type, acteur et plage de dates.

Fichier : dmv-backoffice/src/pages/Dashboard.jsx

Widget "Derniers changements de plan" sur le dashboard admin (admin view uniquement) : affiche les 5 derniers changements avec badge coloré (vert montée, orange descente, bleu offert), nom de l'acteur, plan cible et date. Lien direct vers la page Souscriptions.

Endpoint : GET /api/v1/admin/subscriptions/changes (filtres : action, q, from, to).
Dashboard : GET /api/v1/admin/dashboard retourne désormais recent_plan_changes (5 dernières entrées).


Récapitulatif des fichiers livrés

Backend (api/)

Nouveaux fichiers :

  • app/Modules/AI/ — module complet (26 fichiers PHP)
  • config/ai.php — configuration AI
  • database/migrations/000053_create_ai_prompts_table.php
  • database/migrations/000054_create_ai_usage_logs_table.php
  • database/migrations/000055_create_ai_user_quotas_table.php
  • database/migrations/000056_create_ai_cache_table.php
  • database/migrations/000057_add_ai_credits_to_subscription_plans.php
  • database/migrations/000058_add_acteur_id_to_ai_user_quotas.php
  • database/migrations/000059_add_bonus_to_push_usage.php
  • database/seeders/AiPromptsSeeder.php
  • app/Modules/Admin/Services/PlanQuotaSync.php

Fichiers modifiés :

  • app/Modules/Admin/Services/AdminSubscriptionWriteService.php — injection PlanQuotaSync + passage old plan slug
  • app/Modules/Admin/Services/AdminSubscriptionService.php — ajout listChanges()
  • app/Modules/Admin/Controllers/AdminSubscriptionController.php — ajout méthodes write + changes()
  • app/Modules/Admin/Controllers/AdminDashboardController.php — ajout recent_plan_changes
  • app/Modules/Admin/Providers/AdminServiceProvider.php — enregistrement PlanQuotaSync
  • app/Modules/Monetization/Models/SubscriptionPlan.php — cast ai_credits_mensuel
  • app/Modules/Admin/Services/AdminPlanService.php — champ ai_credits_mensuel
  • app/Modules/Admin/Controllers/AdminPlanController.php — validation ai_credits_mensuel
  • app/Modules/Admin/Routes/api.php — route GET /subscriptions/changes

Frontend dmv-public (dmv-public/)

Nouveaux fichiers :

  • lib/apiClient.ts — client API avec échange token Supabase → Sanctum
  • hooks/useAIPublication.ts — hooks useAIImprove, useAIGenerate, useAIVariants, useAITags
  • hooks/useAIQuota.ts — hook useAIQuota

Fichiers modifiés :

  • app/mon-espace/acteur/MonEspaceActeurClient.tsx — intégration panneau IA dans PubModal

Frontend backoffice (dmv-backoffice/)

Fichiers modifiés :

  • src/pages/Souscriptions.jsx — onglet "Changements de plan" + refacto en sous-composants
  • src/pages/Dashboard.jsx — widget derniers changements de plan
  • src/pages/Plans.jsx — colonne et champ ai_credits_mensuel