Merge remote-tracking branch 'origin/main'
This commit is contained in:
+13
-14
@@ -16,26 +16,25 @@ const closeModal = () => {
|
||||
<template>
|
||||
<div>
|
||||
<LoadingIndicator />
|
||||
|
||||
<NuxtPwaManifest />
|
||||
|
||||
<!-- <UpdatePwaModal-->
|
||||
<!-- :isShow="updateAvailable"-->
|
||||
<!-- @update="handleUpdate"-->
|
||||
<!-- @close="closeModal"-->
|
||||
<!-- />-->
|
||||
<UpdatePwaModal
|
||||
:isShow="updateAvailable"
|
||||
@update="handleUpdate"
|
||||
@close="closeModal"
|
||||
/>
|
||||
|
||||
<NuxtLayout>
|
||||
<ToastProvider>
|
||||
<NuxtPage />
|
||||
|
||||
<ToastContainer />
|
||||
<ToastViewport
|
||||
class="[--viewport-padding:_25px] fixed bottom-0 left-0 flex flex-col p-[var(--viewport-padding)] gap-[10px] w-[390px] max-w-[100vw] m-0 list-none z-[2147483647] outline-none"
|
||||
/>
|
||||
</ToastProvider>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
|
||||
<ToastProvider>
|
||||
<ToastContainer />
|
||||
<ToastViewport
|
||||
class="[--viewport-padding:_25px] fixed bottom-0 left-0 flex flex-col p-[var(--viewport-padding)] gap-[10px] w-[390px] max-w-[100vw] m-0 list-none z-[9999999999999999] outline-none"
|
||||
/>
|
||||
</ToastProvider>
|
||||
|
||||
<VueQueryDevtools dir="ltr" buttonPosition="bottom-left" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -14,13 +14,9 @@ const isSideDrawerOpen = ref(false);
|
||||
|
||||
// queries
|
||||
|
||||
const { data: account, suspense: accountSuspense } = useGetAccount();
|
||||
const { data: account } = useGetAccount();
|
||||
|
||||
accountSuspense();
|
||||
|
||||
const { data: cart, suspense: cartSuspense } = useGetOrdersCart();
|
||||
|
||||
cartSuspense();
|
||||
const { data: cart } = useGetOrdersCart();
|
||||
|
||||
// computed
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ defineProps<Props>();
|
||||
>
|
||||
<Icon :name="icon" size="50" class="**:fill-gray-500" />
|
||||
<span class="text-lg text-gray-500"> {{ title }} </span>
|
||||
<slot v-if="$slots['actions']" name="actions" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ const isLocked = useScrollLock(window);
|
||||
watch(
|
||||
() => isSideShow.value,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
isLocked.value = true;
|
||||
}
|
||||
isLocked.value = newValue ? true : false;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -88,19 +88,19 @@ onMounted(() => {
|
||||
:duration="options.duration ?? 4000"
|
||||
@swipeEnd="onSwipeEnd"
|
||||
v-model:open="open"
|
||||
class="bg-white shadow-md shadow-black/3 border-t-[0.5px] border-slate-200 border-black p-4 grid [grid-template-areas:_'title_action'_'description_action'] grid-cols-[auto_max-content] gap-x-[15px] items-center data-[state=open]:animate-toast-in data-[state=closed]:animate-toast-hide data-[swipe=move]:translate-x-[var(--reka-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-[transform_200ms_ease-out] data-[swipe=end]:animate-toast-out"
|
||||
class="w-full bg-white shadow-md justify-items-start shadow-black/3 border-t-[0.5px] border-slate-200 p-4 grid [grid-template-areas:_'title_action'_'description_action'] grid-cols-[auto_max-content] gap-x-[15px] items-center data-[state=open]:animate-toast-in data-[state=closed]:animate-toast-hide data-[swipe=move]:translate-x-[var(--reka-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-[transform_200ms_ease-out] data-[swipe=end]:animate-toast-out"
|
||||
:class="options.description ? 'rounded-150' : 'rounded-full'"
|
||||
>
|
||||
<ToastTitle
|
||||
:class="[{ 'mb-1.5': options.description }]"
|
||||
class="[grid-area:_title] font-medium text-slate-600 text-sm flex items-center gap-2"
|
||||
class="w-full justify-items-start [grid-area:_title] font-medium text-slate-600 text-sm flex items-center justify-between gap-2"
|
||||
>
|
||||
<Icon :name="statusIcon.name" :class="statusIcon.class" size="24" />
|
||||
<span>{{ message }}</span>
|
||||
<span class="text-start -me-2">{{ message }}</span>
|
||||
</ToastTitle>
|
||||
<ToastDescription v-if="options.description" as-child>
|
||||
<div
|
||||
class="[grid-area:_description] m-0 mr-8 text-slate-500 typo-p-sm text-justify"
|
||||
class="[grid-area:_description] m-0 mr-8 text-slate-500 typo-p-sm text-start"
|
||||
>
|
||||
{{ options.description }}
|
||||
</div>
|
||||
|
||||
@@ -218,11 +218,11 @@ watch(
|
||||
>
|
||||
<div
|
||||
v-if="!!filtersSuccessMessage"
|
||||
class="w-full flex-center gap-0.5"
|
||||
class="w-max rounded-full py-1.5 px-3 text-xs border flex-center gap-0.5 z-[2]"
|
||||
:class="
|
||||
filtersSuccessMessage.status == 'success'
|
||||
? 'text-success-500'
|
||||
: 'text-danger-500'
|
||||
? 'text-success-600 bg-success-100 border-success-600'
|
||||
: ' text-danger-600 bg-danger-100 border-danger-600'
|
||||
"
|
||||
>
|
||||
<span class="text-sm">{{
|
||||
@@ -242,7 +242,7 @@ watch(
|
||||
:disabled="productsIsPending"
|
||||
variant="solid"
|
||||
@click="resetFilters"
|
||||
class="w-full rounded-full py-4 !cursor-pointer disabled:pointer-events-none"
|
||||
class="w-full rounded-full py-4 !cursor-pointer disabled:pointer-events-none z-[3]"
|
||||
>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="productsIsPending" class="flex-center gap-3">
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
|
||||
// state
|
||||
|
||||
const route = useRoute();
|
||||
@@ -7,6 +9,16 @@ const route = useRoute();
|
||||
|
||||
const pageTitle = computed(() => route.meta.pageTitle);
|
||||
const prevPage = computed(() => route.meta.prevPage);
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart } = useGetOrdersCart();
|
||||
|
||||
// computed
|
||||
|
||||
const hasCartItem = computed(
|
||||
() => !!cart.value && cart.value.items.length! > 0
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -52,12 +64,13 @@ const prevPage = computed(() => route.meta.prevPage);
|
||||
class="w-full flex flex-col items-center relative justify-between gap-8 lg:gap-6 lg:flex-row lg:items-start"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col w-full gap-4 lg:gap-6 lg:w-9/12 shrink-0"
|
||||
class="flex flex-col w-full gap-4 lg:gap-6 shrink-0"
|
||||
:class="hasCartItem ? 'lg:w-9/12' : ''"
|
||||
>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
|
||||
<CartSummary />
|
||||
<CartSummary v-if="hasCartItem" />
|
||||
</div>
|
||||
</div>
|
||||
<ProductsSlider title="دیگران این محصولات را هم خریدهاند" />
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
import { useToast } from "~/composables/global/useToast";
|
||||
|
||||
export default defineNuxtRouteMiddleware(async () => {
|
||||
const { data: cart, suspense } = useGetOrdersCart();
|
||||
|
||||
const { addToast } = useToast();
|
||||
|
||||
await suspense();
|
||||
|
||||
if (cart.value?.items.length! > 1) {
|
||||
return;
|
||||
} else {
|
||||
addToast({
|
||||
message: "سبد خرید شما خالی است",
|
||||
options: {
|
||||
status: "error",
|
||||
},
|
||||
});
|
||||
return navigateTo("/");
|
||||
}
|
||||
});
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
definePageMeta({
|
||||
layout: "cart",
|
||||
middleware: ["check-is-logged-in", "check-has-cart-item"],
|
||||
middleware: "check-is-logged-in",
|
||||
pageTitle: "ثبت سفارش",
|
||||
prevPage: { name: "cart-delivery", label: "انتخاب آدرس" },
|
||||
nextPage: { name: "checkout", label: "پرداخت" },
|
||||
|
||||
@@ -7,7 +7,7 @@ import useGetAllAddress from "~/composables/api/account/useGetAllAddress";
|
||||
|
||||
definePageMeta({
|
||||
layout: "cart",
|
||||
middleware: ["check-is-logged-in", "check-has-cart-item"],
|
||||
middleware: "check-is-logged-in",
|
||||
pageTitle: "انتخاب آدرس",
|
||||
prevPage: { name: "cart", label: "سبد خرید" },
|
||||
nextPage: { name: "cart-checkout", label: "تسویه حساب" },
|
||||
|
||||
@@ -7,7 +7,7 @@ import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
|
||||
definePageMeta({
|
||||
layout: "cart",
|
||||
middleware: ["check-is-logged-in", 'check-has-cart-item'],
|
||||
middleware: "check-is-logged-in",
|
||||
pageTitle: "سبد خرید",
|
||||
prevPage: { name: "index", label: "بازگشت به خانه" },
|
||||
nextPage: { name: "cart-delivery", label: "انتخاب آدرس" },
|
||||
@@ -15,12 +15,21 @@ definePageMeta({
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart, isLoading: cartIsLoading } = useGetOrdersCart();
|
||||
const { data: cart, isLoading: cartIsLoading, suspense } = useGetOrdersCart();
|
||||
|
||||
await suspense();
|
||||
|
||||
// computed
|
||||
|
||||
const hasCartItem = computed(
|
||||
() => !!cart.value && cart.value.items.length! > 0
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full flex flex-col gap-4 lg:gap-6">
|
||||
<div
|
||||
v-if="hasCartItem"
|
||||
class="flex items-center justify-between w-full gap-3 px-5 py-4 rounded-xl bg-slate-50 border border-slate-200"
|
||||
>
|
||||
<Skeleton
|
||||
@@ -52,10 +61,16 @@ const { data: cart, isLoading: cartIsLoading } = useGetOrdersCart();
|
||||
|
||||
<div v-else class="w-full h-max">
|
||||
<div v-if="!cart?.items.length" class="flex flex-grow w-full">
|
||||
<Placeholder
|
||||
title="محصولی در سبد خرید یافت نشد :("
|
||||
icon="bi:cart"
|
||||
/>
|
||||
<Placeholder title="سبد خرید شما خالی است :(" icon="bi:cart">
|
||||
<template #actions>
|
||||
<NuxtLink :to="{ name: 'products' }">
|
||||
<Button class="rounded-full" size="md">
|
||||
<span> مشاهده محصولات </span>
|
||||
<Icon name="ci:left-rotation" size="24" />
|
||||
</Button>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</Placeholder>
|
||||
</div>
|
||||
<ul v-else class="w-full flex flex-col gap-4 lg:gap-6">
|
||||
<CartItem
|
||||
|
||||
@@ -124,11 +124,10 @@ watch(
|
||||
<li v-for="(product, index) in products" :key="index">
|
||||
<ProductCard
|
||||
:id="product.id"
|
||||
brand="برند محصول"
|
||||
:title="product.name"
|
||||
:picture="product.image1"
|
||||
:colors="['white', 'black']"
|
||||
:price="product.price"
|
||||
:picture="product.variants[0].images[0].image"
|
||||
:colors="product.colors"
|
||||
:price="product.variants[0].price"
|
||||
:rate="product.rating"
|
||||
:dark-layer="true"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user