288 lines
5.6 KiB
Vue
288 lines
5.6 KiB
Vue
<script>
|
|
import { defineComponent, ref } from "vue";
|
|
import IconEyes from "../icons/IconEyes.vue";
|
|
|
|
export default defineComponent({
|
|
name: "card-component",
|
|
components: { IconEyes },
|
|
props: {
|
|
price: {
|
|
type: String,
|
|
default: "",
|
|
required: true,
|
|
},
|
|
title: {
|
|
type: String,
|
|
default: "",
|
|
required: true,
|
|
},
|
|
discount: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
imgSrc: {
|
|
type: String,
|
|
default: "",
|
|
required: true,
|
|
},
|
|
imgClass: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
headClass: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
isNew: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
size: {
|
|
type: String,
|
|
default: "md-card",
|
|
},
|
|
alt: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
id: {
|
|
type: Number,
|
|
required: true,
|
|
},
|
|
},
|
|
setup({ price, discount }) {
|
|
const isLoaded = ref(false);
|
|
const isError = ref(false);
|
|
const percent = +discount / 100;
|
|
//const priceWithoutLetter = ~~price?.replaceAll("€", "");
|
|
const priceWithoutLetter = price;
|
|
const finalValue = ~~(priceWithoutLetter - priceWithoutLetter * percent);
|
|
console.log(price);
|
|
|
|
const onLoad = () => {
|
|
isLoaded.value = true;
|
|
};
|
|
|
|
const onError = () => {
|
|
isError.value = true;
|
|
};
|
|
|
|
return {
|
|
onLoad,
|
|
onError,
|
|
isLoaded,
|
|
isError,
|
|
finalValue,
|
|
priceWithoutLetter,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="card-container" :class="size">
|
|
<RouterLink
|
|
:to="`/product/${id}`"
|
|
class="card-container-head"
|
|
:class="[headClass]"
|
|
role="heading"
|
|
>
|
|
<div v-if="isNew || discount" class="tags">
|
|
<p v-if="isNew" class="tag new">Nuevo</p>
|
|
<p v-if="discount" class="tag discount">-{{ discount }}%</p>
|
|
</div>
|
|
|
|
<img
|
|
class="card-img"
|
|
:class="[imgClass]"
|
|
:src="imgSrc && !isError ? imgSrc : '../../assets/empty-img.jpg'"
|
|
:alt="alt"
|
|
:key="imgSrc"
|
|
@load="onLoad"
|
|
@error="onError"
|
|
/>
|
|
<q-skeleton
|
|
v-if="!isLoaded"
|
|
class="skeleton"
|
|
width="100%"
|
|
height="100%"
|
|
/>
|
|
|
|
<div class="head-hovered">
|
|
<IconEyes />
|
|
<p class="head-hovered-paragraph">Ver producto</p>
|
|
</div>
|
|
</RouterLink>
|
|
|
|
<div class="card-container-body">
|
|
<p class="card-name" v-if="title">{{ title }}</p>
|
|
|
|
<div class="card-values">
|
|
<p class="price" v-if="finalValue">{{ finalValue }}€</p>
|
|
<p class="price offer tachado" v-if="+price !== finalValue">
|
|
{{ price }}€
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.card-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
user-select: none;
|
|
height: 100%;
|
|
|
|
&:focus {
|
|
outline: 2px solid $secondary;
|
|
}
|
|
|
|
&.md-card {
|
|
& .card-container-head {
|
|
height: 300px;
|
|
@media only screen and (min-width: $med-hg) {
|
|
height: 352px;
|
|
}
|
|
@media only screen and (max-width: $med-md) {
|
|
border-radius: 10px;
|
|
height: 188px;
|
|
}
|
|
}
|
|
}
|
|
|
|
&.lg-card {
|
|
& .card-container-head {
|
|
height: 409px;
|
|
@media only screen and (max-width: $med-lg) {
|
|
border-radius: 10px;
|
|
height: 188px;
|
|
}
|
|
}
|
|
}
|
|
|
|
& .card-container-head {
|
|
border-radius: 15px;
|
|
overflow: hidden;
|
|
position: relative;
|
|
height: 100%;
|
|
max-height: 409px;
|
|
&.list-products-head {
|
|
min-height: 365px;
|
|
@media only screen and (max-width: $med-sm) {
|
|
min-height: 190px;
|
|
}
|
|
}
|
|
|
|
&:focus-visible {
|
|
outline: 2px solid $primary-light;
|
|
}
|
|
|
|
&:hover {
|
|
& .tags {
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
}
|
|
|
|
& .head-hovered {
|
|
visibility: visible;
|
|
background-color: $primary-dark-transparent;
|
|
}
|
|
}
|
|
|
|
& .tags,
|
|
& .head-hovered {
|
|
transition: 100ms ease-out;
|
|
}
|
|
|
|
& .tags {
|
|
position: absolute;
|
|
left: 15px;
|
|
top: 14px;
|
|
display: flex;
|
|
gap: 4px;
|
|
|
|
& .tag {
|
|
border-radius: 3px;
|
|
padding: 2px 6px 2px 9px;
|
|
font-family: $font-lora;
|
|
user-select: none;
|
|
font-weight: 600;
|
|
font-size: $font-12;
|
|
|
|
&.new {
|
|
color: $white;
|
|
background: $primary-dark;
|
|
}
|
|
|
|
&.discount {
|
|
background: $primary-light;
|
|
color: $primary-dark;
|
|
}
|
|
|
|
@media only screen and (max-width: $med-lg) {
|
|
font-size: $font-10;
|
|
}
|
|
}
|
|
}
|
|
|
|
& .card-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
&.list-products {
|
|
@media only screen and (min-width: calc($med-md + 1px)) {
|
|
min-height: 352px;
|
|
}
|
|
|
|
@media only screen and (max-width: $med-md) {
|
|
min-height: 190px;
|
|
}
|
|
}
|
|
|
|
&.carousel {
|
|
max-height: 410px;
|
|
}
|
|
}
|
|
|
|
& .skeleton {
|
|
position: absolute;
|
|
inset: 0;
|
|
background-color: $primary;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
& .head-hovered {
|
|
position: absolute;
|
|
inset: 0;
|
|
visibility: hidden;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
& .head-hovered-paragraph {
|
|
font-family: $font-lora;
|
|
color: $white;
|
|
}
|
|
}
|
|
|
|
@media only screen and (max-width: $med-md) {
|
|
border-radius: 10px;
|
|
}
|
|
}
|
|
|
|
& .card-container-body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
text-align: start;
|
|
& .card-values {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|