merge with front and test clear cache build
@@ -265,32 +265,30 @@
|
||||
/* CONTAINER */
|
||||
|
||||
@utility container {
|
||||
@apply mx-auto;
|
||||
padding-inline: 1.5rem;
|
||||
max-width: 1380px;
|
||||
@apply mx-auto px-6;
|
||||
|
||||
@screen 2xs {
|
||||
padding-inline: 1rem;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
@screen xs {
|
||||
padding-inline: 1rem;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
@screen sm {
|
||||
padding-inline: 1rem;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
@screen md {
|
||||
padding-inline: 2rem;
|
||||
@apply px-8;
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
padding-inline: 3rem;
|
||||
@apply px-12;
|
||||
}
|
||||
|
||||
@screen xl {
|
||||
padding-inline: 5rem;
|
||||
@apply px-20;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,28 +37,20 @@ const { colorObject } = useImageColor(`#category-image-${id.value}`);
|
||||
/>
|
||||
|
||||
<div
|
||||
class="absolute z-20 bottom-0 p-4 md:p-6 flex items-end justify-between w-full"
|
||||
class="absolute z-20 bottom-0 p-4 md:p-6 flex items-center justify-between w-full"
|
||||
>
|
||||
|
||||
<div
|
||||
:class="
|
||||
colorObject?.isLight && !darkLayer
|
||||
? 'text-black'
|
||||
: 'text-white'
|
||||
"
|
||||
class="flex flex-col gap-2"
|
||||
:class="colorObject?.isLight && !darkLayer ? 'text-black': 'text-white'"
|
||||
class="typo-sub-h-sm md:typo-sub-h-md"
|
||||
>
|
||||
<div class="typo-sub-h-sm md:typo-sub-h-md">
|
||||
{{ category }}
|
||||
<span class="typo-p-xs -translate-y-1 inline-block mr-1">
|
||||
{{ count }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="typo-p-sm md:typo-p-md">محصولات ما را مشاهده کنید</span>
|
||||
{{ category }}
|
||||
</div>
|
||||
|
||||
|
||||
<Icon
|
||||
name="ci:arrow-left"
|
||||
class="mb-1 size-5 md:size-6"
|
||||
class="size-5 md:size-6"
|
||||
:class="
|
||||
colorObject?.isLight && !darkLayer
|
||||
? '**:stroke-black'
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
// imports
|
||||
|
||||
import { NAV_LINKS } from "~/constants";
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -125,6 +127,4 @@ import { NAV_LINKS } from "~/constants";
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
</template>
|
||||
@@ -11,35 +11,35 @@ type Highlight = {
|
||||
|
||||
const highlights = ref<Highlight[]>([
|
||||
{
|
||||
icon: "ci:headset",
|
||||
icon: "/img/footer-support.svg",
|
||||
title: "خدمات مشتری",
|
||||
description: "پشتیبانی استثنایی، راهحلهای پایدار برای شما عزیزان"
|
||||
description: "پشتیبانی استثنایی، راهحلهای پایدار برای شما"
|
||||
},
|
||||
{
|
||||
icon: "ci:delivery",
|
||||
icon: "/img/footer-send.svg",
|
||||
title: "ارسال سریع و رایگان",
|
||||
description: "ارسال رایگان برای سفارشهای بالای ۱۵۰ دلار و خورده"
|
||||
description: "ارسال رایگان برای سفارشهای بالای ۱۵۰ دلار"
|
||||
},
|
||||
{
|
||||
icon: "ci:users",
|
||||
icon: "/img/footer-share.svg",
|
||||
title: "معرفی به دوستان",
|
||||
description: "دوستان خود را معرفی کنید و هر دو ۱۵٪ تخفیف بگیرید"
|
||||
description: "ما را به دوستان خود معرفی کنید"
|
||||
},
|
||||
{
|
||||
icon: "ci:shield-done",
|
||||
icon: "/img/footer-security.svg",
|
||||
title: "پرداخت امن",
|
||||
description: "اطلاعات پرداخت شما بهصورت امن پردازش میشود"
|
||||
description: "پرداخت شما بهصورت امن پردازش میشود"
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="w-full border-t-[0.5px] border-slate-200 mt-20">
|
||||
<section class="w-full border-t-[0.5px] border-slate-200">
|
||||
<div class="w-full flex-center py-[5rem] gap-[1.25rem] container">
|
||||
<template v-for="(highlight, index) in highlights" :key="index">
|
||||
<div class="flex flex-col-center gap-[.75rem] w-1/4 px-5">
|
||||
|
||||
<Icon :name="highlight.icon" size="32px" />
|
||||
<img :src="highlight.icon" class="size-[90px]" alt="" />
|
||||
|
||||
<div class="w-full flex-col-center gap-[.25rem]">
|
||||
<span class="typo-sub-h-md text-black text-center">
|
||||
|
||||
@@ -106,7 +106,6 @@ const onSwiper = (swiper: SwiperClass) => {
|
||||
>
|
||||
<ProductCard
|
||||
:id="product.id"
|
||||
brand="برند محصول"
|
||||
:title="product.name"
|
||||
:picture="product.variants[0].images[0].image"
|
||||
:colors="product.colors"
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
|
||||
// types
|
||||
|
||||
type Props = {
|
||||
rate: number
|
||||
}
|
||||
|
||||
// props
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="typo-p-sm">
|
||||
{{ rate }}
|
||||
</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon
|
||||
v-for="i in Math.round(5 - rate)"
|
||||
name="ci:star-solid"
|
||||
class="size-4.5 **:fill-yellow-500"
|
||||
/>
|
||||
<Icon
|
||||
name="ci:star-solid"
|
||||
class="size-4.5 **:fill-yellow-500"
|
||||
/>
|
||||
<Icon
|
||||
name="ci:star-solid"
|
||||
class="size-4.5 **:fill-yellow-500"
|
||||
/>
|
||||
<Icon
|
||||
name="ci:star-solid"
|
||||
class="size-4.5 **:fill-yellow-500"
|
||||
class="size-4.5 **:fill-slate-300"
|
||||
/>
|
||||
<Icon
|
||||
v-for="i in Math.round(rate)"
|
||||
name="ci:star-solid"
|
||||
class="size-4.5 **:fill-yellow-500"
|
||||
/>
|
||||
</div>
|
||||
<span class="typo-p-sm">
|
||||
5.0
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -11,7 +11,6 @@ import { useImageColor } from "~/composables/global/useImageColor";
|
||||
|
||||
type Props = {
|
||||
id: number,
|
||||
brand: string;
|
||||
title: string;
|
||||
colors: string[];
|
||||
price: string;
|
||||
@@ -67,9 +66,9 @@ const { colorObject } = useImageColor(`#product-image-${id.value}`);
|
||||
>
|
||||
|
||||
<div class="flex flex-col gap-2 items-start w-full">
|
||||
<span class="typo-p-sm md:typo-p-md !font-medium">
|
||||
{{ brand }}
|
||||
</span>
|
||||
<!-- <span class="typo-p-sm md:typo-p-md !font-medium">-->
|
||||
<!-- {{ brand }}-->
|
||||
<!-- </span>-->
|
||||
<span class="typo-sub-h-md md:typo-sub-h-lg">
|
||||
{{ title }}
|
||||
</span>
|
||||
|
||||
@@ -57,11 +57,6 @@ watch(() => [shouldPauseVideos.value, swiper_instance.value?.realIndex], () => {
|
||||
// lifecycle
|
||||
|
||||
const initializeGsapAnimation = () => {
|
||||
gsap.to("#header-navbar", {
|
||||
background: "transparent",
|
||||
filter: "invert(100%)"
|
||||
});
|
||||
|
||||
gsapTimeline
|
||||
.fromTo(".header-slider-item", {
|
||||
borderRadius: 0,
|
||||
@@ -129,6 +124,10 @@ onMounted(() => {
|
||||
|
||||
setTimeout(() => {
|
||||
if (window.innerWidth > 768) {
|
||||
gsap.to("#header-navbar", {
|
||||
background: "transparent",
|
||||
filter: "invert(100%)"
|
||||
});
|
||||
scrollTrigger.enable();
|
||||
} else {
|
||||
resetTimelineForMobile();
|
||||
@@ -138,6 +137,10 @@ onMounted(() => {
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
if (window.innerWidth > 768) {
|
||||
gsap.to("#header-navbar", {
|
||||
background: "transparent",
|
||||
filter: "invert(100%)"
|
||||
});
|
||||
scrollTrigger.enable();
|
||||
} else {
|
||||
resetTimelineForMobile();
|
||||
@@ -148,8 +151,8 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
gsapTimeline.progress(1).pause();
|
||||
gsapTimeline.kill();
|
||||
resetTimelineForMobile();
|
||||
scrollTrigger.disable();
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -209,8 +212,7 @@ onUnmounted(() => {
|
||||
<div class="flex items-center gap-4 lg:gap-8">
|
||||
<div
|
||||
class="hover:scale-110 size-[36px] md:size-[42px] lg:size-[50px] relative flex items-center justify-center">
|
||||
<div
|
||||
class="size-full scale-75 bg-white absolute rounded-full animate-ping" />
|
||||
<div class="size-full scale-75 bg-white absolute rounded-full animate-ping" />
|
||||
<button
|
||||
@click="isMuted = !isMuted"
|
||||
class="transition-all cursor-pointer flex-center bg-white z-10 size-full rounded-full"
|
||||
@@ -252,7 +254,6 @@ onUnmounted(() => {
|
||||
v-for="(_slide, index) in homeData!.sliders"
|
||||
:class="swiper_instance?.realIndex === index ? 'bg-white' : 'bg-transparent'"
|
||||
class="border border-white size-2 md:size-3 rounded-full transition-all duration-200"
|
||||
@click="swiper_instance?.slideTo(index)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container max-w-[1000px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-col items-center gap-3 mb-10 lg:mb-16">
|
||||
<span class="typo-p-sm md:typo-p-md text-slate-500">مقایسه محصولات</span>
|
||||
<span class="typo-h-6 md:typo-h-5 lg:typo-h-3 text-black">
|
||||
@@ -55,7 +55,7 @@ watch(
|
||||
</div>
|
||||
<div
|
||||
ref="previewContainerEl"
|
||||
class="rounded-200 overflow-hidden h-[60svh] md:h-[70svh] relative"
|
||||
class="rounded-200 overflow-hidden h-[70svh] md:h-[80svh] relative"
|
||||
>
|
||||
<Transition name="fade">
|
||||
<img
|
||||
@@ -93,10 +93,10 @@ watch(
|
||||
:style="{
|
||||
left: `${clipPathPercent}%`,
|
||||
}"
|
||||
ref="draggableEl"
|
||||
class="select-none w-2 h-full bg-black absolute left-0 flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
ref="draggableEl"
|
||||
class="cursor-grab hover:scale-115 transition-transform rounded-full absolute bg-black size-11 flex items-center justify-center"
|
||||
>
|
||||
<Icon
|
||||
@@ -115,17 +115,23 @@ watch(
|
||||
<span class="typo-p-sm md:typo-p-md">
|
||||
{{ homeData!.difreance_section.description1 }}
|
||||
</span>
|
||||
<span class="typo-h-6 md:typo-h-5 lg:typo-h-3">
|
||||
<NuxtLink
|
||||
:to="homeData!.difreance_section.link1"
|
||||
class="typo-h-6 md:typo-h-5 lg:typo-h-3"
|
||||
>
|
||||
{{ homeData!.difreance_section.title1 }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 text-black">
|
||||
<span class="typo-p-sm md:typo-p-md text-end">
|
||||
{{ homeData!.difreance_section.description2 }}
|
||||
</span>
|
||||
<span class="typo-h-6 md:typo-h-5 lg:typo-h-3 text-end">
|
||||
<NuxtLink
|
||||
:to="homeData!.difreance_section.link2"
|
||||
class="typo-h-6 md:typo-h-5 lg:typo-h-3 text-end"
|
||||
>
|
||||
{{ homeData!.difreance_section.title2 }}
|
||||
</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -91,14 +91,13 @@ onUnmounted(() => {
|
||||
id="products-showcase-container"
|
||||
class="mt-80 mb-40 perspective-midrange w-full h-[125svh] bg-black flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
<NuxtLink
|
||||
v-for="slide in homeData!.show_case_slider"
|
||||
:key="slide.id"
|
||||
:to="slide.link"
|
||||
class="showcase-slide origin-bottom absolute size-full bg-transparent flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="blur-[150px] w-[400px] sm:w-[600px] h-[80px] sm:h-[80px] bg-white/70 absolute z-10"
|
||||
/>
|
||||
|
||||
<img
|
||||
class="w-[280px] xs:w-[350px] lg:w-[500px] xl:w-[650px] z-20 mb-30 sm:mb-20 lg:mb-30"
|
||||
:src="slide.image"
|
||||
@@ -115,6 +114,6 @@ onUnmounted(() => {
|
||||
{{ slide.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
@@ -5,5 +5,3 @@
|
||||
<NuxtPage />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
// import
|
||||
|
||||
import { helpers, required } from "@vuelidate/validators";
|
||||
@@ -20,11 +21,13 @@ type LoginInfo = {
|
||||
// meta
|
||||
|
||||
definePageMeta({
|
||||
middleware: ["check-is-not-logged-in"],
|
||||
middleware: ["check-is-not-logged-in"]
|
||||
});
|
||||
|
||||
// state
|
||||
|
||||
const { $gsap: gsap } = useNuxtApp();
|
||||
|
||||
const { addToast } = useToast();
|
||||
|
||||
const { updateToken, updateRefreshToken } = useAuth();
|
||||
@@ -41,13 +44,13 @@ const formRules = computed(() => {
|
||||
phoneValidator: helpers.withMessage(
|
||||
"شماره تلفن وارد شده معتبر نمی باشد",
|
||||
helpers.regex(/^[1-9][0-9]{9}$/)
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const loginInfo = ref<LoginInfo>({
|
||||
phone: "",
|
||||
phone: ""
|
||||
});
|
||||
|
||||
const formValidator$ = useVuelidate(formRules, loginInfo);
|
||||
@@ -56,16 +59,16 @@ const {
|
||||
timer: otpBlockerTimePassed,
|
||||
start: startOtpBlocker,
|
||||
reset: resetOtpBlocker,
|
||||
isPending: isResendOtpBlocked,
|
||||
isPending: isResendOtpBlocked
|
||||
} = useTimer({
|
||||
duration: 5000,
|
||||
duration: 5000
|
||||
});
|
||||
|
||||
const { mutateAsync: sendOtp, isPending: sendOtpIsPending } = useOtp();
|
||||
const {
|
||||
mutateAsync: signIn,
|
||||
isPending: signInIsPending,
|
||||
status: signInStatus,
|
||||
status: signInStatus
|
||||
} = useSignIn();
|
||||
|
||||
// computed
|
||||
@@ -74,14 +77,14 @@ const sendOtpHandler = async () => {
|
||||
if (!sendOtpIsPending.value) {
|
||||
try {
|
||||
await sendOtp({
|
||||
phone: `0${loginInfo.value.phone}`,
|
||||
phone: `0${loginInfo.value.phone}`
|
||||
});
|
||||
|
||||
addToast({
|
||||
message: "کد برای شما ارسال شد",
|
||||
options: {
|
||||
status: "success",
|
||||
},
|
||||
status: "success"
|
||||
}
|
||||
});
|
||||
|
||||
showOtp.value = true;
|
||||
@@ -89,8 +92,8 @@ const sendOtpHandler = async () => {
|
||||
addToast({
|
||||
message: "مشکلی پیش آمده",
|
||||
options: {
|
||||
status: "error",
|
||||
},
|
||||
status: "error"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -107,7 +110,7 @@ const handleLogin = async () => {
|
||||
try {
|
||||
const response = await signIn({
|
||||
otp: otpCode.value.join(""),
|
||||
phone: `0${loginInfo.value.phone}`,
|
||||
phone: `0${loginInfo.value.phone}`
|
||||
});
|
||||
|
||||
updateToken(response.access);
|
||||
@@ -118,8 +121,8 @@ const handleLogin = async () => {
|
||||
addToast({
|
||||
message: "با موفقیت وارد شدید",
|
||||
options: {
|
||||
status: "success",
|
||||
},
|
||||
status: "success"
|
||||
}
|
||||
});
|
||||
|
||||
navigateTo("/");
|
||||
@@ -146,93 +149,129 @@ const resetForm = () => {
|
||||
otpCode.value = [];
|
||||
showOtp.value = false;
|
||||
};
|
||||
|
||||
// const onMouseMove = (e: MouseEvent) => {
|
||||
// const heylmzEyesElement = document.querySelector("#heylmz-eyes") as HTMLDivElement;
|
||||
// const boundry = heylmzEyesElement.getBoundingClientRect();
|
||||
//
|
||||
// console.log(e.clientX, heylmzEyesElement.clientWidth, boundry.left, e.clientX - heylmzEyesElement.clientWidth);
|
||||
//
|
||||
// const moveX = e.clientX - heylmzEyesElement.clientWidth + 60;
|
||||
// const moveY = e.clientY - heylmzEyesElement.clientHeight - 155;
|
||||
//
|
||||
// gsap.to("#heylmz-eyes", {
|
||||
// x: moveX,
|
||||
// y: moveY
|
||||
// });
|
||||
// };
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="container min-h-[700px] flex flex-col items-center justify-center"
|
||||
>
|
||||
<h1 class="typo-hero-2">فرم ورود</h1>
|
||||
<form @submit.prevent class="max-w-[500px] w-full mt-12">
|
||||
<div v-if="!showOtp" class="flex items-center gap-2 w-full">
|
||||
<Input
|
||||
data-testid="phone-input"
|
||||
class="w-full"
|
||||
v-model="loginInfo.phone"
|
||||
placeholder="9380123456"
|
||||
dir="ltr"
|
||||
:error="formValidator$.phone.$error"
|
||||
>
|
||||
<template #startItem>
|
||||
<span class="text-slate-500"> +98 </span>
|
||||
</template>
|
||||
</Input>
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon
|
||||
class="translate-y-[-1px]"
|
||||
name="twemoji:flag-iran"
|
||||
size="24"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-svh items-center relative">
|
||||
<div
|
||||
class="bg-[url(/img/pattern-1.png)] -z-10 size-full absolute opacity-70"
|
||||
:style="{
|
||||
backgroundSize: 150,
|
||||
mask: 'linear-gradient(to bottom, black 0%, rgba(0,0,0,0.3) 80%)'
|
||||
}"
|
||||
/>
|
||||
<div class="flex items-center justify-center flex-col size-full">
|
||||
|
||||
<OtpInput
|
||||
v-else
|
||||
v-model="otpCode"
|
||||
:status="
|
||||
signInStatus === 'success'
|
||||
? 'success'
|
||||
: signInStatus === 'error'
|
||||
? 'error'
|
||||
: 'idle'
|
||||
"
|
||||
:disabled="signInIsPending || sendOtpIsPending"
|
||||
:autofocus="true"
|
||||
@complete="handleLogin"
|
||||
<img
|
||||
id="heylmz-eyes"
|
||||
class="aspect-square w-[300px] translate-y-[100px]"
|
||||
src="/img/heymlz-seat.gif"
|
||||
alt=""
|
||||
/>
|
||||
|
||||
<Button
|
||||
data-testid="send-otp-code-button"
|
||||
v-if="!showOtp"
|
||||
class="rounded-full w-full mt-4"
|
||||
type="submit"
|
||||
@click="handleLogin"
|
||||
:loading="sendOtpIsPending"
|
||||
:disabled="sendOtpIsPending"
|
||||
<div
|
||||
class="max-w-[600px] w-full p-6 h-[400px] flex flex-col items-center bg-white border shadow-black/10 justify-center border-slate-300 rounded-xl"
|
||||
>
|
||||
ارسال کد
|
||||
</Button>
|
||||
<h1 class="typo-hero-2 mt-8">فرم ورود</h1>
|
||||
|
||||
<div v-else class="flex items-center w-full gap-4 mt-4">
|
||||
<Button
|
||||
class="rounded-full w-full mt-4"
|
||||
type="button"
|
||||
variant="secondary"
|
||||
@click="resetForm"
|
||||
:disabled="signInIsPending || sendOtpIsPending"
|
||||
>
|
||||
تغییر شماره
|
||||
</Button>
|
||||
<Button
|
||||
class="rounded-full w-full mt-4"
|
||||
type="submit"
|
||||
@click="resendOtp"
|
||||
:loading="signInIsPending || sendOtpIsPending"
|
||||
:disabled="
|
||||
<form @submit.prevent class="max-w-[500px] w-full mt-12">
|
||||
<div v-if="!showOtp" class="flex items-center gap-2 w-full">
|
||||
<Input
|
||||
data-testid="phone-input"
|
||||
class="w-full"
|
||||
v-model="loginInfo.phone"
|
||||
placeholder="9380123456"
|
||||
dir="ltr"
|
||||
:error="formValidator$.phone.$error"
|
||||
>
|
||||
<template #startItem>
|
||||
<span class="text-slate-500"> +98 </span>
|
||||
</template>
|
||||
</Input>
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon
|
||||
class="translate-y-[-1px]"
|
||||
name="twemoji:flag-iran"
|
||||
size="24"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<OtpInput
|
||||
v-else
|
||||
v-model="otpCode"
|
||||
:status="
|
||||
signInStatus === 'success'
|
||||
? 'success'
|
||||
: signInStatus === 'error'
|
||||
? 'error'
|
||||
: 'idle'
|
||||
"
|
||||
:disabled="signInIsPending || sendOtpIsPending"
|
||||
:autofocus="true"
|
||||
@complete="handleLogin"
|
||||
/>
|
||||
|
||||
<Button
|
||||
data-testid="send-otp-code-button"
|
||||
v-if="!showOtp"
|
||||
class="rounded-full w-full mt-4"
|
||||
type="submit"
|
||||
@click="handleLogin"
|
||||
:loading="sendOtpIsPending"
|
||||
:disabled="sendOtpIsPending"
|
||||
>
|
||||
ارسال کد
|
||||
</Button>
|
||||
|
||||
<div v-else class="flex items-center w-full gap-4 mt-4">
|
||||
<Button
|
||||
class="rounded-full w-full mt-4"
|
||||
type="button"
|
||||
variant="secondary"
|
||||
@click="resetForm"
|
||||
:disabled="signInIsPending || sendOtpIsPending"
|
||||
>
|
||||
تغییر شماره
|
||||
</Button>
|
||||
<Button
|
||||
class="rounded-full w-full mt-4"
|
||||
type="submit"
|
||||
@click="resendOtp"
|
||||
:loading="signInIsPending || sendOtpIsPending"
|
||||
:disabled="
|
||||
signInIsPending ||
|
||||
isResendOtpBlocked ||
|
||||
sendOtpIsPending
|
||||
"
|
||||
>
|
||||
ارسال مجدد کد
|
||||
{{ isResendOtpBlocked ? otpBlockerTimePassed : "" }}
|
||||
</Button>
|
||||
</div>
|
||||
>
|
||||
ارسال مجدد کد
|
||||
{{ isResendOtpBlocked ? otpBlockerTimePassed : "" }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 justify-center mt-6">
|
||||
<span> بازگشت به فروشگاه </span>
|
||||
<Icon name="ci:left-rotation" size="24" />
|
||||
<NuxtLink to="/" class="flex items-center gap-2 justify-center mt-6">
|
||||
<span> بازگشت به فروشگاه </span>
|
||||
<Icon name="ci:left-rotation" size="24" />
|
||||
</NuxtLink>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
Before Width: | Height: | Size: 806 KiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 606 KiB |
|
Before Width: | Height: | Size: 917 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.0 MiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 261 KiB |
|
Before Width: | Height: | Size: 344 KiB |
|
Before Width: | Height: | Size: 421 KiB |
|
Before Width: | Height: | Size: 648 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 2.3 MiB |
@@ -5,7 +5,7 @@ precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
// Version
|
||||
|
||||
const VERSION = "1.0.911";
|
||||
const VERSION = "1.0.9112";
|
||||
|
||||
// Service Worker Installation
|
||||
self.addEventListener("install", (event) => {
|
||||
|
||||