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 :
- Au premier appel IA, récupère la session Supabase (
supabase.auth.getSession()). - Échange le JWT Supabase contre un token Sanctum via
POST /auth/exchangeavecX-App-Source: dmv. - Stocke le token Sanctum et son expiry (
Date.now() + 3 600 000 ms) ensessionStorage. - Pour les appels suivants : si le token stocké expire dans plus de 5 minutes, il est réutilisé.
- Tous les appels API ajoutent automatiquement les headers
Authorization: Bearer <token>etX-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
- Champ texte : l'acteur écrit une idée brute (ex : "Je cherche un développeur pour mon application").
- Bouton "Générer".
- L'IA retourne un
titreet untextecomplets. - Bouton "Utiliser" → remplit automatiquement les champs titre et texte de la publication.
Mode Améliorer
- Sélecteur de ton :
chaleureux,professionnel,informatif,engageant. - Bouton "Améliorer le texte".
- L'IA retourne un
texte_ameliore+ tableau desuggestions. - Bouton "Utiliser ce texte" → remplace le texte de la publication.
- 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ésent | UI |
|---|---|---|
| Variantes multi-canal (DMV, Facebook, push, SEO) | Oui — useAIVariants | Non |
| Génération de tags | Oui — useAITags | Non |
| Suggestion onboarding acteur | Oui — endpoint backend | Non |
| Affichage du solde de crédits dans l'UI | Oui — useAIQuota | Partiel (verrouillage uniquement) |
| Compteur crédits restants visible | Non | Non |
| Message UX dédié quota épuisé (429) | Non | Non |
| Transmission de la commune au prompt | Non | Non |
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,downgradedetadmin_grantenregistrés danssubscription_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 AIdatabase/migrations/000053_create_ai_prompts_table.phpdatabase/migrations/000054_create_ai_usage_logs_table.phpdatabase/migrations/000055_create_ai_user_quotas_table.phpdatabase/migrations/000056_create_ai_cache_table.phpdatabase/migrations/000057_add_ai_credits_to_subscription_plans.phpdatabase/migrations/000058_add_acteur_id_to_ai_user_quotas.phpdatabase/migrations/000059_add_bonus_to_push_usage.phpdatabase/seeders/AiPromptsSeeder.phpapp/Modules/Admin/Services/PlanQuotaSync.php
Fichiers modifiés :
app/Modules/Admin/Services/AdminSubscriptionWriteService.php— injectionPlanQuotaSync+ passage old plan slugapp/Modules/Admin/Services/AdminSubscriptionService.php— ajoutlistChanges()app/Modules/Admin/Controllers/AdminSubscriptionController.php— ajout méthodes write +changes()app/Modules/Admin/Controllers/AdminDashboardController.php— ajoutrecent_plan_changesapp/Modules/Admin/Providers/AdminServiceProvider.php— enregistrementPlanQuotaSyncapp/Modules/Monetization/Models/SubscriptionPlan.php— castai_credits_mensuelapp/Modules/Admin/Services/AdminPlanService.php— champai_credits_mensuelapp/Modules/Admin/Controllers/AdminPlanController.php— validationai_credits_mensuelapp/Modules/Admin/Routes/api.php— routeGET /subscriptions/changes
Frontend dmv-public (dmv-public/)
Nouveaux fichiers :
lib/apiClient.ts— client API avec échange token Supabase → Sanctumhooks/useAIPublication.ts— hooksuseAIImprove,useAIGenerate,useAIVariants,useAITagshooks/useAIQuota.ts— hookuseAIQuota
Fichiers modifiés :
app/mon-espace/acteur/MonEspaceActeurClient.tsx— intégration panneau IA dansPubModal
Frontend backoffice (dmv-backoffice/)
Fichiers modifiés :
src/pages/Souscriptions.jsx— onglet "Changements de plan" + refacto en sous-composantssrc/pages/Dashboard.jsx— widget derniers changements de plansrc/pages/Plans.jsx— colonne et champai_credits_mensuel