Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import useDeleteDiscountCode from "~/composables/api/orders/useDeleteDiscountCode";
|
||||
import useGetCartOrders from "~/composables/api/orders/useGetCartOrders";
|
||||
import useSubmitDiscountCode from "~/composables/api/orders/useSubmitDiscountCode";
|
||||
import { useToast } from "~/composables/global/useToast";
|
||||
@@ -10,25 +11,31 @@ import { QUERY_KEYS } from "~/constants";
|
||||
|
||||
const route = useRoute();
|
||||
const { $queryClient: queryClient } = useNuxtApp();
|
||||
|
||||
const discountCode = ref("");
|
||||
const { addToast } = useToast();
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart, isLoading: cartIsLoading } = useGetCartOrders();
|
||||
|
||||
const { addToast } = useToast();
|
||||
const discountCode = ref(cart.value?.discount_code?.code || "");
|
||||
|
||||
const {
|
||||
mutateAsync: submitDiscountCode,
|
||||
isPending: submitDiscountCodeIsPending,
|
||||
} = useSubmitDiscountCode();
|
||||
|
||||
const {
|
||||
mutateAsync: deleteDiscountCode,
|
||||
isPending: deleteDiscountCodeIsPending,
|
||||
} = useDeleteDiscountCode();
|
||||
|
||||
// computed
|
||||
|
||||
const nextPage: ComputedRef<{ name: string; label: string } | undefined> =
|
||||
computed(() => route.meta.nextPage);
|
||||
|
||||
const hasSubmittedDiscountCode = computed(() => !!cart.value?.discount_code);
|
||||
|
||||
// methods
|
||||
|
||||
const handleSubmitDiscountCode = () => {
|
||||
@@ -50,6 +57,24 @@ const handleSubmitDiscountCode = () => {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleDeleteDiscountCode = () => {
|
||||
deleteDiscountCode(undefined, {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.cart] });
|
||||
discountCode.value = "";
|
||||
},
|
||||
onError: () => {
|
||||
addToast({
|
||||
message: "خطایی در حذف کد تخفیف رخ داد",
|
||||
options: {
|
||||
status: "error",
|
||||
},
|
||||
});
|
||||
discountCode.value = "";
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -94,7 +119,7 @@ const handleSubmitDiscountCode = () => {
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!!cart?.discount_code"
|
||||
v-if="hasSubmittedDiscountCode"
|
||||
class="flex items-center justify-between w-full text-status-error-primary text-red-700"
|
||||
>
|
||||
<span class="max-w-1/2 text-sm"> تخفیف: </span>
|
||||
@@ -119,19 +144,33 @@ const handleSubmitDiscountCode = () => {
|
||||
v-model="discountCode"
|
||||
placeholder="کد تخفیف"
|
||||
class="!py-3 !pe-2 ps-2.5 w-full !rounded-none !border-e-[0px] !rounded-s-100"
|
||||
:disabled="hasSubmittedDiscountCode"
|
||||
/>
|
||||
<button
|
||||
@click="handleSubmitDiscountCode"
|
||||
@click="
|
||||
hasSubmittedDiscountCode
|
||||
? handleDeleteDiscountCode()
|
||||
: handleSubmitDiscountCode()
|
||||
"
|
||||
class="text-xs px-5 rounded-e-100 py-1.5 text-white bg-black hover:invert border-[1.5px] border-black hover:border-white transition-all disabled:cursor-not-allowed"
|
||||
:disabled="!discountCode.length"
|
||||
:disabled="
|
||||
!discountCode.length ||
|
||||
submitDiscountCodeIsPending ||
|
||||
deleteDiscountCodeIsPending
|
||||
"
|
||||
>
|
||||
<Icon
|
||||
v-if="submitDiscountCodeIsPending"
|
||||
v-if="
|
||||
submitDiscountCodeIsPending ||
|
||||
deleteDiscountCodeIsPending
|
||||
"
|
||||
name="svg-spinners:180-ring-with-bg"
|
||||
size="20"
|
||||
class="**:fill-white"
|
||||
/>
|
||||
<span v-else> ثبت </span>
|
||||
<span v-else>
|
||||
{{ hasSubmittedDiscountCode ? "حذف" : "ثبت" }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -140,11 +140,11 @@ watch(
|
||||
{{ data.product.category }}
|
||||
</span>
|
||||
<div
|
||||
v-if="data.product.discount > 0"
|
||||
v-if="data.discount > 0"
|
||||
class="text-white bg-blue-500 px-3 lg:px-4 py-1.5 lg:py-2 text-[10px] lg:text-xs rounded-full flex items-center gap-1"
|
||||
>
|
||||
<Icon name="bi:percent" class="size-4" />
|
||||
{{ data.product.discount }}
|
||||
{{ data.discount }}
|
||||
تخفیف
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,15 +227,15 @@ watch(
|
||||
<div class="flex items-end gap-2">
|
||||
<div class="flex flex-col">
|
||||
<span
|
||||
v-if="data.product.discount > 0"
|
||||
v-if="data.discount > 0"
|
||||
class="typo-p-sm relative flex-center w-fit line-through"
|
||||
>
|
||||
{{ data.product.price }}
|
||||
{{ data.price }}
|
||||
</span>
|
||||
<span
|
||||
class="typo-p-xl relative flex-center w-fit font-medium"
|
||||
>
|
||||
{{ data.product.final_price }}
|
||||
{{ data.final_price }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -279,11 +279,17 @@ watch(
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="text-sm lg:text-[1.125rem] text-slate-900 font-semibold"
|
||||
>
|
||||
{{ data.product.price }}
|
||||
</span>
|
||||
<div class="flex flex-col">
|
||||
<span
|
||||
v-if="data.discount > 0"
|
||||
class="typo-p-xs relative flex-center w-fit line-through"
|
||||
>
|
||||
{{ data.price }}
|
||||
</span>
|
||||
<span class="typo-p-md relative flex-center w-fit font-medium">
|
||||
{{ data.final_price }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
@@ -15,7 +15,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
disabled: false,
|
||||
placeholder: "وارد نشده",
|
||||
});
|
||||
const { variant, error, modelValue } = toRefs(props);
|
||||
const { variant, error, modelValue, disabled } = toRefs(props);
|
||||
|
||||
// emits
|
||||
|
||||
@@ -38,6 +38,7 @@ const classes = computed(() => {
|
||||
{
|
||||
"input-solid": variant.value === "solid",
|
||||
"input-outlined": variant.value === "outlined",
|
||||
"pointer-events-none opacity-80 text-slate-500": disabled.value,
|
||||
"input-effects": !error.value,
|
||||
[variant.value === "solid"
|
||||
? "input-solid-error"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// imports
|
||||
|
||||
import { useMutation } from "@tanstack/vue-query";
|
||||
import { API_ENDPOINTS } from "~/constants";
|
||||
|
||||
const useDeleteDiscountCode = () => {
|
||||
// state
|
||||
|
||||
const { $axios: axios } = useNuxtApp();
|
||||
|
||||
// methods
|
||||
|
||||
const handleDeleteDiscountCode = async () => {
|
||||
const { data } = await axios.delete(
|
||||
API_ENDPOINTS.orders.cart.delete_discount
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
return useMutation({
|
||||
mutationFn: () => handleDeleteDiscountCode(),
|
||||
});
|
||||
};
|
||||
|
||||
export default useDeleteDiscountCode;
|
||||
@@ -0,0 +1,19 @@
|
||||
export const usePWA = () => {
|
||||
const isInstalledAsPWA = ref(false);
|
||||
|
||||
const checkPWAInstallation = () => {
|
||||
const isStandalone = window.matchMedia(
|
||||
"(display-mode: standalone)"
|
||||
).matches;
|
||||
const isIOSPWA = (window.navigator as any).standalone;
|
||||
isInstalledAsPWA.value = isStandalone || isIOSPWA;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
checkPWAInstallation();
|
||||
});
|
||||
|
||||
return {
|
||||
isInstalledAsPWA,
|
||||
};
|
||||
};
|
||||
@@ -50,6 +50,7 @@ export const API_ENDPOINTS = {
|
||||
delete_all: "/order/cart/all",
|
||||
add_one: "/order/cart/item",
|
||||
add_discount: "/order/cart/discount",
|
||||
delete_discount: "/order/cart/discount",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,50 +1,39 @@
|
||||
import { Workbox } from "workbox-window";
|
||||
import { usePWA } from "~/composables/global/usePwa";
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
const updateAvailable = ref(false);
|
||||
let wb: Workbox | null = null;
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
const { isInstalledAsPWA } = usePWA();
|
||||
|
||||
if ("serviceWorker" in navigator && isInstalledAsPWA.value) {
|
||||
wb = new Workbox("/sw.js");
|
||||
|
||||
const isStandalone = window.matchMedia(
|
||||
"(display-mode: standalone)"
|
||||
).matches;
|
||||
const isIOSPWA = (window.navigator as any).standalone;
|
||||
const isInstalledAsPWA = isStandalone || isIOSPWA;
|
||||
|
||||
// Listen for messages from the service worker
|
||||
navigator.serviceWorker.addEventListener("message", (event) => {
|
||||
if (
|
||||
event.data &&
|
||||
event.data.type === "VERSION_CHECK"
|
||||
) {
|
||||
checkForUpdate(event.data.version);
|
||||
}
|
||||
wb.addEventListener("waiting", () => {
|
||||
checkForUpdate();
|
||||
});
|
||||
|
||||
// Register the service worker and check if there's already a waiting one
|
||||
wb.register().then((registration: any) => {
|
||||
if (registration.waiting) {
|
||||
checkForUpdate();
|
||||
}
|
||||
});
|
||||
wb.register()
|
||||
.then((registration: any) => {
|
||||
if (registration.waiting) {
|
||||
checkForUpdate();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Service worker registration failed:", error);
|
||||
});
|
||||
}
|
||||
|
||||
// 🔹 Function to compare versions and show update modal if needed
|
||||
const checkForUpdate = (newVersion?: string) => {
|
||||
const currentVersion = localStorage.getItem("pwa_version");
|
||||
|
||||
if (newVersion && currentVersion !== newVersion) {
|
||||
updateAvailable.value = true;
|
||||
localStorage.setItem("pwa_version", newVersion);
|
||||
}
|
||||
const checkForUpdate = () => {
|
||||
updateAvailable.value = true;
|
||||
};
|
||||
|
||||
// 🔹 Function to apply the update
|
||||
const handleUpdate = () => {
|
||||
wb?.messageSW({ type: "SKIP_WAITING" });
|
||||
window.location.reload();
|
||||
if (wb) {
|
||||
wb.messageSW({ type: "SKIP_WAITING" }).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
Vendored
+5
-1
@@ -71,7 +71,7 @@ declare global {
|
||||
discount: number;
|
||||
color: string;
|
||||
video: string | null;
|
||||
cart_quantity : number;
|
||||
cart_quantity: number;
|
||||
};
|
||||
|
||||
type Product = {
|
||||
@@ -215,6 +215,10 @@ declare global {
|
||||
discount_amount: string;
|
||||
final_price: string;
|
||||
};
|
||||
discount: number;
|
||||
discount_amount: string;
|
||||
price: string;
|
||||
final_price: string;
|
||||
quantity: number;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user