61 lines
3.4 KiB
Vue
61 lines
3.4 KiB
Vue
|
|
<script setup lang="ts">
|
|||
|
|
// Panier latéral (desktop) sur la page Menu
|
|||
|
|
const { lines, count, subtotal, setQty, mode, bump } = useCart()
|
|||
|
|
const { settings } = useShop()
|
|||
|
|
const fee = computed(() => mode.value === 'livraison' && count.value && subtotal.value < (settings.value?.freeFrom ?? 3500) ? (settings.value?.deliveryFee ?? 250) : 0)
|
|||
|
|
const popping = ref(false)
|
|||
|
|
watch(bump, () => { popping.value = false; requestAnimationFrame(() => { popping.value = true }) })
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<aside class="cs card" :class="{ pop: popping }" aria-labelledby="cs-h">
|
|||
|
|
<div class="row" style="justify-content: space-between">
|
|||
|
|
<h2 id="cs-h" style="font-size: 20px; font-weight: 800; color: #fff">Ton panier</h2>
|
|||
|
|
<span class="small muted">{{ count }} article(s)</span>
|
|||
|
|
</div>
|
|||
|
|
<p v-if="!lines.length" class="empty muted">Ton panier est vide.<br>Le Crousty t'attend 🔥</p>
|
|||
|
|
<ul v-else class="lines">
|
|||
|
|
<li v-for="l in lines" :key="l.key">
|
|||
|
|
<img v-if="l.img" :src="l.img" alt="" class="thumb">
|
|||
|
|
<span v-else class="thumb ph" />
|
|||
|
|
<div class="grow">
|
|||
|
|
<p class="strong" style="font-size: 15px">{{ l.name }} {{ l.size }}</p>
|
|||
|
|
<p class="small muted">{{ [l.meat, l.sauce, ...l.extrasLabel].filter(Boolean).join(' · ') }}</p>
|
|||
|
|
<div class="row" style="justify-content: space-between; margin-top: 6px">
|
|||
|
|
<div class="qty mini">
|
|||
|
|
<button type="button" :aria-label="`Retirer un ${l.name}`" @click="setQty(l.key, l.qty - 1)">−</button>
|
|||
|
|
<span>{{ l.qty }}</span>
|
|||
|
|
<button type="button" :aria-label="`Ajouter un ${l.name}`" @click="setQty(l.key, l.qty + 1)">+</button>
|
|||
|
|
</div>
|
|||
|
|
<strong class="price">{{ eur(l.unit * l.qty) }}</strong>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
<dl class="tot">
|
|||
|
|
<dt>Sous-total</dt><dd>{{ eur(subtotal) }}</dd>
|
|||
|
|
<dt>{{ mode === 'livraison' ? 'Livraison' : 'Retrait sur place' }}</dt><dd>{{ mode === 'livraison' ? eur(fee) : 'Gratuit' }}</dd>
|
|||
|
|
<dt>Frais de service</dt><dd style="color: var(--leaf)">0,00 €</dd>
|
|||
|
|
<dt class="big">Total</dt><dd class="big price">{{ eur(subtotal + fee) }}</dd>
|
|||
|
|
</dl>
|
|||
|
|
<NuxtLink v-if="lines.length" to="/panier" class="btn btn-primary btn-lg btn-block">Commander — {{ eur(subtotal + fee) }}</NuxtLink>
|
|||
|
|
<p class="small muted" style="text-align: center">Commande directe : zéro commission d'appli, 100 % pour le resto 🌴</p>
|
|||
|
|
</aside>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.cs { padding: 22px; display: flex; flex-direction: column; gap: 14px; border: 1px solid rgba(243,227,195,.08); box-shadow: 0 30px 60px rgba(0,0,0,.35); }
|
|||
|
|
.cs.pop { animation: none; }
|
|||
|
|
.empty { padding: 20px 0; text-align: center; }
|
|||
|
|
.lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto; }
|
|||
|
|
.lines li { display: flex; gap: 10px; padding: 10px; border-radius: 16px; background: var(--bg); }
|
|||
|
|
.thumb { width: 54px; height: 54px; object-fit: contain; flex: none; }
|
|||
|
|
.thumb.ph { border-radius: 12px; background: var(--surface-2); }
|
|||
|
|
.qty.mini button { width: 30px; height: 30px; font-size: 16px; }
|
|||
|
|
.tot { margin: 0; padding-top: 12px; border-top: 1px solid var(--line); display: grid; grid-template-columns: 1fr auto; gap: 8px; font-size: 14px; }
|
|||
|
|
.tot dt { opacity: .75; }
|
|||
|
|
.tot dd { margin: 0; font-weight: 700; text-align: right; }
|
|||
|
|
.tot .big { font-size: 20px; font-weight: 800; opacity: 1; color: #fff; }
|
|||
|
|
.tot dd.big { color: var(--orange-1); }
|
|||
|
|
</style>
|