428 lines
11 KiB
Vue
428 lines
11 KiB
Vue
<script>
|
|
import { storeToRefs } from "pinia";
|
|
import { computed, defineComponent, onBeforeMount, ref, watch } from "vue";
|
|
import { useRoute } from "vue-router";
|
|
|
|
import SortSelect from "src/components/@inputs/SortSelect.vue";
|
|
import IconArrowCircleFilledRight from "src/components/icons/IconArrowCircleFilledRight.vue";
|
|
import IconArrowDownWhite from "src/components/icons/IconArrowDownWhite.vue";
|
|
import IconFilter from "src/components/icons/IconFilter.vue";
|
|
import IconPencil from "src/components/icons/IconPencil.vue";
|
|
import DudasSection from "src/components/sections/DudasSection.vue";
|
|
import Card from "src/components/ui/Card.vue";
|
|
import Container from "src/components/ui/Container.vue";
|
|
import Modal from "src/components/ui/Modal.vue";
|
|
|
|
import { quasarNotify } from "src/functions/quasarNotify";
|
|
import { useLocalStorage } from "src/hooks/useLocalStorage";
|
|
import { usePostalCalendar } from "src/hooks/usePostalCalendar";
|
|
import { useCartStore } from "src/stores/cart";
|
|
import { useFormStore } from "src/stores/forms";
|
|
import { useMobileStore } from "src/stores/mobileNav";
|
|
import { useModalStore } from "src/stores/modalStore";
|
|
|
|
export default defineComponent({
|
|
name: "CategoryPage",
|
|
components: {
|
|
IconArrowCircleFilledRight,
|
|
IconArrowDownWhite,
|
|
IconPencil,
|
|
IconFilter,
|
|
Container,
|
|
DudasSection,
|
|
Modal,
|
|
Card,
|
|
SortSelect,
|
|
},
|
|
setup() {
|
|
const route = useRoute();
|
|
|
|
const { getItem } = useLocalStorage();
|
|
|
|
const { isAvailabilityEmpty } = usePostalCalendar({});
|
|
|
|
const mobileStore = useMobileStore();
|
|
const { screenWidth } = storeToRefs(mobileStore);
|
|
|
|
const modalStore = useModalStore();
|
|
const { openModal } = modalStore;
|
|
|
|
const formStore = useFormStore();
|
|
const { sortProductFilters, availability } = storeToRefs(formStore);
|
|
|
|
const cartStore = useCartStore();
|
|
const { products } = storeToRefs(cartStore);
|
|
const { getProducts } = cartStore;
|
|
|
|
const isOpenOrder = ref(false);
|
|
const availabilityStoraged = ref(getItem("availability"));
|
|
const isNotAllCategory = computed(() => {
|
|
return route.path.split("/")[2] !== "all";
|
|
});
|
|
const datePostalCode = ref({});
|
|
|
|
const orderText = {
|
|
"lowest-price": "menor precio",
|
|
"highest-price": "mayor precio",
|
|
recommended: "recomendados",
|
|
latest: "más recientes",
|
|
};
|
|
const categoryObj = {
|
|
plantas: "Floranet Plantas",
|
|
ramos: "Floranet Ramos",
|
|
};
|
|
const dateExpiredMonth = computed(
|
|
() =>
|
|
availability.value.dateExpired?.split("-")[1] ||
|
|
availabilityStoraged.value.dateExpired?.split("-")[1]
|
|
);
|
|
const dateExpiredDay = computed(
|
|
() =>
|
|
availability.value.dateExpired?.split("-")[2] ||
|
|
availabilityStoraged.value.dateExpired?.split("-")[2]
|
|
);
|
|
|
|
const months = {
|
|
"01": "Enero",
|
|
"02": "Febrero",
|
|
"03": "Marzo",
|
|
"04": "Abril",
|
|
"05": "Mayo",
|
|
"06": "Junio",
|
|
"07": "Julio",
|
|
"08": "Agosto",
|
|
"09": "Septiembre",
|
|
10: "Octubre",
|
|
11: "Noviembre",
|
|
12: "Diciembre",
|
|
};
|
|
const currentMonth = months[dateExpiredMonth.value];
|
|
|
|
watch(
|
|
[() => route.path, () => sortProductFilters.value.order],
|
|
([newPath, newOrder]) => {
|
|
const categoryPath = newPath.split("/")[2];
|
|
sortProductFilters.value.category = categoryPath;
|
|
|
|
const params = {};
|
|
|
|
if (categoryPath !== "all") {
|
|
params.type = categoryObj[categoryPath];
|
|
}
|
|
if (categoryPath === "all") {
|
|
params.dateExpired = availabilityStoraged.value.dateExpired;
|
|
params.postalCode = availabilityStoraged.value.postalCode;
|
|
}
|
|
|
|
const paramsObj = {
|
|
"lowest-price": () => {
|
|
params.lowPrice = 1;
|
|
},
|
|
"highest-price": () => {
|
|
params.bigPrice = 1;
|
|
},
|
|
latest: () => {
|
|
params.isNew = 1;
|
|
},
|
|
recommended: () => {
|
|
params.recommend = 1;
|
|
},
|
|
};
|
|
if (newOrder) {
|
|
paramsObj[newOrder]();
|
|
}
|
|
|
|
getProducts(params);
|
|
}
|
|
);
|
|
|
|
watch(
|
|
() => route.path,
|
|
() => {
|
|
datePostalCode.value = isNotAllCategory.value
|
|
? availability.value
|
|
: availabilityStoraged.value;
|
|
}
|
|
);
|
|
|
|
onBeforeMount(async () => {
|
|
const categoryPath = route.path.split("/")[2];
|
|
|
|
if (categoryPath !== "all") {
|
|
await getProducts({
|
|
type: categoryObj[categoryPath],
|
|
});
|
|
datePostalCode.value = availability.value;
|
|
|
|
return;
|
|
}
|
|
|
|
await getProducts(availabilityStoraged.value);
|
|
datePostalCode.value = availabilityStoraged.value;
|
|
if (isAvailabilityEmpty.value) {
|
|
quasarNotify({
|
|
message: "Debes seleccionar una fecha y código postal",
|
|
type: "warning",
|
|
});
|
|
}
|
|
});
|
|
|
|
function openOrderFilter() {
|
|
sortProductFilters.value.isOpenOrderFilter =
|
|
!sortProductFilters.value.isOpenOrderFilter;
|
|
}
|
|
|
|
return {
|
|
openOrderFilter,
|
|
openModal,
|
|
sortProductFilters,
|
|
isOpenOrder,
|
|
screenWidth,
|
|
modalStore,
|
|
orderText,
|
|
products,
|
|
isNotAllCategory,
|
|
availabilityStoraged,
|
|
currentMonth,
|
|
dateExpiredDay,
|
|
datePostalCode,
|
|
availability,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<q-page class="category-container">
|
|
<section class="products-section">
|
|
<header class="products-section-header">
|
|
<Container>
|
|
<div class="product-header-content" v-if="isNotAllCategory">
|
|
<h3 class="product-header-title subtitle">
|
|
{{ sortProductFilters.category }} para obsequiar
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="product-header-filters">
|
|
<div class="product-left-filters">
|
|
<div class="filter-item availability-filter">
|
|
<p class="filter-paragraph availability">
|
|
Disponibilidad para:
|
|
<span
|
|
v-if="
|
|
datePostalCode.dateExpired && datePostalCode.postalCode
|
|
"
|
|
class="green-text"
|
|
>
|
|
{{ dateExpiredDay }} {{ currentMonth }} en
|
|
{{
|
|
availability.postalCode || datePostalCode.postalCode
|
|
}}</span
|
|
>
|
|
</p>
|
|
|
|
<q-btn
|
|
flat
|
|
class="btn filter-btn availability"
|
|
type="button"
|
|
@click="openModal({ modal: 'availability' })"
|
|
>
|
|
<IconPencil />
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="product-right-filters">
|
|
<q-btn
|
|
flat
|
|
class="btn filter-item filters filter-btn"
|
|
type="button"
|
|
@click="openModal({ modal: 'filters' })"
|
|
>
|
|
<p class="filter-paragraph remove-mob">Filtros</p>
|
|
<IconFilter />
|
|
</q-btn>
|
|
|
|
<div
|
|
class="filter-item order-filter"
|
|
:class="sortProductFilters.isOpenOrderFilter && 'active'"
|
|
>
|
|
<div class="order-filters">
|
|
<p class="filter-paragraph">
|
|
Ordenar por:
|
|
<span class="green-text">
|
|
{{ orderText[sortProductFilters.order] || "" }}
|
|
</span>
|
|
</p>
|
|
|
|
<SortSelect v-if="sortProductFilters.isOpenOrderFilter" />
|
|
</div>
|
|
|
|
<q-btn
|
|
flat
|
|
@click="openOrderFilter"
|
|
type="button"
|
|
class="btn filter-btn price-order"
|
|
>
|
|
<IconArrowDownWhite />
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Container>
|
|
</header>
|
|
|
|
<div class="products-section-body">
|
|
<Container cardContainer class="category-container">
|
|
<template v-for="item in products.data" :key="item?.id">
|
|
<Card
|
|
v-if="item"
|
|
:price="item.price"
|
|
:title="item.name"
|
|
:imgSrc="item.image"
|
|
:isNew="item.isNew"
|
|
:id="item.id"
|
|
/>
|
|
</template>
|
|
</Container>
|
|
</div>
|
|
|
|
<footer class="products-section-footer" v-if="isNotAllCategory">
|
|
<RouterLink class="btn rounded outlined" to="/categoria/all">
|
|
Ver todos los diseños <IconArrowCircleFilledRight />
|
|
</RouterLink>
|
|
</footer>
|
|
</section>
|
|
|
|
<dudas-section />
|
|
<Modal modalItem="isOpenAvailability" typeModal="availability" />
|
|
<Modal modalItem="isOpenFilters" typeModal="filter" />
|
|
</q-page>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.products-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
margin-bottom: 82px;
|
|
|
|
& .products-section-header {
|
|
& .product-header-content {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
text-align: center;
|
|
gap: 25px;
|
|
margin-bottom: 93px;
|
|
& .product-header-title::first-letter {
|
|
text-transform: capitalize;
|
|
}
|
|
}
|
|
|
|
& .product-header-filters {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 41px;
|
|
margin-bottom: 78px;
|
|
& .filter-paragraph {
|
|
font-size: $font-14;
|
|
color: $text-gray;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
& .filter-item {
|
|
padding: 4px 0 4px 14px;
|
|
background-color: $secondary-10;
|
|
border-radius: 30px 0 0 30px;
|
|
display: flex;
|
|
align-items: center;
|
|
position: relative;
|
|
user-select: none;
|
|
&.availability-filter {
|
|
padding: 4px 30px 4px 14px;
|
|
}
|
|
&.order-filter {
|
|
padding: 4px 10px 4px 20px;
|
|
text-align: end;
|
|
border-radius: 10px 0px 0px 10px;
|
|
&.active {
|
|
border-radius: 10px 0px 0px 0px;
|
|
}
|
|
|
|
& .order-filters {
|
|
position: relative;
|
|
}
|
|
}
|
|
|
|
&.filters {
|
|
padding: 4px 15px 4px 10px;
|
|
border-radius: 30px;
|
|
}
|
|
&.filter-price-order {
|
|
}
|
|
}
|
|
|
|
& .filter-btn {
|
|
padding: 8px;
|
|
border-radius: 0 30px 30px 0;
|
|
|
|
&.availability,
|
|
&.price-order {
|
|
position: absolute;
|
|
}
|
|
|
|
&.availability {
|
|
right: -27px;
|
|
padding: 6.5px;
|
|
}
|
|
|
|
&.price-order {
|
|
right: -33px;
|
|
padding: 9.5px;
|
|
top: 0;
|
|
}
|
|
}
|
|
|
|
& .product-right-filters {
|
|
display: flex;
|
|
gap: 40px;
|
|
margin-right: 33px;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
@media only screen and (max-width: $med-md) {
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
& .filter-paragraph.remove-mob {
|
|
display: none;
|
|
}
|
|
|
|
& .filter-item.filters {
|
|
padding: 4px 8px;
|
|
}
|
|
|
|
& .product-left-filters {
|
|
flex: 1;
|
|
margin-right: 28px;
|
|
}
|
|
|
|
& .product-right-filters {
|
|
flex: 1;
|
|
justify-content: space-between;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
& .products-section-body {
|
|
margin-bottom: 95px;
|
|
}
|
|
& .products-section-footer {
|
|
align-self: center;
|
|
}
|
|
}
|
|
</style>
|