floranet/src/pages/CategoryPage.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>