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() const user = useUserStore()
user.get() 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> </script>
<style lang="scss"> <style lang="scss">
+26 -3
View File
@@ -4,14 +4,30 @@
<img src="/images/anahitaLogo.webp" alt="Asan Market" /> <img src="/images/anahitaLogo.webp" alt="Asan Market" />
</router-link> </router-link>
<AppDesktopHeaderNavigation /> <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" /> <Button v-bind="btns.login.props" />
</router-link> </router-link>
<div v-else> <div v-else>
<template v-for="({ props, component }, key) in btns.logged" :key="key"> <template v-for="({ props, component }, key) in btns.logged" :key="key">
<Button v-bind="props" @click="overlay($event, component)" /> <Button v-bind="props" @click="overlay($event, component)" />
</template> </template>
</div> </div> -->
</header> </header>
</template> </template>
@@ -66,7 +82,7 @@ const overlay = (event, is) => {
@apply border-[#CCCCCC] h-12 rounded-[0.6rem] #{!important}; @apply border-[#CCCCCC] h-12 rounded-[0.6rem] #{!important};
.p-button-label { .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 { .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 { .p-blockui-container {
@apply absolute; @apply absolute;
} }
+43 -20
View File
@@ -1,31 +1,57 @@
<template> <template>
<div class="header-cart-list-item"> <div class="header-cart-list-item">
<span>{{ quantity }}x</span> <div class="flex">
<img :src="data.coverPath" /> <img :src="product.coverPath" />
<div> <div class="w-full">
<h3>{{ data.category[data.category.length - 1]?.name }}</h3> <h3>{{ product.category[product.category.length - 1]?.name }}</h3>
<h2>{{ data.title }}</h2> <h2>{{ product.title }}</h2>
<span>
<b>{{ numberFormat(data.specialPrice || data.price) }} </b> <span class="text-zinc-800 text-[0.9em] mt-auto">
{{ $t('priceUnit') }} <b>{{ numberFormat(product.specialPrice * productQuantity || product.price * productQuantity) }} </b>
{{ $t("priceUnit") }}
</span> </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>
</div>
<!-- <Button
icon="isax isax-trash"
severity="secondary"
text
@click="$emit('remove', product)"
/> -->
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps(['data', 'quantity']) 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) => const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number) new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script> </script>
<style lang="scss"> <style lang="scss">
.header-cart-list-item { .header-cart-list-item {
box-shadow: 0px 2px 12px #004b8226; 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;
& > div {
& > span { & > span {
@apply absolute left-5 top-4 text-xs font-poppins; @apply absolute left-5 top-4 text-xs font-poppins;
} }
@@ -34,7 +60,7 @@ const numberFormat = (number) =>
@apply w-[9.2rem] h-[9.2rem] p-2; @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; @apply w-max gap-1 flex flex-col py-4 font-vazir mr-6;
h3 { h3 {
@@ -44,14 +70,11 @@ const numberFormat = (number) =>
h2 { 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;
} }
& > div {
span { @apply flex flex-row mr-0 h-14 items-center #{!important};
@apply text-zinc-800 text-[0.9em] mt-auto;
} }
} }
button {
@apply w-10 h-10 mb-2 -mx-2 shrink-0 self-end text-2xl text-[#7F7F7F] rounded-full #{!important};
} }
} }
</style> </style>
+29 -19
View File
@@ -1,33 +1,43 @@
<template> <template>
<div class="header-cart-list"> <div class="header-cart-list">
<h3>{{ $t('itemsSubmittedInCart', { count: cart.count }) }}</h3> <h3>{{ $t("itemsSubmittedInCart", { count: cart.count }) }}</h3>
<div> <div>
<ul> <ul>
<li v-for="({ product, quantity }, i) in items" :key="i"> <li v-for="(item, i) in items" :key="i">
<AppDesktopHeaderCartItem :data="product" :quantity="quantity" @remove="remove" /> <AppDesktopHeaderCartItem
:id="item._id"
:index="i"
@remove="remove"
/>
</li> </li>
</ul> </ul>
</div> </div>
<Button :label="$t('showCart')" @click="show()" /> <Button
:disabled="cart.count < 1"
:label="$t('showCart')"
@click="show()"
/>
</div> </div>
</template> </template>
<script setup> <script setup>
const { popup } = inject('service') const { popup } = inject("service");
const cart = useCartStore() const cart = useCartStore();
const items = computed(() => cart.items) const items = computed(() => cart.items);
const emit = defineEmits(['hide']) const emit = defineEmits(["hide"]);
const router = useRouter() const router = useRouter();
const token = useCookie("token");
const show = () => { const show = () => {
popup.value.hide() popup.value.hide();
router.push('/checkout/cart') if (token.value) router.push("/checkout/cart");
} else router.push("/auth/login?redirect=/checkout/cart");
const remove = async (id) => { };
await cart.update(id) const remove = async (data) => {
if (cart.count < 1) popup.value.hide() await cart.update(data);
} if (cart.count < 1) popup.value.hide();
};
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -36,7 +46,7 @@ const remove = async (id) => {
@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; @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 { & > h3 {
@apply text-sky-700 text-[0.9em] font-medium font-vazir mb-2.5 mr-8 ml-6; @apply text-primary-700 text-[0.9em] font-medium font-vazir mb-2.5 mr-8 ml-6;
} }
& > div { & > div {
@@ -52,11 +62,11 @@ const remove = async (id) => {
} }
& > button { & > button {
@apply bg-sky-700 border-sky-700 mr-8 ml-6 text-xl font-bold font-vazir #{!important}; @apply bg-primary-600 border-primary-600 mr-8 ml-6 text-xl font-bold font-vazir #{!important};
} }
&::before { &::before {
content: ' '; content: " ";
box-shadow: 0px -3px 16px 0px rgba(7, 50, 115, 0.16); box-shadow: 0px -3px 16px 0px rgba(7, 50, 115, 0.16);
@apply absolute inset-x-0 -bottom-3 h-28 z-0; @apply absolute inset-x-0 -bottom-3 h-28 z-0;
} }
+38 -33
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="pre-factor"> <div id="pre-factor">
<div> <div>
<h2> <h2>
<i class="isax isax-receipt-2"></i> <i class="isax isax-receipt-2"></i>
@@ -7,7 +7,7 @@
</h2> </h2>
<p>{{ $t("submitPreFactorDesc") }}</p> <p>{{ $t("submitPreFactorDesc") }}</p>
</div> </div>
<PanelSalesFactor :data="data" /> <PanelSalesFactor :data="factorData" />
<ul> <ul>
<li v-for="(btn, key) in btns" :key="key"> <li v-for="(btn, key) in btns" :key="key">
<Button v-bind="btn.props" @click="click(key)" /> <Button v-bind="btn.props" @click="click(key)" />
@@ -17,23 +17,44 @@
</template> </template>
<script setup> <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 { btns } = init();
const dialog = inject('dialogRef'); const dialog = inject("dialogRef");
const data = dialog.value.data const factorData = dialog.value.data;
const router = useRouter() const router = useRouter();
const store = useCartStore();
const click = (key) => { const click = async (key) => {
if (key == 'send') if (key == "send") {
router.push({ path: '/panel/factors', query: { id: data._id } }); await store.createPayment(factorData._id);
// navigateTo(data.value.url, { external: true });
dialog.value.close() // store.paymentUrl = ''
} }
if (key == "save" || key == "print") {
// Select the element you want to print
const element = document.getElementById("pre-factor");
// 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> </script>
<style lang="scss"> <style lang="scss">
.pre-factor { #pre-factor {
@apply flex flex-col gap-8 rounded-2xl w-[77.5rem] py-8 bg-white overflow-y-auto; @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) { & > div:nth-of-type(1) {
@apply flex flex-col items-center; @apply flex flex-col items-center;
@@ -51,19 +72,19 @@ const click = (key) => {
} }
p { p {
@apply w-[30.2rem] mt-[1.1rem] text-center text-[#4C4C4C] text-lg font-vazir; @apply w-[23rem] px-1 sm:w-[30.2rem] mt-[1.1rem] text-center text-[#4C4C4C] text-base sm:text-lg font-vazir;
} }
} }
& > ul { & > ul {
@apply w-full flex gap-4 px-8; @apply w-full flex flex-wrap gap-4 px-8;
li { li {
button { button {
@apply w-full h-12 #{!important}; @apply w-[12.3rem] h-12 #{!important};
.p-button-label { .p-button-label {
@apply h-[1.6rem] text-lg font-medium font-iran-sans; @apply h-[1.6rem] text-sm lg:text-lg font-medium font-iran-sans;
} }
.p-button-icon { .p-button-icon {
@@ -79,22 +100,6 @@ const click = (key) => {
} }
} }
} }
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];
}
} }
} }
+30 -18
View File
@@ -5,40 +5,52 @@
<label>{{ $t(key) }}</label> <label>{{ $t(key) }}</label>
<span> <span>
{{ numberFormat(value) }} {{ numberFormat(value) }}
{{ key == 'productsCount' ? $t('product') : '' }} {{ key == "productsCount" ? $t("product") : "" }}
</span> </span>
</li> </li>
</ul> </ul>
<Button :label="$t('submitAndViewPreFactor')" :loading="loading" @click="submitOrder()" /> <Button
:label="$t('submitAndViewPreFactor')"
:loading="loading"
@click="submitOrder()"
/>
</div> </div>
</template> </template>
<script setup> <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 items = computed(() => init(data.value));
const data = inject('data')
const items = computed(() => init(data.value)) const token = useCookie("token");
const loading = ref(false) const router = useRouter();
const loading = ref(false);
const submitOrder = async () => { const submitOrder = async () => {
loading.value = true if (token.value) {
const { status, data: res } = await useFetch('/api/orders', { loading.value = true;
headers: { Authorization: useCookie('token') }, method: 'post' const { status, data: res } = await useFetch("/api/orders", {
}) headers: { Authorization: useCookie("token") },
loading.value = false method: "post",
});
loading.value = false;
if (status.value == 'success') { if (status.value == "success") {
dialog.show(resolveComponent('CartDialogPreFactor'), res.value) dialog.show(resolveComponent("CartDialogPreFactor"), res.value);
const cart = useCartStore() const cart = useCartStore();
cart.get() cart.get();
}
} }
} else router.push("/auth/login?redirect=/checkout/cart");
};
const numberFormat = (number) => const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number) new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script> </script>
<style lang="scss"> <style lang="scss">
+8 -3
View File
@@ -11,7 +11,8 @@
<script setup> <script setup>
import init from '../../initialize/cart-total-invoice' import init from '../../initialize/cart-total-invoice'
const { isMobile } = useDevice();
const { breakpoint: device = isMobile ? "mobile" : "desktop" } = useViewport();
const { dialog } = inject('service') const { dialog } = inject('service')
const data = inject('data') const data = inject('data')
@@ -19,6 +20,10 @@ const data = inject('data')
const items = computed(() => init(data.value)) const items = computed(() => init(data.value))
const loading = ref(false) const loading = ref(false)
const position = computed(() => {
if(device == "desktop") return "center"
if(device == "mobile") return "bottom"
})
const submitOrder = async () => { const submitOrder = async () => {
loading.value = true loading.value = true
@@ -28,8 +33,8 @@ const submitOrder = async () => {
loading.value = false loading.value = false
if (status.value == 'success') { if (status.value == 'success') {
dialog.open(resolveComponent('DialogPreFactorSubmit'), { dialog.open(resolveComponent('CartDialogPreFactor'), {
props: { modal: true }, props: { modal: true, position: 'bottom' },
data data
}) })
} }
+19 -12
View File
@@ -1,22 +1,24 @@
<template> <template>
<div class="buy"> <div class="buy">
<p> <p>
<span>{{ $t('priceForYou') }}</span> <span>{{ $t("priceForYou") }}</span>
<small v-if="boxSeller"> <small v-if="boxSeller">
{{ $t('everyBox') }} {{ $t("everyBox") }}
</small> </small>
</p> </p>
<div> <div>
<span v-if="specialPrice"> <span v-if="specialPrice">
{{ numberFormat(specialPrice) }} {{ numberFormat(specialPrice) }}
<small>{{ $t('priceUnit') }}</small> <small>{{ $t("priceUnit") }}</small>
</span> </span>
<span> <span>
{{ numberFormat(price) }} {{ numberFormat(price) }}
<small v-if="!specialPrice"> <small v-if="!specialPrice">
{{ $t('priceUnit') }} {{ $t("priceUnit") }}
</small> </small>
</span> </span>
</div> </div>
<CartQuantity v-if="cart.find(id)" v-model="quantity" :range="orderRange" /> <CartQuantity v-if="cart.find(id)" v-model="quantity" :range="orderRange" />
<Button v-else :label="$t('addToCart')" :loading="cart.loading" @click="quantity = orderRange.min" /> <Button v-else :label="$t('addToCart')" :loading="cart.loading" @click="quantity = orderRange.min" />
@@ -24,17 +26,22 @@
</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 cart = useCartStore()
const quantity = computed({ const quantity = computed({
get: () => cart.find(id)?.quantity || 0, 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) => const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number) new Intl.NumberFormat("fa-IR", { maximumSignificantDigits: 3 }).format(
number
);
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -58,7 +65,6 @@ const numberFormat = (number) =>
& > div:nth-of-type(1) { & > div:nth-of-type(1) {
@apply flex flex-col justify-end gap-2 max-lg:order-last; @apply flex flex-col justify-end gap-2 max-lg:order-last;
span { span {
@apply text-left text-[#333] text-sm font-bold lg:text-[1.6em] font-vazir; @apply text-left text-[#333] text-sm font-bold lg:text-[1.6em] font-vazir;
} }
@@ -87,3 +93,4 @@ const numberFormat = (number) =>
} }
} }
</style> </style>
+29 -18
View File
@@ -1,8 +1,9 @@
import MiniMenu from '../components/app/desktop/header/MiniMenu.vue' import MiniMenu from "../components/app/desktop/header/MiniMenu.vue";
import CartList from '../components/app/desktop/header/cart/List.vue' import CartList from "../components/app/desktop/header/cart/List.vue";
export default () => { export default () => {
const { t } = useI18n() const { t } = useI18n();
const store = useUserStore()
return reactive({ return reactive({
btns: { btns: {
login: { login: {
@@ -10,9 +11,18 @@ export default () => {
label: t("registerOrLogin"), label: t("registerOrLogin"),
icon: "isax isax-login", icon: "isax isax-login",
iconPos: "right", iconPos: "right",
}
}, },
logged: { },
cart: {
props: {
icon: "isax isax-shopping-cart",
severity: "secondary",
badge: computed(() => useCartStore().count),
disabled: computed(() => useCartStore().count < 1),
outlined: true,
},
component: CartList,
},
account: { account: {
props: { props: {
label: t("userAccount"), label: t("userAccount"),
@@ -23,17 +33,18 @@ export default () => {
}, },
component: MiniMenu component: MiniMenu
}, },
cart: { // logged: {
props: { // account: {
icon: "isax isax-shopping-cart", // props: {
severity: "secondary", // label: t("userAccount"),
badge: computed(() => useCartStore().count), // icon: "isax isax-user",
disabled: computed(() => useCartStore().count < 1), // iconPos: "right",
outlined: true, // severity: "secondary",
// outlined: true,
// },
// component: MiniMenu,
// },
// },
}, },
component: CartList });
}, };
},
}
})
}
+1 -1
View File
@@ -5,7 +5,7 @@ export default () => {
btns: { btns: {
send: { send: {
props: { props: {
label: t("submitAndSend") label: t("submitAndPay")
}, },
events: { events: {
click: () => {} click: () => {}
+2 -1
View File
@@ -411,6 +411,7 @@
"updateSuccessfull" : "اطلاعات باموفقیت بروزرسانی شد.", "updateSuccessfull" : "اطلاعات باموفقیت بروزرسانی شد.",
"updatePasswordSuccessfull": "رمزعبور با موفقیت بروزرسانی شد.", "updatePasswordSuccessfull": "رمزعبور با موفقیت بروزرسانی شد.",
"sellerPanel": "پنل فروشنده", "sellerPanel": "پنل فروشنده",
"loading": "درحال بارگذاری ..." "loading": "درحال بارگذاری ...",
"submitAndPay": "ثبت و پرداخت"
} }
+210
View File
@@ -9,6 +9,7 @@
"dependencies": { "dependencies": {
"@pinia/nuxt": "^0.5.1", "@pinia/nuxt": "^0.5.1",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"html2pdf.js": "^0.10.2",
"nuxt": "^3.10.1", "nuxt": "^3.10.1",
"nuxt-swiper": "^1.2.2", "nuxt-swiper": "^1.2.2",
"pinia": "^2.1.7", "pinia": "^2.1.7",
@@ -497,6 +498,17 @@
"@babel/core": "^7.0.0-0" "@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": { "node_modules/@babel/standalone": {
"version": "7.23.10", "version": "7.23.10",
"resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.10.tgz", "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.10.tgz",
@@ -2754,6 +2766,12 @@
"undici-types": "~5.26.4" "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": { "node_modules/@types/resolve": {
"version": "1.20.2", "version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "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", "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz",
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==" "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": { "node_modules/autoprefixer": {
"version": "10.4.17", "version": "10.4.17",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
@@ -3404,6 +3433,14 @@
"integrity": "sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==", "integrity": "sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==",
"optional": true "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": { "node_modules/binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "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": "^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": { "node_modules/buffer-crc32": {
"version": "0.2.13", "version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "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": { "node_modules/chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3989,6 +4062,17 @@
"url": "https://jaywcjlove.github.io/#/sponsor" "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": { "node_modules/core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -4073,6 +4157,14 @@
"postcss": "^8.0.9" "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": { "node_modules/css-select": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "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" "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": { "node_modules/domutils": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
@@ -4592,6 +4690,11 @@
"node": ">= 0.4" "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": { "node_modules/esbuild": {
"version": "0.20.1", "version": "0.20.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
@@ -4831,6 +4934,11 @@
"reusify": "^1.0.4" "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": { "node_modules/file-uri-to-path": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "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" "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": { "node_modules/http-cache-semantics": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -5897,6 +6027,23 @@
"node >= 0.2.0" "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": { "node_modules/kleur": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "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", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==" "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": { "node_modules/picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "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", "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.0.tgz",
"integrity": "sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==" "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": { "node_modules/randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -8689,6 +8851,11 @@
"node": ">=4" "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": { "node_modules/regexp.prototype.flags": {
"version": "1.5.2", "version": "1.5.2",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
@@ -8755,6 +8922,15 @@
"node": ">=0.10.0" "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": { "node_modules/rimraf": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "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": "^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": { "node_modules/standard-as-callback": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", "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" "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": { "node_modules/svg-tags": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", "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", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" "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": { "node_modules/thenify": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "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", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "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": { "node_modules/validate-npm-package-license": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "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": { "dependencies": {
"@pinia/nuxt": "^0.5.1", "@pinia/nuxt": "^0.5.1",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"html2pdf.js": "^0.10.2",
"nuxt": "^3.10.1", "nuxt": "^3.10.1",
"nuxt-swiper": "^1.2.2", "nuxt-swiper": "^1.2.2",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"vue": "^3.4.15",
"quill": "^1.3.7", "quill": "^1.3.7",
"vue": "^3.4.15",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
}, },
"devDependencies": { "devDependencies": {
+10 -7
View File
@@ -16,17 +16,21 @@
<CartBuyersBought /> <CartBuyersBought />
</main> </main>
</NuxtLayout> </NuxtLayout>
</template> </template>
<script setup> <script setup>
const config = reactive({ mobile: { header: false } }) const config = reactive({ mobile: { header: false } });
const { device } = inject('service') const { device } = inject("service");
const cart = useCartStore() const cart = useCartStore();
cart.get() 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> </script>
<style lang="scss"> <style lang="scss">
@@ -44,7 +48,6 @@ provide('data', computed(() => cart.items))
& > li { & > li {
@apply p-6 lg:p-10 border-b last:border-b-0 border-[#E5E5E5]; @apply p-6 lg:p-10 border-b last:border-b-0 border-[#E5E5E5];
} }
} }
} }
+27 -15
View File
@@ -1,22 +1,34 @@
<template> <template>
<div class="flex flex-col w-72 h-max mx-auto mt-60 gap-6 lg:gap-10"> <NuxtLayout :name="device" :config="config">
<InputText <main class="home">
class="w-full rounded-[0.6rem] border shadow-none border-[#CCCCCC] text-zinc-800 font-iran-sans" <HomeTopSlider />
v-model="pass" <HomeMainCategories />
placeholder="پسورد" <HomeBanners />
></InputText> <HomeAmazingOffers />
<Button class="text-center" @click="confirm">تائید</Button> <HomeReviews />
</div> <HomeEstProducts />
<HomePopularCategories />
<HomeLatestPosts />
<HomeProducers :title="$t('producers')" />
</main>
</NuxtLayout>
</template> </template>
<script setup> <script setup>
const router = useRouter(); import init from "../initialize/home";
const pass = ref(""); provide("init", init);
const confirm = () => {
if (pass.value === "s@A123456") { const { device } = inject("service");
router.push("/home") 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> </script>
<style lang="scss"> <style lang="scss">
+94 -34
View File
@@ -1,60 +1,120 @@
export const useCartStore = defineStore('cart', { export const useCartStore = defineStore("cart", {
state: () => { state: () => {
return { return {
items: [], items: [],
loading: false loading: false,
} paymentUrl: "",
};
}, },
getters: { getters: {
count: (state) => state.items.reduce((sum, item) => sum + item.quantity, 0) || 0, count: (state) =>
find: (state) => (id) => state.items.find((item) => item.product?.id == id) state.items.reduce((sum, item) => sum + item.quantity, 0) || 0,
find: (state) => (id) =>
state.items.find((item) => item?.product?.id == id),
}, },
actions: { actions: {
async get() { async get() {
const { status, data } = await useFetch('/api/users/current/cart', { const { status, data } = await useFetch("/api/users/current/cart", {
headers: { Authorization: useCookie('token') } headers: { Authorization: useCookie("token") },
}) });
if (status.value == 'success') { if (status.value == "success") {
this.items = data.value.cart this.items = data.value.cart;
} }
}, },
async clear() { async clear() {
const { status } = await useFetch('/api/users/cart', { const { status } = await useFetch("/api/users/cart", {
headers: { Authorization: useCookie('token') }, method: 'delete', body: {} headers: { Authorization: useCookie("token") },
}) method: "delete",
body: {},
});
if (status.value == 'success') { if (status.value == "success") {
this.items = [] 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) { async update(product, quantity = 0) {
this.loading = true const token = useCookie("token");
const cart = { product }
this.loading = true;
const cart = { product: product.id };
if (quantity > 0) { if (quantity > 0) {
//update //update
let item = this.find(product) let item = this.find(product.id);
if (item) item.quantity = quantity if (item) item.quantity = quantity;
cart.quantity = quantity if (token.value) {
const { status, data } = await useFetch('/api/users/cart', { cart.quantity = quantity;
headers: { Authorization: useCookie('token') }, method: 'put', body: { cart } const { status, data } = await useFetch("/api/users/cart", {
}) headers: { Authorization: token },
if (status.value == 'success') { method: "put",
const temp = { product: data.value, quantity } body: { cart },
if (item) item = temp });
else this.items.push(temp) 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 { } else {
//remove //remove
const { status } = await useFetch('/api/users/cart', { if (token.value) {
headers: { Authorization: useCookie('token') }, method: 'patch', body: { cart } const { status } = await useFetch("/api/users/cart", {
}) headers: { Authorization: useCookie("token") },
if (status.value == 'success') { method: "patch",
this.items = this.items.filter((item) => item.product.id != product) 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 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 };
},
},
});