Skip to content

Instantly share code, notes, and snippets.

@dansp89
Created March 8, 2024 21:49
Show Gist options
  • Save dansp89/7ca59c0477f7b797e9bb177d735e8781 to your computer and use it in GitHub Desktop.
Save dansp89/7ca59c0477f7b797e9bb177d735e8781 to your computer and use it in GitHub Desktop.
// src/stores/useCartStore.ts
import { empty, productSingleImage } from "@/core/helpers/functions";
import ApiService from "@/core/services/ApiService";
import { defineStore } from "pinia";
// Definindo a interface Product baseada na descrição fornecida
interface MediaData {
// Defina os campos da mídia aqui se necessário
}
interface ShopCategory {
id: number;
attributes: {
title: string;
createdAt: string;
updatedAt: string;
key: string;
};
}
interface Product {
id: number;
title: string;
description: string;
descriptionResume: string;
priceRegular: number;
priceSale: number;
priceSaleStart: string;
priceSaleEnd: string;
sku?: string | null;
stock?: number | null;
productCode?: string;
createdAt: string;
updatedAt: string;
priceSaleActiveCron: boolean;
medias?: {
data: MediaData[] | null;
};
shop_categories: {
data: ShopCategory[];
};
}
// Extensão da interface Product para incluir quantidade no carrinho
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface CartProduct extends Product {
id: number;
quantity: number;
}
interface Coupon {
code?: string;
discount?: number;
type?: string;
}
export const useStoreCart = defineStore("cart", {
state: () => ({
items: [],
total: 0,
coupon: {
code: "",
discount: 0,
type: ""
} as Coupon
}),
actions: {
/**
* Adiciona um produto ao carrinho.
* @param {Product} product - O produto a ser adicionado ao carrinho.
* @param {number} [quantity=1] - A quantidade do produto a ser adicionada.
* @param {string} [set='add'] - A ação a ser realizada ('add' para adicionar, 'update' para atualizar).
*/
addProduct(product, qnt = 1, set = "add") {
const index = this.items.findIndex((item) => item.id === product.id);
const price = this.calculatePrice(product);
const stock = !empty(product.stock) ? product.stock : "";
const imageUrl = productSingleImage(product);
if (index !== -1) {
// Produto já existe, incrementar quantidade
// this.items[index].qnt += 1;
if (set === "add") {
this.items[index].qnt += qnt;
} else if (set === "update") {
this.items[index].qnt = qnt;
}
} else {
// Novo produto, adicionar ao carrinho
this.items.push({
id: product.id,
title: product.title,
price: price,
stock: stock,
qnt: qnt,
subtotal: price,
image: imageUrl
});
}
this.updateCartItemSubtotal();
this.calculateTotal();
this.updateCartState();
},
/**
* Remove um produto do carrinho.
* @param {Product} product - O produto a ser removido do carrinho.
*/
removeProduct(product) {
const index = this.items.findIndex((item) => item.id === product.id);
if (index !== -1) {
if (this.items[index].qnt > 1) {
this.items[index].qnt -= 1;
} else {
this.items.splice(index, 1);
}
// this.updateCartItemSubtotal();
this.updateCartState();
}
// this.calculateTotal();
},
/**
* Aplica um cupom de desconto ao carrinho.
* @param {string} code - O código do cupom.
* @param {number} discount - O valor de desconto do cupom.
* @param {string} type - O tipo de desconto do cupom ('percent' ou 'fixed').
*/
async applyCoupon(code, discount = 0, type = "") {
try {
const { data } = await ApiService.get("/shop-coupoms", `?filters[code][$eqi]=${code}`);
console.log(
"Código do cupom::datas",
data,
data?.data.length > 0,
data?.data?.[0]?.attributes
);
const cupom = data?.data?.[0]?.attributes;
this.coupon = {
code: !empty(cupom.code) ? cupom?.code : "",
discount: !empty(cupom.discount) ? cupom?.discount : discount,
type: !empty(cupom.type) ? cupom?.type : type
};
} catch (error) {
console.error("Cupom inválido:", error);
this.coupon = {
code: "",
discount: 0,
type: ""
};
}
this.calculateTotal();
this.updateCartState();
},
/**
* Calcula o valor total do carrinho.
*/
calculateTotal() {
this.total = this.items.reduce((acc, item) => acc + item.subtotal, 0);
if (this.total > 0) {
if (this.coupon) {
if (this.coupon.type === "percent") {
this.total *= 1 - this.coupon.discount / 100;
} else if (this.coupon.type === "fixed") {
this.total -= this.coupon.discount;
}
}
}
},
/**
* Calcula o preço de um produto.
* @param {Product} product - O produto para o qual calcular o preço.
* @returns {number} O preço calculado do produto.
*/
calculatePrice(product) {
if (!product.priceSale || product.priceSale >= product.priceRegular) {
return product.priceRegular;
} else if (product.priceSale > 0 && product.priceSale < product.priceRegular) {
return product.priceSale;
} else {
// Implementar lógica para priceSaleActiveCron aqui
// Pseudocódigo: se hoje está entre priceSaleStart e priceSaleEnd, use priceSale, senão priceRegular
const today = new Date();
const saleStart = new Date(product.priceSaleStart);
const saleEnd = new Date(product.priceSaleEnd);
if (product.priceSaleActiveCron && today >= saleStart && today <= saleEnd) {
return product.priceSale;
} else {
return product.priceRegular;
}
}
},
updateCartItemSubtotal() {
this.items = this.items.map((item) => ({
...item,
subtotal: item.price * item.qnt
}));
},
// loadCartState() {
// // Tentativa de carregar o estado do carrinho do localStorage
// const cartState = localStorage.getItem("cartState");
// if (cartState) {
// const parsedState = JSON.parse(cartState);
// this.items = parsedState.items || [];
// this.total = parsedState.total || 0;
// this.coupon = parsedState.coupon || null;
// console.log("CART::", parsedState);
// // Recalcular o total para garantir que está atualizado
// this.calculateTotal();
// }
// },
loadCartState() {
// console.clear();
const cartState = localStorage.getItem("cartState");
console.log("[loadCartState]::cartState(A)", JSON.stringify(JSON.parse(cartState), null, 2));
if (!empty(cartState)) {
const parsedState = JSON.parse(cartState);
this.$patch({ ...parsedState });
this.calculateTotal();
return parsedState;
}
const cartStateNull = {
items: [],
total: 0,
coupon: this.coupon
};
console.log("[loadCartState]::cartState(B)", JSON.stringify(cartStateNull, null, 2));
return cartStateNull;
},
updateCartState() {
const cartState = {
items: this.items,
total: this.total,
coupon: this.coupon
};
localStorage.setItem("cartState", JSON.stringify(cartState));
this.calculateTotal();
},
clearCartState() {
this.items = [];
this.total = 0;
this.coupon = null;
localStorage.removeItem("cartState");
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment