63 lines
2.9 KiB
Vue
63 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import type { Dish } from '~/server/utils/store'
|
|
|
|
const props = withDefaults(defineProps<{ dish: Dish, layout?: 'grid' | 'row' }>(), { layout: 'grid' })
|
|
const { open } = useCustomize()
|
|
const { open: shopOpen } = useShop()
|
|
const sizes = computed(() => sizesOf(props.dish))
|
|
const can = computed(() => orderable(props.dish) && shopOpen.value)
|
|
const status = computed(() => !props.dish.available ? 'Rupture' : !orderable(props.dish) ? 'Bientôt' : !shopOpen.value ? 'En pause' : '')
|
|
</script>
|
|
|
|
<template>
|
|
<article class="dish card hover-lift" :class="[layout, { off: !dish.available }]">
|
|
<div class="photo wood">
|
|
<DishPhoto :img="dish.img" :alt="dish.name" />
|
|
<span v-if="dish.badge" class="badge tag" :class="`badge-${dish.badge.tone}`">{{ dish.badge.label }}</span>
|
|
<span v-if="!dish.available" class="badge tag-off">Rupture de stock</span>
|
|
</div>
|
|
<div class="body">
|
|
<h3>{{ dish.name }}</h3>
|
|
<p class="desc">{{ dish.desc }}</p>
|
|
<div class="foot">
|
|
<p class="prices">
|
|
<template v-for="(s, i) in sizes" :key="s">
|
|
<span v-if="i" class="muted"> · </span>
|
|
<span class="muted">{{ s }}</span> <strong class="price">{{ eur(dish.prices[s]) }}</strong>
|
|
</template>
|
|
</p>
|
|
<button v-if="can" class="btn btn-primary btn-icon add" type="button" :aria-label="`Ajouter ${dish.name}`" @click="open(dish)">
|
|
<Icon name="plus" :size="22" :stroke="3" />
|
|
</button>
|
|
<span v-else class="chip status">{{ status }}</span>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.dish { overflow: hidden; display: flex; flex-direction: column; }
|
|
.photo { position: relative; height: 190px; }
|
|
.photo :deep(.dish-photo) { position: absolute; inset: 12px 7% 6px; }
|
|
.tag { position: absolute; left: 12px; top: 12px; }
|
|
.tag-off { position: absolute; right: 12px; top: 12px; background: var(--danger); color: var(--bg); }
|
|
.body { flex: 1; padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 6px; }
|
|
h3 { font-size: 19px; font-weight: 800; color: var(--white); }
|
|
.desc { font-size: 14px; opacity: .78; }
|
|
.foot { margin-top: auto; padding-top: 8px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
.prices { font-size: 14px; }
|
|
.prices .price { font-size: 17px; }
|
|
.status { font-size: 13px; padding: 8px 12px; background: var(--surface-2); }
|
|
.off .photo { filter: grayscale(.8) brightness(.7); }
|
|
|
|
/* Variante liste (mobile) */
|
|
.row { flex-direction: row; gap: 14px; padding: 12px; }
|
|
.row .photo { flex: none; width: 112px; height: 124px; border-radius: 16px; overflow: hidden; }
|
|
.row .photo :deep(.dish-photo) { inset: 14px 4px 10px; }
|
|
.row .tag { left: 6px; top: 6px; font-size: 10px; padding: 3px 7px; }
|
|
.row .tag-off { display: none; }
|
|
.row .body { padding: 0; }
|
|
.row h3 { font-size: 17px; }
|
|
.row .desc { font-size: 13px; }
|
|
.row .prices .price { font-size: 15px; }
|
|
</style>
|