wip: shopping cart, product options
This commit is contained in:
@@ -1,66 +1,102 @@
|
||||
import {defineStore} from "pinia";
|
||||
import md5 from 'crypto-js/md5';
|
||||
import ftch from "@/utils/ftch.js";
|
||||
import {$fetch} from "ofetch";
|
||||
import {isNotEmpty} from "@/helpers.js";
|
||||
|
||||
export const useCartStore = defineStore('cart', {
|
||||
state: () => ({
|
||||
items: [],
|
||||
products: [],
|
||||
productsCount: 0,
|
||||
total: 0,
|
||||
isLoading: false,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
getItem(rowId) {
|
||||
return this.items.find(item => item.rowId === rowId) ?? null;
|
||||
},
|
||||
|
||||
hasItem(rowId) {
|
||||
return this.getItem(rowId) !== null;
|
||||
async getProducts() {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const {data} = await ftch('cart');
|
||||
this.products = data.products;
|
||||
this.productsCount = data.count;
|
||||
this.total = data.total;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async addProduct(productId, productName, price, quantity = 1, options = []) {
|
||||
const rowId = this.generateRowId(productId, options);
|
||||
|
||||
const item = {
|
||||
rowId: rowId,
|
||||
productId: productId,
|
||||
productName: productName,
|
||||
price: price,
|
||||
quantity: quantity,
|
||||
options: JSON.parse(JSON.stringify(options)), // ← 💥 глубокая копия!
|
||||
};
|
||||
|
||||
this.items.push(item);
|
||||
|
||||
return rowId;
|
||||
},
|
||||
|
||||
removeItem(rowId) {
|
||||
this.items.splice(this.items.indexOf(rowId), 1);
|
||||
},
|
||||
|
||||
getQuantity(rowId) {
|
||||
if (this.hasItem(rowId)) {
|
||||
return this.getItem(rowId).quantity;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
setQuantity(rowId, quantity) {
|
||||
this.getItem(rowId).quantity = quantity;
|
||||
},
|
||||
|
||||
generateRowId(productId, options) {
|
||||
return md5(productId + JSON.stringify(options)).toString();
|
||||
},
|
||||
|
||||
async checkout() {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const {data} = await ftch('checkout', null, this.items);
|
||||
this.items = data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
const formData = new FormData();
|
||||
formData.append("product_id", productId);
|
||||
formData.append("quantity", quantity);
|
||||
|
||||
// TODO: Add support different types of options
|
||||
options.forEach((option) => {
|
||||
if (option.type === "checkbox" && Array.isArray(option.value)) {
|
||||
option.value.forEach(item => {
|
||||
formData.append(`option[${option.product_option_id}][]`, item.product_option_value_id);
|
||||
});
|
||||
} else if (option.type === "radio" && isNotEmpty(option.value)) {
|
||||
formData.append(`option[${option.product_option_id}]`, option.value.product_option_value_id);
|
||||
} else if (option.type === "select" && isNotEmpty(option.value)) {
|
||||
formData.append(`option[${option.product_option_id}]`, option.value.product_option_value_id);
|
||||
} else if ((option.type === "text" || option.type === 'textarea') && isNotEmpty(option.value)) {
|
||||
formData.append(`option[${option.product_option_id}]`, option.value);
|
||||
}
|
||||
})
|
||||
|
||||
const response = await $fetch('/index.php?route=checkout/cart/add', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(JSON.stringify(response.error));
|
||||
}
|
||||
|
||||
await this.getProducts();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async removeItem(rowId) {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const formData = new FormData();
|
||||
formData.append('key', rowId);
|
||||
await $fetch('/index.php?route=checkout/cart/remove', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
await this.getProducts();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async setQuantity(cartId, quantity) {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const formData = new FormData();
|
||||
formData.append(`quantity[${cartId}]`, quantity);
|
||||
await $fetch('/index.php?route=checkout/cart/edit', {
|
||||
redirect: 'manual',
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
await this.getProducts();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user