diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4ebbc22..2c9288b 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -17,6 +17,13 @@
"terminal.integrated.cursorStyleInactive": "line",
"workbench.iconTheme": "material-icon-theme",
"workbench.colorTheme": "Default Dark+",
+ "editor.codeActionsOnSave": [
+ "source.addMissingImports",
+ "source.organizeImports",
+ "source.fixAll.eslint",
+ "source.fixAll.stylelint"
+ ],
+
"files.exclude": {
"**/.git": true,
"**/.svn": true,
@@ -46,7 +53,6 @@
"git.confirmSync": false,
"javascript.updateImportsOnFileMove.enabled": "always",
"console-ninja.featureSet": "Community",
- "liveServer.settings.donotShowInfoMsg": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.cursorSmoothCaretAnimation": "on",
"editor.fontLigatures": true,
@@ -60,9 +66,7 @@
"source.organizeImports",
"source.fixAll.eslint"
],
- "liveServer.settings.donotVerifyTags": true,
"gitlens.gitCommands.skipConfirmations": ["fetch:command", "switch:command"],
- "symbols.hidesExplorerArrows": false,
"diffEditor.ignoreTrimWhitespace": false,
"svg.preview.mode": "svg",
"[svg]": {
@@ -72,7 +76,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"workbench.tree.indent": 16,
- "window.zoomLevel": 0,
+ "window.zoomLevel": -1,
"git.ignoreRebaseWarning": true,
"editor.largeFileOptimizations": false,
"[javascript]": {
diff --git a/api/controller/product.controller.js b/api/controller/product.controller.js
index 72f0471..69a9b67 100644
--- a/api/controller/product.controller.js
+++ b/api/controller/product.controller.js
@@ -5,45 +5,34 @@ const productsJson = require("./products.json")
class ProductController {
async findAll(req, res) {
-
- const _products = await db.getProducts();
- const mapedProducts = await _products[0].map(function (item) {
- return {
- id: item.id,
- name: item.name,
- description: item.description,
- type: item.type,
- price: item.price,
- specialPrice: item.specialPrice,
- isNew: item.isNew,
- slug: item.slug,
- category: item.category,
- postalCode: item.postalCode,
- dateExpired: item.dateExpired,
- images: [item.image],
- featured: item.featured,
- }
- })
-
- //Gerar produtos fake
- /* const fakeProducts = generateFlowers(50)
- console.log(fakeProducts); */
const params = req.query;
- let productsFilter = mapedProducts
- console.log(params);
+ const _products = await db.getProducts(params.dateExpired, params.postalCode);
+ let productsFilter = _products[0];
- if (Number(params.featured)) {
- productsFilter = productsFilter.filter(item => item.featured === Number(params.featured))
+ if (Number(params.recommend)) {
+ productsFilter = productsFilter.filter(item => item.recommend == Number(params.recommend))
}
- if (params.category) {
- productsFilter = productsFilter.filter(item => item.category === Number(params.category))
+ if (params.type) {
+ productsFilter = productsFilter.filter(item => item.type === params.type)
}
- if (params.postalCode) {
+ /*if (params.postalCode) {
productsFilter = productsFilter.filter(item => item.postalCode === params.postalCode)
}
+ if (params.dateExpired) {
+ const dateSearch = new Date(params.dateExpired);
+ productsFilter = productsFilter.filter(item => {
+ const dateProduct = new Date(item.dateExpired);
+ if (dateProduct >= dateSearch) {
+ return item
+ }
+ })
+ }*/
+ console.log(productsFilter.length);
+
+
if (params.minPrice && !params.maxPrice) {
productsFilter = productsFilter.filter(item => {
- const price = Number(item.price.replace(/€/g, ''))
+ const price = Number(item.price)
if (price >= Number(params.minPrice)) {
return item
}
@@ -51,7 +40,7 @@ class ProductController {
}
if (params.maxPrice && !params.minPrice) {
productsFilter = productsFilter.filter(item => {
- const price = Number(item.price.replace(/€/g, ''))
+ const price = Number(item.price)
if (price <= Number(params.maxPrice)) {
return item
}
@@ -59,71 +48,77 @@ class ProductController {
}
if (params.maxPrice && params.minPrice) {
productsFilter = productsFilter.filter(item => {
- const price = Number(item.price.replace(/€/g, ''))
+ const price = Number(item.price)
if (price >= Number(params.minPrice) && price <= Number(params.maxPrice)) {
- console.log(price);
- return item
- }
- })
- }
- if (params.dateExpired) {
- const [day, month, year] = params.dateExpired.split("/");
- const dateSearch = new Date(year, month - 1, day);
- productsFilter = productsFilter.filter(item => {
- const [day, month, year] = item.dateExpired.split("/");
- const dateProduct = new Date(year, month - 1, day);
- if (dateProduct >= dateSearch) {
return item
}
})
}
+
if (Number(params.bigPrice)) {
productsFilter.sort((a, b) => {
- const itemA = Number(a.price.replace(/€/g, ''))
- const itemB = Number(b.price.replace(/€/g, ''))
+ const itemA = Number(a.price)
+ const itemB = Number(b.price)
return itemB - itemA;
})
}
if (Number(params.lowPrice)) {
productsFilter.sort((a, b) => {
- const itemA = Number(a.price.replace(/€/g, ''))
- const itemB = Number(b.price.replace(/€/g, ''))
+ const itemA = Number(a.price)
+ const itemB = Number(b.price)
return itemA - itemB;
})
}
- if (params.isNew) {
- productsFilter = productsFilter.filter(item => item.isNew === true)
+ if (Number(params.order_descending)) {
+ productsFilter.sort((a, b) => {
+ const itemA = a.order_position
+ const itemB = b.order_position
+ return itemB - itemA;
+ })
}
- let productsFilterPages = []
- const totalItens = params?.itens ? Number(params.itens) : 200
- const page = params.page ? Number(params.page) : 1
- const startIndex = (totalItens * page) - totalItens
- const lastIndex = (totalItens * page)
- const products = productsFilter.slice(startIndex, lastIndex)
- productsFilterPages.push({
- page: page,
- productsPerPage: products.length,
- products: products
- })
+ if (Number(params.order_crescent)) {
+ productsFilter.sort((a, b) => {
+ const itemA = a.order_position
+ const itemB = b.order_position
+ return itemA - itemB;
+ })
+ }
+
+ if (Number(params.isNew)) {
+ console.log(params.isNew);
+ productsFilter = productsFilter.filter(item => item.isNew == Number(params.isNew))
+ }
+
+ /* let productsFilterPages = []
+ const totalItens = params?.itens ? Number(params.itens) : 200
+ const page = params.page ? Number(params.page) : 1
+ const startIndex = (totalItens * page) - totalItens
+ const lastIndex = (totalItens * page)
+ const products = productsFilter.slice(startIndex, lastIndex)
+ productsFilterPages.push({
+ page: page,
+ productsPerPage: products.length,
+ products: products
+ }) */
return res.status(200).send({
- data: productsFilterPages
+ data: productsFilter
})
}
- findBySlug(req, res) {
- const slug = req.params.slug
- const products = productsJson
- const filterSlug = products.filter(item => item.slug === slug)
+ async findById(req, res) {
+ const id = Number(req.params.id)
+ const _products = await db.getProducts();
+ const filterProduct = _products[0].filter(item => item.id === id)
return res.status(200).send({
- data: filterSlug
+ data: filterProduct
})
}
}
-module.exports = new ProductController();
\ No newline at end of file
+module.exports = new ProductController();
diff --git a/api/db/db.js b/api/db/db.js
index b084634..5801e03 100644
--- a/api/db/db.js
+++ b/api/db/db.js
@@ -1,27 +1,27 @@
async function connect() {
- if (global.connection && global.connection.state !== 'disconnected')
- return global.connection;
+ if (global.connection && global.connection.state !== 'disconnected')
+ return global.connection;
- const host = process.env.HOST;
- const port = process.env.PORT;
- const database = process.env.DATABASE;
- const user = process.env.DB_USER;
- const password = process.env.DB_PASSWORD;
+ const host = process.env.HOST;
+ const port = process.env.PORT;
+ const database = process.env.DATABASE;
+ const user = process.env.DB_USER;
+ const password = process.env.DB_PASSWORD;
- const mysql = require("mysql2/promise");
- const connection = await mysql.createConnection("mysql://" + user + ":" + password + "@" + host + ":" + port + "/" + database + "");
- console.log("Connected to MySQL!");
- global.connection = connection;
- return connection;
+ const mysql = require("mysql2/promise");
+ const connection = await mysql.createConnection("mysql://" + user + ":" + password + "@" + host + ":" + port + "/" + database + "");
+ console.log("Connected to MySQL!");
+ global.connection = connection;
+ return connection;
}
-async function getProducts() {
- const conn = await connect();
- const [rows] = await conn.query('CALL catalogue_get("2024-01-30", "08001")');
-
- return rows;
+async function getProducts(dateExpired, postalCode) {
+ console.log("Query in table MySQL!");
+ const conn = await connect();
+ const [rows] = await conn.query(`CALL catalogue_get("${dateExpired}", "${postalCode}")`);
+ return rows;
}
diff --git a/api/index.js b/api/index.js
index 240daa2..40bcdd9 100644
--- a/api/index.js
+++ b/api/index.js
@@ -20,7 +20,7 @@ app.get('/', (req, res) => {
//Products
app.get('/api/products', productController.findAll);
-app.get('/api/products/slug/:slug', productController.findBySlug);
+app.get('/api/products/:id', productController.findById);
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
diff --git a/index.html b/index.html
index a71fcf6..9329f89 100644
--- a/index.html
+++ b/index.html
@@ -51,7 +51,7 @@
src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-element-bundle.min.js"
defer
>
-
+
diff --git a/quasar.config.js b/quasar.config.js
index 65fdc62..7a6fab8 100644
--- a/quasar.config.js
+++ b/quasar.config.js
@@ -28,7 +28,7 @@ module.exports = configure(function (/* ctx */) {
// app boot file (/src/boot)
// --> boot files are part of "main.js"
// https://v2.quasar.dev/quasar-cli-vite/boot-files
- boot: ["i18n", "axios" /* , "stripe" */],
+ boot: ["i18n", "axios" /* , { path: "stripe", server: false } */],
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
css: ["app.scss"],
@@ -119,7 +119,7 @@ module.exports = configure(function (/* ctx */) {
// directives: [],
// Quasar plugins
- plugins: ["Meta", "Loading", "Notify"],
+ plugins: ["Meta", "Loading", "Notify", "LocalStorage", "SessionStorage"],
},
// animations: 'all', // --- includes all animations
diff --git a/src/boot/stripe.js b/src/boot/stripe.js
index 4fd688b..6dabef9 100644
--- a/src/boot/stripe.js
+++ b/src/boot/stripe.js
@@ -3,15 +3,15 @@ import { boot } from "quasar/wrappers";
// "async" is optional;
// more info on params: https://v2.quasar.dev/quasar-cli/boot-files
-export default boot(async ({ app, router, store }) => {
- if (typeof window === "undefined") return;
-
+export default boot(({ app }) => {
const options = {
- pk: process.env.STRIPE_PUBLISHABLE_KEY,
- stripeAccount: process.env.STRIPE_ACCOUNT,
- apiVersion: process.env.API_VERSION,
- locale: process.env.LOCALE,
+ pk: "pk_test_51OZaJdIK1lTlG93d2y0B81n4XrjvjQwqfIUZ7ggb9wEBa1e4h34GlYFYPwjtGl3OUT7DJZlVNX9EMXaCdOBkIC3T007mLnfvCu",
+ stripeAccount: "acct_1OXQt7GMODwoSxWA",
+ apiVersion: "2023-10-16",
+ locale: "pt-BR",
};
+ app.config.globalProperties.$stripe = StripePlugin.install = options;
+
app.use(StripePlugin, options);
});
diff --git a/src/components/@inputs/Calendar.vue b/src/components/@inputs/Calendar.vue
index 241affe..a262502 100644
--- a/src/components/@inputs/Calendar.vue
+++ b/src/components/@inputs/Calendar.vue
@@ -1,63 +1,45 @@
+
+
diff --git a/src/components/ui/Card.vue b/src/components/ui/Card.vue
index 6172fcf..4c9e992 100644
--- a/src/components/ui/Card.vue
+++ b/src/components/ui/Card.vue
@@ -46,22 +46,35 @@ export default defineComponent({
default: "",
},
id: {
- type: String,
+ type: Number,
required: true,
},
},
setup({ price, discount }) {
const isLoaded = ref(false);
+ const isError = ref(false);
const percent = +discount / 100;
- //const priceWithoutLetter = ~~price.replaceAll("€", "");
+ //const priceWithoutLetter = ~~price?.replaceAll("€", "");
const priceWithoutLetter = price;
const finalValue = ~~(priceWithoutLetter - priceWithoutLetter * percent);
+ console.log(price);
const onLoad = () => {
isLoaded.value = true;
};
- return { onLoad, isLoaded, finalValue, priceWithoutLetter };
+ const onError = () => {
+ isError.value = true;
+ };
+
+ return {
+ onLoad,
+ onError,
+ isLoaded,
+ isError,
+ finalValue,
+ priceWithoutLetter,
+ };
},
});
@@ -82,10 +95,11 @@ export default defineComponent({
{{ finalValue }}€
-
+
{{ price }}€
diff --git a/src/components/ui/Modal.vue b/src/components/ui/Modal.vue
index 7471cfd..11b40c9 100644
--- a/src/components/ui/Modal.vue
+++ b/src/components/ui/Modal.vue
@@ -30,6 +30,7 @@ export default defineComponent({
setup({ modalItem, typeModal }) {
const {
onSubmit,
+ setValues,
fields: {
calendar,
calendarAttrs,
@@ -61,6 +62,7 @@ export default defineComponent({
onSubmit,
modalStore,
modalTextContent,
+ setValues,
postalCode,
postalCodeAttrs,
@@ -121,7 +123,7 @@ export default defineComponent({
v-if="modalItem === 'isOpenAvailability'"
class="modal-body-availability"
>
-
+
Notify.create({
+ message,
+ color: "info",
+ position: "top",
+ icon: "info",
+ timeout,
+ }),
+ default: () => {
+ console.error(`Type is invalid! TYPE: ${type}`)
+ }
};
if (type) {
- return obj[type]() || console.error(`Type is invalid! TYPE: ${type}`);
+ return obj[type]() || obj['default']();
}
console.error("Type is required, success, warning or erro");
}
diff --git a/src/hooks/useCheckoutForm.js b/src/hooks/useCheckoutForm.js
new file mode 100644
index 0000000..2244fdb
--- /dev/null
+++ b/src/hooks/useCheckoutForm.js
@@ -0,0 +1,192 @@
+import { toTypedSchema } from "@vee-validate/zod";
+import { useForm } from "vee-validate";
+import { computed, reactive, ref } from "vue";
+
+import { useFormStore } from "src/stores/forms";
+import { checkoutSchema } from "src/utils/zod/schemas";
+import { useRouter } from "vue-router";
+import { useLocalStorage } from "./useLocalStorage";
+
+export function useCheckoutForm() {
+ const { getItem } = useLocalStorage();
+ const { push } = useRouter()
+
+ const formStore = useFormStore();
+ const { handleCheckoutData } = formStore;
+ const { meta, errors, handleSubmit, defineField, resetForm } = useForm({
+ validationSchema: toTypedSchema(checkoutSchema),
+ initialValues: {
+ paymentMethod: "stripe",
+ terms: false,
+ },
+ });
+
+ const [name, nameAttrs] = defineField("name");
+ const [surname, surnameAttrs] = defineField("surname");
+ const [address, addressAttrs] = defineField("address");
+ const [postalCode, postalCodeAttrs] = defineField("postalCode");
+ const [phone, phoneAttrs] = defineField("phone");
+ const [city, cityAttrs] = defineField("city");
+ const [province, provinceAttrs] = defineField("province");
+ const [senderName, senderNameAttrs] = defineField("senderName");
+ const [senderCifNif, senderCifNifAttrs] = defineField("senderCifNif");
+ const [senderEmail, senderEmailAttrs] = defineField("senderEmail");
+ const [senderPhone, senderPhoneAttrs] = defineField("senderPhone");
+ const [senderNotes, senderNotesAttrs] = defineField("senderNotes");
+ const [paymentMethod, paymentMethodAttrs] = defineField("paymentMethod");
+ const [terms, termsAttrs] = defineField("terms");
+
+ const provinceOptions = ref([
+ { code: "01", name: "Araba/Álava" },
+ { code: "02", name: "Albacete" },
+ { code: "03", name: "Alicante/Alacant" },
+ { code: "04", name: "Almería" },
+ { code: "05", name: "Ávila" },
+ { code: "06", name: "Badajoz" },
+ { code: "07", name: "Balears, Illes" },
+ { code: "08", name: "Barcelona" },
+ { code: "09", name: "Burgos" },
+ { code: "10", name: "Cáceres" },
+ { code: "11", name: "Cádiz" },
+ { code: "12", name: "Castellón/Castelló" },
+ { code: "13", name: "Ciudad Real" },
+ { code: "14", name: "Córdoba" },
+ { code: "15", name: "Coruña, A" },
+ { code: "16", name: "Cuenca" },
+ { code: "17", name: "Girona" },
+ { code: "18", name: "Granada" },
+ { code: "19", name: "Guadalajara" },
+ { code: "20", name: "Gipuzkoa" },
+ { code: "21", name: "Huelva" },
+ { code: "22", name: "Huesca" },
+ { code: "23", name: "Jaén" },
+ { code: "24", name: "León" },
+ { code: "25", name: "Lleida" },
+ { code: "26", name: "Rioja, La" },
+ { code: "27", name: "Lugo" },
+ { code: "28", name: "Madrid" },
+ { code: "29", name: "Málaga" },
+ { code: "30", name: "Murcia" },
+ { code: "31", name: "Navarra" },
+ { code: "32", name: "Ourense" },
+ { code: "33", name: "Asturias" },
+ { code: "34", name: "Palencia" },
+ { code: "35", name: "Palmas, Las" },
+ { code: "36", name: "Pontevedra" },
+ { code: "37", name: "Salamanca" },
+ { code: "38", name: "Santa Cruz de Tenerife" },
+ { code: "39", name: "Cantabria" },
+ { code: "40", name: "Segovia" },
+ { code: "41", name: "Sevilla" },
+ { code: "42", name: "Soria" },
+ { code: "43", name: "Tarragona" },
+ { code: "44", name: "Teruel" },
+ { code: "45", name: "Toledo" },
+ { code: "46", name: "Valencia/València" },
+ { code: "47", name: "Valladolid" },
+ { code: "48", name: "Bizkaia" },
+ { code: "49", name: "Zamora" },
+ { code: "50", name: "Zaragoza" },
+ { code: "51", name: "Ceuta" },
+ { code: "52", name: "Melilla" },
+ ]);
+
+ const stepActive = reactive({ data: 1 });
+ const stepList = reactive({
+ data: [
+ {
+ value: 1,
+ name: "Paso 1",
+ description: "Datos de facturación",
+ active: true,
+ },
+ {
+ value: 2,
+ name: "Paso 2",
+ description: "Confirmación",
+ active: false,
+ },
+ {
+ value: 3,
+ name: "Paso 3",
+ description: "Pago",
+ active: false,
+ },
+ ],
+ });
+ const stepsFormated = computed(() => {
+ return stepList["data"].map((step) => {
+ if (step.value === stepActive["data"]) {
+ return { ...step, active: true };
+ }
+ return step;
+ });
+ });
+
+ const handleClickStep = (value) => {
+ stepActive["data"] = value;
+ };
+
+ const checkoutBlock = ref(true);
+ const onSubmit = handleSubmit((values) => {
+ handleCheckoutData(values);
+ stepList.data[2].active = true;
+ checkoutBlock.value = false;
+ resetForm();
+ });
+
+ const cart = getItem("cart");
+ const totalPrice = ref(0)
+ totalPrice.value = cart?.reduce((acc, { price }) => {
+ if (price) {
+ const priceWithoutLetter = price?.replace("€", "");
+ return +priceWithoutLetter + acc;
+ }
+ }, 0);
+
+ return {
+ handleClickStep,
+ provinceOptions,
+ stepsFormated,
+ stepList,
+ checkoutBlock,
+ cart,
+ totalPrice,
+ formState: {
+ meta,
+ errors,
+ onSubmit,
+ submitLoading: ref(false),
+ },
+ fields: {
+ name,
+ nameAttrs,
+ surname,
+ surnameAttrs,
+ address,
+ addressAttrs,
+ postalCode,
+ postalCodeAttrs,
+ phone,
+ phoneAttrs,
+ city,
+ cityAttrs,
+ province,
+ provinceAttrs,
+ senderName,
+ senderNameAttrs,
+ senderCifNif,
+ senderCifNifAttrs,
+ senderEmail,
+ senderEmailAttrs,
+ senderPhone,
+ senderPhoneAttrs,
+ senderNotes,
+ senderNotesAttrs,
+ paymentMethod,
+ paymentMethodAttrs,
+ terms,
+ termsAttrs,
+ },
+ };
+}
diff --git a/src/hooks/useLocalStorage.js b/src/hooks/useLocalStorage.js
new file mode 100644
index 0000000..68a4fdf
--- /dev/null
+++ b/src/hooks/useLocalStorage.js
@@ -0,0 +1,25 @@
+import { LocalStorage } from "quasar";
+
+export function useLocalStorage() {
+ const addItem = (key, value) => {
+ LocalStorage.set(`@${key}`, value);
+ };
+
+ const getItem = (key) => {
+ const data = JSON.parse(LocalStorage.getItem(`@${key}`));
+
+
+ return (data || []);
+ };
+
+ const removeItem = (key) => {
+ LocalStorage.remove(`@${key}`);
+ };
+
+
+ return {
+ addItem,
+ getItem,
+ removeItem,
+ };
+}
diff --git a/src/hooks/usePostalCalendar.js b/src/hooks/usePostalCalendar.js
index e51fffe..b498b4e 100644
--- a/src/hooks/usePostalCalendar.js
+++ b/src/hooks/usePostalCalendar.js
@@ -1,10 +1,10 @@
import { toTypedSchema } from "@vee-validate/zod";
import { storeToRefs } from "pinia";
import { useForm } from "vee-validate";
-import { watch } from "vue";
-import { useRouter } from "vue-router";
+import { ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
-import { apiBack } from "src/boot/axios";
+import { invertDate } from "src/functions/invertDate";
import { quasarNotify } from "src/functions/quasarNotify";
import { useCartStore } from "src/stores/cart";
import { useFormStore } from "src/stores/forms";
@@ -13,38 +13,50 @@ import { useRangePriceStore } from "src/stores/rangePrice";
import { availabilitySchema } from "src/utils/zod/schemas";
import { rangePriceSchema } from "src/utils/zod/schemas/rangePriceSchema";
+/**
+ * Custom hook for managing the postal and calendar functionality.
+ *
+ * @param {Object} options - The options for the hook.
+ * @param {string} options.modalItem - The modal item isOpenAvailability || isOpenFilters.
+ * @param {string} options.type - The type of the hook. home || product || availability || filter
+ * @returns {Object} - The hook functions and data.
+ */
export function usePostalCalendar({ modalItem = "", type = "home" }) {
- const { push } = useRouter();
+ const route = useRoute();
+ const { push } = useRouter()
const rangePriceStore = useRangePriceStore();
const { rangeValue } = storeToRefs(rangePriceStore);
const modalStore = useModalStore();
- const { isOpenAvailability } = storeToRefs(modalStore);
+ const { openModal } = modalStore
const formStore = useFormStore();
- const { availability, sortProductFilters } = storeToRefs(formStore);
+ const { sortProductFilters } = storeToRefs(formStore);
const cartStore = useCartStore();
const { addToCart, getProducts } = cartStore;
- const { currentProduct, products } = storeToRefs(cartStore);
+ const { products, homeSection } = storeToRefs(cartStore);
const min = 0;
const max = 200;
+ const category = ref(route.path.split("/")[2])
- const { handleSubmit, handleReset, defineField, errors } = useForm({
- validationSchema: toTypedSchema(
- type !== "filter" ? availabilitySchema : rangePriceSchema
- ),
- initialValues: {
- range: {
- min,
- max,
+ const { handleSubmit, handleReset, defineField, errors, setValues } = useForm(
+ {
+ validationSchema: toTypedSchema(
+ type !== "filter" ? availabilitySchema : rangePriceSchema
+ ),
+ initialValues: {
+ range: {
+ min,
+ max,
+ },
+ postalCode: "",
+ date: "",
},
- postalCode: "",
- date: "",
- },
- });
+ }
+ );
const [calendar, calendarAttrs] = defineField("date");
const [postalCode, postalCodeAttrs] = defineField("postalCode");
const [priceRange, priceRangeAttrs] = defineField("range");
@@ -56,6 +68,8 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
quasarNotify({ message: newErrors.postalCode, type: "erro" }),
date: () => quasarNotify({ message: newErrors.date, type: "erro" }),
range: () => quasarNotify({ message: newErrors.range, type: "erro" }),
+ dedication: () =>
+ quasarNotify({ message: newErrors.dedication, type: "erro" }),
};
const keys = Object.keys(newErrors);
keys.forEach((key) => {
@@ -63,47 +77,73 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
});
});
+ watch(
+ [() => route.path, () => sortProductFilters.value],
+ ([newPath]) => {
+ const categoryPath = newPath.split("/")[2];
+ category.value = categoryPath;
+ }
+ );
+
const onSubmit = handleSubmit((values) => {
const postalAndDateParams = {
postalCode: values.postalCode,
- dateExpired: values.date,
+ dateExpired: invertDate(values.date),
+ };
+
+ const categoryObj = {
+ plantas: "Floranet Plantas",
+ ramos: "Floranet Ramos",
};
const objVal = {
home: async () => {
console.log(type);
- getProducts(
+ await getProducts(
{
- itens: 30,
- category: 1,
postalCode: values.postalCode,
- dateExpired: values.date,
+ dateExpired: invertDate(values.date),
},
- () => push("/categoria/ramos")
+ () => homeSection.value.scrollIntoView()
);
},
product: async () => {
console.log(type);
- try {
- const {
- data: { data },
- } = await apiBack.get(`products/slug/${currentProduct.value.id}`, {
- params: postalAndDateParams,
- });
- } catch (error) {
- console.error(error);
- push("/");
+ await getProducts(postalAndDateParams);
+
+ const hasProduct = 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 id = +route.path.split('/')[2];
+
+ return item.postalCode === values.postalCode && item.id === id && values.date <= dateExpired
+ });
+
+ if (!hasProduct) {
+ push('/categoria/ramos')
+ quasarNotify({ message: 'Seleccione una nueva fecha y un nuevo código postal.', type: 'warning' })
+
+ setTimeout(() => {
+ openModal({ modal: 'availability' })
+ }, 2000)
+
+ return
}
+
+ addToCart(products.value.current, dedication)
},
availability: async () => {
console.log(type);
- getProducts({
- itens: 20,
+ await getProducts({
postalCode: values.postalCode,
- dateExpired: values.date,
+ dateExpired: invertDate(values.date),
});
},
filter: async () => {
@@ -112,26 +152,21 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
rangeValue.value.max = values.range.max;
rangeValue.value.min = values.range.min;
- const category = sortProductFilters.value.category;
- const categoryObj = {
- plantas: 1,
- ramos: 2,
- };
-
const params = {
- itens: 20,
- category: categoryObj[category],
+ type: categoryObj[category.value],
minPrice: values.range.min,
maxPrice: values.range.max,
};
- getProducts(params);
+ await getProducts(params);
+ },
+ default: () => {
+ console.error(
+ `INVALID TYPE! TYPE: ${type}, ONLY HOME, PRODUCT AND FILTER ARE VALID!`
+ );
},
};
- objVal[type]() ||
- console.error(
- `INVALID TYPE! TYPE: ${type}, ONLY HOME, PRODUCT AND FILTER ARE VALID!`
- );
+ objVal[type]() || objVal["default"]();
if (modalItem) {
modalStore[modalItem] = false;
@@ -141,6 +176,7 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
return {
onSubmit,
+ setValues,
modalStore,
fields: {
calendar,
diff --git a/src/hooks/useProductPage.js b/src/hooks/useProductPage.js
new file mode 100644
index 0000000..e720b35
--- /dev/null
+++ b/src/hooks/useProductPage.js
@@ -0,0 +1,51 @@
+import { storeToRefs } from "pinia";
+import { useCartStore } from "src/stores/cart";
+import { useModalStore } from "src/stores/modalStore";
+import { watch } from "vue";
+import { useRoute } from "vue-router";
+import { usePostalCalendar } from "./usePostalCalendar";
+
+export function useProductPage() {
+ const route = useRoute();
+
+ const {
+ fields: { dedication, dedicationAttrs },
+ } = usePostalCalendar({ modalItem: "isOpenAvailability" });
+
+ const modalStore = useModalStore();
+ const { openModal } = modalStore;
+
+ const cartStore = useCartStore();
+ const { getProduct, getProducts } = cartStore;
+ const { products, featuredProducts, addCartLoadingBtn } =
+ storeToRefs(cartStore);
+
+ watch(
+ () => products.value.current?.type,
+ (newCategory) => {
+ getProducts({
+ // type: newCategory,
+ });
+ }
+ );
+
+ watch(
+ () => route.params.id,
+ (newId) => {
+ getProduct(newId);
+ }
+ );
+
+ const checkImageValidity = (imageLink) => {
+ const validExtensions = [".jpg", ".jpeg", ".png"];
+
+ if (imageLink) {
+ const extension = imageLink.substring(imageLink.lastIndexOf("."));
+ return validExtensions.includes(extension.toLowerCase());
+ }
+
+ return true;
+ };
+
+ return { checkImageValidity, openModal }
+}
diff --git a/src/layouts/DefaultLayout.vue b/src/layouts/DefaultLayout.vue
index 7d31a69..8b2376d 100644
--- a/src/layouts/DefaultLayout.vue
+++ b/src/layouts/DefaultLayout.vue
@@ -27,9 +27,11 @@ export default defineComponent({
-
-
-
+
+
+
+
+
diff --git a/src/mock/cards.js b/src/mock/cards.js
index 62776e2..e64c41b 100644
--- a/src/mock/cards.js
+++ b/src/mock/cards.js
@@ -26,7 +26,7 @@ export function mockGenerator({ length }) {
slug: fakerES.commerce.isbn({ separator: "-", variant: 13 }),
category: fakerES.number.int({ min: 1, max: 2 }),
postalCode: "12345",
- dateExpired: "30/01/2024",
+ dateExpired: "2024-01-30",
images: Array.from(
{ length: fakerES.number.int({ min: 2, max: 6 }) },
() => fakerES.image.urlPicsumPhotos()
diff --git a/src/pages/CategoryPage.vue b/src/pages/CategoryPage.vue
index ef6167d..5efc813 100644
--- a/src/pages/CategoryPage.vue
+++ b/src/pages/CategoryPage.vue
@@ -12,8 +12,10 @@ 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 { 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({
@@ -32,6 +34,9 @@ export default defineComponent({
setup() {
const route = useRoute();
+ const mobileStore = useMobileStore();
+ const { screenWidth } = storeToRefs(mobileStore);
+
const modalStore = useModalStore();
const { openModal } = modalStore;
@@ -66,8 +71,8 @@ export default defineComponent({
latest: "más recientes",
};
const categoryObj = {
- plantas: 1,
- ramos: 2,
+ plantas: "Floranet Plantas",
+ ramos: "Floranet Ramos",
};
watch(availability, (newDate) => {
@@ -83,14 +88,13 @@ export default defineComponent({
sortProductFilters.value.category = categoryPath;
const params = {
- category: categoryObj[categoryPath],
- itens: window.screen.width <= 445 ? 16 : 20,
+ type: categoryObj[categoryPath],
};
const paramsObj = {
"lowest-price": () => (params.lowPrice = 1),
"highest-price": () => (params.bigPrice = 1),
latest: () => (params.isNew = 1),
- // recommended: () => params.featured = 1,
+ recommended: () => (params.recommend = 1),
};
if (newOrder) {
paramsObj[newOrder]();
@@ -104,8 +108,7 @@ export default defineComponent({
const categoryPath = route.path.split("/")[2];
await getProducts({
- category: categoryObj[categoryPath],
- itens: window.screen.width <= 445 ? 16 : 20,
+ type: categoryObj[categoryPath],
});
});
@@ -122,11 +125,12 @@ export default defineComponent({
}
return {
- sortProductFilters,
openOrderFilter,
openModal,
+ sortProductFilters,
availability,
isOpenOrder,
+ screenWidth,
modalStore,
orderText,
products,
@@ -145,9 +149,6 @@ export default defineComponent({
{{ sortProductFilters.category }} para obsequiar
@@ -218,25 +219,14 @@ export default defineComponent({
-
+
diff --git a/src/pages/CheckoutPage.vue b/src/pages/CheckoutPage.vue
index b29b772..9793ca3 100644
--- a/src/pages/CheckoutPage.vue
+++ b/src/pages/CheckoutPage.vue
@@ -1,14 +1,9 @@