fixed add to cart bugs

This commit is contained in:
mohadese-nm
2024-10-02 09:38:51 +03:30
parent dad18b1a34
commit 1c2169b807
16 changed files with 840 additions and 443 deletions
+14
View File
@@ -44,6 +44,20 @@ categories.get()
const user = useUserStore()
user.get()
const token = useCookie("token");
const cart = useCartStore();
if (import.meta.client && localStorage.getItem("cart"))
cart.items = JSON.parse(localStorage.getItem("cart") || "{}");
watch(
() => cart.items,
(value) => {
if (!token.value) {
localStorage.setItem("cart", JSON.stringify(value));
}
},
{ deep: true }
);
</script>
<style lang="scss">
+26 -3
View File
@@ -4,14 +4,30 @@
<img src="/images/anahitaLogo.webp" alt="Asan Market" />
</router-link>
<AppDesktopHeaderNavigation />
<router-link v-if="!logged" :to="{ path: '/auth/login' }">
<div>
<router-link v-if="!logged" :to="{ path: '/auth/login' }" class="w-40">
<Button v-bind="btns.login.props" class="not-logged" />
</router-link>
<Button
v-else
v-bind="btns.account.props"
@click="overlay($event, btns.account.component)"
class="text-[#333333] min-w-36"
/>
<Button
v-bind="btns.cart.props"
@click="overlay($event, btns.cart.component)"
class="text-[#333333] w-16 basket"
/>
</div>
<!-- <router-link v-if="!logged" :to="{ path: '/auth/login' }">
<Button v-bind="btns.login.props" />
</router-link>
<div v-else>
<template v-for="({ props, component }, key) in btns.logged" :key="key">
<Button v-bind="props" @click="overlay($event, component)" />
</template>
</div>
</div> -->
</header>
</template>
@@ -66,7 +82,7 @@ const overlay = (event, is) => {
@apply border-[#CCCCCC] h-12 rounded-[0.6rem] #{!important};
.p-button-label {
@apply text-[#333333] text-lg font-medium font-vazir whitespace-nowrap;
@apply text-lg font-medium font-vazir whitespace-nowrap;
}
.p-button-icon {
@@ -91,6 +107,13 @@ const overlay = (event, is) => {
}
}
.not-logged {
@apply w-40 text-white p-2 #{!important};
.p-button-icon {
@apply text-white text-2xl;
}
}
.p-blockui-container {
@apply absolute;
}
+58 -35
View File
@@ -1,57 +1,80 @@
<template>
<div class="header-cart-list-item">
<span>{{ quantity }}x</span>
<img :src="data.coverPath" />
<div>
<h3>{{ data.category[data.category.length - 1]?.name }}</h3>
<h2>{{ data.title }}</h2>
<span>
<b>{{ numberFormat(data.specialPrice || data.price) }} </b>
{{ $t('priceUnit') }}
</span>
<div class="flex">
<img :src="product.coverPath" />
<div class="w-full">
<h3>{{ product.category[product.category.length - 1]?.name }}</h3>
<h2>{{ product.title }}</h2>
<span class="text-zinc-800 text-[0.9em] mt-auto">
<b>{{ numberFormat(product.specialPrice * productQuantity || product.price * productQuantity) }} </b>
{{ $t("priceUnit") }}
</span>
<div class="flex flex-row justify-start w-48">
<CartQuantity
v-if="cart.items[index]"
v-model="productQuantity"
:range="product.orderRange"
/>
</div>
</div>
<Button icon="isax isax-trash" severity="secondary" text @click="$emit('remove', data.id)" />
</div>
<!-- <Button
icon="isax isax-trash"
severity="secondary"
text
@click="$emit('remove', product)"
/> -->
</div>
</template>
</template>
<script setup>
defineProps(['data', 'quantity'])
<script setup>
const props = defineProps(["id", "index"]);
const cart = useCartStore();
console.log(props.id);
console.log(props.index);
const product = cart.items[props.index].product;
console.log(product);
const productQuantity = computed({
get: () => cart.items[props.index].quantity || 0,
set: (v) => cart.update(product, v),
});
const numberFormat = (number) =>
new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script>
const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number)
</script>
<style lang="scss">
.header-cart-list-item {
<style lang="scss">
.header-cart-list-item {
box-shadow: 0px 2px 12px #004b8226;
@apply flex p-2 pl-6 w-[26.9rem] h-[10.1rem] bg-white rounded-lg shadow border relative;
@apply flex p-2 pl-6 w-[26.9rem] bg-white rounded-lg shadow border relative;
&>span {
& > div {
& > span {
@apply absolute left-5 top-4 text-xs font-poppins;
}
}
img {
img {
@apply w-[9.2rem] h-[9.2rem] p-2;
}
}
div {
div:nth-of-type(1) {
@apply w-max gap-1 flex flex-col py-4 font-vazir mr-6;
h3 {
@apply text-right text-neutral-400 text-[0.9em] font-medium;
@apply text-right text-neutral-400 text-[0.9em] font-medium;
}
h2 {
@apply w-[13.1rem] h-14 text-right text-zinc-800 text-[1.1em] font-bold line-clamp-2;
@apply w-[13.1rem] h-14 text-right text-zinc-800 text-[1.1em] font-bold line-clamp-2;
}
span {
@apply text-zinc-800 text-[0.9em] mt-auto;
& > div {
@apply flex flex-row mr-0 h-14 items-center #{!important};
}
}
}
}
</style>
button {
@apply w-10 h-10 mb-2 -mx-2 shrink-0 self-end text-2xl text-[#7F7F7F] rounded-full #{!important};
}
}
</style>
+54 -44
View File
@@ -1,64 +1,74 @@
<template>
<div class="header-cart-list">
<h3>{{ $t('itemsSubmittedInCart', { count: cart.count }) }}</h3>
<div>
<ul>
<li v-for="({ product, quantity }, i) in items" :key="i">
<AppDesktopHeaderCartItem :data="product" :quantity="quantity" @remove="remove" />
</li>
</ul>
</div>
<Button :label="$t('showCart')" @click="show()" />
<div class="header-cart-list">
<h3>{{ $t("itemsSubmittedInCart", { count: cart.count }) }}</h3>
<div>
<ul>
<li v-for="(item, i) in items" :key="i">
<AppDesktopHeaderCartItem
:id="item._id"
:index="i"
@remove="remove"
/>
</li>
</ul>
</div>
<Button
:disabled="cart.count < 1"
:label="$t('showCart')"
@click="show()"
/>
</div>
</template>
<script setup>
const { popup } = inject('service')
const cart = useCartStore()
const items = computed(() => cart.items)
const { popup } = inject("service");
const cart = useCartStore();
const items = computed(() => cart.items);
const emit = defineEmits(['hide'])
const router = useRouter()
const emit = defineEmits(["hide"]);
const router = useRouter();
const token = useCookie("token");
const show = () => {
popup.value.hide()
router.push('/checkout/cart')
}
const remove = async (id) => {
await cart.update(id)
if (cart.count < 1) popup.value.hide()
}
popup.value.hide();
if (token.value) router.push("/checkout/cart");
else router.push("/auth/login?redirect=/checkout/cart");
};
const remove = async (data) => {
await cart.update(data);
if (cart.count < 1) popup.value.hide();
};
</script>
<style lang="scss">
.header-cart-list {
box-shadow: 0px 2px 10px 0px rgba(0, 75, 130, 0.16);
@apply rtl w-[30.9rem] h-[40.6rem] flex flex-col gap-5 py-6 pl-2 bg-white rounded-2xl border overflow-hidden relative;
box-shadow: 0px 2px 10px 0px rgba(0, 75, 130, 0.16);
@apply rtl w-[30.9rem] h-[40.6rem] flex flex-col gap-5 py-6 pl-2 bg-white rounded-2xl border overflow-hidden relative;
&>h3 {
@apply text-sky-700 text-[0.9em] font-medium font-vazir mb-2.5 mr-8 ml-6;
& > h3 {
@apply text-primary-700 text-[0.9em] font-medium font-vazir mb-2.5 mr-8 ml-6;
}
& > div {
@apply overflow-y-auto h-[29.8rem];
ul {
@apply w-full flex py-3 pr-8 pl-4 flex-col gap-3 items-center;
}
&>div {
@apply overflow-y-auto h-[29.8rem];
ul {
@apply w-full flex py-3 pr-8 pl-4 flex-col gap-3 items-center;
}
&::-webkit-scrollbar {
@apply hidden;
}
&::-webkit-scrollbar {
@apply hidden;
}
}
&>button {
@apply bg-sky-700 border-sky-700 mr-8 ml-6 text-xl font-bold font-vazir #{!important};
}
& > button {
@apply bg-primary-600 border-primary-600 mr-8 ml-6 text-xl font-bold font-vazir #{!important};
}
&::before {
content: ' ';
box-shadow: 0px -3px 16px 0px rgba(7, 50, 115, 0.16);
@apply absolute inset-x-0 -bottom-3 h-28 z-0;
}
&::before {
content: " ";
box-shadow: 0px -3px 16px 0px rgba(7, 50, 115, 0.16);
@apply absolute inset-x-0 -bottom-3 h-28 z-0;
}
}
</style>
+89 -84
View File
@@ -1,108 +1,113 @@
<template>
<div class="pre-factor">
<div>
<h2>
<i class="isax isax-receipt-2"></i>
<span>{{ $t("submitPreFactor") }}</span>
</h2>
<p>{{ $t("submitPreFactorDesc") }}</p>
</div>
<PanelSalesFactor :data="data" />
<ul>
<li v-for="(btn, key) in btns" :key="key">
<Button v-bind="btn.props" @click="click(key)" />
</li>
</ul>
<div id="pre-factor">
<div>
<h2>
<i class="isax isax-receipt-2"></i>
<span>{{ $t("submitPreFactor") }}</span>
</h2>
<p>{{ $t("submitPreFactorDesc") }}</p>
</div>
<PanelSalesFactor :data="factorData" />
<ul>
<li v-for="(btn, key) in btns" :key="key">
<Button v-bind="btn.props" @click="click(key)" />
</li>
</ul>
</div>
</template>
<script setup>
import init from '../../../initialize/pre-factor.js'
import init from "../../../initialize/pre-factor.js";
import html2pdf from "html2pdf.js";
const { btns } = init();
const dialog = inject('dialogRef');
const data = dialog.value.data
const router = useRouter()
const dialog = inject("dialogRef");
const factorData = dialog.value.data;
const router = useRouter();
const store = useCartStore();
const click = (key) => {
if (key == 'send')
router.push({ path: '/panel/factors', query: { id: data._id } });
const click = async (key) => {
if (key == "send") {
await store.createPayment(factorData._id);
// navigateTo(data.value.url, { external: true });
// store.paymentUrl = ''
}
if (key == "save" || key == "print") {
// Select the element you want to print
const element = document.getElementById("pre-factor");
dialog.value.close()
}
// Configure options for html2pdf
const options = {
margin: 1,
filename: "preFactor.pdf",
image: { type: "jpeg", quality: 0.98 },
html2canvas: { scale: 1 },
jsPDF: { unit: "in", format: "a3", orientation: "landscape" },
};
// Generate the PDF
html2pdf().set(options).from(element).save();
}
dialog.value.close();
};
</script>
<style lang="scss">
.pre-factor {
@apply flex flex-col gap-8 rounded-2xl w-[77.5rem] py-8 bg-white overflow-y-auto;
#pre-factor {
@apply flex flex-col gap-8 rounded-2xl w-screen lg:w-[79vw] h-auto py-2 bg-white overflow-y-hidden;
&>div:nth-of-type(1) {
@apply flex flex-col items-center;
& > div:nth-of-type(1) {
@apply flex flex-col items-center;
h2 {
@apply flex items-center gap-4 text-[#333333];
h2 {
@apply flex items-center gap-4 text-[#333333];
i {
@apply text-2xl;
}
i {
@apply text-2xl;
}
span {
@apply text-xl font-bold font-vazir;
}
}
p {
@apply w-[30.2rem] mt-[1.1rem] text-center text-[#4C4C4C] text-lg font-vazir;
}
span {
@apply text-xl font-bold font-vazir;
}
}
&>ul {
@apply w-full flex gap-4 px-8;
li {
button {
@apply w-full h-12 #{!important};
.p-button-label {
@apply h-[1.6rem] text-lg font-medium font-iran-sans;
}
.p-button-icon {
@apply text-2xl text-[#7F7F7F];
}
&.p-button-secondary {
@apply border-[#7F7F7F] justify-center;
.p-button-label {
@apply grow-0 text-[#7F7F7F];
}
}
}
}
li:nth-of-type(1) {
@apply w-[12.3rem];
}
li:nth-of-type(2) {
@apply w-[12.3rem] ml-auto;
}
li:nth-of-type(3) {
@apply w-[25.1rem];
}
li:nth-of-type(4) {
@apply w-[10.8rem];
}
p {
@apply w-[23rem] px-1 sm:w-[30.2rem] mt-[1.1rem] text-center text-[#4C4C4C] text-base sm:text-lg font-vazir;
}
}
& > ul {
@apply w-full flex flex-wrap gap-4 px-8;
li {
button {
@apply w-[12.3rem] h-12 #{!important};
.p-button-label {
@apply h-[1.6rem] text-sm lg:text-lg font-medium font-iran-sans;
}
.p-button-icon {
@apply text-2xl text-[#7F7F7F];
}
&.p-button-secondary {
@apply border-[#7F7F7F] justify-center;
.p-button-label {
@apply grow-0 text-[#7F7F7F];
}
}
}
}
}
}
body:has(.pre-factor) {
.sales-factor {
h2 {
@apply hidden #{!important};
}
.sales-factor {
h2 {
@apply hidden #{!important};
}
}
}
</style>
+58 -46
View File
@@ -1,73 +1,85 @@
<template>
<div class="cart-total-aside">
<ul>
<li v-for="(value, key) in items" :key="key">
<label>{{ $t(key) }}</label>
<span>
{{ numberFormat(value) }}
{{ key == 'productsCount' ? $t('product') : '' }}
</span>
</li>
</ul>
<Button :label="$t('submitAndViewPreFactor')" :loading="loading" @click="submitOrder()" />
</div>
<div class="cart-total-aside">
<ul>
<li v-for="(value, key) in items" :key="key">
<label>{{ $t(key) }}</label>
<span>
{{ numberFormat(value) }}
{{ key == "productsCount" ? $t("product") : "" }}
</span>
</li>
</ul>
<Button
:label="$t('submitAndViewPreFactor')"
:loading="loading"
@click="submitOrder()"
/>
</div>
</template>
<script setup>
import init from '../../../initialize/cart-total-invoice'
import init from "../../../initialize/cart-total-invoice";
const { dialog } = inject("service");
const data = inject("data");
const { dialog } = inject('service')
const data = inject('data')
const items = computed(() => init(data.value));
const items = computed(() => init(data.value))
const token = useCookie("token");
const loading = ref(false)
const router = useRouter();
const loading = ref(false);
const submitOrder = async () => {
loading.value = true
const { status, data: res } = await useFetch('/api/orders', {
headers: { Authorization: useCookie('token') }, method: 'post'
})
loading.value = false
if (token.value) {
loading.value = true;
const { status, data: res } = await useFetch("/api/orders", {
headers: { Authorization: useCookie("token") },
method: "post",
});
loading.value = false;
if (status.value == 'success') {
dialog.show(resolveComponent('CartDialogPreFactor'), res.value)
const cart = useCartStore()
cart.get()
if (status.value == "success") {
dialog.show(resolveComponent("CartDialogPreFactor"), res.value);
const cart = useCartStore();
cart.get();
}
}
} else router.push("/auth/login?redirect=/checkout/cart");
};
const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number)
new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script>
<style lang="scss">
.cart-total-aside {
@apply w-full lg:max-w-[28.1rem] lg:h-[25rem] flex flex-col justify-between p-6 grow;
@apply lg:bg-neutral-50 lg:rounded-[0.6rem] lg:border border-neutral-200 font-vazir lg:mr-auto;
@apply w-full lg:max-w-[28.1rem] lg:h-[25rem] flex flex-col justify-between p-6 grow;
@apply lg:bg-neutral-50 lg:rounded-[0.6rem] lg:border border-neutral-200 font-vazir lg:mr-auto;
ul {
@apply flex flex-col gap-[1.1rem] lg:gap-6 lg:mt-2;
ul {
@apply flex flex-col gap-[1.1rem] lg:gap-6 lg:mt-2;
li {
@apply flex justify-between items-center;
li {
@apply flex justify-between items-center;
label {
@apply text-zinc-500 text-sm lg:text-xl font-medium;
}
label {
@apply text-zinc-500 text-sm lg:text-xl font-medium;
}
span {
@apply text-zinc-800 text-lg lg:text-2xl lg:font-medium;
}
}
span {
@apply text-zinc-800 text-lg lg:text-2xl lg:font-medium;
}
}
}
button {
@apply max-lg:hidden;
button {
@apply max-lg:hidden;
span {
@apply text-xl font-bold;
}
span {
@apply text-xl font-bold;
}
}
}
</style>
+8 -3
View File
@@ -11,7 +11,8 @@
<script setup>
import init from '../../initialize/cart-total-invoice'
const { isMobile } = useDevice();
const { breakpoint: device = isMobile ? "mobile" : "desktop" } = useViewport();
const { dialog } = inject('service')
const data = inject('data')
@@ -19,6 +20,10 @@ const data = inject('data')
const items = computed(() => init(data.value))
const loading = ref(false)
const position = computed(() => {
if(device == "desktop") return "center"
if(device == "mobile") return "bottom"
})
const submitOrder = async () => {
loading.value = true
@@ -28,8 +33,8 @@ const submitOrder = async () => {
loading.value = false
if (status.value == 'success') {
dialog.open(resolveComponent('DialogPreFactorSubmit'), {
props: { modal: true },
dialog.open(resolveComponent('CartDialogPreFactor'), {
props: { modal: true, position: 'bottom' },
data
})
}
+71 -64
View File
@@ -1,89 +1,96 @@
<template>
<div class="buy">
<p>
<span>{{ $t('priceForYou') }}</span>
<small v-if="boxSeller">
{{ $t('everyBox') }}
</small>
</p>
<div>
<span v-if="specialPrice">
{{ numberFormat(specialPrice) }}
<small>{{ $t('priceUnit') }}</small>
</span>
<span>
{{ numberFormat(price) }}
<small v-if="!specialPrice">
{{ $t('priceUnit') }}
</small>
</span>
</div>
<CartQuantity v-if="cart.find(id)" v-model="quantity" :range="orderRange" />
<Button v-else :label="$t('addToCart')" :loading="cart.loading" @click="quantity = orderRange.min" />
<p>
<span>{{ $t("priceForYou") }}</span>
<small v-if="boxSeller">
{{ $t("everyBox") }}
</small>
</p>
<div>
<span v-if="specialPrice">
{{ numberFormat(specialPrice) }}
<small>{{ $t("priceUnit") }}</small>
</span>
<span>
{{ numberFormat(price) }}
<small v-if="!specialPrice">
{{ $t("priceUnit") }}
</small>
</span>
</div>
<CartQuantity v-if="cart.find(id)" v-model="quantity" :range="orderRange" />
<Button v-else :label="$t('addToCart')" :loading="cart.loading" @click="quantity = orderRange.min" />
</div>
</template>
</template>
<script setup>
<script setup>
const product = inject("data");
const { id, orderRange, boxSeller, specialPrice, price } = product;
const { id, orderRange, boxSeller, specialPrice, price } = inject('data')
const cart = useCartStore()
const quantity = computed({
const cart = useCartStore();
const quantity = computed({
get: () => cart.find(id)?.quantity || 0,
set: (v) => cart.update(id, v)
})
set: (v) => cart.update(product, v),
});
// const productAddedToCart = computed(() => {
// cart.items.find((item) => item.product._id == id);
// });
// console.log(productAddedToCart);
const numberFormat = (number) =>
new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script>
const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number)
</script>
<style lang="scss">
.product .buy {
<style lang="scss">
.product .buy {
@apply flex flex-wrap justify-between items-center px-6 pt-1 pb-2.5 lg:gap-6 shadow-[0px_-3px_5px_#00000005];
@apply fixed inset-x-0 bottom-0 h-[6.2rem] bg-white shadow border-t border-[#F1F2F4] lg:h-auto;
@apply z-10 lg:z-0 lg:static lg:bg-transparent lg:shadow-none lg:border-t-0 lg:p-0 lg:gap-y-6 lg:mt-auto;
p {
@apply w-full lg:w-max text-[#7F7F7F] font-medium font-vazir pr-1.5 lg:p-0;
@apply w-full lg:w-max text-[#7F7F7F] font-medium font-vazir pr-1.5 lg:p-0;
span {
@apply text-xs lg:text-xl leading-[2.1rem];
}
span {
@apply text-xs lg:text-xl leading-[2.1rem];
}
small {
@apply text-[0.7em] lg:text-base leading-[1.9rem];
}
small {
@apply text-[0.7em] lg:text-base leading-[1.9rem];
}
}
&>div:nth-of-type(1) {
@apply flex flex-col justify-end gap-2 max-lg:order-last;
& > div:nth-of-type(1) {
@apply flex flex-col justify-end gap-2 max-lg:order-last;
span {
@apply text-left text-[#333] text-sm font-bold lg:text-[1.6em] font-vazir;
}
span {
@apply text-left text-[#333] text-sm font-bold lg:text-[1.6em] font-vazir;
small {
@apply text-xs font-medium lg:hidden;
}
&:has(span:nth-child(2)) {
span:first-child {
@apply max-lg:-mt-8;
}
small {
@apply text-xs font-medium lg:hidden;
}
&:has(span:nth-child(2)) {
span:first-child {
@apply max-lg:-mt-8;
}
span:last-child {
@apply line-through text-xs lg:text-base text-gray-600;
}
span:last-child {
@apply line-through text-xs lg:text-base text-gray-600;
}
}
}
&>button {
@apply w-[10.8rem] h-[2.6rem] lg:w-[25.1rem] lg:h-14 #{!important};
& > button {
@apply w-[10.8rem] h-[2.6rem] lg:w-[25.1rem] lg:h-14 #{!important};
.p-button-label {
@apply text-xs lg:text-xl font-bold font-iran-sans;
}
.p-button-label {
@apply text-xs lg:text-xl font-bold font-iran-sans;
}
}
}
</style>
}
</style>
+48 -37
View File
@@ -1,39 +1,50 @@
import MiniMenu from '../components/app/desktop/header/MiniMenu.vue'
import CartList from '../components/app/desktop/header/cart/List.vue'
import MiniMenu from "../components/app/desktop/header/MiniMenu.vue";
import CartList from "../components/app/desktop/header/cart/List.vue";
export default () => {
const { t } = useI18n()
return reactive({
btns: {
login: {
props: {
label: t("registerOrLogin"),
icon: "isax isax-login",
iconPos: "right",
}
},
logged: {
account: {
props: {
label: t("userAccount"),
icon: "isax isax-user",
iconPos: "right",
severity: "secondary",
outlined: true,
},
component: MiniMenu
},
cart: {
props: {
icon: "isax isax-shopping-cart",
severity: "secondary",
badge: computed(() => useCartStore().count),
disabled: computed(() => useCartStore().count < 1),
outlined: true,
},
component: CartList
},
},
}
})
}
const { t } = useI18n();
const store = useUserStore()
return reactive({
btns: {
login: {
props: {
label: t("registerOrLogin"),
icon: "isax isax-login",
iconPos: "right",
},
},
cart: {
props: {
icon: "isax isax-shopping-cart",
severity: "secondary",
badge: computed(() => useCartStore().count),
disabled: computed(() => useCartStore().count < 1),
outlined: true,
},
component: CartList,
},
account: {
props: {
label: t("userAccount"),
icon: "isax isax-user",
iconPos: "right",
severity: "secondary",
outlined: true,
},
component: MiniMenu
},
// logged: {
// account: {
// props: {
// label: t("userAccount"),
// icon: "isax isax-user",
// iconPos: "right",
// severity: "secondary",
// outlined: true,
// },
// component: MiniMenu,
// },
// },
},
});
};
+1 -1
View File
@@ -5,7 +5,7 @@ export default () => {
btns: {
send: {
props: {
label: t("submitAndSend")
label: t("submitAndPay")
},
events: {
click: () => {}
+2 -1
View File
@@ -411,6 +411,7 @@
"updateSuccessfull" : "اطلاعات باموفقیت بروزرسانی شد.",
"updatePasswordSuccessfull": "رمزعبور با موفقیت بروزرسانی شد.",
"sellerPanel": "پنل فروشنده",
"loading": "درحال بارگذاری ..."
"loading": "درحال بارگذاری ...",
"submitAndPay": "ثبت و پرداخت"
}
+210
View File
@@ -9,6 +9,7 @@
"dependencies": {
"@pinia/nuxt": "^0.5.1",
"chart.js": "^4.4.1",
"html2pdf.js": "^0.10.2",
"nuxt": "^3.10.1",
"nuxt-swiper": "^1.2.2",
"pinia": "^2.1.7",
@@ -497,6 +498,17 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
"integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/standalone": {
"version": "7.23.10",
"resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.10.tgz",
@@ -2754,6 +2766,12 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/raf": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
"optional": true
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
@@ -3352,6 +3370,17 @@
"resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz",
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg=="
},
"node_modules/atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"bin": {
"atob": "bin/atob.js"
},
"engines": {
"node": ">= 4.5.0"
}
},
"node_modules/autoprefixer": {
"version": "10.4.17",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
@@ -3404,6 +3433,14 @@
"integrity": "sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==",
"optional": true
},
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -3489,6 +3526,17 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/btoa": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
"bin": {
"btoa": "bin/btoa.js"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@@ -3695,6 +3743,31 @@
}
]
},
"node_modules/canvg": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz",
"integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==",
"optional": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"@types/raf": "^3.4.0",
"core-js": "^3.8.3",
"raf": "^3.4.1",
"regenerator-runtime": "^0.13.7",
"rgbcolor": "^1.0.1",
"stackblur-canvas": "^2.0.0",
"svg-pathdata": "^6.0.3"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/canvg/node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"optional": true
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3989,6 +4062,17 @@
"url": "https://jaywcjlove.github.io/#/sponsor"
}
},
"node_modules/core-js": {
"version": "3.38.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz",
"integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==",
"hasInstallScript": true,
"optional": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -4073,6 +4157,14 @@
"postcss": "^8.0.9"
}
},
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
@@ -4449,6 +4541,12 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz",
"integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==",
"optional": true
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
@@ -4592,6 +4690,11 @@
"node": ">= 0.4"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/esbuild": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
@@ -4831,6 +4934,11 @@
"reusify": "^1.0.4"
}
},
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -5304,6 +5412,28 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/html2pdf.js": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/html2pdf.js/-/html2pdf.js-0.10.2.tgz",
"integrity": "sha512-WyHVeMb18Bp7vYTmBv1GVsThH//K7SRfHdSdhHPkl4JvyQarNQXnailkYn0QUbRRmnN5rdbbmSIGEsPZtzPy2Q==",
"dependencies": {
"es6-promise": "^4.2.5",
"html2canvas": "^1.0.0",
"jspdf": "^2.3.1"
}
},
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -5897,6 +6027,23 @@
"node >= 0.2.0"
]
},
"node_modules/jspdf": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz",
"integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
"dependencies": {
"@babel/runtime": "^7.23.2",
"atob": "^2.1.2",
"btoa": "^1.2.1",
"fflate": "^0.8.1"
},
"optionalDependencies": {
"canvg": "^3.0.6",
"core-js": "^3.6.0",
"dompurify": "^2.5.4",
"html2canvas": "^1.0.0-rc.5"
}
},
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -7820,6 +7967,12 @@
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"optional": true
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -8542,6 +8695,15 @@
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.0.tgz",
"integrity": "sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A=="
},
"node_modules/raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"optional": true,
"dependencies": {
"performance-now": "^2.1.0"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -8689,6 +8851,11 @@
"node": ">=4"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
@@ -8755,6 +8922,15 @@
"node": ">=0.10.0"
}
},
"node_modules/rgbcolor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
"optional": true,
"engines": {
"node": ">= 0.8.15"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -9315,6 +9491,15 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/stackblur-canvas": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
"optional": true,
"engines": {
"node": ">=0.1.14"
}
},
"node_modules/standard-as-callback": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
@@ -9526,6 +9711,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svg-pathdata": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"optional": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -9741,6 +9935,14 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -10188,6 +10390,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}
},
"node_modules/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+2 -1
View File
@@ -13,11 +13,12 @@
"dependencies": {
"@pinia/nuxt": "^0.5.1",
"chart.js": "^4.4.1",
"html2pdf.js": "^0.10.2",
"nuxt": "^3.10.1",
"nuxt-swiper": "^1.2.2",
"pinia": "^2.1.7",
"vue": "^3.4.15",
"quill": "^1.3.7",
"vue": "^3.4.15",
"vue-router": "^4.2.5"
},
"devDependencies": {
+38 -35
View File
@@ -1,53 +1,56 @@
<template>
<NuxtLayout :name="device" :config="config">
<main class="cart">
<CartTabs />
<section>
<div>
<ul v-if="cart.items.length > 0">
<li v-for="(item, i) in cart.items" :key="i">
<CartItem :data="item.product" />
</li>
</ul>
<CartTotalAside />
</div>
</section>
<CartTotalFixed v-if="device == 'mobile'" />
<CartBuyersBought />
</main>
</NuxtLayout>
<NuxtLayout :name="device" :config="config">
<main class="cart">
<CartTabs />
<section>
<div>
<ul v-if="cart.items.length > 0">
<li v-for="(item, i) in cart.items" :key="i">
<CartItem :data="item.product" />
</li>
</ul>
<CartTotalAside />
</div>
</section>
<CartTotalFixed v-if="device == 'mobile'" />
<CartBuyersBought />
</main>
</NuxtLayout>
</template>
<script setup>
const config = reactive({ mobile: { header: false } })
const { device } = inject('service')
const config = reactive({ mobile: { header: false } });
const { device } = inject("service");
const cart = useCartStore()
cart.get()
const cart = useCartStore();
if (import.meta.client && localStorage.getItem("cart")) {
cart.items = JSON.parse(localStorage.getItem("cart") || "{}");
} else cart.get();
provide('data', computed(() => cart.items))
provide(
"data",
computed(() => cart.items)
);
</script>
<style lang="scss">
.cart {
@apply w-full flex flex-col gap-[2.6rem] pb-32 lg:gap-6 lg:pt-10;
@apply w-full flex flex-col gap-[2.6rem] pb-32 lg:gap-6 lg:pt-10;
&>section:not([class]) {
@apply w-full min-h-96 flex lg:mb-[6.4rem];
& > section:not([class]) {
@apply w-full min-h-96 flex lg:mb-[6.4rem];
&>div {
@apply container flex flex-col items-center lg:items-start lg:flex-row gap-6;
& > div {
@apply container flex flex-col items-center lg:items-start lg:flex-row gap-6;
&>ul {
@apply max-w-[67.6rem] flex flex-col border-b lg:rounded-[0.6rem] lg:border border-[#E5E5E5] grow;
& > ul {
@apply max-w-[67.6rem] flex flex-col border-b lg:rounded-[0.6rem] lg:border border-[#E5E5E5] grow;
&>li {
@apply p-6 lg:p-10 border-b last:border-b-0 border-[#E5E5E5];
}
}
& > li {
@apply p-6 lg:p-10 border-b last:border-b-0 border-[#E5E5E5];
}
}
}
}
}
</style>
+27 -15
View File
@@ -1,22 +1,34 @@
<template>
<div class="flex flex-col w-72 h-max mx-auto mt-60 gap-6 lg:gap-10">
<InputText
class="w-full rounded-[0.6rem] border shadow-none border-[#CCCCCC] text-zinc-800 font-iran-sans"
v-model="pass"
placeholder="پسورد"
></InputText>
<Button class="text-center" @click="confirm">تائید</Button>
</div>
<NuxtLayout :name="device" :config="config">
<main class="home">
<HomeTopSlider />
<HomeMainCategories />
<HomeBanners />
<HomeAmazingOffers />
<HomeReviews />
<HomeEstProducts />
<HomePopularCategories />
<HomeLatestPosts />
<HomeProducers :title="$t('producers')" />
</main>
</NuxtLayout>
</template>
<script setup>
const router = useRouter();
const pass = ref("");
const confirm = () => {
if (pass.value === "s@A123456") {
router.push("/home")
}
}
import init from "../initialize/home";
provide("init", init);
const { device } = inject("service");
const config = reactive({
mobile: { header: { search: true, menu: true } },
});
const { status, data, error } = await useFetch("/api/pages/landing");
if (status.value == "success") {
useSeoMeta(data.value.meta || {});
provide("data", data.value);
} else throw createError(error.value);
</script>
<style lang="scss">
+113 -53
View File
@@ -1,60 +1,120 @@
export const useCartStore = defineStore('cart', {
export const useCartStore = defineStore("cart", {
state: () => {
return {
items: [],
loading: false
}
return {
items: [],
loading: false,
paymentUrl: "",
};
},
getters: {
count: (state) => state.items.reduce((sum, item) => sum + item.quantity, 0) || 0,
find: (state) => (id) => state.items.find((item) => item.product?.id == id)
count: (state) =>
state.items.reduce((sum, item) => sum + item.quantity, 0) || 0,
find: (state) => (id) =>
state.items.find((item) => item?.product?.id == id),
},
actions: {
async get() {
const { status, data } = await useFetch('/api/users/current/cart', {
headers: { Authorization: useCookie('token') }
})
async get() {
const { status, data } = await useFetch("/api/users/current/cart", {
headers: { Authorization: useCookie("token") },
});
if (status.value == 'success') {
this.items = data.value.cart
}
},
async clear() {
const { status } = await useFetch('/api/users/cart', {
headers: { Authorization: useCookie('token') }, method: 'delete', body: {}
})
if (status.value == 'success') {
this.items = []
}
},
async update(product, quantity = 0) {
this.loading = true
const cart = { product }
if (quantity > 0) {
//update
let item = this.find(product)
if (item) item.quantity = quantity
cart.quantity = quantity
const { status, data } = await useFetch('/api/users/cart', {
headers: { Authorization: useCookie('token') }, method: 'put', body: { cart }
})
if (status.value == 'success') {
const temp = { product: data.value, quantity }
if (item) item = temp
else this.items.push(temp)
}
} else {
//remove
const { status } = await useFetch('/api/users/cart', {
headers: { Authorization: useCookie('token') }, method: 'patch', body: { cart }
})
if (status.value == 'success') {
this.items = this.items.filter((item) => item.product.id != product)
}
}
this.loading = false
if (status.value == "success") {
this.items = data.value.cart;
}
}
})
},
async clear() {
const { status } = await useFetch("/api/users/cart", {
headers: { Authorization: useCookie("token") },
method: "delete",
body: {},
});
if (status.value == "success") {
this.items = [];
}
},
async create() {
if (this.items.length > 0) {
const cart = Object.assign([], this.items).map((item) => {
item.product = item.product.id;
return item;
});
this.items = [];
const { status } = await useFetch("/api/users/cart", {
headers: { Authorization: useCookie("token") },
method: "put",
body: { cart },
});
if (status.value == "success") {
localStorage.removeItem("cart");
this.get();
}
}
},
async update(product, quantity = 0) {
const token = useCookie("token");
this.loading = true;
const cart = { product: product.id };
if (quantity > 0) {
//update
let item = this.find(product.id);
if (item) item.quantity = quantity;
if (token.value) {
cart.quantity = quantity;
const { status, data } = await useFetch("/api/users/cart", {
headers: { Authorization: token },
method: "put",
body: { cart },
});
if (status.value == "success") {
const temp = { product: data.value, quantity };
if (item) item = temp;
else this.items.push(temp);
}
} else {
const temp = { product, quantity };
if (item) item = temp;
else this.items.push(temp);
}
} else {
//remove
if (token.value) {
const { status } = await useFetch("/api/users/cart", {
headers: { Authorization: useCookie("token") },
method: "patch",
body: { cart },
});
if (status.value == "success") {
this.items = this.items.filter(
(item) => item.product.id != product.id
);
}
} else {
this.items = this.items.filter(
(item) => item.product.id != product.id
);
}
}
this.loading = false;
},
async createPayment(id) {
const { status, data } = await useFetch(
`/api/orders/swift/payment/${id}`,
{
headers: { Authorization: useCookie("token"), method: "post" },
}
);
if (status.value == "success") {
console.log(data.value.url);
this.paymentUrl = data.value.url;
window.open(data.value.url, "_blank");
}
return { data, status };
},
},
});