Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -1,7 +1,59 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
address?: Address;
|
||||||
|
isSelected?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
// emit
|
||||||
|
|
||||||
|
const emit = defineEmits(["select"]);
|
||||||
|
|
||||||
|
// computed
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<button
|
||||||
|
@click="!!address ? emit('select', address) : null"
|
||||||
|
:class="
|
||||||
|
isSelected
|
||||||
|
? 'border-cyan-500 ring-2 ring-offset-2 ring-cyan-500'
|
||||||
|
: 'border-gray-300'
|
||||||
|
"
|
||||||
|
class="flex flex-col items-center transition-all cursor-pointer w-full gap-4 p-4 border rounded-xl bg-gray-50"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-start w-full lg:text-[1.125rem] font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
آدرس
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center justify-between w-full gap-4 lg:flex-row"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="w-full text-start text-sm lg:text-[1rem] lg:w-9/12 text-gray-700"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
!!address
|
||||||
|
? `ایران, ${address.province}, ${address.city}, ${address.full_address}, کدپستی ${address.postal_code}`
|
||||||
|
: "افزودن آدرس جدید"
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end w-full lg:w-3/12">
|
||||||
|
<AddressModal
|
||||||
|
@add="(data) => $emit('add', data)"
|
||||||
|
:address="address"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
address?: Address;
|
||||||
|
};
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const { address } = toRefs(props);
|
||||||
|
|
||||||
|
// emit
|
||||||
|
|
||||||
|
const emit = defineEmits(["add"]);
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const isShow = ref(false);
|
||||||
|
|
||||||
|
const addressData = ref<
|
||||||
|
Pick<Address, "province" | "city" | "postal_code" | "full_address">
|
||||||
|
>({
|
||||||
|
province: address.value?.province ?? "",
|
||||||
|
city: address.value?.city ?? "",
|
||||||
|
postal_code: address.value?.postal_code ?? "",
|
||||||
|
full_address: address.value?.full_address ?? "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// computed
|
||||||
|
|
||||||
|
const isEditing = computed(() => !!address.value);
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
if (!isEditing.value) {
|
||||||
|
addressData.value = {
|
||||||
|
province: "",
|
||||||
|
city: "",
|
||||||
|
postal_code: "",
|
||||||
|
full_address: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
isShow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNew = () => {
|
||||||
|
emit("add", { ...addressData.value, id: Date.now() });
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogRoot
|
||||||
|
v-model:open="isShow"
|
||||||
|
@update:open="
|
||||||
|
(state) => {
|
||||||
|
!state ? closeModal() : null;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<DialogTrigger>
|
||||||
|
<button
|
||||||
|
class="flex items-center gap-1 rtl:flex-row-reverse font-iran-yekan-x cursor-pointer"
|
||||||
|
>
|
||||||
|
<span class="font-bold text-cyan-500 text-sm lg:text-[1rem]">
|
||||||
|
{{ !!address ? "ویرایش آدرس" : "افزودن آدرس" }}
|
||||||
|
</span>
|
||||||
|
<Icon
|
||||||
|
v-if="!!address"
|
||||||
|
name="bi:pen"
|
||||||
|
class="**:fill-cyan-500"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-else
|
||||||
|
name="bi:plus"
|
||||||
|
class="**:stroke-cyan-500"
|
||||||
|
size="20"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay
|
||||||
|
class="bg-black/20 data-[state=open]:animate-overlay-show fixed inset-0 z-30"
|
||||||
|
/>
|
||||||
|
<DialogContent
|
||||||
|
class="data-[state=open]:animate-content-show text-black font-iran-yekan-x fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[50rem] translate-x-[-50%] translate-y-[-50%] rounded-3xl bg-white shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none z-[100]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-full flex items-center px-6 justify-between py-[1.8rem] border-b border-slate-200"
|
||||||
|
>
|
||||||
|
<DialogClose
|
||||||
|
class="inline-flex size-8 items-center justify-center transition-all rounded-full bg-gray-50 border border-slate-200 hover:border-black focus:outline-none"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<Icon name="bi:x-lg" class="**:fill-red-600" />
|
||||||
|
</DialogClose>
|
||||||
|
<DialogTitle class="typo-sub-h-xl font-semibold">
|
||||||
|
{{ !!address ? "ویرایش آدرس" : "افزودن آدرس" }}
|
||||||
|
</DialogTitle>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-col-center gap-6 px-6 py-10" dir="rtl">
|
||||||
|
<div
|
||||||
|
class="grid w-full grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<label
|
||||||
|
for="province"
|
||||||
|
class="text-xs font-semibold lg:text-sm text-gray-900"
|
||||||
|
>استان
|
||||||
|
<span class="text-sm text-red-500"
|
||||||
|
>*</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
|
||||||
|
<ComboBox
|
||||||
|
id="province"
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
name: 'استان ها',
|
||||||
|
children: [
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
v-model="addressData.province"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<label
|
||||||
|
for="city"
|
||||||
|
class="text-xs font-semibold lg:text-sm text-gray-900"
|
||||||
|
>شهر
|
||||||
|
<span class="text-sm text-red-500"
|
||||||
|
>*</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
<ComboBox
|
||||||
|
id="city"
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
name: 'استان ها',
|
||||||
|
children: [
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
{ name: 'مشهد' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
v-model="addressData.city"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<label
|
||||||
|
for="post"
|
||||||
|
class="text-xs font-semibold lg:text-sm text-gray-900"
|
||||||
|
>کد پستی
|
||||||
|
<span class="text-sm text-red-500"
|
||||||
|
>*</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
id="post"
|
||||||
|
type="text"
|
||||||
|
placeholder="جست و جو"
|
||||||
|
class="rounded-xl"
|
||||||
|
v-model="addressData.postal_code"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col w-full gap-2">
|
||||||
|
<label
|
||||||
|
for="address"
|
||||||
|
class="text-xs font-semibold lg:text-sm text-gray-900"
|
||||||
|
>آدرس کامل
|
||||||
|
<span class="text-sm text-red-500">*</span></label
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
id="address"
|
||||||
|
placeholder="آدرس خود را بنویسید"
|
||||||
|
v-model="addressData.full_address"
|
||||||
|
class="flex items-center field-sizing-content resize-none bg-slate-50 border-slate-200 hover:border-black max-h-[10rem] text-black justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-3.5 selection:bg-slate-100 rounded-100 outline-none flex-1 text-sm placeholder-slate-400"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6 border-t border-slate-200 flex gap-3">
|
||||||
|
<Button @click="addNew" class="rounded-full px-10"
|
||||||
|
>ثبت</Button
|
||||||
|
>
|
||||||
|
<DialogClose aria-label="Close">
|
||||||
|
<Button variant="outlined" class="rounded-full px-10">
|
||||||
|
انصراف
|
||||||
|
</Button>
|
||||||
|
</DialogClose>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</DialogPortal>
|
||||||
|
</DialogRoot>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -17,7 +17,7 @@ const handleDeleteFromCart = () => {};
|
|||||||
class="size-[88px] aspect-square shrink-0 rounded-100 border border-gray-300 overflow-hidden"
|
class="size-[88px] aspect-square shrink-0 rounded-100 border border-gray-300 overflow-hidden"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="../assets/images/products/product-1.png"
|
src="/img/product-1.jpg"
|
||||||
class="object-cover size-full"
|
class="object-cover size-full"
|
||||||
alt="product"
|
alt="product"
|
||||||
/>
|
/>
|
||||||
@@ -47,13 +47,13 @@ const handleDeleteFromCart = () => {};
|
|||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="counter == 1"
|
v-if="counter == 1"
|
||||||
name="bi:dash"
|
name="bi:trash"
|
||||||
class="**:stroke-gray-800"
|
class="**:fill-red-700"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
v-else
|
v-else
|
||||||
name="bi:trash"
|
name="bi:dash"
|
||||||
class="**:fill-red-700"
|
class="**:stroke-gray-800"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div class="flex items-center w-full gap-4">
|
||||||
|
<div
|
||||||
|
class="size-[3.5rem] shrink-0 rounded-100 border border-gray-300 overflow-hidden"
|
||||||
|
>
|
||||||
|
<img src="/img/product-1.jpg" alt="product" class="object-conver" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="text-xs font-semibold lg:text-sm text-gray-800 line-clamp-2"
|
||||||
|
>
|
||||||
|
فشارسنج بازویی امرن Omron M3
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ type Option = {
|
|||||||
type Props = {
|
type Props = {
|
||||||
options: Option[];
|
options: Option[];
|
||||||
modelValue: string[];
|
modelValue: string[];
|
||||||
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// props
|
// props
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
placeholder: "جست و جو",
|
||||||
|
});
|
||||||
|
|
||||||
const { modelValue } = toRefs(props);
|
const { modelValue } = toRefs(props);
|
||||||
|
|
||||||
@@ -48,11 +51,11 @@ watch(
|
|||||||
<template>
|
<template>
|
||||||
<ComboboxRoot class="relative" dir="rtl" v-model="value">
|
<ComboboxRoot class="relative" dir="rtl" v-model="value">
|
||||||
<ComboboxAnchor
|
<ComboboxAnchor
|
||||||
class="w-full inline-flex items-center justify-between rounded-full border border-slate-200 hover:border-slate-300 focus:border-slate-800 px-[1rem] text-sm leading-none py-3.5 gap-[5px] bg-slate-50 text-black hover:bg-white/90 transition-all data-[placeholder]:text-black/80 typo-label-sm outline-none"
|
class="w-full inline-flex items-center justify-between rounded-xl border-[1.5px] border-slate-200 focus:border-slate-800 px-[1rem] text-sm leading-none py-3.5 gap-[5px] bg-slate-50 text-black hover:border-black transition-all data-[placeholder]:text-black/80 typo-label-sm outline-none"
|
||||||
>
|
>
|
||||||
<ComboboxInput
|
<ComboboxInput
|
||||||
class="!bg-transparent outline-none text-black h-full selection:bg-slate-100 placeholder-stone-400"
|
class="!bg-transparent outline-none text-black h-full selection:bg-slate-100 placeholder-slate-400"
|
||||||
placeholder="جست و جوی دسته بندی"
|
:placeholder="placeholder"
|
||||||
/>
|
/>
|
||||||
<ComboboxTrigger>
|
<ComboboxTrigger>
|
||||||
<Icon name="ci:chevron-down" class="size-5" />
|
<Icon name="ci:chevron-down" class="size-5" />
|
||||||
@@ -60,7 +63,7 @@ watch(
|
|||||||
</ComboboxAnchor>
|
</ComboboxAnchor>
|
||||||
|
|
||||||
<ComboboxContent
|
<ComboboxContent
|
||||||
class="absolute z-10 w-full mt-1.5 bg-slate-50 overflow-hidden rounded-3xl shadow-sm border border-slate-200 will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=bottom]:animate-slideUpAndFade"
|
class="absolute z-10 w-full mt-1.5 bg-slate-50 overflow-hidden rounded-xl shadow-sm border border-slate-200 will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=bottom]:animate-slideUpAndFade"
|
||||||
>
|
>
|
||||||
<ComboboxViewport class="p-[1rem]">
|
<ComboboxViewport class="p-[1rem]">
|
||||||
<ComboboxEmpty
|
<ComboboxEmpty
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variant?: "solid" | "outlined";
|
variant?: "solid" | "outlined";
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@@ -12,7 +11,7 @@ type Props = {
|
|||||||
// props
|
// props
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
variant: "solid"
|
variant: "solid",
|
||||||
});
|
});
|
||||||
const { variant, message, error, disabled } = toRefs(props);
|
const { variant, message, error, disabled } = toRefs(props);
|
||||||
|
|
||||||
@@ -28,15 +27,15 @@ const inputRef = ref<HTMLInputElement | null>(null);
|
|||||||
|
|
||||||
const classes = computed(() => {
|
const classes = computed(() => {
|
||||||
return [
|
return [
|
||||||
"flex items-center justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-3 rounded-100",
|
"flex items-center text-black justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-3.5 selection:bg-slate-100 rounded-100",
|
||||||
{
|
{
|
||||||
"input-solid": variant.value === "solid",
|
"input-solid": variant.value === "solid",
|
||||||
"input-outlined": variant.value === "outlined",
|
"input-outlined": variant.value === "outlined",
|
||||||
"input-effects": !error.value,
|
"input-effects": !error.value,
|
||||||
[variant.value === "solid"
|
[variant.value === "solid"
|
||||||
? "input-solid-error"
|
? "input-solid-error"
|
||||||
: "input-outlined-error"]: error.value
|
: "input-outlined-error"]: error.value,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -45,7 +44,6 @@ const classes = computed(() => {
|
|||||||
const onInput = (e: any) => {
|
const onInput = (e: any) => {
|
||||||
emit("update:modelValue", e.target.value);
|
emit("update:modelValue", e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -56,7 +54,7 @@ const onInput = (e: any) => {
|
|||||||
:value="modelValue"
|
:value="modelValue"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
class="outline-none flex-1"
|
class="outline-none flex-1 text-sm placeholder-slate-400"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const onSwiper = (swiper: SwiperClass) => {
|
|||||||
<template>
|
<template>
|
||||||
<section class="w-full flex flex-col gap-[4rem] px-0 py-[5rem] container">
|
<section class="w-full flex flex-col gap-[4rem] px-0 py-[5rem] container">
|
||||||
<div class="w-full flex justify-between items-center">
|
<div class="w-full flex justify-between items-center">
|
||||||
<span class="text-black typo-h-3">
|
<span class="text-black typo-h-4">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
<div class="flex-center gap-[.5rem]">
|
<div class="flex-center gap-[.5rem]">
|
||||||
|
|||||||
@@ -95,6 +95,22 @@ const nextPage = computed(() => route.meta.nextPage);
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label
|
||||||
|
v-if="route.name == 'cart-checkout'"
|
||||||
|
class="flex items-center w-full group gap-2 p-3 my-5 text-sm transition-all border text-gray-600 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-cyan-500 bg-gray-50 border-gray-200 rounded-100"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="کد تخفیف"
|
||||||
|
class="w-full border-none focus:border-none focus:outline-none placeholder:text-gray-600 h-[22px]"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="ring ring-offset-[-4px] active:ring-offset-2 transition-all duration-75 font-bold text-cyan-500 rounded-50"
|
||||||
|
>
|
||||||
|
ثبت
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
|
||||||
<NuxtLink :to="{ name: nextPage.name }">
|
<NuxtLink :to="{ name: nextPage.name }">
|
||||||
<Button
|
<Button
|
||||||
start-icon="bi:arrow-right"
|
start-icon="bi:arrow-right"
|
||||||
|
|||||||
@@ -1,14 +1,116 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// meta
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "cart",
|
layout: "cart",
|
||||||
pageTitle: "ثبت سفارش",
|
pageTitle: "ثبت سفارش",
|
||||||
prevPage: { name: "cart-delivery", label: "انتخاب آدرس" },
|
prevPage: { name: "cart-delivery", label: "انتخاب آدرس" },
|
||||||
nextPage: { name: "checkout", label: "پرداخت" },
|
nextPage: { name: "checkout", label: "پرداخت" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type PaymentGateway = {
|
||||||
|
id: number;
|
||||||
|
picture: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const paymentGateways = ref<PaymentGateway[]>([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
picture: "/zarinpal.png",
|
||||||
|
title: "زرین پال",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
picture: "/saman-bank.png",
|
||||||
|
title: "بانک سامان",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
picture: "/mellat-bank.png",
|
||||||
|
title: "بانک ملت",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
picture: "/jibimo.png",
|
||||||
|
title: "جیبی مو",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
picture: "/idpay.png",
|
||||||
|
title: "آی دی پی",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const selectedGateway = ref<PaymentGateway>(paymentGateways.value[0]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div class="flex flex-col w-full gap-5">
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center w-full gap-4 p-4 border border-gray-300 rounded-xl bg-gray-50"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-start w-full text-[1.125rem] font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
روش پرداخت
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="w-full grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(gateway, index) in paymentGateways"
|
||||||
|
@click="selectedGateway = { ...gateway }"
|
||||||
|
:key="index"
|
||||||
|
:class="
|
||||||
|
selectedGateway.id == gateway.id
|
||||||
|
? 'ring-2 ring-offset-2 ring-cyan-500 border-cyan-500'
|
||||||
|
: 'border-slate-200'
|
||||||
|
"
|
||||||
|
class="w-full p-5 border rounded-xl flex flex-col gap-4 transition-all cursor-pointer"
|
||||||
|
>
|
||||||
|
<div class="aspect-square flex-center">
|
||||||
|
<img :src="gateway.picture" class="object-cover" />
|
||||||
|
</div>
|
||||||
|
<span class="typo-label-sm text-black">
|
||||||
|
{{ gateway.title }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center w-full gap-4 p-4 border lg:gap-6 border-gray-300 rounded-xl bg-gray-50"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-start w-full lg:text-[1.125rem] font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
خلاصه سفارش
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="grid w-full grid-cols-1 gap-6 lg:grid-cols-3 md:grid-cols-2"
|
||||||
|
>
|
||||||
|
<MinimalCartItem v-for="i in 9" />
|
||||||
|
|
||||||
|
<div class="h-7 flex-center col-span-full lg:hidden">
|
||||||
|
<button class="gap-2 flex-center">
|
||||||
|
<span class="text-sm font-bold text-cyan-500">
|
||||||
|
مشاهده بیشتر
|
||||||
|
</span>
|
||||||
|
<Icon
|
||||||
|
name="bi:chevron-down"
|
||||||
|
class="**:stroke-cyan-500"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -1,14 +1,178 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// meta
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "cart",
|
layout: "cart",
|
||||||
pageTitle: "انتخاب آدرس",
|
pageTitle: "انتخاب آدرس",
|
||||||
prevPage: { name: "cart", label: "سبد خرید" },
|
prevPage: { name: "cart", label: "سبد خرید" },
|
||||||
nextPage: { name: "cart-checkout", label: "تسویه حساب" },
|
nextPage: { name: "cart-checkout", label: "تسویه حساب" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type DeliveryData = {
|
||||||
|
address: Address | null;
|
||||||
|
deliveryMethod: {
|
||||||
|
tipax: boolean;
|
||||||
|
pishtaz: boolean;
|
||||||
|
peyk: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const addresses = ref<Address[]>([]);
|
||||||
|
|
||||||
|
const deliveryData = ref<DeliveryData>({
|
||||||
|
address: null,
|
||||||
|
deliveryMethod: {
|
||||||
|
peyk: false,
|
||||||
|
pishtaz: true,
|
||||||
|
tipax: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const handleAddNewAddress = (address: Address) => {
|
||||||
|
addresses.value.push(address);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectAddress = (address: Address) => {
|
||||||
|
deliveryData.value.address = { ...address };
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col w-full gap-6"></div>
|
<div class="flex flex-col w-full gap-5">
|
||||||
|
<AddressItem @add="handleAddNewAddress" />
|
||||||
|
<div v-if="addresses.length > 0" class="flex flex-col w-full gap-6">
|
||||||
|
<span class="typo-sub-h-xl"> آدرس های شما </span>
|
||||||
|
<div class="flex flex-col gap-6 w-full">
|
||||||
|
<AddressItem
|
||||||
|
v-for="(address, index) in addresses"
|
||||||
|
:key="index"
|
||||||
|
:address="address"
|
||||||
|
@select="handleSelectAddress"
|
||||||
|
:isSelected="address.id == deliveryData.address?.id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center w-full gap-4 p-4 border border-gray-300 rounded-xl bg-gray-50"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-start w-full lg:text-[1.125rem] font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
زمان و شیوه ارسال
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<label
|
||||||
|
@click="deliveryData.deliveryMethod.pishtaz = true"
|
||||||
|
:class="
|
||||||
|
deliveryData.deliveryMethod.pishtaz
|
||||||
|
? 'ring-cyan-500 ring-offset-2 ring-2'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
class="flex flex-col select-none w-full gap-2 p-3 transition-all border cursor-pointer delivery-option focus-within:ring-2 ring-cyan-500 ring-offset-2 focus-within:border-cyan-500 rounded-100 border-gray-300 bg-gray-50"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between w-full">
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<SwitchRoot
|
||||||
|
v-model="deliveryData.deliveryMethod.pishtaz"
|
||||||
|
:defaultValue="false"
|
||||||
|
class="w-[3rem] h-[1.8rem] shrink-0 flex data-[state=unchecked]:bg-slate-200 data-[state=checked]:bg-cyan-500 border border-slate-300 data-[state=checked]:border-cyan-800/20 rounded-full relative transition-all focus-within:outline-none"
|
||||||
|
>
|
||||||
|
<SwitchThumb
|
||||||
|
class="size-6 my-auto bg-white text-sm ms-1 flex items-center justify-center shadow-xl rounded-full transition-transform translate-x-0.5 will-change-transform data-[state=checked]:-translate-x-[68%]"
|
||||||
|
/>
|
||||||
|
</SwitchRoot>
|
||||||
|
<span
|
||||||
|
class="w-full text-gray-800 text-sm lg:text-[1rem]"
|
||||||
|
>پست پیشتاز</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="text-gray-800 text-sm lg:text-[1rem]">
|
||||||
|
۱۵۰٬۰۰۰ تومان
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label
|
||||||
|
class="flex items-center opacity-50 select-none pointer-events-none justify-between w-full p-3 transition-all border cursor-pointer delivery-option focus-within:ring-2 ring-cyan-500 ring-offset-2 focus-within:border-cyan-500 rounded-100 border-gray-300 bg-gray-50"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<SwitchRoot
|
||||||
|
v-model="deliveryData.deliveryMethod.tipax"
|
||||||
|
class="w-[3rem] h-[1.8rem] shrink-0 flex data-[state=unchecked]:bg-slate-200 data-[state=checked]:bg-cyan-500 border border-slate-300 data-[state=checked]:border-cyan-800/20 rounded-full relative transition-all focus-within:outline-none"
|
||||||
|
>
|
||||||
|
<SwitchThumb
|
||||||
|
class="size-6 my-auto bg-white text-sm ms-1 flex items-center justify-center shadow-xl rounded-full transition-transform translate-x-0.5 will-change-transform data-[state=checked]:-translate-x-[68%]"
|
||||||
|
/>
|
||||||
|
</SwitchRoot>
|
||||||
|
<span class="w-full text-gray-800 text-sm lg:text-[1rem]"
|
||||||
|
>تیپاکس</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="text-gray-800 text-sm lg:text-[1rem]">
|
||||||
|
۱۵۰٬۰۰۰ تومان
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label
|
||||||
|
class="flex items-center opacity-50 select-none pointer-events-none justify-between w-full p-3 transition-all border cursor-pointer delivery-option focus-within:ring-2 ring-cyan-500 ring-offset-2 focus-within:border-cyan-500 rounded-100 border-gray-300 bg-gray-50"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<SwitchRoot
|
||||||
|
v-model="deliveryData.deliveryMethod.peyk"
|
||||||
|
class="w-[3rem] h-[1.8rem] shrink-0 flex data-[state=unchecked]:bg-slate-200 data-[state=checked]:bg-cyan-500 border border-slate-300 data-[state=checked]:border-cyan-800/20 rounded-full relative transition-all focus-within:outline-none"
|
||||||
|
>
|
||||||
|
<SwitchThumb
|
||||||
|
class="size-6 my-auto bg-white text-sm ms-1 flex items-center justify-center shadow-xl rounded-full transition-transform translate-x-0.5 will-change-transform data-[state=checked]:-translate-x-[68%]"
|
||||||
|
/>
|
||||||
|
</SwitchRoot>
|
||||||
|
<span class="w-full text-gray-800 text-sm lg:text-[1rem]"
|
||||||
|
>ارسال با پیک (فقط ارسال درون شهری شیراز)</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="text-gray-800 text-sm lg:text-[1rem]">
|
||||||
|
۱۵۰٬۰۰۰ تومان
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center w-full gap-4 p-4 border lg:gap-6 border-gray-300 rounded-xl bg-gray-50"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-start w-full lg:text-[1.125rem] font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
خلاصه سفارش
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="grid w-full grid-cols-1 gap-6 lg:grid-cols-3 md:grid-cols-2"
|
||||||
|
>
|
||||||
|
<MinimalCartItem v-for="i in 9" />
|
||||||
|
|
||||||
|
<div class="h-7 flex-center col-span-full lg:hidden">
|
||||||
|
<button class="gap-2 flex-center">
|
||||||
|
<span class="text-sm font-bold text-cyan-500">
|
||||||
|
مشاهده بیشتر
|
||||||
|
</span>
|
||||||
|
<Icon
|
||||||
|
name="bi:chevron-down"
|
||||||
|
class="**:stroke-cyan-500"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 291 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 498 KiB |
Vendored
+43
-29
@@ -9,38 +9,52 @@ declare global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type Chat = {
|
type Chat = {
|
||||||
id: number,
|
id: number;
|
||||||
sender: "ai" | "user",
|
sender: "ai" | "user";
|
||||||
content: string
|
content: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Product = {
|
type Product = {
|
||||||
"id": number,
|
id: number;
|
||||||
"price": number,
|
price: number;
|
||||||
"name": string,
|
name: string;
|
||||||
"description": string,
|
description: string;
|
||||||
"currency": string,
|
currency: string;
|
||||||
"image": string,
|
image: string;
|
||||||
"rating": number,
|
rating: number;
|
||||||
"view": number,
|
view: number;
|
||||||
"sell": number,
|
sell: number;
|
||||||
"in_stock": number,
|
in_stock: number;
|
||||||
"discount": number,
|
discount: number;
|
||||||
"slug": string,
|
slug: string;
|
||||||
"meta_description": string | null,
|
meta_description: string | null;
|
||||||
"meta_keywords": null,
|
meta_keywords: null;
|
||||||
"meta_rating": number | null
|
meta_rating: number | null;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Category = {
|
type Category = {
|
||||||
"id": number,
|
id: number;
|
||||||
"name": string,
|
name: string;
|
||||||
"slug": string,
|
slug: string;
|
||||||
"icon": string,
|
icon: string;
|
||||||
"meta_title": string,
|
meta_title: string;
|
||||||
"meta_description": string,
|
meta_description: string;
|
||||||
"parent": number,
|
parent: number;
|
||||||
"children": "string"
|
children: "string";
|
||||||
}
|
};
|
||||||
|
|
||||||
|
type Address = {
|
||||||
|
id: number;
|
||||||
|
province: string;
|
||||||
|
city: string;
|
||||||
|
postal_code: string;
|
||||||
|
full_address: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DeliveryMethod = {
|
||||||
|
type: string;
|
||||||
|
date: string;
|
||||||
|
hour: string;
|
||||||
|
price: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user