liste-bebe-macia-capde-front/components/GiftCard.vue

289 lines
6.4 KiB
Vue

<script setup>
const props = defineProps({
item: { type: Object, default: () => {} },
statusMessage: { type: String, default: "" },
});
let showDetails = ref(true);
const formError = ref("");
const isFormVisible = ref(false);
function showReservation() {
isFormVisible.value = !isFormVisible.value;
}
const reserved = ref(false);
const fromName = ref("");
const emit = defineEmits(["reserved"]);
const sendReservation = (id, reserve, name) => {
console.log(fromName);
if (reserved.value && fromName.value.length > 1) {
emit("reserved", { id, reserve, name });
formError.value = "";
} else {
formError.value = "Veuillez remplir le formulaire";
}
};
</script>
<template>
<section class="gift flow">
<div class="gift__info">
<h2 class="h3">
<NuxtLink :to="item.url">{{ item.name }}</NuxtLink>
</h2>
<div class="gift__status">
<p v-if="!item.reserved">🎉 Ce cadeau est disponible&nbsp;!</p>
<p v-else>
Ce cadeau est déjà réservé par
<span class="from-name">{{ item.from || "¯\_(ツ)_/¯" }}</span> 🤗
</p>
</div>
<p v-if="!item.reserved && item.prix" class="h2 gift__price">
{{ item.prix }}&nbsp;€
</p>
<button v-if="!item.reserved" @click="showReservation" class="btn">
Réserver
</button>
</div>
<div v-if="!item.reserved" class="gift__actions">
<div v-if="isFormVisible" class="flow">
<form>
<div class="field form__confirmation">
<label :for="`name-${item.id}`">Votre nom (requis)</label>
<input
type="text"
name="name"
:id="`name-${item.id}`"
placeholder="Jeanne"
v-model="fromName"
required
/>
</div>
<div class="field form__reservation">
<input
type="checkbox"
name="check"
:id="`check-${item.id}`"
v-model="reserved"
required
/>
<label :for="`check-${item.id}`">Confirmer la réservation</label>
</div>
<button
@click.prevent="sendReservation(item.id, reserved, fromName)"
:disabled="reserved && fromName.length > 1 ? false : true"
>
Valider le cadeau
</button>
</form>
<div
v-if="statusMessage || formError"
aria-live="polite"
aria-atomic="false"
class="form__errors"
>
<p v-if="statusMessage">
{{ statusMessage }}
</p>
<p v-if="formError">
{{ formError }}
</p>
</div>
</div>
<details
v-if="!item.reserved"
class="flow"
:open="showDetails"
@click.prevent="showDetails = !showDetails"
>
<summary>
<span v-if="showDetails">Masquer les détails</span>
<span v-else>Voir les détails</span>
</summary>
<div class="gift__details">
<NuxtPicture
v-if="item.photo"
format="avif,webp"
class="gift__photo"
:src="`https://contenu.liste-bebe-macia-capde.fr/assets/${item.photo.id}?width=200&height=200&fit=inside`"
loading="lazy"
width="200"
height="200"
fit="inside"
alt=""
/>
<div class="gift__buying">
<span v-if="item.used" class="gift__used">Occasion ok&nbsp;!</span>
<p
v-if="!item.reserved && item.description"
class="gift__description"
>
{{ item.description }}
</p>
</div>
</div>
</details>
</div>
</section>
</template>
<style scoped>
.gift {
container-type: inline-size;
container-name: card;
border-radius: 8px;
padding: var(--space-xs-s);
box-shadow: 0 0 8px 0 hsla(24, 91%, 35%, 0.2);
background-color: white;
}
.gift__info {
display: flex;
flex-direction: column;
gap: var(--space-s-m);
align-items: center;
text-align: center;
}
.gift__status {
color: var(--color-yellow-dark);
}
details {
margin-block-start: var(--space-xs);
text-align: center;
}
details summary {
font-size: var(--size--1);
font-weight: bold;
text-transform: uppercase;
color: var(--color-yellow-dark);
}
.gift__details {
display: flex;
flex-direction: column;
gap: var(--space-xs);
align-items: center;
}
.gift__photo {
align-self: center;
}
.gift__buying {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2xs);
}
.gift__price {
margin-block: var(--space-3xs);
padding: var(--space-2xs);
text-align: center;
font-weight: 500;
align-self: center;
border-block: 2px solid var(--color-green-dark);
}
.gift__used {
padding: var(--space-3xs) var(--space-2xs);
font-size: var(--size--1);
background-color: var(--color-green-light);
border-radius: 40px;
}
.gift__description {
padding: var(--space-2xs) var(--space-xs);
font-size: var(--size-0);
border-radius: 8px;
color: var(--color-green-light);
background-color: var(--color-green-dark);
}
.from-name {
text-transform: capitalize;
}
.btn {
margin-block-start: auto;
padding: var(--space-2xs) var(--space-xs);
position: relative;
align-self: center;
font-size: var(--size-0);
border-radius: 8px;
border: 1px solid var(--color-green-light);
background-color: white;
transition: background-color 0.3s ease;
}
.btn:focus-within,
.btn:hover {
background-color: var(--color-yellow-light);
}
form,
.form__confirmation {
display: flex;
flex-flow: column wrap;
gap: var(--space-xs);
}
.form__reservation label {
margin-inline-start: var(--space-3xs);
}
.form__confirmation input {
padding: var(--space-3xs) var(--space-2xs);
font-size: var(--size--1);
font-weight: bold;
border: 1px solid var(--color-green-dark);
}
form button {
padding: var(--space-2xs) var(--space-2xs);
font-size: var(--size--1);
border: 1px solid transparent;
border-radius: 8px;
transition-property: background-color, color;
transition-duration: 0.3s;
transition-timing-function: ease;
}
form button:not([disabled]) {
color: var(--color-yellow-light);
border-color: var(--color-green-dark);
background-color: var(--color-green-dark);
}
form button:not([disabled]):is(:hover, :focus) {
color: var(--color-green-dark);
background-color: var(--color-yellow-light);
}
.form__errors {
font-size: var(--size--1);
}
@container card (min-inline-size: 60rem) {
.gift__info {
flex-flow: row wrap;
justify-content: flex-start;
row-gap: var(--space-2xs);
}
.gift__price {
margin: 0;
margin-inline-start: auto;
}
.gift__actions {
display: grid;
grid-template-columns: 1fr 2fr;
gap: var(--space-s-m);
align-content: end;
}
details {
margin: 0;
text-align: right;
grid-column: 2 / 3;
}
.gift__details {
flex-flow: row nowrap;
justify-content: flex-end;
}
.gift__description {
text-align: left;
}
.gift__buying {
align-items: flex-start;
}
}
</style>