Périmètre

Cette documentation couvre l'écran personal-shopper et son intégration API.

Route concernée :

  • /personal-shopper

Attention : le moteur back du personal shopper n'est pas implémenté dans ce repo. Le repo contient :

  • le front Angular
  • le service HTTP d'intégration
  • la configuration d'environnement
  • la configuration Apache de proxy

Fonctionnel

Objectif

Permettre à un utilisateur de décrire un besoin en langage naturel et d'obtenir une sélection de produits pertinente, dans une logique de conversation.

Exemples de besoins :

  • une ambiance
  • une couleur
  • une matière
  • un usage
  • une famille de produits

Expérience utilisateur

L'utilisateur arrive sur un écran conversationnel avec :

  • un état vide avec suggestions de requêtes
  • une zone de saisie libre
  • un bouton Nouvelle conversation

Le composant gère :

  • l'envoi au Enter
  • le retour à la ligne avec Maj + Enter
  • le resize automatique du textarea
  • le scroll intelligent vers les nouvelles réponses

Réponses de l'assistant

Une réponse peut contenir :

  • un message textuel seul
  • un message textuel et une liste de produits
  • un message de clarification si l'API estime que la demande est trop vague
  • un message d'erreur

Quand des produits sont retournés, ils sont affichés sous forme de cartes avec :

  • un libellé produit
  • une date de réassort éventuelle
  • un packshot
  • une liste de variantes
  • pour chaque variante : taille, SKU, statut de stock
  • un bouton pour ouvrir le produit

Navigation et ouverture produit

Les cartes ouvrent le produit sur le site web via un lien deeplink déduit du SKU.

Le personal shopper ne renvoie pas vers la visualisation PIM interne. Il est orienté consultation produit côté site.

Fonctions d'assistance

L'écran propose aussi :

  • Nouvelle conversation pour repartir à zéro avec un nouvel identifiant de conversation
  • Réessayer en cas d'échec sur le dernier message
  • une Vue dev qui expose la réponse brute du backend pour le tour de conversation courant

La Vue dev est utile pour diagnostiquer :

  • les filtres interprétés
  • les produits retournés
  • les erreurs backend
  • les demandes de clarification

Technique

Stack et périmètre réel

Ce repo contient uniquement la couche front d'intégration.

Le moteur de conversation est un service externe appelé via :

  • en local : http://localhost:8443/api/chat
  • en prod : /api/shopper/api/chat via proxy Apache

Fichiers clés :

  • linvosges_utilitaire_akeneo/src/app/features/personal-shopper/personal-shopper.component.ts
  • linvosges_utilitaire_akeneo/src/app/features/personal-shopper/personal-shopper.component.html
  • linvosges_utilitaire_akeneo/src/app/core/services/personal-shopper-api.service.ts
  • linvosges_utilitaire_akeneo/src/app/core/models/personal-shopper.model.ts
  • apache-vhost-akeneo.conf
  • linvosges_utilitaire_akeneo/src/environments/environment.ts
  • linvosges_utilitaire_akeneo/src/environments/environment.prod.ts

Architecture générale

PersonalShopperComponent  -> PersonalShopperApiService    -> POST {baseUrl}/api/chat      -> service shopper externe 
En production : Angular /api/shopper  -> Apache ProxyPass /api/shopper/ http://127.0.0.1:8443/

Contrat d'appel

Requête :

{  "message": "Je cherche une housse de couette bleue esprit montagne",  "conversationId": "uuid-ou-id-technique"
}

Réponse de succès attendue :

{  "success": true,  "needsClarification": false,  "assistantMessage": "Texte de réponse",  "appliedFilters": {},  "data": []
}

Réponse d'erreur attendue :

{  "success": false,  "message": "Message d'erreur"
}

Enchaînement des appels

Utilisateur  -> PersonalShopperComponent.submitMessage()  -> append du message user dans le state local  -> PersonalShopperApiService.sendMessage()  -> POST /api/chat sur le service shopper  -> réponse API  -> appendMessage() côté assistant  -> rendu des cartes produit éventuelles

Gestion d'état front

Le composant gère tout l'état conversationnel avec des signal() Angular :

  • messages
  • draftMessage
  • conversationId
  • isLoading
  • lastFailedMessage
  • imageLoadErrors
  • devModalPayload

Il n'y a pas de store global dédié.

Concurrence et robustesse

Le composant évite les effets de course avec :

  • requestToken
  • activeRequestToken

Concrètement :

  • chaque appel prend un token
  • seule la réponse du token actif peut modifier l'état
  • un reset de conversation invalide les requêtes précédentes

Cette logique protège l'UI contre les réponses tardives.

Rendu produit

Le front ne reconstruit pas un produit Akeneo complet. Il consomme un format plus simple :

  • un produit conversationnel
  • une liste de variantes
  • un score ou des métadonnées de pertinence

Le composant dérive ensuite :

  • le label produit à partir du slug et du type produit web
  • le SKU principal à partir de la première variante exploitable
  • l'URL packshot via le deeplink site
  • l'URL site du produit via addLinkToWebsite()

Gestion des images

Les images ne passent pas par le backend Node du repo.

Le composant affiche directement :

  • https://www.linvosges.com/fr/deeplink/packshotBySku/:sku

Si le chargement échoue :

  • le SKU est marqué dans imageLoadErrors
  • un fallback visuel est affiché

Stock et variantes

Le composant mappe actuellement certains statuts de stock :

  • DPC -> Disponible
  • DIF -> Disponible en différé

Les variantes affichent :

  • dimension ERP
  • SKU
  • pastille de statut

Configuration d'environnement

En local :

  • personalShopperApiBaseUrl = http://localhost:8443

En production :

  • personalShopperApiBaseUrl = /api/shopper

Apache assure ensuite le proxy vers 127.0.0.1:8443.

Points d'attention

  • le backend shopper n'est pas versionné ici
  • le contrat API doit rester stable, sinon l'écran casse rapidement
  • la Vue dev expose volontairement la charge utile brute, utile en qualification mais à surveiller si l'outil s'ouvre à un public plus large
  • les liens produit et packshots sont construits pour LV

Limites actuelles

  • pas de persistance locale de l'historique de conversation
  • pas de pagination ou chargement incrémental des résultats
  • pas de gestion explicite d'annulation HTTP côté front
  • aucune logique shopper back n'est testable depuis ce repo seul