floranet/src/stores/cart.js

254 lines
6.3 KiB
JavaScript

import { defineStore, storeToRefs } from "pinia";
import { computed, ref } from "vue";
import { useRouter } from "vue-router";
import { apiBack } from "src/boot/axios";
import { quasarNotify } from "src/functions/quasarNotify";
import { useLocalStorage } from "src/hooks/useLocalStorage";
import { useFormStore } from "./forms";
export const useCartStore = defineStore("cart", () => {
const { push } = useRouter();
const { addItem, getItem } = useLocalStorage();
const formStore = useFormStore();
const { availability: availabilityForm } = storeToRefs(formStore);
//! Elements
const checkoutRef = ref(null);
const homeSection = ref(null);
const initialValues = [
{
id: null,
name: "",
price: null,
image: "",
description: "",
dateExpired: "",
isNew: null,
type: "",
postalCode: "",
order_position: null,
recommend: null,
},
];
//! Variables
const cart = ref(getItem("cart"));
const availability = ref(getItem("availability"));
const addCartLoadingBtn = ref(false);
const routeId = ref(null);
const products = ref({
data: initialValues,
prev: initialValues,
current: initialValues,
next: initialValues,
});
function transformOptionsToParams(options = {}) {
const optionsObj = {
postalCode: options.postalCode,
dateExpired: options.dateExpired,
type: options.type,
minPrice: options.minPrice,
maxPrice: options.maxPrice,
bigPrice: options.bigPrice,
lowPrice: options.lowPrice,
isNew: options.isNew,
order_crescent: options.order_crescent,
order_descending: options.order_descending,
recommend: options.recommend,
};
const validKeys = Object.keys(options).filter(
(key) => options[key] !== undefined
);
const params = validKeys.reduce((acc, key) => {
acc[key] = optionsObj[key];
return acc;
}, {});
return params;
}
const isEmpty = ref(false);
async function getProducts(
options = {
postalCode: undefined,
dateExpired: undefined,
type: undefined,
minPrice: undefined,
maxPrice: undefined,
bigPrice: undefined,
lowPrice: undefined,
isNew: undefined,
order_crescent: undefined,
order_descending: undefined,
recommend: undefined,
},
callback
) {
const params = transformOptionsToParams(options);
try {
const {
data: { data },
} = await apiBack.get("products", { params });
if (data.length === 0) {
isEmpty.value = true;
return quasarNotify({
message:
"No hay productos disponibles para la fecha y el código postal seleccionados",
type: "erro",
});
}
isEmpty.value = false;
products.value.data = data;
if (callback) {
callback();
}
console.groupCollapsed("%c PRODUCTS FETCHED!", "color: green;");
console.groupCollapsed("%c PRODUCTS DATA", "color: tomato;");
console.table(products.value.data);
console.groupEnd();
console.groupCollapsed("%c PREV PRODUCT", "color: tomato;");
console.table(products.value.prev);
console.groupEnd();
console.groupCollapsed(
`%c CURRENT PRODUCT: ${products.value.current.slug}`,
"color: tomato;"
);
console.table(products.value.current);
console.groupEnd();
console.groupCollapsed("%c NEXT PRODUCT", "color: tomato;");
console.table(products.value.next);
console.groupEnd();
console.groupEnd();
} catch (err) {
new Error(`FATAL ERROR ::: ${err}`);
}
}
async function getProduct(
id,
options = {
type: undefined,
postalCode: undefined,
dateExpired: undefined,
},
debug = false
) {
if (id) {
routeId.value = id;
try {
const params = transformOptionsToParams(options);
const promises = [
apiBack.get(`products/${+id - 1}`),
apiBack.get(`products/${+id}`),
apiBack.get(`products/${+id + 1}`),
];
const results = await Promise.allSettled(promises);
const [prev, current, next] = results.map((res) => {
const result = {
fulfilled: res.value?.data,
rejected: res.reason,
};
return result[res.status].data[0];
});
products.value.prev = prev;
products.value.current = current;
products.value.next = next;
if (!current) {
push({ name: "NotFound" });
}
if (debug) {
console.groupCollapsed(
`%c PRODUCT FETCHED! SLUG: ${routeId.value}`,
"color: green;"
);
console.table(products.value.prev);
console.table(products.value.current);
console.table(products.value.next);
console.groupEnd();
}
if (products.value.current.response?.status === 404) {
push({ name: "NotFound" });
}
} catch (err) {
console.error(`FATAL ERROR ::: ${err}`);
}
}
}
async function addToCart(product, message) {
const params = transformOptionsToParams(
availabilityForm.value || availability.value
);
await getProducts(params);
const hasCurrentProduct = computed(() => {
return cart.value.find((p) => p.id === product.id);
});
if (isEmpty.value) {
push("/");
return quasarNotify({
message:
"No hay productos disponibles para la fecha y el código postal seleccionados",
type: "erro",
});
}
if (!products.value.data.some((item) => item.id === product.id)) {
push("/");
return quasarNotify({
message:
"Este producto no está disponible en su zona, intente añadir un nuevo código postal",
type: "erro",
});
}
if (hasCurrentProduct.value) {
return quasarNotify({
message: "Este producto ya está en el carrito",
type: "info",
});
}
const arr = [...cart.value];
arr.push({ ...product, message: message.value });
cart.value = arr;
addItem("cart", arr);
await push("/checkout");
quasarNotify({
message: "Producto añadido al carrito.",
type: "success",
});
}
return {
checkoutRef,
homeSection,
cart,
addCartLoadingBtn,
products,
getProducts,
addToCart,
getProduct,
};
});