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, }; });