@graphiboxdev/app-shopping-cart
v1.2.52
Published
Shopping cart module for Autopartspro
Readme
@graphiboxdev/app-shopping-cart
Module Nuxt 4 — panier d'achat et tunnel de commande pour l'écosystème Autopartspro.
Nuxt 4 module — shopping cart and checkout flow for the Autopartspro ecosystem.
Navigation rapide / Quick navigation
Français
Présentation
@graphiboxdev/app-shopping-cart est un module Nuxt 4 clé-en-main qui fournit un panier d'achat complet et un tunnel de commande pour les applications Autopartspro.
Fonctionnalités principales :
- Panier invité et connecté — persistance via
localStorage/sessionStoragepour les visiteurs non connectés, migration automatique vers le panier serveur à la connexion. - Tunnel de commande 4 étapes — livraison → paiement → récapitulatif → confirmation, avec navigation et validation par étape.
- Tarification HT/TTC — calcul des montants hors taxe et toutes taxes comprises, support multi-devise et multi-locale.
- Consignes — gestion des articles à consigne (bouteilles, contenants) incluse dans les totaux.
- Informations véhicule — association de plaque d'immatriculation et données véhicule par article.
- Intégration ERP — envoi optionnel des commandes vers un système ERP tiers.
- Passerelle bancaire — paiement par carte bancaire via une passerelle dédiée.
- SSR — hydratation correcte côté serveur via
onServerPrefetch. - 16 composants UI — basés sur Nuxt UI v4 et Tailwind CSS v4, responsive, mode sombre inclus.
Installation
npm install @graphiboxdev/app-shopping-cartAjouter le module dans nuxt.config.ts :
export default defineNuxtConfig({
modules: ['@graphiboxdev/app-shopping-cart'],
})Prérequis
| Dépendance | Version minimale | Rôle |
|---|---|---|
| Nuxt | ^4.0.0 | Framework requis |
| @nuxt/ui | ^4.0.0 | Composants UI (requis pour les composants visuels) |
| Tailwind CSS | ^4.0.0 | Styles (configuré automatiquement par le module) |
| Node.js | LTS | Environnement d'exécution |
Le module injecte automatiquement une directive
@sourcepour ses composants dans la feuille de style racine Tailwind de l'application (celle qui contient@import "tailwindcss"), via un plugin Vite. Aucune configuration Tailwind manuelle n'est nécessaire avec le pipeline Vite standard de Nuxt.Si votre pipeline CSS ne passe pas par Vite (setup PostCSS pur), importez le fallback embarqué depuis cette même feuille racine :
@import "@graphiboxdev/app-shopping-cart/tailwind.css";
Configuration
Options du module (nuxt.config.ts)
export default defineNuxtConfig({
modules: ['@graphiboxdev/app-shopping-cart'],
graphiToolbox: {
maxQuantity: 99, // Quantité maximale par article (défaut : 99)
persistence: 'localStorage', // 'localStorage' | 'sessionStorage' | 'none'
checkout: {
requireAccount: false, // Forcer la connexion avant commande (défaut : false)
},
},
})| Option | Type | Défaut | Description |
|---|---|---|---|
| maxQuantity | number | 99 | Quantité maximale par article |
| persistence | 'localStorage' \| 'sessionStorage' \| 'none' | 'localStorage' | Mode de persistance panier invité |
| checkout.requireAccount | boolean | false | Connexion obligatoire avant commande |
Configuration dynamique (runtime)
La configuration dynamique (devise, locale, endpoints API, identifiants client) est gérée via useBoxCartConfig() — un état global réactif mis à jour à l'exécution :
// Dans un plugin ou un layout
const cartConfig = useBoxCartConfig()
cartConfig.value = {
currency: 'EUR',
locale: 'fr-FR',
isHt: true, // Affichage en HT (true) ou TTC (false)
addToCartFeedback: 'slideover', // Retour visuel à l'ajout : 'slideover' | 'toast' | 'none'
addToCartModalAutoCloseDelay: 10000, // Délai de fermeture automatique en ms
hidePurchasePrice: false, // Masque les prix d'achat dans le retour visuel d'ajout
email: '[email protected]', // Email du client connecté
establishmentId: 123, // ID établissement
entityId: 456, // ID entité
api: {
baseUrl: 'https://api.example.com',
endpoints: {
cart: {
get: '/v3/cart/getCart',
add: '/v3/cart/addProduct',
update: '/v3/cart/updateProduct',
delete: '/v3/cart/deleteProduct',
kill: '/v3/cart/killCart',
},
bank: '/bank',
order: '/orders',
deliveries: '/deliveries',
paymentMethods: '/payment-methods',
},
},
}Synchronisation avec i18n :
const { locale } = useI18n()
const cartConfig = useBoxCartConfig()
watch(locale, (lang) => {
cartConfig.value = {
...cartConfig.value,
locale: lang,
currency: lang === 'en' ? 'USD' : 'EUR',
}
}, { immediate: true })Utilisation rapide
Afficher le panier
<template>
<BoxCart />
</template>Ajouter un article au panier
const { addItem } = useBoxShoppingCart()
await addItem({
id: 'REF-001',
label: 'Filtre à huile',
reference: 'FH-12345',
quantity: 2,
conditioning: 1,
soldBy: 1,
price: {
ht: 12.50,
ttc: 15.00,
tva: 20,
},
stock: { available: true },
})Formater un prix
const formatPrice = useBoxPriceFormatter()
formatPrice(19.99) // → '19,99 €'Panier dans un panneau latéral
<template>
<BoxCartSlideover />
</template>Retour visuel à l'ajout au panier — slideover ou toast
<BoxCartAddedFeedback /> monte l'un ou l'autre selon addToCartFeedback (config panier), surchargeable par le prop mode :
<template>
<!-- Suit la config : 'slideover' (défaut), 'toast' ou 'none' -->
<BoxCartAddedFeedback
show-checkout
@checkout="navigateTo('/checkout')"
@view-cart="navigateTo('/panier')"
@continue-shopping="() => {}"
@login-required="openLogin()"
/>
</template>| Mode | Composant monté | Usage |
| --- | --- | --- |
| 'slideover' | <BoxCartSlideover /> | Panneau latéral : récapitulatif complet, article ajouté mis en évidence, quantités éditables, CTA commande |
| 'toast' | <BoxCartAddedToast /> | Notification discrète : informe de l'ajout (visuel, référence, quantité, total panier) sans interrompre la navigation |
| 'none' | — | Aucun retour visuel |
Le mode toast requiert <UApp /> à la racine de l'application (fournisseur de toasts Nuxt UI). Les ajouts successifs ne s'empilent pas : le toast en cours est complété avec le nouvel article, animé d'une pulsation, et son minuteur repart de zéro.
<template>
<!-- Toast seul, sans passer par le wrapper -->
<BoxCartAddedToast
title="Ajouté à votre panier"
:show-view-cart="true"
:show-checkout="false"
@view-cart="navigateTo('/panier')"
/>
</template>Masquer les prix d'achat — hidePurchasePrice (config dynamique) retire le prix unitaire net, les remises et les totaux du retour visuel d'ajout (slideover et toast) ; seul le prix public reste affiché. Le reste du module (page panier, tunnel de commande) n'est pas concerné.
Le flag est réactif : un bouton de l'application peut le basculer, la fenêtre déjà ouverte se met à jour immédiatement.
<script setup lang="ts">
const cartConfig = useBoxCartConfig()
function togglePurchasePrices(): void {
cartConfig.value.hidePurchasePrice = !cartConfig.value.hidePurchasePrice
}
</script>
<template>
<UButton
:icon="cartConfig.hidePurchasePrice ? 'i-heroicons-eye-slash' : 'i-heroicons-eye'"
:label="cartConfig.hidePurchasePrice ? 'Afficher les prix d\'achat' : 'Masquer les prix d\'achat'"
@click="togglePurchasePrices"
/>
</template>Tunnel de commande
<template>
<BoxOrderStepper />
</template>API — Composables
Tous les composables sont auto-importés — aucun import explicite n'est nécessaire dans les composants ou pages.
useBoxCartConfig()
Retourne un Ref<BoxCartRuntimeConfig> — l'état global de configuration du module.
const cartConfig = useBoxCartConfig()
cartConfig.value.currency // 'EUR'
cartConfig.value.locale // 'fr-FR'useBoxPriceFormatter()
Retourne une fonction de formatage de prix basée sur la config courante.
const formatPrice = useBoxPriceFormatter()
formatPrice(1299.9) // '1 299,90 €'useBoxShoppingCart()
État et opérations du panier.
const {
items, // Ref<CartItem[]> — articles du panier
count, // Ref<number> — nombre d'articles distincts
quantity, // Ref<number> — quantité totale
totalHt, // Ref<number> — total HT
totalTtc, // Ref<number> — total TTC
totalVat, // Ref<number> — total TVA
weight, // Ref<number> — poids total
cartLoading, // Ref<boolean> — état de chargement
pricesLoading, // Ref<boolean> — rafraîchissement des prix en cours
isLogged, // Ref<boolean> — utilisateur connecté
isItemAdded, // Ref<boolean> — un ajout vient d'avoir lieu (pilote le slideover)
lastAddedItem, // Ref<CartItem | null> — dernier article ajouté
addToCartEventId, // Ref<number> — incrémenté à chaque ajout (pilote le toast)
cancelAddToCartAutoClose, // () => void — annule la fermeture automatique en attente
addItem, // (item: CartItem, mode?) => Promise<boolean>
addItems, // (items: CartItem[]) => Promise<boolean>
deleteItem, // (item: CartItem) => Promise<boolean>
updateItemQuantity, // (item: CartItem, qty: number) => Promise<boolean>
updateItemsPrices, // (items: CartItem[]) => Promise<void> — maj des prix (ex: à la connexion)
clearCart, // () => Promise<void>
} = useBoxShoppingCart()useBoxOrder()
État et navigation du tunnel de commande.
const {
activeSteps, // ComputedRef<CheckoutStep[]>
currentStep, // Ref<CheckoutStep>
currentStepIndex, // ComputedRef<number>
isFirstStep, // ComputedRef<boolean>
isLastStep, // ComputedRef<boolean>
canGoNext, // ComputedRef<boolean>
selectedDelivery, // Ref<DeliveryMethod | null>
selectedPayment, // Ref<PaymentMethod | null>
summaryForm, // Ref<{ comment: string, customerRef: string }>
status, // Ref<PaymentStatus>
errorMessage, // Ref<string>
confirmationId, // Ref<number | null>
loadDeliveries, // () => Promise<DeliveryMethod[]>
loadPaymentMethods, // () => Promise<PaymentMethod[]>
selectDelivery, // (method: DeliveryMethod) => void
selectPayment, // (method: PaymentMethod) => void
goToStep, // (step: CheckoutStep) => void
nextStep, // () => void
prevStep, // () => void
submitOrder, // (cartId: string, totalTtc: number) => Promise<void>
resetOrder, // () => void
} = useBoxOrder()Types des étapes :
| Étape | Description |
|---|---|
| 'delivery' | Sélection du mode de livraison |
| 'payment' | Sélection du moyen de paiement |
| 'summary' | Récapitulatif et champs complémentaires |
| 'confirmation' | Confirmation de commande |
Statuts de paiement (PaymentStatus) :
| Statut | Description |
|---|---|
| 'idle' | État initial |
| 'pending' | Soumission en cours |
| 'success' | Commande confirmée |
| 'failed' | Erreur lors de la soumission |
| 'refused' | Paiement refusé par la passerelle |
useBoxCartItemPrice(item)
Calcul des prix à l'article.
const { isHt, step, unitPrice, lineTotal } = useBoxCartItemPrice(item)
// step → conditionnement (soldBy ou 1)
// unitPrice → prix unitaire selon mode HT/TTC
// lineTotal → total ligne = (unitPrice + consigne éventuelle) × quantity × soldByuseBoxWsCart()
Appels HTTP vers le service panier (mapping interne ↔ API). Usage avancé — normalement consommé uniquement via useBoxShoppingCart().
useBoxWsBank()
Intégration passerelle bancaire.
const { createBankCheckout } = useBoxWsBank()
const result = await createBankCheckout(orderId, paymentMethodId, amountEuros)
// result → BankCheckoutResponse | nullAPI — Composants
Tous les composants sont auto-importés.
Composants panier
| Composant | Description |
|---|---|
| <BoxCart /> | Panier complet (tableau desktop + cartes mobile) |
| <BoxCartItem /> | Article individuel du panier |
| <BoxCartSkeleton /> | Squelette de chargement |
| <BoxCartTotals /> | Bloc totaux (HT, TVA, TTC) |
| <BoxCartProductImage /> | Image produit avec fallback |
| <BoxCartVehicleInfo /> | Infos véhicule associé à un article |
| <BoxCartDrawer /> | Panier en tiroir (drawer) |
| <BoxCartSlideover /> | Panier en panneau latéral (slideover) |
| <BoxCartAddedFeedback /> | Retour visuel à l'ajout : monte le slideover ou le toast selon addToCartFeedback |
| <BoxCartAddedToast /> | Toast d'information « article ajouté » (Nuxt UI), sans empilement |
| <BoxCartAddedToastBody /> | Contenu détaillé du toast (visuel, référence, quantité, totaux) |
Modales
| Composant | Description |
|---|---|
| <BoxCartLoginModal /> | Modale de connexion requise |
| <BoxCartDeleteModal /> | Modale de confirmation de suppression |
| <BoxCartClearModal /> | Modale de confirmation de vidage du panier |
Composants tunnel de commande
| Composant | Description |
|---|---|
| <BoxOrderStepper /> | Orchestrateur multi-étapes du tunnel |
| <BoxOrderDeliveryStep /> | Étape sélection livraison |
| <BoxOrderPaymentStep /> | Étape sélection paiement |
| <BoxOrderSummaryStep /> | Étape récapitulatif et champs complémentaires |
| <BoxOrderConfirmation /> | Page de confirmation finale |
API — Endpoints serveur
Le module expose les endpoints suivants via le serveur Nuxt (Nitro) :
| Méthode | Route | Description |
|---|---|---|
| GET | /api/_box/cart | Récupérer le panier |
| POST | /api/_box/cart/addProduct | Ajouter un produit |
| POST | /api/_box/cart/updateProduct | Modifier la quantité |
| POST | /api/_box/cart/deleteProduct | Supprimer un produit |
| POST | /api/_box/order | Soumettre une commande |
| GET | /api/_box/order/deliveries | Récupérer les modes de livraison |
| GET | /api/_box/order/payments | Récupérer les moyens de paiement |
| POST | /api/_box/erp/order | Envoyer la commande à l'ERP |
| POST | /api/_box/bank/checkout | Initier un paiement bancaire |
Ces routes sont des proxies vers l'API externe configurée dans useBoxCartConfig().api.
Bonnes pratiques
- Initialiser
useBoxCartConfig()tôt — dans un plugin Nuxt ou le layout racine, avant tout rendu du panier, avec les données utilisateur réelles (email, establishmentId, entityId). - Ne pas hardcoder les endpoints API dans
nuxt.config.ts— utiliseruseBoxCartConfig()pour les mettre à jour dynamiquement selon le contexte utilisateur. - Synchroniser avec i18n — mettre à jour
localeetcurrencydansuseBoxCartConfig()lors des changements de langue. - Mode HT vs TTC — configurer
isHtselon le profil utilisateur (professionnel → HT, particulier → TTC).
Limites connues
- Le module est conçu pour l'écosystème Autopartspro — certaines structures de données (consignes, infos véhicule, conditionnement) sont spécifiques à ce domaine.
- La compatibilité est limitée à Nuxt
^4.0.0 < 5.0.0— non compatible Nuxt 3. - Les endpoints serveur agissent comme des proxies : l'API externe doit être correctement configurée via
useBoxCartConfig(). - TODO: documenter le format exact des réponses d'erreur API pour la gestion d'erreur côté consommateur.
Contribution
Ce module est un package interne de l'écosystème Graphibox / Autopartspro.
# Installer les dépendances
npm install
# Préparer et lancer le playground
npm run dev
# Build
npm run prepack
# Tests
npm run test
npm run test:types
# Lint
npm run lintLicence
English
Overview
@graphiboxdev/app-shopping-cart is a turnkey Nuxt 4 module providing a full-featured shopping cart and checkout flow for Autopartspro applications.
Key features:
- Guest and authenticated cart —
localStorage/sessionStoragepersistence for unauthenticated users, automatic migration to the server cart on login. - 4-step checkout flow — delivery → payment → summary → confirmation, with per-step navigation and validation.
- HT/TTC pricing — pre-tax and tax-included amounts, multi-currency and multi-locale support.
- Deposits (consignes) — deposit-item management included in totals.
- Vehicle information — license plate and vehicle data associated per cart item.
- ERP integration — optional order forwarding to a third-party ERP system.
- Bank payment gateway — credit card payment via a dedicated gateway.
- SSR — correct server-side hydration via
onServerPrefetch. - 16 UI components — built on Nuxt UI v4 and Tailwind CSS v4, responsive with dark mode support.
Installation
npm install @graphiboxdev/app-shopping-cartAdd the module to nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@graphiboxdev/app-shopping-cart'],
})Requirements
| Dependency | Minimum version | Role |
|---|---|---|
| Nuxt | ^4.0.0 | Required framework |
| @nuxt/ui | ^4.0.0 | UI components (required for visual components) |
| Tailwind CSS | ^4.0.0 | Styles (auto-configured by the module) |
| Node.js | LTS | Runtime environment |
The module automatically injects a
@sourcedirective for its components into the app's Tailwind root stylesheet (the one containing@import "tailwindcss"), through a Vite plugin. No manual Tailwind configuration is needed with Nuxt's standard Vite pipeline.If your CSS pipeline does not go through Vite (pure PostCSS setup), import the bundled fallback from that same root stylesheet:
@import "@graphiboxdev/app-shopping-cart/tailwind.css";
Configuration
Module options (nuxt.config.ts)
export default defineNuxtConfig({
modules: ['@graphiboxdev/app-shopping-cart'],
graphiToolbox: {
maxQuantity: 99, // Maximum quantity per item (default: 99)
persistence: 'localStorage', // 'localStorage' | 'sessionStorage' | 'none'
checkout: {
requireAccount: false, // Force login before checkout (default: false)
},
},
})| Option | Type | Default | Description |
|---|---|---|---|
| maxQuantity | number | 99 | Maximum quantity per cart item |
| persistence | 'localStorage' \| 'sessionStorage' \| 'none' | 'localStorage' | Guest cart persistence mode |
| checkout.requireAccount | boolean | false | Require login before checkout |
Runtime configuration
Dynamic configuration (currency, locale, API endpoints, customer identifiers) is managed via useBoxCartConfig() — a global reactive state updated at runtime:
// In a Nuxt plugin or root layout
const cartConfig = useBoxCartConfig()
cartConfig.value = {
currency: 'EUR',
locale: 'fr-FR',
isHt: true, // Display pre-tax (true) or tax-included (false)
addToCartFeedback: 'slideover', // Add-to-cart feedback: 'slideover' | 'toast' | 'none'
addToCartModalAutoCloseDelay: 10000, // Auto-close delay in ms
hidePurchasePrice: false, // Hide purchase prices in the add-to-cart feedback
email: '[email protected]', // Logged-in customer email
establishmentId: 123, // Establishment ID
entityId: 456, // Entity ID
api: {
baseUrl: 'https://api.example.com',
endpoints: {
cart: {
get: '/v3/cart/getCart',
add: '/v3/cart/addProduct',
update: '/v3/cart/updateProduct',
delete: '/v3/cart/deleteProduct',
kill: '/v3/cart/killCart',
},
bank: '/bank',
order: '/orders',
deliveries: '/deliveries',
paymentMethods: '/payment-methods',
},
},
}Syncing with i18n:
const { locale } = useI18n()
const cartConfig = useBoxCartConfig()
watch(locale, (lang) => {
cartConfig.value = {
...cartConfig.value,
locale: lang,
currency: lang === 'en' ? 'USD' : 'EUR',
}
}, { immediate: true })Quick start
Display the cart
<template>
<BoxCart />
</template>Add an item to the cart
const { addItem } = useBoxShoppingCart()
await addItem({
id: 'REF-001',
label: 'Oil filter',
reference: 'FH-12345',
quantity: 2,
conditioning: 1,
soldBy: 1,
price: {
ht: 12.50,
ttc: 15.00,
tva: 20,
},
stock: { available: true },
})Format a price
const formatPrice = useBoxPriceFormatter()
formatPrice(19.99) // → '19.99 €' or '$19.99' depending on configCart in a slideover panel
<template>
<BoxCartSlideover />
</template>Add-to-cart feedback — slideover or toast
<BoxCartAddedFeedback /> mounts either one based on addToCartFeedback (cart config), overridable with the mode prop:
<template>
<!-- Follows the config: 'slideover' (default), 'toast' or 'none' -->
<BoxCartAddedFeedback
show-checkout
@checkout="navigateTo('/checkout')"
@view-cart="navigateTo('/cart')"
@continue-shopping="() => {}"
@login-required="openLogin()"
/>
</template>| Mode | Mounted component | Usage |
| --- | --- | --- |
| 'slideover' | <BoxCartSlideover /> | Side panel: full recap, added item highlighted, editable quantities, checkout CTA |
| 'toast' | <BoxCartAddedToast /> | Discreet notification: confirms the add (image, reference, quantity, cart total) without interrupting browsing |
| 'none' | — | No feedback |
Toast mode requires <UApp /> at the app root (Nuxt UI toast provider). Successive adds do not stack: the running toast is completed with the new item, pulses, and its timer restarts from zero.
<template>
<!-- Toast on its own, without the wrapper -->
<BoxCartAddedToast
title="Added to your cart"
:show-view-cart="true"
:show-checkout="false"
@view-cart="navigateTo('/cart')"
/>
</template>Hiding purchase prices — hidePurchasePrice (runtime config) removes the net unit price, the discounts and the totals from the add-to-cart feedback (slideover and toast); only the public price stays visible. The rest of the module (cart page, checkout flow) is unaffected.
The flag is reactive: an app-level button can toggle it and the already-open panel updates instantly.
<script setup lang="ts">
const cartConfig = useBoxCartConfig()
function togglePurchasePrices(): void {
cartConfig.value.hidePurchasePrice = !cartConfig.value.hidePurchasePrice
}
</script>
<template>
<UButton
:icon="cartConfig.hidePurchasePrice ? 'i-heroicons-eye-slash' : 'i-heroicons-eye'"
:label="cartConfig.hidePurchasePrice ? 'Show purchase prices' : 'Hide purchase prices'"
@click="togglePurchasePrices"
/>
</template>Checkout flow
<template>
<BoxOrderStepper />
</template>API — Composables
All composables are auto-imported — no explicit import needed in components or pages.
useBoxCartConfig()
Returns a Ref<BoxCartRuntimeConfig> — the module's global configuration state.
const cartConfig = useBoxCartConfig()
cartConfig.value.currency // 'EUR'
cartConfig.value.locale // 'fr-FR'useBoxPriceFormatter()
Returns a price formatting function based on the current config.
const formatPrice = useBoxPriceFormatter()
formatPrice(1299.9) // '1,299.90 €'useBoxShoppingCart()
Cart state and operations.
const {
items, // Ref<CartItem[]> — cart items
count, // Ref<number> — number of distinct items
quantity, // Ref<number> — total item quantity
totalHt, // Ref<number> — pre-tax total
totalTtc, // Ref<number> — tax-included total
totalVat, // Ref<number> — total VAT
weight, // Ref<number> — total weight
cartLoading, // Ref<boolean> — loading state
pricesLoading, // Ref<boolean> — price refresh in progress
isLogged, // Ref<boolean> — user is authenticated
isItemAdded, // Ref<boolean> — an add just happened (drives the slideover)
lastAddedItem, // Ref<CartItem | null> — last added item
addToCartEventId, // Ref<number> — incremented on every add (drives the toast)
cancelAddToCartAutoClose, // () => void — cancels the pending auto-close
addItem, // (item: CartItem, mode?) => Promise<boolean>
addItems, // (items: CartItem[]) => Promise<boolean>
deleteItem, // (item: CartItem) => Promise<boolean>
updateItemQuantity, // (item: CartItem, qty: number) => Promise<boolean>
updateItemsPrices, // (items: CartItem[]) => Promise<void> — refresh prices (e.g. on login)
clearCart, // () => Promise<void>
} = useBoxShoppingCart()useBoxOrder()
Checkout flow state and navigation.
const {
activeSteps, // ComputedRef<CheckoutStep[]>
currentStep, // Ref<CheckoutStep>
currentStepIndex, // ComputedRef<number>
isFirstStep, // ComputedRef<boolean>
isLastStep, // ComputedRef<boolean>
canGoNext, // ComputedRef<boolean>
selectedDelivery, // Ref<DeliveryMethod | null>
selectedPayment, // Ref<PaymentMethod | null>
summaryForm, // Ref<{ comment: string, customerRef: string }>
status, // Ref<PaymentStatus>
errorMessage, // Ref<string>
confirmationId, // Ref<number | null>
loadDeliveries, // () => Promise<DeliveryMethod[]>
loadPaymentMethods, // () => Promise<PaymentMethod[]>
selectDelivery, // (method: DeliveryMethod) => void
selectPayment, // (method: PaymentMethod) => void
goToStep, // (step: CheckoutStep) => void
nextStep, // () => void
prevStep, // () => void
submitOrder, // (cartId: string, totalTtc: number) => Promise<void>
resetOrder, // () => void
} = useBoxOrder()Step types:
| Step | Description |
|---|---|
| 'delivery' | Delivery method selection |
| 'payment' | Payment method selection |
| 'summary' | Order summary and additional fields |
| 'confirmation' | Final order confirmation |
Payment status (PaymentStatus):
| Status | Description |
|---|---|
| 'idle' | Default state |
| 'pending' | Submission in progress |
| 'success' | Order confirmed |
| 'failed' | Submission error |
| 'refused' | Payment refused by gateway |
useBoxCartItemPrice(item)
Per-item price calculations.
const { isHt, step, unitPrice, lineTotal } = useBoxCartItemPrice(item)
// step → conditioning unit (soldBy or 1)
// unitPrice → unit price according to HT/TTC mode
// lineTotal → line total = (unitPrice + deposit if applicable) × quantity × soldByuseBoxWsCart()
HTTP calls to the cart web service (internal ↔ API mapping). Advanced use — normally consumed only via useBoxShoppingCart().
useBoxWsBank()
Bank payment gateway integration.
const { createBankCheckout } = useBoxWsBank()
const result = await createBankCheckout(orderId, paymentMethodId, amountEuros)
// result → BankCheckoutResponse | nullAPI — Components
All components are auto-imported.
Cart components
| Component | Description |
|---|---|
| <BoxCart /> | Full cart (desktop table + mobile cards) |
| <BoxCartItem /> | Individual cart item |
| <BoxCartSkeleton /> | Loading skeleton |
| <BoxCartTotals /> | Totals block (pre-tax, VAT, tax-included) |
| <BoxCartProductImage /> | Product image with fallback |
| <BoxCartVehicleInfo /> | Vehicle info associated with an item |
| <BoxCartDrawer /> | Cart as a drawer |
| <BoxCartSlideover /> | Cart as a side panel (slideover) |
| <BoxCartAddedFeedback /> | Add-to-cart feedback: mounts the slideover or the toast based on addToCartFeedback |
| <BoxCartAddedToast /> | "Item added" information toast (Nuxt UI), never stacks |
| <BoxCartAddedToastBody /> | Toast detailed content (image, reference, quantity, totals) |
Modals
| Component | Description |
|---|---|
| <BoxCartLoginModal /> | Login required modal |
| <BoxCartDeleteModal /> | Delete item confirmation modal |
| <BoxCartClearModal /> | Clear cart confirmation modal |
Checkout components
| Component | Description |
|---|---|
| <BoxOrderStepper /> | Multi-step checkout orchestrator |
| <BoxOrderDeliveryStep /> | Delivery selection step |
| <BoxOrderPaymentStep /> | Payment method selection step |
| <BoxOrderSummaryStep /> | Summary and additional fields step |
| <BoxOrderConfirmation /> | Final confirmation screen |
API — Server endpoints
The module exposes the following server-side routes via Nitro:
| Method | Route | Description |
|---|---|---|
| GET | /api/_box/cart | Retrieve the cart |
| POST | /api/_box/cart/addProduct | Add a product |
| POST | /api/_box/cart/updateProduct | Update quantity |
| POST | /api/_box/cart/deleteProduct | Remove a product |
| POST | /api/_box/order | Submit an order |
| GET | /api/_box/order/deliveries | Get available delivery methods |
| GET | /api/_box/order/payments | Get available payment methods |
| POST | /api/_box/erp/order | Forward order to ERP |
| POST | /api/_box/bank/checkout | Initiate a bank payment |
These routes act as proxies to the external API configured via useBoxCartConfig().api.
Best practices
- Initialize
useBoxCartConfig()early — in a Nuxt plugin or root layout, before any cart component renders, with real user data (email, establishmentId, entityId). - Do not hardcode API endpoints in
nuxt.config.ts— useuseBoxCartConfig()to update them dynamically based on user context. - Sync with i18n — update
localeandcurrencyinuseBoxCartConfig()on language changes. - HT vs TTC mode — set
isHtbased on the user profile (business customers → HT, consumers → TTC).
Known limitations
- The module is designed for the Autopartspro ecosystem — some data structures (deposits/consignes, vehicle info, conditioning) are domain-specific.
- Compatibility is limited to Nuxt
^4.0.0 < 5.0.0— not compatible with Nuxt 3. - Server endpoints act as proxies: the external API must be correctly configured via
useBoxCartConfig(). - TODO: document the exact error response format for consumer-side error handling.
Contributing
This module is an internal package in the Graphibox / Autopartspro ecosystem.
# Install dependencies
npm install
# Prepare and start the playground
npm run dev
# Build
npm run prepack
# Tests
npm run test
npm run test:types
# Lint
npm run lint