Overview
This roadmap outlines the plan to create a centralized listener hook that synchronizes Empathy context (cart, wishlist, whitelabel) with VTEX state changes (orderForm, session, wishlist).
Core Logic
The listener will primarily react to orderForm changes, which serves as the "heartbeat" of the store's state changes.
useEmpathyListener Hook
A new custom hook will be responsible for orchestrating updates.
Triggers:
- Mount: Initial sync.
- OrderForm Update: React to changes in
useOrderForm. - Window Events: Listen to
orderFormUpdated.vtex(backup trigger).
Actions on Trigger:
-
Sync Session (Region/Whitelabel)
- Call
refetch()fromuseFullSession. - Decoding
regionIdfromnamespaces.checkout.regionId. - Update Empathy:
setSnippetConfig({ whitelabel: { regionId: '...' } }).
- Call
-
Sync Cart
- Read
orderForm.items. - Format items to Empathy structure (
id,sku,price,quantity). - Update Empathy:
setSnippetConfig({ cart: [...] }).
- Read
-
Sync Wishlist
- Note: Wishlist is expensive to fetch entirely. We need a strategy.
- Option A: Fetch all wishlist items (might be slow if list is huge).
- Option B: handleWishlist already manages its state locally + API. We might expose a
refetchWishlistmethod. - Recommended: execute a "Get All Wishlist" query (or rely on
checkItemfor visible products if possible, but user asked to sync changes). We will likely need agetUserWishlistquery. - Update Empathy:
setSnippetConfig({ wishlist: [productIds] }).
file Structure
_10react/_10 hooks/_10 useEmpathyListener.ts // Central orchestrator_10 useSessionListener.ts // (Existing) Refactor to export data + refetch_10 Components/_10 EmpathySearchbar/_10 index.tsx // Mounts useEmpathyListener
Implementation Steps
Phase 1: Preparation (Current)
- Analyze
vtex.session-client. - Create useSessionListener prototype.
- Research/Verify Wishlist generic query (
vtex.wish-listgeneric query typically requires iterating or getting a specific list).
Phase 2: Listener Core
- Create
useEmpathyListener.ts. - Implement
useOrderFormdependency. - Add
useEffectlistening toorderForm.
Phase 3: Connect Data Sources
- Cart: Map
orderForm.items-> Empathy Cart format. - Session: Integrate useSessionListener logic into the new listener or expose
refetch. - Wishlist: Implement
useQueryfor "Get Wishlist" (likelyGetWishlistfromvtex.wish-list).
Phase 4: Integration
- Replace isolated hooks in EmpathySearchbar with centralized
useEmpathyListener. - Verify functionality (Add to cart -> Console log / Empathy update).
🚀 Evolutivos Propuestos
1. Sincronización Automática de Carrito
Objetivo: Leer el carrito de VTEX al cargar la página y sincronizarlo con Empathy.
Implementación:
_19useEffect(() => {_19 const initialCart: { [key: string]: number } = {};_19 cartItems.forEach((item: any) => {_19 initialCart[item.id] = item.quantity;_19 });_19_19 (window as any).InterfaceX?.init();_19 (window as any).InterfaceX?.setSnippetConfig({ cart: initialCart });_19}, []);_19_19// Sincronizar cuando cambie_19useEffect(() => {_19 if (!(window as any).InterfaceX) return;_19 const syncedCart: { [key: string]: number } = {};_19 cartItems.forEach((item: any) => {_19 syncedCart[item.id] = item.quantity;_19 });_19 (window as any).InterfaceX.setSnippetConfig({ cart: syncedCart });_19}, [cartItems]);
Beneficios:
- ✅ Usuario ve inmediatamente qué productos ya tiene
- ✅ Sincronización bidireccional
- ✅ Mejor UX
2. Integración de regionId con Whitelabel
Objetivo: Leer la región del usuario y pasarla a Empathy para búsquedas específicas por región.
Implementación:
_29// utils/getRegionId.ts_29export const getRegionId = async (): Promise<string | null> => {_29 const sessionPromise = getSessionPromise();_29 if (!sessionPromise) return null;_29 try {_29 const sessionRes = await sessionPromise;_29 return sessionRes?.response?.namespaces?.public?.regionId?.value || null;_29 } catch {_29 return null;_29 }_29};_29_29// En EmpathySearchbar_29useEffect(() => {_29 (async () => {_29 const regionId = await getRegionId();_29 (window as any).initX = {_29 // ... config ..._29 whitelabel: regionId ? { regionId } : undefined,_29 callbacks: { ... }_29 };_29 (window as any).InterfaceX?.init();_29 if (regionId) {_29 (window as any).InterfaceX?.setSnippetConfig({ _29 whitelabel: { regionId } _29 });_29 }_29 })();_29}, []);
Beneficios:
- ✅ Búsquedas contextuales por región
- ✅ Productos específicos por ubicación
- ✅ Mejor relevancia de resultados
3. Pre-carga de Wishlist
Objetivo: Marcar automáticamente productos que ya están en wishlist al cargar la página.
GraphQL Query nueva:
_10query GetWishlistItems($shopperId: String!, $name: String!) {_10 list(shopperId: $shopperId, name: $name)_10 @context(provider: "vtex.wish-list"){_10 data {_10 productId_10 sku_10 title_10 }_10 }_10}
Implementación:
_25export const useInitialWishlist = () => {_25 const [loadWishlisted] = useLazyQuery(GET_WISHLIST_ITEMS);_25_25 const loadAndSyncWishlist = async () => {_25 try {_25 const { isAuthenticated, shopperId } = await checkSession();_25 if (!isAuthenticated) return;_25_25 const result = await loadWishlisted({_25 variables: { shopperId: String(shopperId), name: 'Wishlist' }_25 });_25_25 const wishlistedItems = result?.data?.list?.data || [];_25 const wishlistedSkus = wishlistedItems.map((item: any) => item.sku);_25_25 (window as any).InterfaceX?.setSnippetConfig({_25 wishlist: wishlistedSkus_25 });_25 } catch (error) {_25 console.error('Error loading wishlist:', error);_25 }_25 };_25_25 return { loadAndSyncWishlist };_25};
Beneficios:
- ✅ Productos favoritos aparecen con corazón "filled"
- ✅ Mejor experiencia de usuario
- ✅ Consistencia entre sesiones