Merge branch 'master' into develop
This commit is contained in:
commit
bfb66a7c0d
|
@ -0,0 +1,22 @@
|
|||
const db = require("../../db/db");
|
||||
|
||||
class ContactController {
|
||||
async Create(req, res) {
|
||||
try {
|
||||
const { name, phone, email, message } = req.body;
|
||||
console.log(name, phone, email, message);
|
||||
const contact = await db.contact_Request(name, phone, email, message);
|
||||
|
||||
return res.status(200).send({
|
||||
data: contact[0]
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return res.status(422).send({
|
||||
message: "error al guardar contacto"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ContactController();
|
|
@ -0,0 +1,13 @@
|
|||
const db = require("../../db/db");
|
||||
|
||||
class DeliveryController {
|
||||
async findByPostalCode(req, res) {
|
||||
const { postalCode } = req.query;
|
||||
const dates = await db.deliveryDate_get(postalCode);
|
||||
return res.status(200).send({
|
||||
data: dates[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new DeliveryController();
|
|
@ -0,0 +1,23 @@
|
|||
const db = require("../../db/db");
|
||||
const paypal = require('paypal-rest-sdk');
|
||||
const paymentServices = require('./payment.services')
|
||||
|
||||
class PaymentController {
|
||||
async Create(req, res) {
|
||||
return await paymentServices.Create(req, res)
|
||||
}
|
||||
|
||||
async Success(req, res) {
|
||||
return await paymentServices.Success(req, res)
|
||||
}
|
||||
|
||||
Cancel(req, res) {
|
||||
return res.status(200).send({
|
||||
data: {
|
||||
menssage: "cancelado"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new PaymentController();
|
|
@ -0,0 +1,113 @@
|
|||
const db = require("../../db/db");
|
||||
const payPalProviders = require('./paypal.providers')
|
||||
const redsysProviders = require('./redsys.providers')
|
||||
|
||||
class PaymentServices {
|
||||
async Create(req, res) {
|
||||
try {
|
||||
//parâmetros para retornar os produtos que serão comprados
|
||||
const { products, dateExpired, postalCode, customer, type } = req.body
|
||||
const _products = await db.getProducts(dateExpired, postalCode)
|
||||
|
||||
const productsFilter = _products[0].filter((item) => {
|
||||
if (products.includes(item.id)) {
|
||||
return item
|
||||
}
|
||||
});
|
||||
|
||||
if (productsFilter.length !== products.length) {
|
||||
return res.status(422).send({
|
||||
data: {
|
||||
message: "Uno de los productos no existe."
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let priceIntial = 0
|
||||
let price = productsFilter.reduce((accumulator, curValue) => accumulator + Number(curValue.price), priceIntial)
|
||||
|
||||
let productsIds = ''
|
||||
for (let i = 0; i < products.length; i++) {
|
||||
productsIds += `${products[i]}${i === products.length - 1 ? '' : '-'}`
|
||||
}
|
||||
|
||||
//Create new order
|
||||
const jsonOrderData = JSON.stringify({
|
||||
"customer": {
|
||||
customerData: {
|
||||
...customer.customerData,
|
||||
type: type,
|
||||
products: productsFilter
|
||||
}
|
||||
},
|
||||
})
|
||||
const order = await db.orderData_put(jsonOrderData);
|
||||
const orderFk = order[0][0].orderFk
|
||||
|
||||
if (type === "paypal") {
|
||||
const data = await payPalProviders.New(orderFk, price)
|
||||
return res.status(200).send({
|
||||
data: { ...data, orderId: orderFk }
|
||||
})
|
||||
}
|
||||
if (type === "redsys") {
|
||||
const data = await redsysProviders.New(orderFk, price)
|
||||
return res.status(200).send({
|
||||
data: { ...data, orderId: orderFk }
|
||||
})
|
||||
}
|
||||
/* if (newOrder) {
|
||||
return res.status(200).send({
|
||||
data: { link: newOrder.links, orderId: orderFk }
|
||||
})
|
||||
} */
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return res.status(422).send({
|
||||
data: {
|
||||
message: "Error al iniciar el pago"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async Success(req, res) {
|
||||
try {
|
||||
//Parameters payment
|
||||
const { paymentId, PayerID, orderId } = req.body
|
||||
const payerId = { 'payer_id': PayerID };
|
||||
|
||||
//API validation payent and confirnm order
|
||||
paypal.payment.execute(paymentId, payerId, async function (error, payment) {
|
||||
if (error) {
|
||||
return res.status(422).send({
|
||||
data: {
|
||||
message: "payment not successful"
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (payment.state == 'approved') {
|
||||
await db.order_confirm(orderId)
|
||||
return res.status(200).send({
|
||||
data: {
|
||||
id: payment.id,
|
||||
message: "payment completed successfully",
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return res.status(422).send({
|
||||
data: {
|
||||
message: "payment not successful"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new PaymentServices();
|
|
@ -0,0 +1,59 @@
|
|||
const paypal = require('paypal-rest-sdk');
|
||||
|
||||
class PayPalProviders {
|
||||
async New(orderFk, price) {
|
||||
try {
|
||||
const payReq = JSON.stringify({
|
||||
'intent': 'sale',
|
||||
'redirect_urls': {
|
||||
'return_url': `${process.env.BASE_URL}/checkout/success?orderId=${orderFk}`,
|
||||
'cancel_url': `${process.env.BASE_URL}/checkout/error`
|
||||
},
|
||||
'payer': {
|
||||
'payment_method': 'paypal'
|
||||
},
|
||||
'transactions': [{
|
||||
'amount': {
|
||||
'total': 0.0000000001,
|
||||
'currency': 'EUR'
|
||||
},
|
||||
'description': 'This is the payment transaction description.'
|
||||
}]
|
||||
});
|
||||
|
||||
//Starting checkout process and returning sandbox url
|
||||
const newOrder = await new Promise(async (resolve, reject) => {
|
||||
paypal.payment.create(payReq, function (error, payment) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
//capture HATEOAS links
|
||||
var links = {};
|
||||
payment.links.forEach(function (linkObj) {
|
||||
links[linkObj.rel] = {
|
||||
'href': linkObj.href,
|
||||
'method': linkObj.method
|
||||
};
|
||||
})
|
||||
//if redirect url present, redirect user
|
||||
if (links.hasOwnProperty('approval_url')) {
|
||||
resolve(
|
||||
{
|
||||
id: payment.id,
|
||||
link: links['approval_url'].href,
|
||||
}
|
||||
)
|
||||
} else {
|
||||
console.error('no redirect URI present');
|
||||
}
|
||||
}
|
||||
});
|
||||
}).then(res => res)
|
||||
return newOrder
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new PayPalProviders();
|
|
@ -0,0 +1,39 @@
|
|||
const Redsys = require('redsys-easy');
|
||||
const {
|
||||
SANDBOX_URLS,
|
||||
PRODUCTION_URLS,
|
||||
TRANSACTION_TYPES
|
||||
} = Redsys
|
||||
|
||||
class RedsysProviders {
|
||||
async New(orderFk, price) {
|
||||
console.log("Chama");
|
||||
try {
|
||||
const redsys = new Redsys({
|
||||
secretKey: 'sq7HjrUOBfKmC576ILgskD5srU870gJ7',
|
||||
urls: SANDBOX_URLS, // Also PRODUCTION_URLS
|
||||
});
|
||||
const obj = {
|
||||
amount: price,
|
||||
currency: 'EUR',
|
||||
order: orderFk,
|
||||
merchantName: 'Floraner',
|
||||
merchantCode: '999008881',
|
||||
transactionType: TRANSACTION_TYPES.AUTHORIZATION, // '0'
|
||||
terminal: '001',
|
||||
merchantURL: `${process.env.BASE_URL}/payments/redsys/notification`,
|
||||
successURL: `${process.env.BASE_URL}/checkout/success?orderId=${orderFk}`,
|
||||
errorURL: `${process.env.BASE_URL}/checkout/error`
|
||||
}
|
||||
|
||||
const form = redsys.redirectPetition(obj)
|
||||
|
||||
console.log(form);
|
||||
return true
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new RedsysProviders();
|
|
@ -0,0 +1,34 @@
|
|||
const RedsysPos = require('redsys-pos');
|
||||
const {
|
||||
CURRENCIES, TRANSACTION_TYPES
|
||||
} = RedsysPos;
|
||||
|
||||
class RedsysProviders {
|
||||
async New(orderFk, price) {
|
||||
console.log("Chama");
|
||||
try {
|
||||
const MERCHANT_KEY = "sq7HjrUOBfKmC576ILgskD5srU870gJ7";
|
||||
const redsys = new RedsysPos(MERCHANT_KEY);
|
||||
const obj = JSON.stringify({
|
||||
amount: 100, // 100 euros
|
||||
orderReference: orderFk,
|
||||
merchantName: "Floranet",
|
||||
merchantCode: "999008881",
|
||||
currency: CURRENCIES.EUR,
|
||||
transactionType: TRANSACTION_TYPES.AUTHORIZATION, // '0'
|
||||
terminal: "001",
|
||||
merchantURL: `${process.env.BASE_URL}/payments/redsys/notification`,
|
||||
successURL: `${process.env.BASE_URL}/checkout/success?orderId=${orderFk}`,
|
||||
errorURL: `${process.env.BASE_URL}/checkout/error`
|
||||
});
|
||||
|
||||
console.log(obj);
|
||||
const result = redsys.makePaymentParameters(obj);
|
||||
return ""
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new RedsysProviders();
|
|
@ -0,0 +1,33 @@
|
|||
const RedsysPos = require('redsys-pos');
|
||||
const {
|
||||
CURRENCIES, TRANSACTION_TYPES
|
||||
} = RedsysPos;
|
||||
|
||||
class RedsysProviders {
|
||||
async New(orderFk, price) {
|
||||
try {
|
||||
const MERCHANT_KEY = "sq7HjrUOBfKmC576ILgskD5srU870gJ7";
|
||||
const redsys = new RedsysPos(MERCHANT_KEY);
|
||||
const obj = {
|
||||
amount: String(price),
|
||||
orderReference: String(orderFk),
|
||||
merchantName: "Floranet",
|
||||
merchantCode: "999008881",
|
||||
currency: CURRENCIES.EUR,
|
||||
transactionType: TRANSACTION_TYPES.AUTHORIZATION, // '0'
|
||||
terminal: "001",
|
||||
merchantURL: `${process.env.BASE_URL}/payments/redsys/notification`,
|
||||
successURL: `${process.env.BASE_URL}/checkout/success?orderId=${orderFk}`,
|
||||
errorURL: `${process.env.BASE_URL}/checkout/error`
|
||||
};
|
||||
|
||||
const result = redsys.makePaymentParameters(obj);
|
||||
console.log(result);
|
||||
return result
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new RedsysProviders();
|
|
@ -0,0 +1,114 @@
|
|||
const db = require("../../db/db");
|
||||
<<<<<<<< HEAD:api/controller/product/product.controller.js
|
||||
|
||||
const productsJson = require("./products.json")
|
||||
========
|
||||
>>>>>>>> master:api/controller/Product/product.controller.js
|
||||
|
||||
class ProductController {
|
||||
async findAll(req, res) {
|
||||
|
||||
const params = req.query;
|
||||
const _products = await db.getProducts(params.dateExpired, params.postalCode);
|
||||
let productsFilter = _products[0]
|
||||
|
||||
if (Number(params.recommend)) {
|
||||
productsFilter = productsFilter.filter(item => item.recommend == params.recommend)
|
||||
}
|
||||
if (params.type) {
|
||||
productsFilter = productsFilter.filter(item => item.type === params.type)
|
||||
}
|
||||
|
||||
if (params.minPrice && !params.maxPrice) {
|
||||
productsFilter = productsFilter.filter(item => {
|
||||
const price = Number(item.price)
|
||||
if (price >= Number(params.minPrice)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
if (params.maxPrice && !params.minPrice) {
|
||||
productsFilter = productsFilter.filter(item => {
|
||||
const price = Number(item.price)
|
||||
if (price <= Number(params.maxPrice)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
if (params.maxPrice && params.minPrice) {
|
||||
productsFilter = productsFilter.filter(item => {
|
||||
const price = Number(item.price)
|
||||
if (price >= Number(params.minPrice) && price <= Number(params.maxPrice)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if (Number(params.bigPrice)) {
|
||||
productsFilter.sort((a, b) => {
|
||||
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)
|
||||
const itemB = Number(b.price)
|
||||
return itemA - itemB;
|
||||
})
|
||||
}
|
||||
|
||||
if (Number(params.order_descending)) {
|
||||
productsFilter.sort((a, b) => {
|
||||
const itemA = a.order_position
|
||||
const itemB = b.order_position
|
||||
return itemB - itemA;
|
||||
})
|
||||
}
|
||||
|
||||
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: productsFilter
|
||||
})
|
||||
}
|
||||
|
||||
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: filterProduct
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ProductController();
|
|
@ -0,0 +1,23 @@
|
|||
const db = require("../../db/db");
|
||||
|
||||
class ProvincesController {
|
||||
async findAll(req, res) {
|
||||
const params = req.query;
|
||||
const tmpProvinces = await db.getProvinces();
|
||||
|
||||
let provinces = [];
|
||||
|
||||
tmpProvinces.forEach(element => {
|
||||
provinces = [...provinces,{
|
||||
code: element.id,
|
||||
name: element.name
|
||||
}];
|
||||
})
|
||||
|
||||
return res.status(200).send({
|
||||
data: provinces
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ProvincesController();
|
|
@ -1,6 +1,9 @@
|
|||
const db = require("../../db/db");
|
||||
<<<<<<<< HEAD:api/controller/product/product.controller.js
|
||||
|
||||
const productsJson = require("./products.json")
|
||||
========
|
||||
>>>>>>>> master:api/controller/Product/product.controller.js
|
||||
|
||||
class ProductController {
|
||||
async findAll(req, res) {
|
||||
|
|
32
api/db/db.js
32
api/db/db.js
|
@ -26,7 +26,10 @@ async function getProducts(dateExpired, postalCode) {
|
|||
//Procedure for create transactions, do not carry out any manipulation at the bank
|
||||
async function orderData_put(jsonOrderData) {
|
||||
const conn = await connect();
|
||||
<<<<<<< HEAD
|
||||
console.log(jsonOrderData);
|
||||
=======
|
||||
>>>>>>> master
|
||||
const [rows] = await conn.query(`CALL orderData_put(?)`, [jsonOrderData], (err, results) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
|
@ -36,7 +39,17 @@ async function orderData_put(jsonOrderData) {
|
|||
});
|
||||
return rows;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
async function order_confirm(orderFk) {
|
||||
const conn = await connect();
|
||||
const [rows] = await conn.query(`CALL order_confirm(${orderFk})`);
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
>>>>>>> master
|
||||
//Procedure for get transactions, do not carry out any manipulation at the bank
|
||||
async function orderData_get() {
|
||||
const conn = await connect();
|
||||
|
@ -55,4 +68,21 @@ async function getProvinces() {
|
|||
}
|
||||
|
||||
|
||||
module.exports = { getProducts, orderData_get, orderData_put, getProvinces }
|
||||
<<<<<<< HEAD
|
||||
module.exports = { getProducts, orderData_get, orderData_put, getProvinces }
|
||||
=======
|
||||
async function deliveryDate_get(postalCode) {
|
||||
const conn = await connect();
|
||||
const [rows] = await conn.query(`CALL deliveryDate_get("${postalCode}")`);
|
||||
return rows;
|
||||
}
|
||||
|
||||
async function contact_Request(name, phone, email, message) {
|
||||
const conn = await connect();
|
||||
const [rows] = await conn.query(`CALL contact_Request("${name}", "${phone}", "${email}", "${message}")`);
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
module.exports = { getProducts, orderData_get, orderData_put, getProvinces, deliveryDate_get, contact_Request, order_confirm }
|
||||
>>>>>>> master
|
||||
|
|
19
api/index.js
19
api/index.js
|
@ -2,9 +2,17 @@ const cors = require('cors');
|
|||
const express = require('express');
|
||||
const path = require('path');
|
||||
const paypal = require('paypal-rest-sdk');
|
||||
<<<<<<< HEAD
|
||||
const productController = require('./controller/product/product.controller');
|
||||
const paymengtController = require('./controller/payment/payment.controller');
|
||||
const provincesController = require('./controller/provinces/provinces.controller');
|
||||
=======
|
||||
const productController = require('./controller/Product/product.controller');
|
||||
const paymengtController = require('./controller/Payment/payment.controller');
|
||||
const provincesController = require('./controller/Provinces/provinces.controller');
|
||||
const deliveryController = require('./controller/Delivery/delivery.controller');
|
||||
const contactController = require('./controller/Contact/contact.controller');
|
||||
>>>>>>> master
|
||||
|
||||
paypal.configure({
|
||||
'mode': 'sandbox',
|
||||
|
@ -15,7 +23,7 @@ paypal.configure({
|
|||
const app = express();
|
||||
const port = 9999;
|
||||
|
||||
const allowedOrigins = ['http://localhost:9100', 'https://floranet.onecommerce.dev/'];
|
||||
const allowedOrigins = ['http://localhost:9100', 'https://floranet.onecommerce.dev','http://49.13.85.117','http://floranet.onecommerce.dev'];
|
||||
const corsOptions = {
|
||||
origin: allowedOrigins,
|
||||
optionsSuccessStatus: 200,
|
||||
|
@ -42,7 +50,14 @@ app.post('/api/payment/', paymengtController.Create)
|
|||
app.post('/api/payment/success', paymengtController.Success)
|
||||
app.get('/api/payment/cancel', paymengtController.Cancel)
|
||||
app.get('/api/provinces', provincesController.findAll)
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
app.get('/api/delivery/dates', deliveryController.findByPostalCode)
|
||||
app.post('/api/contact/save', contactController.Create)
|
||||
|
||||
|
||||
>>>>>>> master
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server listening at http://localhost:${port}`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
<link rel="icon" type="image/ico" href="icons/floranet-favicon.jpg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/vue-tel-input/dist/vue-tel-input.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Mulish:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;0,1000;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900;1,1000&family=Questrial&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
|
||||
rel="stylesheet"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"name": "floranet",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@floating-ui/vue": "^1.0.6",
|
||||
"@quasar/extras": "^1.16.4",
|
||||
"@vee-validate/zod": "^4.12.2",
|
||||
"@vue-stripe/vue-stripe": "^4.5.0",
|
||||
|
@ -21,9 +22,11 @@
|
|||
"quasar": "^2.6.0",
|
||||
"vee-validate": "^4.12.2",
|
||||
"vue": "^3.0.0",
|
||||
"vue-country-flag-next": "^2.3.2",
|
||||
"vue-i18n": "^9.0.0",
|
||||
"vue-image-zoomer": "^2.2.3",
|
||||
"vue-router": "^4.0.0",
|
||||
"vue-tel-input": "^8.3.1",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -135,9 +138,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@faker-js/faker": {
|
||||
<<<<<<< HEAD
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.0.tgz",
|
||||
"integrity": "sha512-htW87352wzUCdX1jyUQocUcmAaFqcR/w082EC8iP/gtkF0K+aKcBp0hR5Arb7dzR8tQ1TrhE9DNa5EbJELm84w==",
|
||||
=======
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz",
|
||||
"integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -150,6 +159,63 @@
|
|||
"npm": ">=6.14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
|
||||
"integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
|
||||
"integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.0.0",
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
|
||||
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
||||
},
|
||||
"node_modules/@floating-ui/vue": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/vue/-/vue-1.0.6.tgz",
|
||||
"integrity": "sha512-EdrOljjkpkkqZnrpqUcPoz9NvHxuTjUtSInh6GMv3+Mcy+giY2cE2pHh9rpacRcZ2eMSCxel9jWkWXTjLmY55w==",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.6.1",
|
||||
"@floating-ui/utils": "^0.2.1",
|
||||
"vue-demi": ">=0.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/vue/node_modules/vue-demi": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.14",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||
|
@ -279,9 +345,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
|
@ -581,9 +647,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/express-serve-static-core": {
|
||||
<<<<<<< HEAD
|
||||
"version": "4.17.42",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.42.tgz",
|
||||
"integrity": "sha512-ckM3jm2bf/MfB3+spLPWYPUH573plBFwpOhqQ2WottxYV85j1HQFlxmnTq57X1yHY9awZPig06hL/cLMgNWHIQ==",
|
||||
=======
|
||||
"version": "4.17.43",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz",
|
||||
"integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
|
@ -626,9 +698,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
<<<<<<< HEAD
|
||||
"version": "20.11.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.13.tgz",
|
||||
"integrity": "sha512-5G4zQwdiQBSWYTDAH1ctw2eidqdhMJaNsiIDKHFr55ihz5Trl2qqR8fdrT732yPBho5gkNxXm67OxWFBqX9aPg==",
|
||||
=======
|
||||
"version": "20.11.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
|
||||
"integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
|
@ -711,18 +789,28 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz",
|
||||
"integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@vue/shared": "3.4.15",
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz",
|
||||
"integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.9",
|
||||
"@vue/shared": "3.4.19",
|
||||
>>>>>>> master
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz",
|
||||
"integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==",
|
||||
|
@ -743,25 +831,57 @@
|
|||
"@vue/shared": "3.4.15",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.5",
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz",
|
||||
"integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.4.19",
|
||||
"@vue/shared": "3.4.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz",
|
||||
"integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.9",
|
||||
"@vue/compiler-core": "3.4.19",
|
||||
"@vue/compiler-dom": "3.4.19",
|
||||
"@vue/compiler-ssr": "3.4.19",
|
||||
"@vue/shared": "3.4.19",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.6",
|
||||
>>>>>>> master
|
||||
"postcss": "^8.4.33",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz",
|
||||
"integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz",
|
||||
"integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.19",
|
||||
"@vue/shared": "3.4.19"
|
||||
>>>>>>> master
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/devtools-api": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz",
|
||||
"integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA=="
|
||||
"version": "6.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
|
||||
"integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz",
|
||||
"integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==",
|
||||
|
@ -785,10 +905,36 @@
|
|||
"dependencies": {
|
||||
"@vue/runtime-core": "3.4.15",
|
||||
"@vue/shared": "3.4.15",
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz",
|
||||
"integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.4.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz",
|
||||
"integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.19",
|
||||
"@vue/shared": "3.4.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz",
|
||||
"integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==",
|
||||
"dependencies": {
|
||||
"@vue/runtime-core": "3.4.19",
|
||||
"@vue/shared": "3.4.19",
|
||||
>>>>>>> master
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz",
|
||||
"integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==",
|
||||
|
@ -804,6 +950,23 @@
|
|||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g=="
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz",
|
||||
"integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.4.19",
|
||||
"@vue/shared": "3.4.19"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.4.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
|
||||
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
|
||||
>>>>>>> master
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "10.7.2",
|
||||
|
@ -820,9 +983,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vueuse/core/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
|
@ -864,9 +1027,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
|
@ -1288,9 +1451,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
<<<<<<< HEAD
|
||||
"version": "4.22.3",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
|
||||
"integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
|
||||
=======
|
||||
"version": "4.23.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
|
||||
"integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1307,8 +1476,13 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
<<<<<<< HEAD
|
||||
"caniuse-lite": "^1.0.30001580",
|
||||
"electron-to-chromium": "^1.4.648",
|
||||
=======
|
||||
"caniuse-lite": "^1.0.30001587",
|
||||
"electron-to-chromium": "^1.4.668",
|
||||
>>>>>>> master
|
||||
"node-releases": "^2.0.14",
|
||||
"update-browserslist-db": "^1.0.13"
|
||||
},
|
||||
|
@ -1361,13 +1535,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
|
||||
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"set-function-length": "^1.1.1"
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
@ -1393,9 +1572,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
<<<<<<< HEAD
|
||||
"version": "1.0.30001581",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz",
|
||||
"integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==",
|
||||
=======
|
||||
"version": "1.0.30001587",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
|
||||
"integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1435,16 +1620,10 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
|
@ -1457,6 +1636,9 @@
|
|||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
|
@ -1853,16 +2035,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
|
||||
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0"
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/define-lazy-prop": {
|
||||
|
@ -1949,9 +2134,15 @@
|
|||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
<<<<<<< HEAD
|
||||
"version": "1.4.651",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.651.tgz",
|
||||
"integrity": "sha512-jjks7Xx+4I7dslwsbaFocSwqBbGHQmuXBJUK9QBZTIrzPq3pzn6Uf2szFSP728FtLYE3ldiccmlkOM/zhGKCpA==",
|
||||
=======
|
||||
"version": "1.4.670",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz",
|
||||
"integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A==",
|
||||
>>>>>>> master
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/elementtree": {
|
||||
|
@ -2013,6 +2204,25 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz",
|
||||
|
@ -2369,9 +2579,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
@ -2462,9 +2672,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue": {
|
||||
<<<<<<< HEAD
|
||||
"version": "9.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.21.0.tgz",
|
||||
"integrity": "sha512-B3NgZRtbi9kSl7M0x/PqhSMk7ULJUwWxQpTvM8b2Z6gNTORK0YSt5v1vzwY84oMs/2+3BWH5XmTepaQebcJwfA==",
|
||||
=======
|
||||
"version": "9.21.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.21.1.tgz",
|
||||
"integrity": "sha512-XVtI7z39yOVBFJyi8Ljbn7kY9yHzznKXL02qQYn+ta63Iy4A9JFBw6o4OSB9hyD2++tVT+su9kQqetUyCCwhjw==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
|
@ -2765,9 +2981,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
<<<<<<< HEAD
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
|
||||
"integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==",
|
||||
=======
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||
>>>>>>> master
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4"
|
||||
|
@ -3028,15 +3250,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
|
@ -3133,11 +3359,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.2"
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
@ -3166,9 +3392,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
|
||||
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
|
||||
"integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
|
@ -3253,9 +3479,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
|
||||
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
|
@ -3500,12 +3726,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/isbinaryfile": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz",
|
||||
"integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz",
|
||||
"integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
"node": ">= 18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/gjtorikian/"
|
||||
|
@ -3749,6 +3975,11 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.10.56",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.56.tgz",
|
||||
"integrity": "sha512-d0GdKshNnyfl5gM7kZ9rXjGiAbxT/zCXp0k+EAzh8H4zrb2R7GXtMCrULrX7UQxtfx6CLy/vz/lomvW79FAFdA=="
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
|
@ -3873,9 +4104,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.5",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
|
||||
"integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
|
||||
"version": "0.30.7",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz",
|
||||
"integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
},
|
||||
|
@ -4497,9 +4728,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/pinia/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
|
@ -4540,9 +4771,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.33",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
|
||||
"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
|
||||
"version": "8.4.35",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
|
||||
"integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -4656,9 +4887,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/quasar": {
|
||||
<<<<<<< HEAD
|
||||
"version": "2.14.3",
|
||||
"resolved": "https://registry.npmjs.org/quasar/-/quasar-2.14.3.tgz",
|
||||
"integrity": "sha512-7WzbtZxykLn2ic5oNpepZ2ZjDVpmxyVD4KC9rWe+Ia+4Er61svGr4jOuttN+Ok7IerLSCmKIRyjQMgasF60rFA==",
|
||||
=======
|
||||
"version": "2.14.4",
|
||||
"resolved": "https://registry.npmjs.org/quasar/-/quasar-2.14.4.tgz",
|
||||
"integrity": "sha512-l+bSGVMcesVydX1IeWyAAjqCRfigwaonIDqxodvNjZwkifZF29YdCMh9bief2l9k9r23kMl7P5Oqs6EA5ja4ag==",
|
||||
>>>>>>> master
|
||||
"engines": {
|
||||
"node": ">= 10.18.1",
|
||||
"npm": ">= 6.13.4",
|
||||
|
@ -5007,9 +5244,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
|
@ -5115,6 +5352,7 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
<<<<<<< HEAD
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
|
||||
"integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
|
||||
|
@ -5122,6 +5360,16 @@
|
|||
"define-data-property": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.2",
|
||||
=======
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
|
||||
"integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.2",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.3",
|
||||
>>>>>>> master
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.1"
|
||||
},
|
||||
|
@ -5168,13 +5416,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
|
||||
"integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
"object-inspect": "^1.9.0"
|
||||
"call-bind": "^1.0.6",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"object-inspect": "^1.13.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
@ -5698,6 +5950,7 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
<<<<<<< HEAD
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz",
|
||||
"integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==",
|
||||
|
@ -5707,6 +5960,17 @@
|
|||
"@vue/runtime-dom": "3.4.15",
|
||||
"@vue/server-renderer": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
=======
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz",
|
||||
"integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.19",
|
||||
"@vue/compiler-sfc": "3.4.19",
|
||||
"@vue/runtime-dom": "3.4.19",
|
||||
"@vue/server-renderer": "3.4.19",
|
||||
"@vue/shared": "3.4.19"
|
||||
>>>>>>> master
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
|
@ -5722,6 +5986,17 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-coerce-props/-/vue-coerce-props-1.0.0.tgz",
|
||||
"integrity": "sha512-4fdRMXO6FHzmE7H4soAph6QmPg3sL/RiGdd+axuxuU07f02LNMns0jMM88fmt1bvSbN+2Wyd8raho6p6nXUzag=="
|
||||
},
|
||||
"node_modules/vue-country-flag-next": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-country-flag-next/-/vue-country-flag-next-2.3.2.tgz",
|
||||
"integrity": "sha512-Lv12L1VTwlBgizpZ3xPEPO3zuIETaJmeSiPuLOWLLgu2EakwU/o72iKYiKcdZ6BXiSkfss+Ski5fDzjuxZ1DcA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-eslint-parser": {
|
||||
"version": "9.4.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
|
||||
|
@ -5787,6 +6062,15 @@
|
|||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-tel-input": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-tel-input/-/vue-tel-input-8.3.1.tgz",
|
||||
"integrity": "sha512-+YMFf1Dq/H9xJ2QQ0dDtPrCRNdfWCMCZ78/29qV9BJ9cf7BAFv4jpBPNQU4DyOqoOd0BEujVw9SRJ+fcXPO21Q==",
|
||||
"dependencies": {
|
||||
"libphonenumber-js": "^1.10.51",
|
||||
"vue": "^3.3.9"
|
||||
}
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
|
|
10
package.json
10
package.json
|
@ -16,6 +16,7 @@
|
|||
"backend": "json-server -p 3000 -d 600 -w src/services/json-server/db.json --routes src/services/json-server/routes.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/vue": "^1.0.6",
|
||||
"@quasar/extras": "^1.16.4",
|
||||
"@vee-validate/zod": "^4.12.2",
|
||||
"@vue-stripe/vue-stripe": "^4.5.0",
|
||||
|
@ -24,14 +25,23 @@
|
|||
"express": "^4.18.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"mysql2": "^3.7.0",
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
"node-redsys-api": "^0.0.5",
|
||||
>>>>>>> master
|
||||
"paypal-rest-sdk": "^1.8.1",
|
||||
"pinia": "^2.0.11",
|
||||
"quasar": "^2.6.0",
|
||||
"redsys-easy": "^5.2.3",
|
||||
"redsys-pay": "^1.2.0",
|
||||
"redsys-pos": "^1.0.2",
|
||||
"vee-validate": "^4.12.2",
|
||||
"vue": "^3.0.0",
|
||||
"vue-country-flag-next": "^2.3.2",
|
||||
"vue-i18n": "^9.0.0",
|
||||
"vue-image-zoomer": "^2.2.3",
|
||||
"vue-router": "^4.0.0",
|
||||
"vue-tel-input": "^8.3.1",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
const { configure } = require("quasar/wrappers");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = configure(function (/* ctx */) {
|
||||
module.exports = configure(function (ctx) {
|
||||
return {
|
||||
eslint: {
|
||||
// fix: true,
|
||||
|
@ -28,7 +28,15 @@ 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" /* , { path: "stripe", server: false } */],
|
||||
boot: [
|
||||
"i18n",
|
||||
"axios",
|
||||
{
|
||||
path: "VueCountryFlag",
|
||||
server: false,
|
||||
},
|
||||
{ path: "VueTelInput", server: false },
|
||||
],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||
css: ["app.scss"],
|
||||
|
@ -49,6 +57,12 @@ module.exports = configure(function (/* ctx */) {
|
|||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
||||
build: {
|
||||
env: {
|
||||
API: ctx.dev
|
||||
? "http://localhost:9999/api/"
|
||||
: "https://floranet-back.onecommerce.dev/api/",
|
||||
},
|
||||
|
||||
target: {
|
||||
browser: ["es2019", "edge88", "firefox78", "chrome87", "safari13.1"],
|
||||
node: "node16",
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { boot } from "quasar/wrappers";
|
||||
import CountryFlag from "vue-country-flag-next";
|
||||
|
||||
export default boot(({ app }) => {
|
||||
app.use(CountryFlag);
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import { boot } from "quasar/wrappers";
|
||||
import VueTelInput from "vue-tel-input";
|
||||
|
||||
export default boot(({ app }) => {
|
||||
const options = {
|
||||
mode: "auto",
|
||||
dropdownOptions: {
|
||||
showDialCodeInSelection: true,
|
||||
showFlags: true,
|
||||
showDialCodeInList: true,
|
||||
},
|
||||
autoFormat: true,
|
||||
};
|
||||
|
||||
app.use(VueTelInput, options);
|
||||
});
|
|
@ -7,8 +7,8 @@ import { boot } from "quasar/wrappers";
|
|||
// good idea to move this instance creation inside of the
|
||||
// "export default () => {}" function below (which runs individually
|
||||
// for each client)
|
||||
const api = axios.create({ baseURL: "http://localhost:3000/jsonServer/" });
|
||||
const apiBack = axios.create({ baseURL: "http://localhost:9999/api/" });
|
||||
|
||||
const apiBack = axios.create({ baseURL: process.env.API });
|
||||
|
||||
export default boot(({ app }) => {
|
||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||
|
@ -17,10 +17,9 @@ export default boot(({ app }) => {
|
|||
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
|
||||
// so you won't necessarily have to import axios in each vue file
|
||||
|
||||
app.config.globalProperties.$api = api;
|
||||
app.config.globalProperties.$apiBack = apiBack;
|
||||
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
|
||||
// so you can easily perform requests against your app's API
|
||||
});
|
||||
|
||||
export { api, apiBack };
|
||||
export { apiBack };
|
||||
|
|
|
@ -10,16 +10,10 @@ import IconCalendar from "../icons/IconCalendar.vue";
|
|||
export default defineComponent({
|
||||
name: "calendar-input",
|
||||
components: { IconCalendar },
|
||||
inheritAttrs: true,
|
||||
props: {
|
||||
setValues: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
setup({ setValues }) {
|
||||
props: ["modelValue", "bindValue", "setValues"],
|
||||
setup({ setValues }, { emit }) {
|
||||
const formStore = useFormStore();
|
||||
const { availability } = storeToRefs(formStore);
|
||||
const { availability, postalCodeValid } = storeToRefs(formStore);
|
||||
|
||||
const [year, month, day] = fullCurrentDate.replaceAll("/", "-").split("-");
|
||||
const currentDate = `${day}-${month}-${year}`;
|
||||
|
@ -33,6 +27,7 @@ export default defineComponent({
|
|||
return date >= fullCurrentDate;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
onBeforeMount(() => {
|
||||
setValues({ date: invertDate(proxyDate.value) });
|
||||
});
|
||||
|
@ -53,13 +48,47 @@ export default defineComponent({
|
|||
format24h: false,
|
||||
pluralDay: "dias",
|
||||
};
|
||||
=======
|
||||
function updateModel(value) {
|
||||
emit("update:modelValue", value);
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
onBeforeMount(() => {
|
||||
setValues({ date: invertDate(proxyDate.value) });
|
||||
});
|
||||
|
||||
watch(proxyDate, (newProxy) => {
|
||||
setValues({ date: invertDate(newProxy) });
|
||||
});
|
||||
|
||||
const LOCALE = {
|
||||
days: "Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"),
|
||||
daysShort: "Dom_Lun_Mar_Mié_Jue_Vie_Sáb".split("_"),
|
||||
months:
|
||||
"Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split(
|
||||
"_"
|
||||
),
|
||||
monthsShort: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic".split("_"),
|
||||
firstDayOfWeek: 1,
|
||||
format24h: false,
|
||||
pluralDay: "dias",
|
||||
};
|
||||
|
||||
return {
|
||||
availability,
|
||||
postalCodeValid,
|
||||
proxyDate,
|
||||
<<<<<<< HEAD
|
||||
locale,
|
||||
updateProxy,
|
||||
optionsValidDates,
|
||||
=======
|
||||
LOCALE,
|
||||
updateProxy,
|
||||
optionsValidDates,
|
||||
updateModel,
|
||||
>>>>>>> master
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -78,9 +107,15 @@ export default defineComponent({
|
|||
>
|
||||
<q-date
|
||||
v-model="proxyDate"
|
||||
<<<<<<< HEAD
|
||||
:options="optionsValidDates"
|
||||
:locale="locale"
|
||||
today-btn
|
||||
=======
|
||||
:options="postalCodeValid.dataOptions"
|
||||
:locale="LOCALE"
|
||||
:readonly="!postalCodeValid.isValid"
|
||||
>>>>>>> master
|
||||
mask="YYYY-MM-DD"
|
||||
>
|
||||
<div class="row items-center justify-end q-gutter-sm">
|
||||
|
@ -94,7 +129,18 @@ export default defineComponent({
|
|||
<div class="custom-block-content">
|
||||
<p class="custom-head-paragraph">¿Cuándo?</p>
|
||||
|
||||
<slot></slot>
|
||||
<q-input
|
||||
:model-value="modelValue"
|
||||
@update:model-value="updateModel"
|
||||
v-bind="bindValue"
|
||||
class="custom-date-input"
|
||||
:error="false"
|
||||
placeholder="Elige una fecha"
|
||||
mask="##/##/####"
|
||||
borderless
|
||||
dense
|
||||
:disable="!postalCodeValid.isValid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,13 +1,86 @@
|
|||
<script>
|
||||
<<<<<<< HEAD
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
=======
|
||||
import { storeToRefs } from "pinia";
|
||||
import { defineComponent, ref } from "vue";
|
||||
|
||||
import { apiBack } from "src/boot/axios";
|
||||
import { quasarNotify } from "src/functions/quasarNotify";
|
||||
import { useFormStore } from "src/stores/forms";
|
||||
import * as M from "src/utils/zod/messages";
|
||||
>>>>>>> master
|
||||
import IconPostalCode from "../icons/IconPostalCode.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "postal-code",
|
||||
<<<<<<< HEAD
|
||||
components: { IconPostalCode },
|
||||
setup() {
|
||||
return {};
|
||||
=======
|
||||
components: { IconPostalCode /* IconInfo, */ /* IconSearch */ },
|
||||
props: ["modelValue", "bindValue", "setFieldError"],
|
||||
setup({ setFieldError, modelValue }, { emit }) {
|
||||
const formStore = useFormStore();
|
||||
const { postalCodeValid } = storeToRefs(formStore);
|
||||
|
||||
const postalCodeInput = ref(modelValue);
|
||||
|
||||
function updateModel(value) {
|
||||
emit("update:modelValue", value);
|
||||
postalCodeInput.value = value;
|
||||
}
|
||||
|
||||
const isPostalCodeLoading = ref(false);
|
||||
async function onBlur() {
|
||||
try {
|
||||
if (postalCodeInput.value.length < 5) {
|
||||
quasarNotify({
|
||||
type: "info",
|
||||
message: `${M.fiveLength}, Cantidad de caracteres: ${postalCodeInput.value.length}`,
|
||||
});
|
||||
setFieldError("postalCode", M.fiveLength);
|
||||
return;
|
||||
}
|
||||
|
||||
isPostalCodeLoading.value = true;
|
||||
|
||||
//TODO - Promesa consultando la api para ver las fechas existentes
|
||||
const {
|
||||
data: { data },
|
||||
} = await apiBack.get(`/delivery/dates`, {
|
||||
params: { postalCode: postalCodeInput.value },
|
||||
});
|
||||
const dates = data.map(({ dated }) => {
|
||||
const getDate = new Date(dated);
|
||||
const day = getDate.getDate().toString().padStart(2, "0");
|
||||
const month = (getDate.getMonth() + 1).toString().padStart(2, "0");
|
||||
const year = getDate.getFullYear();
|
||||
const formattedDate = `${year}/${month}/${day}`;
|
||||
|
||||
return formattedDate;
|
||||
});
|
||||
|
||||
postalCodeValid.value.dataOptions = dates;
|
||||
postalCodeValid.value.isValid = true;
|
||||
isPostalCodeLoading.value = false;
|
||||
} catch (error) {
|
||||
quasarNotify({
|
||||
type: "erro",
|
||||
message:
|
||||
"Se ha producido un error en el proceso de identificación del código postal",
|
||||
});
|
||||
isPostalCodeLoading.value = false;
|
||||
console.error(`FATAL ERROR ::: ${error}`);
|
||||
} finally {
|
||||
// console.log("click");
|
||||
}
|
||||
}
|
||||
|
||||
return { updateModel, onBlur, isPostalCodeLoading };
|
||||
>>>>>>> master
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -17,9 +90,39 @@ export default defineComponent({
|
|||
<IconPostalCode />
|
||||
|
||||
<div class="custom-block-content">
|
||||
<p class="custom-head-paragraph">¿Dónde?</p>
|
||||
<p class="custom-head-paragraph">
|
||||
¿Dónde?
|
||||
<!-- <IconInfo /> -->
|
||||
</p>
|
||||
|
||||
<<<<<<< HEAD
|
||||
<slot></slot>
|
||||
=======
|
||||
<q-input
|
||||
:model-value="modelValue"
|
||||
@update:model-value="updateModel"
|
||||
v-bind="bindValue"
|
||||
class="custom-main-paragraph"
|
||||
:error="false"
|
||||
placeholder="código postal"
|
||||
mask="#####"
|
||||
borderless
|
||||
dense
|
||||
@blur="onBlur"
|
||||
/>
|
||||
>>>>>>> master
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-input-el .custom-block-content .search-btn {
|
||||
padding: 8px;
|
||||
& .q-btn__content {
|
||||
& svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,16 +11,36 @@ export default defineComponent({
|
|||
default: 0,
|
||||
required: true,
|
||||
},
|
||||
minDefault: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true,
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 200,
|
||||
required: true,
|
||||
},
|
||||
maxDefault: {
|
||||
type: Number,
|
||||
default: 200,
|
||||
required: true,
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
},
|
||||
bindValue: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
setup(props, { emit }) {
|
||||
const rangePriceStore = useRangePriceStore();
|
||||
|
||||
return { rangePriceStore };
|
||||
const updateModel = (value) => {
|
||||
emit("update:modelValue", value);
|
||||
};
|
||||
|
||||
return { rangePriceStore, updateModel };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -29,7 +49,14 @@ export default defineComponent({
|
|||
<div class="range-container">
|
||||
<p class="filter-item-paragraph">Precio</p>
|
||||
|
||||
<slot></slot>
|
||||
<q-range
|
||||
:model-value="modelValue"
|
||||
@update:model-value="updateModel"
|
||||
v-bind="bindValue"
|
||||
:min="minDefault"
|
||||
:max="maxDefault"
|
||||
color="primary"
|
||||
/>
|
||||
|
||||
<div class="range-price-content">
|
||||
<p class="filter-item-paragraph min-price">
|
||||
|
|
|
@ -33,8 +33,7 @@ export default defineComponent({
|
|||
</li>
|
||||
|
||||
<li class="footer-list-item">
|
||||
<p class="footer-list-content">
|
||||
</p>
|
||||
<p class="footer-list-content"></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -44,7 +43,7 @@ export default defineComponent({
|
|||
<RouterLink to="/categoria/plantas">Plantas</RouterLink><br />
|
||||
<!-- <RouterLink to="/">Nosotros</RouterLink><br />
|
||||
<RouterLink to="/faq">FAQs</RouterLink><br /> -->
|
||||
<RouterLink to="/contacta">Contacta</RouterLink>
|
||||
<RouterLink to="/#question-section">Contacta</RouterLink>
|
||||
</li>
|
||||
|
||||
<li class="footer-list-item">
|
||||
|
@ -57,7 +56,7 @@ export default defineComponent({
|
|||
<IconArrowCircleRight /> Preguntas frecuentes
|
||||
</RouterLink> -->
|
||||
<br />
|
||||
<RouterLink to="/example">
|
||||
<RouterLink to="/#question-section">
|
||||
<IconArrowCircleRight /> Contacta con nosotros
|
||||
</RouterLink>
|
||||
</p>
|
||||
|
@ -66,12 +65,10 @@ export default defineComponent({
|
|||
<li class="footer-list-item">
|
||||
<p class="footer-list-content">
|
||||
Floranet ©{{ year }} <br /><br />
|
||||
<RouterLink to="/example">Aviso Legal</RouterLink> <br />
|
||||
<RouterLink to="/example">Condiciones de uso</RouterLink><br />
|
||||
<RouterLink to="/example">Política de cookies</RouterLink><br />
|
||||
<RouterLink to="/example">
|
||||
Política de Redes Sociales
|
||||
</RouterLink>
|
||||
<RouterLink to="/">Aviso Legal</RouterLink> <br />
|
||||
<RouterLink to="/">Condiciones de uso</RouterLink><br />
|
||||
<RouterLink to="/">Política de cookies</RouterLink><br />
|
||||
<RouterLink to="/"> Política de Redes Sociales </RouterLink>
|
||||
<br /><br />
|
||||
|
||||
Desarrollado por diligent
|
||||
|
@ -141,6 +138,12 @@ a:hover {
|
|||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: calc($med-xlg + 100px)) {
|
||||
&.footer-primary {
|
||||
flex: 0 0 min(100%, 480px);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $med-lg) {
|
||||
&.footer-primary {
|
||||
flex: 0 0 min(100%, 275px);
|
||||
|
@ -150,6 +153,11 @@ a:hover {
|
|||
flex: 0 0 min(100%, 545px);
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: $med-md + 600px) {
|
||||
&.footer-primary {
|
||||
flex: 0 0 min(100%, 300px);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $med-md) {
|
||||
justify-content: space-evenly;
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<script>
|
||||
import { autoUpdate, useFloating } from "@floating-ui/vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "icon-info",
|
||||
setup() {
|
||||
const iconRef = ref(null);
|
||||
const tooltipRef = ref(null);
|
||||
|
||||
const isHidden = ref(true);
|
||||
const hideTooltip = () => {
|
||||
isHidden.value = true;
|
||||
};
|
||||
const showTooltip = () => {
|
||||
isHidden.value = false;
|
||||
};
|
||||
|
||||
const { floatingStyles } = useFloating(iconRef, tooltipRef, {
|
||||
placement: "top-start",
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
return { floatingStyles, isHidden, hideTooltip, showTooltip };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="info-container">
|
||||
<svg
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
width="48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@mouseenter="showTooltip"
|
||||
@mouseleave="hideTooltip"
|
||||
>
|
||||
<path d="M0 0h48v48h-48z" fill="transparent" />
|
||||
<path
|
||||
d="M22 34h4v-12h-4v12zm2-30c-11.05 0-20 8.95-20 20s8.95 20 20 20 20-8.95 20-20-8.95-20-20-20zm0 36c-8.82 0-16-7.18-16-16s7.18-16 16-16 16 7.18 16 16-7.18 16-16 16zm-2-22h4v-4h-4v4z"
|
||||
fill="#117564"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<a
|
||||
href="https://www.google.com/maps"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
:style="[floatingStyles, '--clr: #117564']"
|
||||
:class="[isHidden && 'hidden', 'tooltip info', 'paragraph-sm', 'link']"
|
||||
@mouseenter="showTooltip"
|
||||
@mouseleave="hideTooltip"
|
||||
>
|
||||
Si no sabes tu código postal pincha aquí
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info-container {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
aspect-ratio: 1/1;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
& svg {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,13 +1,11 @@
|
|||
<script>
|
||||
import { useIntersectionObserver } from "@vueuse/core";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import Calendar from "src/components/@inputs/Calendar.vue";
|
||||
import PostalCode from "src/components/@inputs/PostalCode.vue";
|
||||
import IconSearch from "src/components/icons/IconSearch.vue";
|
||||
import { usePostalCalendar } from "src/hooks/usePostalCalendar";
|
||||
import { useMobileStore } from "src/stores/mobileNav";
|
||||
import { useVerticalCarouselImgs } from "src/hooks/useVerticalCarouselImgs";
|
||||
|
||||
export default defineComponent({
|
||||
name: "vertical-carousel-imgs",
|
||||
|
@ -17,42 +15,32 @@ export default defineComponent({
|
|||
default: () => [""],
|
||||
},
|
||||
},
|
||||
components: { IconSearch, Calendar, PostalCode },
|
||||
setup() {
|
||||
const {
|
||||
onSubmit,
|
||||
setValues,
|
||||
setFieldError,
|
||||
fields: { calendar, calendarAttrs, postalCode, postalCodeAttrs },
|
||||
errors,
|
||||
} = usePostalCalendar({ type: "home" });
|
||||
|
||||
const mobileStore = useMobileStore();
|
||||
const { screenWidth } = storeToRefs(mobileStore);
|
||||
const { handleResize } = mobileStore;
|
||||
|
||||
const target = ref(null);
|
||||
const navPos = ref("bottom");
|
||||
|
||||
useIntersectionObserver(target, ([{ isIntersecting }]) => {
|
||||
mobileStore.isCarouselVisible = isIntersecting;
|
||||
});
|
||||
document.addEventListener("resize", handleResize);
|
||||
const { navPos, screenWidth, slide, target } = useVerticalCarouselImgs();
|
||||
|
||||
return {
|
||||
slide: ref("style"),
|
||||
slide,
|
||||
navPos,
|
||||
target,
|
||||
screenWidth,
|
||||
errors,
|
||||
onSubmit,
|
||||
setValues,
|
||||
|
||||
setFieldError,
|
||||
postalCode,
|
||||
postalCodeAttrs,
|
||||
calendar,
|
||||
calendarAttrs,
|
||||
};
|
||||
},
|
||||
components: { IconSearch, Calendar, PostalCode },
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -86,12 +74,16 @@ export default defineComponent({
|
|||
<h1 class="carousel-header-title">
|
||||
Regala un verano lleno de flores y plantas
|
||||
</h1>
|
||||
<<<<<<< HEAD
|
||||
|
||||
<!-- <p class="carousel-header-paragraph"></p> -->
|
||||
=======
|
||||
>>>>>>> master
|
||||
</header>
|
||||
|
||||
<form @submit="onSubmit" class="carousel-content-body">
|
||||
<div class="carousel-content-item">
|
||||
<<<<<<< HEAD
|
||||
<Calendar :setValues="setValues">
|
||||
<q-input
|
||||
borderless
|
||||
|
@ -119,14 +111,27 @@ export default defineComponent({
|
|||
dense
|
||||
/>
|
||||
</PostalCode>
|
||||
=======
|
||||
<PostalCode
|
||||
v-model="postalCode"
|
||||
v-bind:bindValue="postalCodeAttrs"
|
||||
:setFieldError="setFieldError"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="carousel-content-item">
|
||||
<Calendar
|
||||
v-model="calendar"
|
||||
v-bind:bindValue="calendarAttrs"
|
||||
:setValues="setValues"
|
||||
/>
|
||||
>>>>>>> master
|
||||
</div>
|
||||
|
||||
<q-btn type="submit" class="btn carousel-content-item">
|
||||
<IconSearch /> ver disponibilidad
|
||||
</q-btn>
|
||||
</form>
|
||||
|
||||
<!-- <footer class="carousel-content-footer"></footer> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -173,6 +178,18 @@ export default defineComponent({
|
|||
border-radius: 10px 0 0 10px;
|
||||
overflow: hidden;
|
||||
min-height: 96px;
|
||||
|
||||
/* & .carousel-content {
|
||||
border-radius: 10px 10px 0 0;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 2;
|
||||
background-color: $white;
|
||||
} */
|
||||
|
||||
& .carousel-content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -23,9 +23,11 @@ export default defineComponent({
|
|||
>
|
||||
<Container class="question-container-form">
|
||||
<header class="question-content">
|
||||
<LogoWhite />
|
||||
<LogoWhite class="white-logo" />
|
||||
|
||||
<p class="question-paragraph">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore...
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
@ -70,6 +72,16 @@ p {
|
|||
|
||||
& .question-content {
|
||||
flex: 1 0 min(100%, 540px);
|
||||
|
||||
& .white-logo {
|
||||
width: min(100%, 335px);
|
||||
height: 75px;
|
||||
@media only screen and (max-width: $med-xmd) {
|
||||
width: min(100%, 175px);
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
& .question-paragraph {
|
||||
line-height: 35px;
|
||||
font-size: $font-25;
|
||||
|
|
|
@ -31,6 +31,7 @@ export default defineComponent({
|
|||
const {
|
||||
onSubmit,
|
||||
setValues,
|
||||
setFieldError,
|
||||
fields: {
|
||||
calendar,
|
||||
calendarAttrs,
|
||||
|
@ -39,6 +40,8 @@ export default defineComponent({
|
|||
priceRange,
|
||||
priceRangeAttrs,
|
||||
},
|
||||
isPostalCalendarEmpty,
|
||||
isAvailabilityEmpty,
|
||||
errors,
|
||||
modalStore,
|
||||
} = usePostalCalendar({
|
||||
|
@ -63,6 +66,10 @@ export default defineComponent({
|
|||
modalStore,
|
||||
modalTextContent,
|
||||
setValues,
|
||||
setFieldError,
|
||||
|
||||
isAvailabilityEmpty,
|
||||
isPostalCalendarEmpty,
|
||||
|
||||
postalCode,
|
||||
postalCodeAttrs,
|
||||
|
@ -106,16 +113,14 @@ export default defineComponent({
|
|||
class="modal-body-filters"
|
||||
>
|
||||
<div class="filter-field">
|
||||
<PriceRange :min="priceRange.min" :max="priceRange.max">
|
||||
<q-range
|
||||
v-model="priceRange"
|
||||
v-bind="priceRangeAttrs"
|
||||
:min="0"
|
||||
:max="200"
|
||||
color="primary"
|
||||
/>
|
||||
<!-- @change="rangePriceStore.handlePriceRange" -->
|
||||
</PriceRange>
|
||||
<PriceRange
|
||||
:minDefault="0"
|
||||
:maxDefault="200"
|
||||
v-model="priceRange"
|
||||
v-bind:bindValue="priceRangeAttrs"
|
||||
:min="priceRange.min"
|
||||
:max="priceRange.max"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -123,6 +128,7 @@ export default defineComponent({
|
|||
v-if="modalItem === 'isOpenAvailability'"
|
||||
class="modal-body-availability"
|
||||
>
|
||||
<<<<<<< HEAD
|
||||
<Calendar :setValues="setValues">
|
||||
<q-input
|
||||
borderless
|
||||
|
@ -148,6 +154,19 @@ export default defineComponent({
|
|||
dense
|
||||
/>
|
||||
</PostalCode>
|
||||
=======
|
||||
<PostalCode
|
||||
v-model="postalCode"
|
||||
v-bind:bindValue="postalCodeAttrs"
|
||||
:setFieldError="setFieldError"
|
||||
/>
|
||||
|
||||
<Calendar
|
||||
v-model="calendar"
|
||||
v-bind:bindValue="calendarAttrs"
|
||||
:setValues="setValues"
|
||||
/>
|
||||
>>>>>>> master
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -159,23 +178,11 @@ export default defineComponent({
|
|||
align="center"
|
||||
class="modal-footer"
|
||||
form="filters-form"
|
||||
:disabled="modalItem === 'isOpenFilters' && isPostalCalendarEmpty"
|
||||
>
|
||||
<!-- v-close-popup -->
|
||||
<IconSearch />
|
||||
<p>ver disponibilidad</p>
|
||||
</q-btn>
|
||||
<!-- <q-btn
|
||||
flat
|
||||
type="button"
|
||||
align="center"
|
||||
class="modal-footer"
|
||||
form="filters-form"
|
||||
@click="handleSubmit({ content: modalItem })"
|
||||
v-close-popup
|
||||
>
|
||||
<IconSearch />
|
||||
<p>ver disponibilidad</p>
|
||||
</q-btn> -->
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
@ -238,6 +245,10 @@ export default defineComponent({
|
|||
margin-bottom: 29px;
|
||||
&.availability {
|
||||
gap: 65px;
|
||||
|
||||
@media only screen and (max-width: $med-md) {
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
& .modal-body-paragraph {
|
||||
|
|
|
@ -1,25 +1,33 @@
|
|||
<script>
|
||||
import { useQuasar } from "quasar";
|
||||
import { useFormStore } from "src/stores/forms";
|
||||
import { useForm } from "vee-validate";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import IconArrowRightOne from "src/components/icons/IconArrowRightOne.vue";
|
||||
import { questionSchema } from "src/utils/zod/schemas/questionSchema";
|
||||
import { useQuestionForm } from "src/hooks/useQuestionForm";
|
||||
|
||||
export default defineComponent({
|
||||
name: "QuestionForm",
|
||||
components: { IconArrowRightOne },
|
||||
setup() {
|
||||
const $q = useQuasar();
|
||||
const formStore = useFormStore();
|
||||
const { handleQuestionData } = formStore;
|
||||
|
||||
const { errors, meta, defineField, handleSubmit, handleReset } = useForm({
|
||||
validationSchema: questionSchema,
|
||||
initialValues: {
|
||||
terms: false,
|
||||
const {
|
||||
questionPhoneRef,
|
||||
formState: { isQuestionSubmitLoading, onSubmit, errors, meta },
|
||||
fields: {
|
||||
email,
|
||||
emailAttrs,
|
||||
firstName,
|
||||
firstNameAttrs,
|
||||
message,
|
||||
messageAttrs,
|
||||
phone,
|
||||
phoneAttrs,
|
||||
query,
|
||||
queryAttrs,
|
||||
secondName,
|
||||
secondNameAttrs,
|
||||
terms,
|
||||
termsAttrs,
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
});
|
||||
const [firstName, firstNameAttrs] = defineField("name");
|
||||
const [secondName, secondNameAttrs] = defineField("surname");
|
||||
|
@ -40,9 +48,13 @@ export default defineComponent({
|
|||
return;
|
||||
}
|
||||
});
|
||||
=======
|
||||
} = useQuestionForm();
|
||||
>>>>>>> master
|
||||
|
||||
return {
|
||||
errors,
|
||||
isQuestionSubmitLoading,
|
||||
questionPhoneRef,
|
||||
firstName,
|
||||
firstNameAttrs,
|
||||
secondName,
|
||||
|
@ -58,6 +70,7 @@ export default defineComponent({
|
|||
terms,
|
||||
termsAttrs,
|
||||
onSubmit,
|
||||
errors,
|
||||
meta,
|
||||
};
|
||||
},
|
||||
|
@ -77,6 +90,7 @@ export default defineComponent({
|
|||
class="name"
|
||||
outlined
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model="secondName"
|
||||
v-bind="secondNameAttrs"
|
||||
|
@ -87,6 +101,7 @@ export default defineComponent({
|
|||
class="nickname"
|
||||
outlined
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model="email"
|
||||
v-bind="emailAttrs"
|
||||
|
@ -96,20 +111,25 @@ export default defineComponent({
|
|||
type="email"
|
||||
label="Email"
|
||||
class="email"
|
||||
autocomplete="email"
|
||||
outlined
|
||||
/>
|
||||
<q-input
|
||||
v-model="phone"
|
||||
v-bind="phoneAttrs"
|
||||
:error-message="errors.phone"
|
||||
:error="!!errors.phone"
|
||||
bg-color="white"
|
||||
type="tel"
|
||||
label="Teléfono"
|
||||
class="telephone"
|
||||
mask="(##) ##### ####"
|
||||
outlined
|
||||
/>
|
||||
|
||||
<div class="field-control field-input telephone">
|
||||
<vue-tel-input
|
||||
v-model="phone"
|
||||
v-bind="phoneAttrs"
|
||||
:styleClasses="['custom-input', !!errors.phone && 'error']"
|
||||
ref="questionPhoneRef"
|
||||
:inputOptions="{
|
||||
placeholder: 'Teléfono*',
|
||||
}"
|
||||
/>
|
||||
<p v-if="!!errors.phone" class="error">
|
||||
{{ errors.phone }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<q-input
|
||||
v-model="query"
|
||||
v-bind="queryAttrs"
|
||||
|
@ -150,6 +170,7 @@ export default defineComponent({
|
|||
class="question-submit-btn btn rounded"
|
||||
flat
|
||||
:disable="!meta.valid"
|
||||
:loading="isQuestionSubmitLoading"
|
||||
>
|
||||
Enviar solicitud <IconArrowRightOne />
|
||||
</q-btn>
|
||||
|
@ -201,6 +222,49 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
& .field-control.field-input {
|
||||
flex: 1 0 min(100%, 218px);
|
||||
|
||||
&.telephone {
|
||||
flex: 0 0 calc(50% - 5px);
|
||||
@media only screen and (max-width: $med-lg) {
|
||||
flex: 1 0 min(100%, 390px);
|
||||
}
|
||||
}
|
||||
|
||||
& .custom-input {
|
||||
padding: 10.5px 1px;
|
||||
border-radius: 4px;
|
||||
transition: 200ms ease-in-out;
|
||||
background-color: $white;
|
||||
&:hover {
|
||||
border-color: $black;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
border-color: $primary;
|
||||
box-shadow: inset 0 0 0 1px $primary;
|
||||
}
|
||||
|
||||
&.error {
|
||||
border-color: $negative;
|
||||
box-shadow: inset 0 0 0 1px $negative;
|
||||
}
|
||||
|
||||
& .vti__input::placeholder {
|
||||
font-family: $font-questrial;
|
||||
font-size: $font-12;
|
||||
}
|
||||
}
|
||||
|
||||
& p.error {
|
||||
font-family: $font-questrial;
|
||||
color: $negative;
|
||||
font-size: $font-12;
|
||||
padding: 8px 12px 0;
|
||||
}
|
||||
}
|
||||
|
||||
& .question-submit-btn {
|
||||
align-self: flex-start;
|
||||
@media only screen and (max-width: $med-lg) {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./date";
|
||||
export * from "./objValitation";
|
|
@ -0,0 +1,15 @@
|
|||
export let countryFlagObj = {};
|
||||
|
||||
const countryFlagObjMessage = (code = "") => {
|
||||
const { default: defaultValue, ...rest } = countryFlagObj;
|
||||
const objectKeys = Object.keys(rest).join(", ");
|
||||
|
||||
return `El código de país ${code} no es válido! Apoyamos los siguientes códigos de país: ${objectKeys}.`;
|
||||
};
|
||||
|
||||
countryFlagObj = {
|
||||
34: "es",
|
||||
351: "pt",
|
||||
33: "fr",
|
||||
default: countryFlagObjMessage,
|
||||
};
|
|
@ -343,6 +343,50 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
.tooltip {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
background-color: $white;
|
||||
border: 1px solid $primary-dark;
|
||||
|
||||
&.info {
|
||||
left: 16px !important;
|
||||
top: -20px !important;
|
||||
padding: 2px 6px;
|
||||
white-space: nowrap;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.paragraph-sm {
|
||||
color: $primary;
|
||||
font-size: $font-14;
|
||||
font-family: $font-questrial;
|
||||
color: var(--clr);
|
||||
&.link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
//! Vue-tel-input
|
||||
.vti__input {
|
||||
font-family: $font-questrial;
|
||||
font-size: $font-14;
|
||||
|
||||
&::placeholder {
|
||||
font-size: $font-14;
|
||||
font-family: $font-questrial;
|
||||
}
|
||||
}
|
||||
|
||||
>>>>>>> master
|
||||
//! QUASAR
|
||||
.q-virtual-scroll__content .q-item .q-item__label {
|
||||
font-family: $font-questrial;
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
& .custom-head-paragraph,
|
||||
& .custom-main-paragraph {
|
||||
line-height: 20px;
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
& .custom-head-paragraph {
|
||||
font-size: $font-12;
|
||||
opacity: 0.4;
|
||||
// opacity: 0.4;
|
||||
}
|
||||
|
||||
& .custom-main-paragraph {
|
||||
|
|
|
@ -26,20 +26,25 @@ export function quasarNotify({ message = "", type, timeout = 1000 }) {
|
|||
icon: "report_problem",
|
||||
timeout,
|
||||
}),
|
||||
info: () => Notify.create({
|
||||
message,
|
||||
color: "info",
|
||||
position: "top",
|
||||
icon: "info",
|
||||
timeout,
|
||||
}),
|
||||
info: () =>
|
||||
Notify.create({
|
||||
message,
|
||||
color: "info",
|
||||
position: "top",
|
||||
icon: "info",
|
||||
timeout,
|
||||
}),
|
||||
default: () => {
|
||||
console.error(`Type is invalid! TYPE: ${type}`)
|
||||
}
|
||||
console.error(`Type is invalid! TYPE: ${type}`);
|
||||
},
|
||||
};
|
||||
|
||||
if (type) {
|
||||
return obj[type]() || obj['default']();
|
||||
return obj[type]() || obj["default"]();
|
||||
}
|
||||
console.error("Type is required, success, warning or erro");
|
||||
|
||||
const { default: defaultValue, ...rest } = obj;
|
||||
const objTypes = Object.keys(rest).join(", ");
|
||||
|
||||
console.error(`Type is required, valid types: ${objTypes}`);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
import { autoUpdate, useFloating } from "@floating-ui/vue";
|
||||
import { toTypedSchema } from "@vee-validate/zod";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useForm } from "vee-validate";
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import { computed, reactive, ref, watch } from "vue";
|
||||
|
||||
import { apiBack } from "src/boot/axios";
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
import { quasarNotify } from "src/functions/quasarNotify";
|
||||
>>>>>>> master
|
||||
import { useFormStore } from "src/stores/forms";
|
||||
import { checkoutSchema } from "src/utils/zod/schemas";
|
||||
import { useLocalStorage } from "./useLocalStorage";
|
||||
|
@ -10,13 +16,70 @@ import { useLocalStorage } from "./useLocalStorage";
|
|||
export function useCheckoutForm() {
|
||||
const { addItem, getItem, removeItem } = useLocalStorage();
|
||||
|
||||
//! Elements ref
|
||||
const postalCodeRef = ref(null);
|
||||
const postalCodeTooltip = ref(null);
|
||||
const phoneInputRef = ref(null);
|
||||
const phoneSenderInputRef = ref(null);
|
||||
const redsysFormRef = ref(null);
|
||||
|
||||
//! Form
|
||||
const formStore = useFormStore();
|
||||
const { availability: availabilityForm } = storeToRefs(formStore);
|
||||
const { handleCheckoutData } = formStore;
|
||||
|
||||
const availability =
|
||||
availabilityForm.value.dateExpired || getItem("availability");
|
||||
|
||||
const phoneData = ref({
|
||||
country: {
|
||||
name: "",
|
||||
iso2: "",
|
||||
dialCode: "",
|
||||
priority: 0,
|
||||
areaCodes: null,
|
||||
},
|
||||
countryCallingCode: "",
|
||||
nationalNumber: "",
|
||||
number: "",
|
||||
countryCode: "",
|
||||
valid: false,
|
||||
formatted: "",
|
||||
});
|
||||
const phoneSenderData = ref({
|
||||
country: {
|
||||
name: "",
|
||||
iso2: "",
|
||||
dialCode: "",
|
||||
priority: 0,
|
||||
areaCodes: null,
|
||||
},
|
||||
countryCallingCode: "",
|
||||
nationalNumber: "",
|
||||
number: "",
|
||||
countryCode: "",
|
||||
valid: false,
|
||||
formatted: "",
|
||||
});
|
||||
|
||||
const provinceOptions = ref([
|
||||
{ code: "es", name: "España" },
|
||||
// { code: "fr", name: "Francia" },
|
||||
// { code: "pt", name: "Portugal" },
|
||||
]);
|
||||
|
||||
const { meta, errors, handleSubmit, defineField, resetForm } = useForm({
|
||||
validationSchema: toTypedSchema(checkoutSchema),
|
||||
initialValues: {
|
||||
<<<<<<< HEAD
|
||||
paymentMethod: "paypal",
|
||||
=======
|
||||
paymentMethod: "",
|
||||
>>>>>>> master
|
||||
terms: false,
|
||||
postalCode: availabilityForm.value.postalCode || availability.postalCode,
|
||||
phone: "",
|
||||
senderPhone: "",
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -24,17 +87,22 @@ export function useCheckoutForm() {
|
|||
const [surname, surnameAttrs] = defineField("surname");
|
||||
const [address, addressAttrs] = defineField("address");
|
||||
const [postalCode, postalCodeAttrs] = defineField("postalCode");
|
||||
const [phone, phoneAttrs] = defineField("phone");
|
||||
const [phone, phoneAttrs] = defineField("phone", {
|
||||
validateOnModelUpdate: false,
|
||||
});
|
||||
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 [senderPhone, senderPhoneAttrs] = defineField("senderPhone", {
|
||||
validateOnModelUpdate: false,
|
||||
});
|
||||
const [senderNotes, senderNotesAttrs] = defineField("senderNotes");
|
||||
const [paymentMethod, paymentMethodAttrs] = defineField("paymentMethod");
|
||||
const [terms, termsAttrs] = defineField("terms");
|
||||
|
||||
<<<<<<< HEAD
|
||||
|
||||
|
||||
//TODO hacer el await de las provincias
|
||||
|
@ -94,6 +162,39 @@ export function useCheckoutForm() {
|
|||
{ code: "51", name: "Ceuta" },
|
||||
{ code: "52", name: "Melilla" },
|
||||
]);
|
||||
=======
|
||||
//! Tooltip hook
|
||||
const { floatingStyles } = useFloating(postalCodeRef, postalCodeTooltip, {
|
||||
placement: "top-start",
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const isHidden = ref(true);
|
||||
const hideTooltip = () => {
|
||||
isHidden.value = true;
|
||||
};
|
||||
const showTooltip = () => {
|
||||
isHidden.value = false;
|
||||
};
|
||||
|
||||
// TODO hacer el await de las provincias
|
||||
/**
|
||||
* const provinceOptions = getProvinces();
|
||||
* onBeforeMount(async () => {});
|
||||
* */
|
||||
|
||||
watch(
|
||||
[
|
||||
() => phoneInputRef.value?.modelValue,
|
||||
() => phoneSenderInputRef.value?.modelValue,
|
||||
],
|
||||
([a, b]) => {
|
||||
phoneData.value = phoneInputRef.value.phoneObject;
|
||||
phoneSenderData.value = phoneSenderInputRef.value.phoneObject;
|
||||
}
|
||||
);
|
||||
|
||||
>>>>>>> master
|
||||
const stepActive = reactive({ data: 1 });
|
||||
const stepList = reactive({
|
||||
data: [
|
||||
|
@ -136,7 +237,10 @@ export function useCheckoutForm() {
|
|||
|
||||
const checkoutBlock = ref(true);
|
||||
const cart = getItem("cart");
|
||||
<<<<<<< HEAD
|
||||
const availability = getItem("availability");
|
||||
=======
|
||||
>>>>>>> master
|
||||
const totalPrice = computed(() => {
|
||||
return cart?.reduce((acc, { price }) => {
|
||||
if (price) {
|
||||
|
@ -146,6 +250,7 @@ export function useCheckoutForm() {
|
|||
}, 0);
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
const isLoadingSubmit = ref(false);
|
||||
const isErrorSubmit = ref(false);
|
||||
|
||||
|
@ -166,11 +271,43 @@ export function useCheckoutForm() {
|
|||
return { id, message: "" };
|
||||
});
|
||||
|
||||
=======
|
||||
const redsysData = ref({
|
||||
Ds_MerchantParameters: "",
|
||||
Ds_Signature: "",
|
||||
Ds_SignatureVersion: "",
|
||||
orderId: null,
|
||||
});
|
||||
|
||||
const isLoadingSubmit = ref(false);
|
||||
const isErrorSubmit = ref(false);
|
||||
|
||||
/**
|
||||
* Handles the fetching of the payment method.
|
||||
*
|
||||
* @param {string} type - The type of payment method paypal or redsys are valid!.
|
||||
* @param {Object} values - The values needed for the payment method.
|
||||
* @returns {Promise<void>} - A promise that resolves when the payment method is fetched.
|
||||
*/
|
||||
const handleFetchPaymentMethod = async ({ type, values }) => {
|
||||
console.log({ type, values });
|
||||
|
||||
try {
|
||||
const productsId = cart.map((item) => item.id);
|
||||
const cartItensData = cart.map(({ id, message, ...rest }) => ({
|
||||
id,
|
||||
message: message || "",
|
||||
}));
|
||||
>>>>>>> master
|
||||
const deliveryData = {
|
||||
customerData: {
|
||||
custumerName: `${values.name} ${values.surname}`,
|
||||
email: values.senderEmail,
|
||||
<<<<<<< HEAD
|
||||
custumerPhone: values.phone,
|
||||
=======
|
||||
custumerPhone: phoneData.value.number,
|
||||
>>>>>>> master
|
||||
},
|
||||
itemData: cartItensData,
|
||||
deliveryData: {
|
||||
|
@ -178,6 +315,7 @@ export function useCheckoutForm() {
|
|||
deliveryName: values.senderName,
|
||||
address: values.address,
|
||||
postalCode: availability.postalCode,
|
||||
<<<<<<< HEAD
|
||||
deliveryPhone: values.senderPhone,
|
||||
deliveryMessage: values.senderNotes,
|
||||
},
|
||||
|
@ -203,11 +341,110 @@ export function useCheckoutForm() {
|
|||
isErrorSubmit.value = true;
|
||||
isLoadingSubmit.value = false;
|
||||
} finally {
|
||||
=======
|
||||
deliveryPhone: phoneSenderData.value.number,
|
||||
deliveryMessage: values.senderNotes,
|
||||
},
|
||||
};
|
||||
|
||||
const customerName = `${values.name} ${values.surname}`;
|
||||
|
||||
addItem("costumer", deliveryData);
|
||||
const productData = {
|
||||
products: productsId,
|
||||
dateExpired: availability.dateExpired,
|
||||
postalCode: postalCode.value,
|
||||
customer: {
|
||||
customerData: {
|
||||
customerName,
|
||||
email: values.senderEmail,
|
||||
customerPhone: phoneData.value.number,
|
||||
message: values.senderNotes,
|
||||
deliveryName: values.senderName || customerName,
|
||||
address: values.address,
|
||||
deliveryPhone:
|
||||
phoneSenderData.value.number || phoneData.value.number,
|
||||
},
|
||||
},
|
||||
type: values.paymentMethod,
|
||||
};
|
||||
addItem("payment", values.paymentMethod);
|
||||
|
||||
const typeObj = {
|
||||
paypal: async () => {
|
||||
const {
|
||||
data: { data },
|
||||
} = await apiBack.post("payment", productData);
|
||||
console.log(data);
|
||||
|
||||
location.href = data.link;
|
||||
},
|
||||
redsys: async () => {
|
||||
const {
|
||||
data: { data },
|
||||
} = await apiBack.post("payment", productData);
|
||||
redsysData.value = data;
|
||||
|
||||
redsysFormRef.value.click();
|
||||
},
|
||||
default: () => {
|
||||
console.error(
|
||||
`FATAL ERROR ::: Payment method not found, TYPE: ${type}`
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const paymentMethod = typeObj[type] || typeObj["default"];
|
||||
await paymentMethod();
|
||||
|
||||
// removeItem("cart");
|
||||
// removeItem("availability");
|
||||
} catch (error) {
|
||||
console.error(`FATAL ERROR ::: ${error}`);
|
||||
|
||||
quasarNotify({
|
||||
type: "erro",
|
||||
message:
|
||||
"Se produjo un error al procesar tu compra, inténtalo de nuevo.",
|
||||
});
|
||||
|
||||
isErrorSubmit.value = true;
|
||||
} finally {
|
||||
isLoadingSubmit.value = false;
|
||||
>>>>>>> master
|
||||
handleCheckoutData(values);
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
const onSuccess = async (values, actions) => {
|
||||
const INVALID_NUMBER =
|
||||
"Número no válido introducido, por favor, compruébelo e inténtelo de nuevo";
|
||||
|
||||
if (!phoneData.value.valid) {
|
||||
actions.setFieldError("phone", INVALID_NUMBER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (values.senderPhone.length > 0 && !phoneSenderData.value.valid) {
|
||||
actions.setFieldError("senderPhone", INVALID_NUMBER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingSubmit.value = true;
|
||||
stepsFormated.value[1].active = true;
|
||||
|
||||
await handleFetchPaymentMethod({
|
||||
type: values.paymentMethod,
|
||||
values,
|
||||
});
|
||||
};
|
||||
|
||||
>>>>>>> master
|
||||
const onSubmit = handleSubmit(onSuccess);
|
||||
|
||||
return {
|
||||
|
@ -219,7 +456,29 @@ export function useCheckoutForm() {
|
|||
cart,
|
||||
totalPrice,
|
||||
isError,
|
||||
<<<<<<< HEAD
|
||||
onError,
|
||||
=======
|
||||
redsysData,
|
||||
|
||||
phoneInputRef,
|
||||
phoneSenderInputRef,
|
||||
redsysFormRef,
|
||||
|
||||
phone: { phoneData, phoneSenderData },
|
||||
|
||||
onError,
|
||||
tooltip: {
|
||||
postalCode: {
|
||||
postalCodeRef,
|
||||
postalCodeTooltip,
|
||||
floatingStyles,
|
||||
isHidden,
|
||||
hideTooltip,
|
||||
showTooltip,
|
||||
},
|
||||
},
|
||||
>>>>>>> master
|
||||
formState: {
|
||||
meta,
|
||||
errors,
|
||||
|
|
|
@ -4,6 +4,7 @@ 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";
|
||||
|
@ -24,14 +25,24 @@ import { useLocalStorage } from "./useLocalStorage";
|
|||
*/
|
||||
export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
||||
const route = useRoute();
|
||||
<<<<<<< HEAD
|
||||
const { push, go } = useRouter();
|
||||
const { addItem, getItem, removeItem } = useLocalStorage();
|
||||
=======
|
||||
const { push } = useRouter();
|
||||
const { addItem, getItem, removeItem } = useLocalStorage();
|
||||
|
||||
const modalStore = useModalStore();
|
||||
>>>>>>> master
|
||||
|
||||
const rangePriceStore = useRangePriceStore();
|
||||
const { rangeValue } = storeToRefs(rangePriceStore);
|
||||
|
||||
<<<<<<< HEAD
|
||||
const modalStore = useModalStore();
|
||||
|
||||
=======
|
||||
>>>>>>> master
|
||||
const formStore = useFormStore();
|
||||
const { sortProductFilters, availability: availabilityForm } =
|
||||
storeToRefs(formStore);
|
||||
|
@ -43,6 +54,7 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
const min = 0;
|
||||
const max = 200;
|
||||
const category = ref(route.path.split("/")[2]);
|
||||
<<<<<<< HEAD
|
||||
const availability = ref(getItem("availability"));
|
||||
const isAvailabilityEmpty = computed(() => {
|
||||
return Object.keys(availability.value).length === 0;
|
||||
|
@ -68,6 +80,66 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
},
|
||||
}
|
||||
);
|
||||
=======
|
||||
const categoryObj = {
|
||||
plantas: "Floranet Plantas",
|
||||
ramos: "Floranet Ramos",
|
||||
};
|
||||
const availability = ref(getItem("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;
|
||||
});
|
||||
|
||||
const [YEAR, MONTH, DAY] = fullCurrentDate.replaceAll("/", "-").split("-");
|
||||
const CURRENT_DATE = `${DAY}-${MONTH}-${YEAR}`;
|
||||
const {
|
||||
handleSubmit,
|
||||
handleReset,
|
||||
defineField,
|
||||
errors,
|
||||
setValues,
|
||||
setFieldError,
|
||||
} = useForm({
|
||||
validateOnMount: false,
|
||||
validationSchema: toTypedSchema(
|
||||
type !== "filter" ? availabilitySchema : rangePriceSchema
|
||||
),
|
||||
initialValues: {
|
||||
range: {
|
||||
min,
|
||||
max,
|
||||
},
|
||||
postalCode: "",
|
||||
date: CURRENT_DATE,
|
||||
},
|
||||
initialTouched: {
|
||||
date: false,
|
||||
postalCode: true,
|
||||
},
|
||||
});
|
||||
>>>>>>> master
|
||||
|
||||
const options = {
|
||||
validateOnBlur: false,
|
||||
|
@ -95,6 +167,13 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
watch([() => route.path, () => sortProductFilters.value], ([newPath]) => {
|
||||
const categoryPath = newPath.split("/")[2];
|
||||
category.value = categoryPath;
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
availabilityForm.value.dateExpired = "";
|
||||
availability.value.postalCode = "";
|
||||
sortProductFilters.value.isOpenOrderFilter = false;
|
||||
sortProductFilters.value.order = undefined;
|
||||
>>>>>>> master
|
||||
});
|
||||
|
||||
const removeCart = () => {
|
||||
|
@ -104,6 +183,11 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
|
||||
const onSuccess = async (values) => {
|
||||
const handleAvailability = async () => {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
console.log(type);
|
||||
|
||||
>>>>>>> master
|
||||
addItem("availability", {
|
||||
postalCode: values.postalCode,
|
||||
dateExpired: invertDate(values.date),
|
||||
|
@ -113,6 +197,10 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
availabilityForm.value.postalCode = values.postalCode;
|
||||
|
||||
await getProducts({
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
type: categoryObj[category.value],
|
||||
>>>>>>> master
|
||||
postalCode: values.postalCode,
|
||||
dateExpired: invertDate(values.date),
|
||||
});
|
||||
|
@ -169,10 +257,13 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
|
||||
const id = +route.path.split("/")[2];
|
||||
|
||||
<<<<<<< HEAD
|
||||
console.log(item.postalCode === values.postalCode);
|
||||
console.log(item.id === id);
|
||||
console.log(dateSelected <= dateExpired);
|
||||
|
||||
=======
|
||||
>>>>>>> master
|
||||
return (
|
||||
item.postalCode === values.postalCode &&
|
||||
item.id === id &&
|
||||
|
@ -204,6 +295,7 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
type: categoryObj[category.value],
|
||||
minPrice: values.range.min,
|
||||
maxPrice: values.range.max,
|
||||
<<<<<<< HEAD
|
||||
};
|
||||
console.log(params);
|
||||
|
||||
|
@ -212,6 +304,20 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
params.dateExpired = availability.value.dateExpired;
|
||||
|
||||
const { type, ...rest } = params;
|
||||
=======
|
||||
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;
|
||||
console.log(rest);
|
||||
>>>>>>> master
|
||||
await getProducts({ ...rest });
|
||||
return;
|
||||
}
|
||||
|
@ -261,7 +367,15 @@ export function usePostalCalendar({ modalItem = "", type = "home" }) {
|
|||
setValues,
|
||||
handleReset,
|
||||
modalStore,
|
||||
<<<<<<< HEAD
|
||||
isAvailabilityEmpty,
|
||||
=======
|
||||
setFieldError,
|
||||
isAvailabilityEmpty,
|
||||
isPostalCalendarEmpty,
|
||||
availabilityFormKeys,
|
||||
category,
|
||||
>>>>>>> master
|
||||
fields: {
|
||||
calendar,
|
||||
calendarAttrs,
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
import { useForm } from "vee-validate";
|
||||
import { ref } from "vue";
|
||||
|
||||
import { apiBack } from "src/boot/axios";
|
||||
import { quasarNotify } from "src/functions/quasarNotify";
|
||||
import { useFormStore } from "src/stores/forms";
|
||||
import { questionSchema } from "src/utils/zod/schemas";
|
||||
import { watch } from "vue";
|
||||
|
||||
export function useQuestionForm() {
|
||||
const formStore = useFormStore();
|
||||
const { handleQuestionData } = formStore;
|
||||
|
||||
//! Elements
|
||||
const questionPhoneRef = ref(null);
|
||||
const questionPhoneData = ref({
|
||||
country: {
|
||||
name: "",
|
||||
iso2: "",
|
||||
dialCode: "",
|
||||
priority: 0,
|
||||
areaCodes: null,
|
||||
},
|
||||
countryCallingCode: "",
|
||||
nationalNumber: "",
|
||||
number: "",
|
||||
countryCode: "",
|
||||
valid: false,
|
||||
formatted: "",
|
||||
});
|
||||
|
||||
const { errors, meta, defineField, handleSubmit, handleReset } = useForm({
|
||||
validationSchema: questionSchema,
|
||||
initialValues: {
|
||||
terms: false,
|
||||
},
|
||||
});
|
||||
const [firstName, firstNameAttrs] = defineField("name");
|
||||
const [secondName, secondNameAttrs] = defineField("surname");
|
||||
const [email, emailAttrs] = defineField("email");
|
||||
const [phone, phoneAttrs] = defineField("phone", {
|
||||
validateOnModelUpdate: false,
|
||||
});
|
||||
const [query, queryAttrs] = defineField("query");
|
||||
const [message, messageAttrs] = defineField("message");
|
||||
const [terms, termsAttrs] = defineField("terms");
|
||||
|
||||
watch(
|
||||
() => questionPhoneRef.value?.modelValue,
|
||||
() => {
|
||||
questionPhoneData.value = questionPhoneRef.value.phoneObject;
|
||||
}
|
||||
);
|
||||
|
||||
const isQuestionSubmitLoading = ref(false);
|
||||
const isQuestionSubmitError = ref(false);
|
||||
const onSubmit = handleSubmit(async (values, actions) => {
|
||||
isQuestionSubmitLoading.value = true;
|
||||
|
||||
if (!questionPhoneData.value.valid) {
|
||||
actions.setFieldError("phone", "El teléfono no es válido");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const contactData = {
|
||||
name: `${values.name} ${values.surname}`,
|
||||
phone: questionPhoneData.value.number,
|
||||
email: values.email,
|
||||
message: values.message,
|
||||
};
|
||||
await apiBack.post("contact/save", contactData);
|
||||
|
||||
isQuestionSubmitLoading.value = false;
|
||||
quasarNotify({ type: "success", message: "Mensaje enviado" });
|
||||
} catch (error) {
|
||||
console.error(`FATAL ERROR ::: ${error}`);
|
||||
|
||||
isQuestionSubmitLoading.value = false;
|
||||
isQuestionSubmitError.value = true;
|
||||
} finally {
|
||||
handleQuestionData(values);
|
||||
handleReset();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
questionPhoneData,
|
||||
questionPhoneRef,
|
||||
formState: {
|
||||
isQuestionSubmitLoading,
|
||||
onSubmit,
|
||||
errors,
|
||||
meta,
|
||||
},
|
||||
fields: {
|
||||
firstName,
|
||||
firstNameAttrs,
|
||||
secondName,
|
||||
secondNameAttrs,
|
||||
email,
|
||||
emailAttrs,
|
||||
phone,
|
||||
phoneAttrs,
|
||||
query,
|
||||
queryAttrs,
|
||||
message,
|
||||
messageAttrs,
|
||||
terms,
|
||||
termsAttrs,
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { useIntersectionObserver } from "@vueuse/core";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useMobileStore } from "src/stores/mobileNav";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
export function useVerticalCarouselImgs() {
|
||||
const mobileStore = useMobileStore();
|
||||
const { screenWidth } = storeToRefs(mobileStore);
|
||||
const { handleResize } = mobileStore;
|
||||
|
||||
const target = ref(null);
|
||||
const navPos = ref("bottom");
|
||||
const slide = ref("style");
|
||||
|
||||
onMounted(() => {
|
||||
screenWidth.value = window.innerWidth;
|
||||
});
|
||||
|
||||
useIntersectionObserver(target, ([{ isIntersecting }]) => {
|
||||
mobileStore.isCarouselVisible = isIntersecting;
|
||||
});
|
||||
document.addEventListener("resize", handleResize);
|
||||
|
||||
return { screenWidth, navPos, slide, target };
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
<script>
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, defineComponent, onBeforeMount, ref, watch } from "vue";
|
||||
<<<<<<< HEAD
|
||||
import { useRoute } from "vue-router";
|
||||
=======
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
>>>>>>> master
|
||||
|
||||
import SortSelect from "src/components/@inputs/SortSelect.vue";
|
||||
import IconArrowCircleFilledRight from "src/components/icons/IconArrowCircleFilledRight.vue";
|
||||
|
@ -36,6 +40,9 @@ export default defineComponent({
|
|||
},
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const { push } = useRouter();
|
||||
const { getItem } = useLocalStorage();
|
||||
const { isAvailabilityEmpty } = usePostalCalendar({});
|
||||
|
||||
const { getItem } = useLocalStorage();
|
||||
|
||||
|
@ -160,6 +167,11 @@ export default defineComponent({
|
|||
await getProducts(availabilityStoraged.value);
|
||||
datePostalCode.value = availabilityStoraged.value;
|
||||
if (isAvailabilityEmpty.value) {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
await push("/");
|
||||
|
||||
>>>>>>> master
|
||||
quasarNotify({
|
||||
message: "Debes seleccionar una fecha y código postal",
|
||||
type: "warning",
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
<<<<<<< HEAD
|
||||
=======
|
||||
<script>
|
||||
import Container from "src/components/ui/Container.vue";
|
||||
import { useLocalStorage } from "src/hooks/useLocalStorage";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "CheckoutErrorPage",
|
||||
components: { Container },
|
||||
setup() {
|
||||
const { removeItem } = useLocalStorage();
|
||||
|
||||
removeItem("cart");
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
>>>>>>> master
|
||||
<template>
|
||||
<q-page class="checkout-error-page error-message">
|
||||
<container>
|
||||
|
@ -6,6 +25,7 @@
|
|||
</q-page>
|
||||
</template>
|
||||
|
||||
<<<<<<< HEAD
|
||||
<script>
|
||||
import Container from "src/components/ui/Container.vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
@ -16,6 +36,8 @@ export default defineComponent({
|
|||
});
|
||||
</script>
|
||||
|
||||
=======
|
||||
>>>>>>> master
|
||||
<style lang="scss" scoped>
|
||||
.checkout-error-page {
|
||||
}
|
||||
|
|
|
@ -22,6 +22,20 @@ export default defineComponent({
|
|||
totalPrice,
|
||||
isError,
|
||||
onError,
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
redsysData,
|
||||
tooltip: {
|
||||
postalCode: {
|
||||
postalCodeRef,
|
||||
postalCodeTooltip,
|
||||
floatingStyles,
|
||||
isHidden,
|
||||
hideTooltip,
|
||||
showTooltip,
|
||||
},
|
||||
},
|
||||
>>>>>>> master
|
||||
formState: { errors, meta, onSubmit, isLoadingSubmit },
|
||||
fields: {
|
||||
name,
|
||||
|
@ -53,6 +67,9 @@ export default defineComponent({
|
|||
terms,
|
||||
termsAttrs,
|
||||
},
|
||||
phoneInputRef,
|
||||
phoneSenderInputRef,
|
||||
redsysFormRef,
|
||||
} = useCheckoutForm();
|
||||
|
||||
onBeforeMount(() => {
|
||||
|
@ -63,6 +80,18 @@ export default defineComponent({
|
|||
handleClickStep,
|
||||
onSubmit,
|
||||
onError,
|
||||
redsysData,
|
||||
|
||||
phoneInputRef,
|
||||
phoneSenderInputRef,
|
||||
redsysFormRef,
|
||||
|
||||
postalCodeRef,
|
||||
postalCodeTooltip,
|
||||
floatingStyles,
|
||||
isHidden,
|
||||
hideTooltip,
|
||||
showTooltip,
|
||||
|
||||
checkoutBlock,
|
||||
stepsFormated,
|
||||
|
@ -114,21 +143,12 @@ export default defineComponent({
|
|||
<template>
|
||||
<q-page class="checkout-page">
|
||||
<Container tag="section">
|
||||
<header class="header-title" :class="!checkoutBlock && 'success'">
|
||||
<h1 class="pege-title" v-if="checkoutBlock">
|
||||
{{
|
||||
checkoutBlock
|
||||
? "¿A quién y dónde lo entregamos?"
|
||||
: '"¡Muchas gracias Jerom!"'
|
||||
}}
|
||||
</h1>
|
||||
<header class="header-title">
|
||||
<h1 class="pege-title">¿A quién y dónde lo entregamos"</h1>
|
||||
|
||||
<p class="page-subtitle checkout" v-if="checkoutBlock">
|
||||
{{
|
||||
checkoutBlock
|
||||
? "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||
: "¡Tu pedido se ha realizado con éxito! Gracias por confiar en nosotros, en breves recibirás un correo con la confirmación de tu pedido."
|
||||
}}
|
||||
<p class="page-subtitle checkout">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
@ -172,265 +192,289 @@ export default defineComponent({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="checkoutBlock">
|
||||
<div class="checkout-content">
|
||||
<div class="checkout-form">
|
||||
<q-form
|
||||
method="post"
|
||||
id="checkout-form"
|
||||
@submit.prevent="onSubmit"
|
||||
>
|
||||
<div class="form-fields-container delivery">
|
||||
<header class="checkout-header-form">
|
||||
<h3>Instrucciones para la entrega</h3>
|
||||
</header>
|
||||
<div class="checkout-content">
|
||||
<div class="checkout-form">
|
||||
<q-form method="post" id="checkout-form" @submit.prevent="onSubmit">
|
||||
<div class="form-fields-container delivery">
|
||||
<header class="checkout-header-form">
|
||||
<h3>Instrucciones para la entrega</h3>
|
||||
</header>
|
||||
|
||||
<div class="checkout-fields">
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Nombre*"
|
||||
name="name"
|
||||
type="text"
|
||||
v-model="name"
|
||||
v-bind:="nameAttrs"
|
||||
:error="!!errors.name"
|
||||
:error-message="errors.name"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="checkout-fields">
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Nombre*"
|
||||
name="name"
|
||||
type="text"
|
||||
v-model="name"
|
||||
v-bind:="nameAttrs"
|
||||
:error="!!errors.name"
|
||||
:error-message="errors.name"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Apellidos*"
|
||||
name="surname"
|
||||
type="text"
|
||||
v-model="surname"
|
||||
v-bind:="surnameAttrs"
|
||||
:error="!!errors.surname"
|
||||
:error-message="errors.surname"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Apellidos*"
|
||||
name="surname"
|
||||
type="text"
|
||||
v-model="surname"
|
||||
v-bind:="surnameAttrs"
|
||||
:error="!!errors.surname"
|
||||
:error-message="errors.surname"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Dirección*"
|
||||
name="address"
|
||||
type="text"
|
||||
v-model="address"
|
||||
v-bind:="addressAttrs"
|
||||
:error="!!errors.address"
|
||||
:error-message="errors.address"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Dirección*"
|
||||
name="address"
|
||||
type="text"
|
||||
v-model="address"
|
||||
v-bind:="addressAttrs"
|
||||
:error="!!errors.address"
|
||||
:error-message="errors.address"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Código postal*"
|
||||
name="postalCode"
|
||||
type="text"
|
||||
mask="#####"
|
||||
v-model="postalCode"
|
||||
v-bind:="postalCodeAttrs"
|
||||
:error="!!errors.postalCode"
|
||||
:error-message="errors.postalCode"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Código postal*"
|
||||
name="postalCode"
|
||||
type="text"
|
||||
mask="#####"
|
||||
v-model="postalCode"
|
||||
v-bind:="postalCodeAttrs"
|
||||
:error="!!errors.postalCode"
|
||||
:error-message="errors.postalCode"
|
||||
ref="postalCodeRef"
|
||||
readonly
|
||||
outlined
|
||||
@mouseenter="showTooltip"
|
||||
@mouseleave="hideTooltip"
|
||||
>
|
||||
<template #after>
|
||||
<q-btn
|
||||
to="/"
|
||||
:style="'--clr: #ffffff'"
|
||||
class="btn custom-btn-input paragraph-sm"
|
||||
label="EDITAR"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<div class="field-control field-select">
|
||||
<q-select
|
||||
name="province"
|
||||
v-model="province"
|
||||
v-bind:="provinceAttrs"
|
||||
:error="!!errors.province"
|
||||
:error-message="errors.province"
|
||||
:options="provinceOptions"
|
||||
option-value="code"
|
||||
option-label="name"
|
||||
label="Provincia*"
|
||||
stack-label
|
||||
map-options
|
||||
emit-value
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-select">
|
||||
<q-input
|
||||
placeholder="Ciudad*"
|
||||
name="city"
|
||||
type="text"
|
||||
v-model="city"
|
||||
v-bind:="cityAttrs"
|
||||
:error="!!errors.city"
|
||||
:error-message="errors.city"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input telephone">
|
||||
<q-input
|
||||
placeholder="Teléfono*"
|
||||
name="phone"
|
||||
type="text"
|
||||
mask="(##) ##### ####"
|
||||
v-model="phone"
|
||||
v-bind:="phoneAttrs"
|
||||
:error="!!errors.phone"
|
||||
:error-message="errors.phone"
|
||||
outlined
|
||||
/>
|
||||
<div
|
||||
ref="postalCodeTooltip"
|
||||
:style="[floatingStyles, '--clr: #117564']"
|
||||
:class="['tooltip ', isHidden && 'hidden']"
|
||||
@mouseenter="showTooltip"
|
||||
@mouseleave="hideTooltip"
|
||||
>
|
||||
<p class="paragraph-sm">
|
||||
No se puede editar este campo
|
||||
<a
|
||||
href="https://www.google.com/maps"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
class="paragraph-sm link"
|
||||
>
|
||||
¿No conoce su código postal?
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-fields-container sender">
|
||||
<header class="checkout-header-form">
|
||||
<h3>Remitente</h3>
|
||||
</header>
|
||||
<div class="field-control field-select">
|
||||
<q-select
|
||||
name="province"
|
||||
v-model="province"
|
||||
v-bind:="provinceAttrs"
|
||||
:error="!!errors.province"
|
||||
:error-message="errors.province"
|
||||
:options="provinceOptions"
|
||||
option-value="code"
|
||||
option-label="name"
|
||||
label="País*"
|
||||
stack-label
|
||||
map-options
|
||||
emit-value
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="checkout-fields">
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Nombre y apellidos o nombre de empresa"
|
||||
name="senderName"
|
||||
type="text"
|
||||
v-model="senderName"
|
||||
v-bind:="senderNameAttrs"
|
||||
:error="!!errors.senderName"
|
||||
:error-message="errors.senderName"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="field-control field-select">
|
||||
<q-input
|
||||
placeholder="Ciudad*"
|
||||
name="city"
|
||||
type="text"
|
||||
v-model="city"
|
||||
v-bind:="cityAttrs"
|
||||
:error="!!errors.city"
|
||||
:error-message="errors.city"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="CIF / NIF"
|
||||
name="senderCifNif"
|
||||
type="text"
|
||||
mask="#########"
|
||||
v-model="senderCifNif"
|
||||
v-bind:="senderCifNifAttrs"
|
||||
:error="!!errors.senderCifNif"
|
||||
:error-message="errors.senderCifNif"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Email"
|
||||
name="senderEmail"
|
||||
type="email"
|
||||
v-model="senderEmail"
|
||||
v-bind:="senderEmailAttrs"
|
||||
:error="!!errors.senderEmail"
|
||||
:error-message="errors.senderEmail"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Teléfono"
|
||||
name="senderPhone"
|
||||
type="text"
|
||||
mask="(##) ##### ####"
|
||||
v-model="senderPhone"
|
||||
v-bind:="senderPhoneAttrs"
|
||||
:error="!!errors.senderPhone"
|
||||
:error-message="errors.senderPhone"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Notas sobre tu pedido (Opcional), por ejemplo, notas especiales para la entrega"
|
||||
name="senderNotes"
|
||||
type="textarea"
|
||||
v-model="senderNotes"
|
||||
v-bind:="senderNotesAttrs"
|
||||
:error="!!errors.senderNotes"
|
||||
:error-message="errors.senderNotes"
|
||||
class="message"
|
||||
autogrow
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
<div class="field-control field-input telephone">
|
||||
<vue-tel-input
|
||||
v-model="phone"
|
||||
v-bind="phoneAttrs"
|
||||
:styleClasses="[
|
||||
'custom-input',
|
||||
!!errors.phone && 'error',
|
||||
]"
|
||||
ref="phoneInputRef"
|
||||
:inputOptions="{
|
||||
placeholder: 'Teléfono*',
|
||||
}"
|
||||
/>
|
||||
<p v-if="!!errors.phone" class="error">
|
||||
{{ errors.phone }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</q-form>
|
||||
</div>
|
||||
|
||||
<div class="form-fields-container sender">
|
||||
<header class="checkout-header-form">
|
||||
<h3>Remitente</h3>
|
||||
</header>
|
||||
|
||||
<div class="checkout-fields">
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Nombre y apellidos o nombre de empresa"
|
||||
name="senderName"
|
||||
type="text"
|
||||
v-model="senderName"
|
||||
v-bind:="senderNameAttrs"
|
||||
:error="!!errors.senderName"
|
||||
:error-message="errors.senderName"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="CIF / NIF"
|
||||
name="senderCifNif"
|
||||
type="text"
|
||||
v-model="senderCifNif"
|
||||
v-bind:="senderCifNifAttrs"
|
||||
:error="!!errors.senderCifNif"
|
||||
:error-message="errors.senderCifNif"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Email"
|
||||
name="senderEmail"
|
||||
type="email"
|
||||
v-model="senderEmail"
|
||||
v-bind:="senderEmailAttrs"
|
||||
:error="!!errors.senderEmail"
|
||||
:error-message="errors.senderEmail"
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input telephone">
|
||||
<vue-tel-input
|
||||
v-model="senderPhone"
|
||||
v-bind="senderPhoneAttrs"
|
||||
:styleClasses="[
|
||||
'custom-input',
|
||||
!!errors.senderPhone && 'error',
|
||||
]"
|
||||
ref="phoneSenderInputRef"
|
||||
:inputOptions="{
|
||||
placeholder: 'Teléfono*',
|
||||
}"
|
||||
/>
|
||||
<p v-if="!!errors.senderPhone" class="error">
|
||||
{{ errors.senderPhone }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="field-control field-input">
|
||||
<q-input
|
||||
placeholder="Notas sobre tu pedido (Opcional), por ejemplo, notas especiales para la entrega"
|
||||
name="senderNotes"
|
||||
type="textarea"
|
||||
v-model="senderNotes"
|
||||
v-bind:="senderNotesAttrs"
|
||||
:error="!!errors.senderNotes"
|
||||
:error-message="errors.senderNotes"
|
||||
class="message"
|
||||
autogrow
|
||||
outlined
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-form>
|
||||
|
||||
<form
|
||||
v-if="paymentMethod === 'redsys' && meta.valid"
|
||||
name="from"
|
||||
action="https://sis-t.redsys.es:25443/sis/realizarPago"
|
||||
method="POST"
|
||||
class="hide"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="Ds_SignatureVersion"
|
||||
:value="redsysData.Ds_SignatureVersion"
|
||||
/>
|
||||
<input
|
||||
type="hidden"
|
||||
name="Ds_MerchantParameters"
|
||||
:value="redsysData.Ds_MerchantParameters"
|
||||
/>
|
||||
<input
|
||||
type="hidden"
|
||||
name="Ds_Signature"
|
||||
:value="redsysData.Ds_Signature"
|
||||
/>
|
||||
<input ref="redsysFormRef" type="submit" value="Go to pay" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<aside class="checkout-aside">
|
||||
<div class="checkout-delivery-date" :class="meta.valid && 'active'">
|
||||
<header class="checkout-aside-header green-text">
|
||||
<strong class="checkout-aside-title"> Fecha de entrega </strong>
|
||||
</header>
|
||||
|
||||
<div class="checkout-delivery-body">
|
||||
<p class="green-text">13 de julio - De 11h - 12 h</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="checkout-aside">
|
||||
<div
|
||||
class="checkout-delivery-date"
|
||||
:class="(meta.valid || !checkoutBlock) && 'active'"
|
||||
>
|
||||
<header class="checkout-aside-header green-text">
|
||||
<strong class="checkout-aside-title">
|
||||
Fecha de entrega
|
||||
</strong>
|
||||
</header>
|
||||
<div class="checkout-summary">
|
||||
<header class="checkout-aside-header gray-bg">
|
||||
<strong class="checkout-aside-title">
|
||||
Resumen del pedido
|
||||
</strong>
|
||||
</header>
|
||||
|
||||
<div class="checkout-delivery-body">
|
||||
<p class="green-text">13 de julio - De 11h - 12 h</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkout-summary">
|
||||
<header class="checkout-aside-header gray-bg">
|
||||
<strong class="checkout-aside-title">
|
||||
Resumen del pedido
|
||||
</strong>
|
||||
</header>
|
||||
|
||||
<div class="checkout-summary-body gray-bg">
|
||||
<ul class="checkout-summary-list">
|
||||
<li
|
||||
class="checkout-summary-item"
|
||||
v-for="({ name, price }, index) in cart"
|
||||
:key="index"
|
||||
>
|
||||
<p>
|
||||
{{ name }}
|
||||
<span>{{ price }}€</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="green-text">Envio Gratuíto</p>
|
||||
</div>
|
||||
|
||||
<footer class="checkout-summary-footer">
|
||||
<p class="checkout-summary-paragraph">Total</p>
|
||||
<p class="checkout-summary-paragraph summary-price">
|
||||
{{ totalPrice }}€
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div class="checkout-payment-methods gray-bg">
|
||||
<header class="checkout-aside-header">
|
||||
<strong class="checkout-aside-title">Método de pago</strong>
|
||||
</header>
|
||||
|
||||
<div class="checkout-payment-body">
|
||||
<!-- <q-radio
|
||||
v-model="paymentMethod"
|
||||
v-bind="paymentMethodAttrs"
|
||||
val="credit"
|
||||
color="primary"
|
||||
<div class="checkout-summary-body gray-bg">
|
||||
<ul class="checkout-summary-list">
|
||||
<li
|
||||
class="checkout-summary-item"
|
||||
v-for="({ name, price }, index) in cart"
|
||||
:key="index"
|
||||
>
|
||||
<p>
|
||||
Tarjeta
|
||||
<span class="card-flags">
|
||||
<IconMaster /><IconVisa /> <IconAny /> <IconExpress />
|
||||
</span>
|
||||
{{ name }}
|
||||
<span>{{ price }}€</span>
|
||||
</p>
|
||||
<<<<<<< HEAD
|
||||
</q-radio> -->
|
||||
|
||||
<q-radio
|
||||
|
@ -504,19 +548,74 @@ export default defineComponent({
|
|||
|
||||
<p class="checkout-product-price">{{ price }}€</p>
|
||||
</div>
|
||||
=======
|
||||
>>>>>>> master
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="green-text">Envio Gratuíto</p>
|
||||
</div>
|
||||
|
||||
<footer class="checkout-success-footer">
|
||||
<p class="checkout-success-paragraph">Total</p>
|
||||
<p class="checkout-success-paragraph">
|
||||
{{ totalPrice?.toFixed(2) }}€
|
||||
<footer class="checkout-summary-footer">
|
||||
<p class="checkout-summary-paragraph">Total</p>
|
||||
<p class="checkout-summary-paragraph summary-price">
|
||||
{{ totalPrice }}€
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="checkout-payment-methods gray-bg">
|
||||
<header class="checkout-aside-header">
|
||||
<strong
|
||||
class="checkout-aside-title"
|
||||
:style="!!errors.paymentMethod && 'color: red'"
|
||||
>
|
||||
Método de pago
|
||||
</strong>
|
||||
<p v-if="!!errors.paymentMethod"></p>
|
||||
</header>
|
||||
|
||||
<div class="checkout-payment-body">
|
||||
<q-radio
|
||||
v-model="paymentMethod"
|
||||
v-bind="paymentMethodAttrs"
|
||||
val="paypal"
|
||||
color="primary"
|
||||
>
|
||||
<p>Paypal</p>
|
||||
</q-radio>
|
||||
|
||||
<q-radio
|
||||
v-model="paymentMethod"
|
||||
v-bind="paymentMethodAttrs"
|
||||
val="redsys"
|
||||
color="primary"
|
||||
>
|
||||
<p>Redsys</p>
|
||||
</q-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkout-terms">
|
||||
<q-checkbox v-model="terms" v-bind="termsAttrs" class="terms">
|
||||
<p :style="!!errors.terms && 'color: red;'">
|
||||
He leído y estoy de acuerdo con los términosy condiciones de
|
||||
la tienda Floranet
|
||||
</p>
|
||||
</q-checkbox>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
class="btn"
|
||||
type="submit"
|
||||
form="checkout-form"
|
||||
:loading="isLoadingSubmit"
|
||||
>
|
||||
PROCEDER AL PAGO
|
||||
</q-btn>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</q-page>
|
||||
|
@ -528,10 +627,19 @@ export default defineComponent({
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
@media only screen and (max-width: $med-sm) {
|
||||
flex-wrap: wrap;
|
||||
|
||||
& .border-step {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .step-item-container {
|
||||
min-width: 200px;
|
||||
width: min(100%, 200px);
|
||||
}
|
||||
|
||||
& .border-step {
|
||||
|
@ -938,5 +1046,44 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .custom-input {
|
||||
padding: 10.5px 1px;
|
||||
border-radius: 4px;
|
||||
transition: 200ms ease-in-out;
|
||||
&:hover {
|
||||
border-color: $black;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
border-color: $primary;
|
||||
box-shadow: inset 0 0 0 1px $primary;
|
||||
}
|
||||
|
||||
&.error {
|
||||
border-color: $negative;
|
||||
box-shadow: inset 0 0 0 1px $negative;
|
||||
}
|
||||
|
||||
& .vti__input::placeholder {
|
||||
font-family: $font-questrial;
|
||||
font-size: $font-12;
|
||||
}
|
||||
}
|
||||
|
||||
& p.error {
|
||||
font-family: $font-questrial;
|
||||
color: $negative;
|
||||
font-size: $font-12;
|
||||
padding: 8px 12px 0;
|
||||
}
|
||||
|
||||
& .custom-btn-input {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
& .q-field__native {
|
||||
font-family: "Roboto" !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
<script>
|
||||
<<<<<<< HEAD
|
||||
import { apiBack } from "src/boot/axios";
|
||||
import { useCheckoutForm } from "src/hooks/useCheckoutForm";
|
||||
import { useLocalStorage } from "src/hooks/useLocalStorage";
|
||||
import { defineComponent, onBeforeMount, reactive, ref } from "vue";
|
||||
=======
|
||||
import { storeToRefs } from "pinia";
|
||||
import { apiBack } from "src/boot/axios";
|
||||
import { useCheckoutForm } from "src/hooks/useCheckoutForm";
|
||||
import { useLocalStorage } from "src/hooks/useLocalStorage";
|
||||
import { useCartStore } from "src/stores/cart";
|
||||
import { defineComponent, onBeforeMount, ref } from "vue";
|
||||
>>>>>>> master
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -11,6 +20,7 @@ export default defineComponent({
|
|||
const { query } = useRoute();
|
||||
const { push } = useRouter();
|
||||
const { getItem, removeItem } = useLocalStorage();
|
||||
<<<<<<< HEAD
|
||||
console.log(query);
|
||||
const costumerData = getItem("costumer");
|
||||
|
||||
|
@ -20,12 +30,32 @@ export default defineComponent({
|
|||
async function getSuccessData() {
|
||||
try {
|
||||
productsPurchased.data = await new Promise(async (resolve, reject) => {
|
||||
=======
|
||||
const cartStore = useCartStore();
|
||||
const { cart: cartStoreArr } = storeToRefs(cartStore);
|
||||
const cart = getItem("cart");
|
||||
|
||||
const totalPrice = ref(0);
|
||||
if (cart) {
|
||||
totalPrice.value = cart.reduce((acc, { price }) => acc + +price, 0);
|
||||
}
|
||||
|
||||
async function getSuccessData() {
|
||||
if (!query.orderId) return push("/checkout/error");
|
||||
|
||||
try {
|
||||
await new Promise(async (resolve, reject) => {
|
||||
>>>>>>> master
|
||||
try {
|
||||
const {
|
||||
data: { data },
|
||||
} = await apiBack.post("payment/success", {
|
||||
<<<<<<< HEAD
|
||||
// params: query,
|
||||
data: JSON.stringify({ customer: costumerData, ...query }),
|
||||
=======
|
||||
...query,
|
||||
>>>>>>> master
|
||||
});
|
||||
resolve(data.products);
|
||||
removeItem("costumer");
|
||||
|
@ -33,11 +63,14 @@ export default defineComponent({
|
|||
reject(error);
|
||||
}
|
||||
}).then((res) => res);
|
||||
<<<<<<< HEAD
|
||||
|
||||
totalPrice.value = await productsPurchased.data.reduce(
|
||||
(acc, { price }) => acc + Number(price),
|
||||
0
|
||||
);
|
||||
=======
|
||||
>>>>>>> master
|
||||
} catch (error) {
|
||||
console.error(`FATAL ERROR ::: ${error}`);
|
||||
push("/checkout/error");
|
||||
|
@ -45,17 +78,30 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
<<<<<<< HEAD
|
||||
const queryObj = {
|
||||
paymentId: query.paymentId,
|
||||
=======
|
||||
/* const queryObj = {
|
||||
orderId: query.orderId,
|
||||
>>>>>>> master
|
||||
productsIds: query.productsIds,
|
||||
PayerID: query.PayerID,
|
||||
};
|
||||
for (const [_, value] of Object.entries(queryObj)) {
|
||||
if (!value) return push("/");
|
||||
<<<<<<< HEAD
|
||||
}
|
||||
|
||||
await getSuccessData();
|
||||
console.log(productsPurchased.data);
|
||||
=======
|
||||
} */
|
||||
|
||||
if (cart.length === 0) return push("/");
|
||||
|
||||
await getSuccessData();
|
||||
>>>>>>> master
|
||||
});
|
||||
|
||||
const { isError, onError } = useCheckoutForm();
|
||||
|
@ -80,7 +126,17 @@ export default defineComponent({
|
|||
},
|
||||
];
|
||||
|
||||
<<<<<<< HEAD
|
||||
return { isError, onError, steppers, productsPurchased, totalPrice };
|
||||
=======
|
||||
cartStoreArr.value = [];
|
||||
setTimeout(() => {
|
||||
removeItem("cart");
|
||||
removeItem("payment");
|
||||
}, 5000);
|
||||
|
||||
return { isError, onError, steppers, totalPrice, cart };
|
||||
>>>>>>> master
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -129,7 +185,11 @@ export default defineComponent({
|
|||
<div class="checkout-success-content">
|
||||
<ul class="checkout-success-list">
|
||||
<li
|
||||
<<<<<<< HEAD
|
||||
v-for="({ name, price, image }, index) in productsPurchased.data"
|
||||
=======
|
||||
v-for="({ name, price, image }, index) in cart"
|
||||
>>>>>>> master
|
||||
:key="index"
|
||||
class="checkout-success-item"
|
||||
>
|
||||
|
@ -155,7 +215,11 @@ export default defineComponent({
|
|||
|
||||
<footer class="checkout-success-footer">
|
||||
<p class="checkout-success-paragraph">Total</p>
|
||||
<<<<<<< HEAD
|
||||
<p class="checkout-success-paragraph">{{ totalPrice }}€</p>
|
||||
=======
|
||||
<p class="checkout-success-paragraph">{{ totalPrice.toFixed(2) }}€</p>
|
||||
>>>>>>> master
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -49,7 +49,11 @@ export default defineComponent({
|
|||
const { availability: availabilityForm } = storeToRefs(formStore);
|
||||
|
||||
const availability = ref(getItem("availability"));
|
||||
<<<<<<< HEAD
|
||||
const filteredAvailabilityForm = computed(() => {
|
||||
=======
|
||||
const availabilityFormKeys = computed(() => {
|
||||
>>>>>>> master
|
||||
return Object.fromEntries(
|
||||
Object.entries(availabilityForm.value).filter(
|
||||
([key, value]) => value !== ""
|
||||
|
@ -59,8 +63,13 @@ export default defineComponent({
|
|||
|
||||
const isAvailabilityEmpty = computed(() => {
|
||||
return (
|
||||
<<<<<<< HEAD
|
||||
Object.keys(filteredAvailabilityForm.value || availability.value)
|
||||
.length === 0
|
||||
=======
|
||||
Object.keys(availabilityFormKeys.value || availability.value).length ===
|
||||
0
|
||||
>>>>>>> master
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -262,7 +271,11 @@ export default defineComponent({
|
|||
:loading="addCartLoadingBtn"
|
||||
color="primary"
|
||||
class="btn sm-btn"
|
||||
<<<<<<< HEAD
|
||||
label="AÑADIR AL CARRITO"
|
||||
=======
|
||||
label="COMPRAR"
|
||||
>>>>>>> master
|
||||
@click="addModal"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -77,11 +77,7 @@ const routes = [
|
|||
name: "Contacta",
|
||||
component: () => import("pages/ContactaPage.vue"),
|
||||
},
|
||||
{
|
||||
path: "/example",
|
||||
name: "Example",
|
||||
component: () => import("pages/ExamplePage.vue"),
|
||||
},
|
||||
|
||||
{
|
||||
path: "/:catchAll(.*)*",
|
||||
name: "NotFound",
|
||||
|
|
|
@ -37,6 +37,7 @@ export const useCartStore = defineStore("cart", () => {
|
|||
//! Variables
|
||||
const cart = ref(getItem("cart"));
|
||||
const availability = ref(getItem("availability"));
|
||||
<<<<<<< HEAD
|
||||
const filteredAvailabilityForm = computed(() => {
|
||||
return Object.fromEntries(
|
||||
Object.entries(availabilityForm.value).filter(
|
||||
|
@ -50,6 +51,9 @@ export const useCartStore = defineStore("cart", () => {
|
|||
.length === 0
|
||||
);
|
||||
});
|
||||
=======
|
||||
|
||||
>>>>>>> master
|
||||
const addCartLoadingBtn = ref(false);
|
||||
const routeId = ref(null);
|
||||
const products = ref({
|
||||
|
@ -221,6 +225,10 @@ export const useCartStore = defineStore("cart", () => {
|
|||
type: "erro",
|
||||
});
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
>>>>>>> master
|
||||
if (!products.value.data.some((item) => item.id === product.id)) {
|
||||
push("/");
|
||||
return quasarNotify({
|
||||
|
@ -241,6 +249,11 @@ export const useCartStore = defineStore("cart", () => {
|
|||
arr.push({ ...product, message: message.value });
|
||||
cart.value = arr;
|
||||
addItem("cart", arr);
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
await push("/checkout");
|
||||
>>>>>>> master
|
||||
quasarNotify({
|
||||
message: "Producto añadido al carrito.",
|
||||
type: "success",
|
||||
|
|
|
@ -2,6 +2,10 @@ import { defineStore } from "pinia";
|
|||
|
||||
export const useFormStore = defineStore("forms", {
|
||||
state: () => ({
|
||||
postalCodeValid: {
|
||||
isValid: false,
|
||||
dataOptions: [],
|
||||
},
|
||||
sortProductFilters: {
|
||||
isOpenOrderFilter: false,
|
||||
order: undefined,
|
||||
|
|
|
@ -1,7 +1,31 @@
|
|||
export function handlePhoneVal(val) {
|
||||
const regex = /[\(\) ]/g;
|
||||
const valWithoutSpaceAndParenteses = val.replace(regex, "");
|
||||
const valLength = valWithoutSpaceAndParenteses.length;
|
||||
import { countryFlagObj } from "src/constants";
|
||||
|
||||
return valLength > 0 && valLength === 11;
|
||||
import * as R from "./regex";
|
||||
|
||||
export function getCountryCode(countryNumber) {
|
||||
return (
|
||||
countryFlagObj[countryNumber] || countryFlagObj["default"](countryNumber)
|
||||
);
|
||||
}
|
||||
|
||||
export function handleValidCountryCode(countryNumber) {
|
||||
const validCountryCodes = ["34", "351", "33"];
|
||||
const isCountryCodeValid = validCountryCodes.includes(countryNumber);
|
||||
|
||||
return isCountryCodeValid;
|
||||
}
|
||||
|
||||
export function transformPhoneVal(val) {
|
||||
const obj = {
|
||||
length: val.replace(R.selectSpaceAndSum, "").length,
|
||||
val: val.replace(R.selectParenthesesSpacesDashes, ""),
|
||||
};
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function handlePhoneVal(input) {
|
||||
const { length, val } = input;
|
||||
|
||||
return length === 0;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
export const nameMessage =
|
||||
"Sólo se aceptan una palabra y caracteres no numéricos";
|
||||
export const phoneMessage =
|
||||
"El número de teléfono debe contener 11 caracteres numéricos válidos";
|
||||
"El teléfono no es válido, por favor, introduzca un número de teléfono válido.";
|
||||
export const onlyMinimumTwoCharacters = "Añade al menos dos caracteres";
|
||||
export const onlyTextMessage = "Sólo son válidas las letras";
|
||||
export const requiredMessage = "Campo obligatorio";
|
||||
export const emailMessage =
|
||||
"Introduzca una dirección de correo electrónico válida.";
|
||||
export const onlyTextAndNumbersMessage =
|
||||
"Sólo son válidas las letras y números";
|
||||
export const onlyNumbers = "¡Sólo se aceptan números!";
|
||||
export const fiveLength = "El código postal debe tener 5 dígitos";
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
export const justOneWord = /^[A-Za-z]+$/;
|
||||
export const justLetters = /^[A-Za-z ]+$/;
|
||||
export const justOneWord = /^[A-Za-z\u00C0-\u00FF]+$/;
|
||||
export const justLetters = /^[A-Za-z\u00C0-\u00FF ]+$/;
|
||||
export const justLettersAndNumbers = /^[A-Za-z0-9]+$/;
|
||||
export const justNumbers = /^[0-9 ]+$/;
|
||||
export const selectSpaceAndSum = /\s|\+/g;
|
||||
export const selectValuesWithSum = /\+\d+/g;
|
||||
export const selectParenthesesSpacesDashes = /[\s()-]/g;
|
||||
|
|
|
@ -1,38 +1,53 @@
|
|||
import { z } from "zod";
|
||||
|
||||
import { handlePhoneVal, justLetters, justOneWord, postalCode } from "..";
|
||||
|
||||
import * as GP from "../globalProperties";
|
||||
import * as M from "../messages";
|
||||
import * as R from "../regex";
|
||||
|
||||
const checkoutObjVal = {
|
||||
name: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.regex(justOneWord, M.nameMessage),
|
||||
.regex(R.justOneWord, M.nameMessage),
|
||||
surname: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.regex(justOneWord, M.nameMessage),
|
||||
.regex(R.justOneWord, M.nameMessage),
|
||||
address: z.string({ required_error: M.requiredMessage }),
|
||||
postalCode,
|
||||
postalCode: GP.postalCode,
|
||||
city: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.min(2, M.onlyMinimumTwoCharacters)
|
||||
.regex(justLetters, M.onlyTextMessage),
|
||||
.regex(R.justLetters, M.onlyTextMessage),
|
||||
province: z.string({ required_error: M.requiredMessage }),
|
||||
<<<<<<< HEAD
|
||||
phone: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.refine(handlePhoneVal, M.phoneMessage),
|
||||
senderName: z.string().regex(justLetters, M.nameMessage),
|
||||
=======
|
||||
phone: z.string({ required_error: M.requiredMessage }).refine((val) => {
|
||||
return val.length > 0;
|
||||
}, M.requiredMessage),
|
||||
senderName: z.string().regex(R.justLetters),
|
||||
>>>>>>> master
|
||||
senderCifNif: z
|
||||
.string()
|
||||
.length(9, "El código postal debe tener 9 caracteres numéricos válidos"),
|
||||
.regex(R.justLettersAndNumbers, M.onlyTextAndNumbersMessage),
|
||||
senderEmail: z.string().email(M.emailMessage),
|
||||
senderPhone: z.string().refine(handlePhoneVal, M.phoneMessage),
|
||||
senderPhone: z.string().refine((val) => {
|
||||
return val.length >= 0;
|
||||
}, M.phoneMessage),
|
||||
senderNotes: z.string(),
|
||||
<<<<<<< HEAD
|
||||
paymentMethod: z
|
||||
.enum(["credit", "paypal"], {
|
||||
required_error: "Seleccione uno de los métodos de pago!",
|
||||
})
|
||||
.default("paypal"),
|
||||
=======
|
||||
paymentMethod: z.enum(["redsys", "paypal"], {
|
||||
required_error: "Seleccione uno de los métodos de pago!",
|
||||
}),
|
||||
>>>>>>> master
|
||||
terms: z.boolean().refine((val) => {
|
||||
return val === true;
|
||||
}, "Acepte las condiciones antes de continuar con la compra"),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { toTypedSchema } from "@vee-validate/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { handlePhoneVal, justOneWord } from "..";
|
||||
import { justOneWord } from "..";
|
||||
import * as M from "../messages";
|
||||
|
||||
const questionObjVal = {
|
||||
|
@ -14,9 +14,13 @@ const questionObjVal = {
|
|||
email: z.string({ required_error: M.requiredMessage }).email(M.emailMessage),
|
||||
phone: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.refine(handlePhoneVal, M.phoneMessage),
|
||||
query: z.string({ required_error: M.requiredMessage }).min(1),
|
||||
message: z.string({ required_error: M.requiredMessage }).min(1),
|
||||
.min(1, M.requiredMessage),
|
||||
query: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.min(1, M.requiredMessage),
|
||||
message: z
|
||||
.string({ required_error: M.requiredMessage })
|
||||
.min(1, M.requiredMessage),
|
||||
terms: z.boolean({ required_error: M.requiredMessage }).refine((val) => {
|
||||
return val === true;
|
||||
}),
|
||||
|
|
Loading…
Reference in New Issue