floranet/src/hooks/usePostalCalendar.js

326 lines
9.1 KiB
JavaScript

import { toTypedSchema } from "@vee-validate/zod";
import { storeToRefs } from "pinia";
import { useForm } from "vee-validate";
import { computed, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { fullCurrentDate } from "src/constants";
import { invertDate } from "src/functions/invertDate";
import { quasarNotify } from "src/functions/quasarNotify";
import { useCartStore } from "src/stores/cart";
import { useFormStore } from "src/stores/forms";
import { useModalStore } from "src/stores/modalStore";
import { useRangePriceStore } from "src/stores/rangePrice";
import { availabilitySchema } from "src/utils/zod/schemas";
import { rangePriceSchema } from "src/utils/zod/schemas/rangePriceSchema";
import { useLocalStorage } from "./useLocalStorage";
/**
* Custom hook for managing postal calendar functionality.
*
* @param {Object} options - The options for the hook.
* @param {string} options.modalItem - The modal item.
* @param {string} options.type - The type of the calendar.
* @returns {Object} - The hook functions and properties.
*/
export function usePostalCalendar({ modalItem = "", type = "home" }) {
const route = useRoute();
const { push } = useRouter();
const { addItem, getItemSession, removeItem } = useLocalStorage();
const modalStore = useModalStore();
const rangePriceStore = useRangePriceStore();
const { rangeValue } = storeToRefs(rangePriceStore);
const formStore = useFormStore();
const { sortProductFilters, availability: availabilityForm } =
storeToRefs(formStore);
const cartStore = useCartStore();
const { addToCart, getProducts } = cartStore;
const { products, cart } = storeToRefs(cartStore);
const min = 0;
const max = 200;
const category = ref(route.path.split("/")[2]);
const categoryObj = {
plantas: "Floranet Plantas",
ramos: "Floranet Ramos",
};
const availability = ref(getItemSession("availability"));
const availabilityFormKeys = computed(() => {
return Object.fromEntries(
Object.entries(availabilityForm.value).filter(
([key, value]) => value !== ""
)
);
});
const isAvailabilityEmpty = computed(() => {
return (
Object.keys(availability.value || availabilityFormKeys.value).length === 0
);
});
const isPostalCalendarEmpty = computed(() => {
if (category.value === "ramos" || category.value === "plantas") {
const isAvailabilityEmptyForm =
Object.keys(availabilityFormKeys.value).length === 0;
return isAvailabilityEmptyForm;
}
return isAvailabilityEmpty.value;
});
let DATE_INITIAL
const [YEAR, MONTH, DAY] = fullCurrentDate.replaceAll("/", "-").split("-");
const CURRENT_DATE = `${DAY}-${MONTH}-${YEAR}`;
DATE_INITIAL = CURRENT_DATE
if (availability.value.dateExpired) {
const [yearStorage, monthStorage, dayStorage] = availability.value.dateExpired.replaceAll("/", "-").split("-");
const STORAGE_DATE = `${dayStorage}-${monthStorage}-${yearStorage}`;
DATE_INITIAL = STORAGE_DATE
}
const POSTAL_CODE_INITIAL = availability.value.postalCode ? availability.value.postalCode : ""
const {
handleSubmit,
handleReset,
defineField,
errors,
setValues,
setFieldError,
} = useForm({
validateOnMount: false,
validationSchema: toTypedSchema(
type !== "filter" ? availabilitySchema : rangePriceSchema
),
initialValues: {
range: {
min,
max,
},
postalCode: POSTAL_CODE_INITIAL,
date: DATE_INITIAL,
},
initialTouched: {
date: availability.value.dateExpired ? true : false,
postalCode: true,
},
});
const options = {
validateOnBlur: false,
validateOnChange: false,
validateOnInput: false,
validateOnModelUpdate: false,
};
const [calendar, calendarAttrs] = defineField("date", options);
const [postalCode, postalCodeAttrs] = defineField("postalCode", options);
const [priceRange, priceRangeAttrs] = defineField("range", options);
const [dedication, dedicationAttrs] = defineField("dedication");
watch(errors, (newErrors) => {
const hasErrors = {
range: newErrors.range,
dedication: newErrors.dedication,
};
for (const [field, hasError] of Object.entries(hasErrors)) {
if (hasError) {
quasarNotify({ message: newErrors[field], type: "erro" });
}
}
});
watch([() => route.path, () => sortProductFilters.value], ([newPath]) => {
const categoryPath = newPath.split("/")[2];
category.value = categoryPath;
availabilityForm.value.dateExpired = "";
availability.value.postalCode = "";
sortProductFilters.value.isOpenOrderFilter = false;
sortProductFilters.value.order = undefined;
});
const removeCart = () => {
removeItem("cart");
cart.value = [];
};
const onSuccess = async (values) => {
const handleAvailability = async () => {
addItem("availability", {
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
});
removeCart();
availabilityForm.value.dateExpired = invertDate(values.date);
availabilityForm.value.postalCode = values.postalCode;
await getProducts({
type: categoryObj[category.value],
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
});
};
const handleHome = async () => {
addItem("availability", {
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
});
availabilityForm.value.dateExpired = invertDate(values.date);
availabilityForm.value.postalCode = values.postalCode;
removeCart();
const callback = async () => {
await push("/categoria/all");
};
await getProducts(
{
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
},
callback
);
};
const handleProduct = async () => {
addItem("availability", {
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
});
removeCart();
availabilityForm.value.dateExpired = invertDate(values.date);
availabilityForm.value.postalCode = values.postalCode;
await getProducts({
postalCode: values.postalCode,
dateExpired: invertDate(values.date),
});
const hasProduct = computed(() => {
return products.value.data.some((item) => {
const date = new Date(item.dateExpired);
const day = date.getDate();
const month = (date.getMonth() + 1).toString().padStart(2, "0");
const year = date.getFullYear();
const dateExpired = `${day}/${month}/${year}`;
const dateSelected = values.date.replaceAll("-", "/");
const id = +route.path.split("/")[2];
return (
item.postalCode === values.postalCode &&
item.id === id &&
dateSelected <= dateExpired
);
});
});
if (!hasProduct.value) {
quasarNotify({
message: "Código postal y fecha de caducidad añadidos con éxito",
type: "success",
});
return;
}
// go();
addToCart(products.value.current, dedication);
};
const handleFilter = async () => {
rangeValue.value.max = values.range.max;
rangeValue.value.min = values.range.min;
const params = {
type: categoryObj[category.value],
minPrice: values.range.min,
maxPrice: values.range.max,
postalCode: availabilityForm.value.postalCode,
dateExpired: availabilityForm.value.dateExpired,
};
if (category.value === "all") {
params.postalCode =
availability.value.postalCode || availabilityForm.value.postalCode;
params.dateExpired =
availability.value.dateExpired || availabilityForm.value.dateExpired;
const { type, ...rest } = params;
await getProducts({ ...rest });
return;
}
getProducts(params);
};
const handleDefault = () => {
console.error(
`INVALID TYPE! TYPE: ${type}, ONLY HOME, PRODUCT AND FILTER ARE VALID!`
);
};
const handlers = {
availability: handleAvailability,
home: handleHome,
product: handleProduct,
filter: handleFilter,
default: handleDefault,
};
const handler = handlers[type] || handlers.default;
await handler();
if (modalItem) {
modalStore[modalItem] = false;
}
handleReset();
};
const onError = ({ values, errors, results }) => {
const hasErrors = {
postalCode: !!errors.postalCode,
date: !!errors.date,
};
for (const [field, hasError] of Object.entries(hasErrors)) {
if (hasError) {
quasarNotify({ message: errors[field], type: "erro" });
}
}
};
const onSubmit = handleSubmit(onSuccess, onError);
return {
onSubmit,
setValues,
handleReset,
modalStore,
setFieldError,
isAvailabilityEmpty,
isPostalCalendarEmpty,
availabilityFormKeys,
category,
fields: {
calendar,
calendarAttrs,
postalCode,
postalCodeAttrs,
priceRange,
priceRangeAttrs,
dedication,
dedicationAttrs,
},
errors,
};
}