Merge remote-tracking branch 'origin/main'

This commit is contained in:
marzban-dev
2025-03-19 17:39:22 +03:30
87 changed files with 3583 additions and 395 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ const { variant, size, loading } = toRefs(props);
// computed
const classes = computed(() => {
return [
"flex items-center justify-center transition-all cursor-pointer",
"flex items-center justify-center transition-all cursor-pointer max-lg:text-xs",
{
"btn-solid": variant.value === "solid",
"btn-secondary": variant.value === "secondary",
+2 -1
View File
@@ -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"
+24 -13
View File
@@ -1,31 +1,42 @@
<script lang="ts" setup>
// types
type Props = {
title: string,
products: ProductListItem[]
}
title?: string;
products: ProductListItem[];
withHeader?: boolean;
};
// props
defineProps<Props>();
withDefaults(defineProps<Props>(), {
withHeader: true,
});
</script>
<template>
<section class="w-full flex flex-col gap-10 md:gap-[4rem] py-[5rem] container">
<div class="w-full flex justify-between items-center">
<span class="text-black typo-h-6 max-sm:text-xl md:typo-h-5 lg:typo-h-4">
<section
class="w-full flex flex-col gap-10 md:gap-[4rem] py-[5rem] container"
>
<div v-if="withHeader" class="w-full flex justify-between items-center">
<span
class="text-black typo-h-6 max-sm:text-xl md:typo-h-5 lg:typo-h-4"
>
{{ title }}
</span>
<NuxtLink to="/products">
<Button variant="outlined" class="rounded-full max-sm:typo-label-sm max-sm:py-2" end-icon="ci:arrow-left">
<Button
variant="outlined"
class="rounded-full max-sm:typo-label-sm max-sm:py-2"
end-icon="ci:arrow-left"
>
نمایش همه
</Button>
</NuxtLink>
</div>
<div class="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-y-8 gap-5 sm:gap-8">
<ul
class="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-y-8 gap-5 sm:gap-8"
>
<ProductCard
v-for="product in products"
:key="product.id"
@@ -37,6 +48,6 @@ defineProps<Props>();
:rate="product.rating"
:dark-layer="true"
/>
</div>
</ul>
</section>
</template>
</template>
@@ -13,48 +13,57 @@ const highlights = ref<Highlight[]>([
{
icon: "/img/footer-support.svg",
title: "خدمات مشتری",
description: "پشتیبانی استثنایی، راه‌حل‌های پایدار برای شما"
description: "پشتیبانی استثنایی، راه‌حل‌های پایدار برای شما",
},
{
icon: "/img/footer-send.svg",
title: "ارسال سریع و رایگان",
description: "ارسال رایگان برای سفارش‌های بالای ۱۵۰ دلار"
description: "ارسال رایگان برای سفارش‌های بالای ۱۵۰ دلار",
},
{
icon: "/img/footer-share.svg",
title: "معرفی به دوستان",
description: "ما را به دوستان خود معرفی کنید"
description: "ما را به دوستان خود معرفی کنید",
},
{
icon: "/img/footer-security.svg",
title: "پرداخت امن",
description: "پرداخت شما به‌صورت امن پردازش می‌شود"
}
description: "پرداخت شما به‌صورت امن پردازش می‌شود",
},
]);
</script>
<template>
<section class="w-full border-t-[0.5px] border-slate-200">
<div class="w-full py-[5rem] gap-12 xs:gap-8 sm:gap-12 xl:gap-0 container grid grid-cols-1 xs:grid-cols-2 lg:grid-cols-4">
<div
class="w-full py-[5rem] gap-8 sm:gap-12 xl:gap-0 container grid grid-cols-2 lg:grid-cols-4"
>
<template v-for="(highlight, index) in highlights" :key="index">
<div class="flex flex-col-center gap-[.75rem] px-5">
<img :src="highlight.icon" class="size-[70px] md:size-[90px]" alt="" />
<img
:src="highlight.icon"
class="size-[70px] md:size-[90px]"
alt=""
/>
<div class="w-full flex-col-center gap-[.25rem]">
<span class="typo-sub-h-md text-black text-center">
<span
class="typo-sub-h-sm lg:typo-sub-h-md text-black text-center"
>
{{ highlight.title }}
</span>
<p class="text-slate-500 typo-p-sm mt-1 text-center">
<p
class="text-slate-500 typo-p-xs lg:typo-p-sm mt-1 text-center"
>
{{ highlight.description }}
</p>
</div>
</div>
<!-- <div-->
<!-- class="w-[1px] h-[5rem] bg-slate-200"-->
<!-- v-if="index + 1 != highlights.length"-->
<!-- />-->
<!-- <div-->
<!-- class="w-[1px] h-[5rem] bg-slate-200"-->
<!-- v-if="index + 1 != highlights.length"-->
<!-- />-->
</template>
</div>
</section>
+1 -1
View File
@@ -43,7 +43,7 @@ const closeSideDrawer = () => {
<div
@click.stop
:class="modelValue ? 'translate-x-0' : 'translate-x-[100%]'"
class="md:hidden cursor-default flex top-0 right-0 fixed z-999 transition-all flex-col bg-white w-[350px] h-full gap-8 pt-12"
class="md:hidden cursor-default flex top-0 right-0 fixed z-999 transition-all duration-500 rounded-e-xl flex-col bg-white w-[300px] h-full gap-8 pt-12"
>
<div class="flex items-center flex-col justify-end gap-[1.5rem]">
<Tooltip v-if="!!account && !!token" title="حساب کاربری">
@@ -30,11 +30,10 @@ await suspense();
const onSwiper = (swiper: SwiperClass) => {
swiper_instance.value = swiper;
};
</script>
<template>
<section class="w-full flex flex-col gap-10 md:gap-[4rem] py-[5rem] lg:container">
<section class="w-full flex flex-col gap-10 md:gap-[4rem]">
<div class="w-full flex justify-between items-center max-lg:container">
<span class="text-black typo-h-6 md:typo-h-5 lg:typo-h-4">
{{ title }}
@@ -92,12 +91,12 @@ const onSwiper = (swiper: SwiperClass) => {
:breakpoints="{
640: {
centeredSlides: true,
slidesPerView : 2.5
slidesPerView: 2.5,
},
1024 : {
1024: {
centeredSlides: false,
slidesPerView : 3
}
slidesPerView: 3,
},
}"
>
<SwiperSlide
@@ -1,5 +1,4 @@
<script lang="ts" setup>
// import
import Tag from "~/components/global/Tag.vue";
@@ -10,7 +9,7 @@ import { useImageColor } from "~/composables/global/useImageColor";
// types
type Props = {
id: number,
id: number;
title: string;
colors: string[];
price: string;
@@ -28,77 +27,89 @@ const { id } = toRefs(props);
// state
const { colorObject } = useImageColor(`#product-image-${id.value}`);
</script>
<template>
<NuxtLink :to="'/product/' + id">
<div class="@container">
<div
class="group relative size-full aspect-square rounded-xl @[280px]:rounded-2xl bg-white brightness-[98%] overflow-hidden p-6"
>
<img
:id="`product-image-${id}`"
:src="picture"
class="group-hover:scale-105 transition-transform duration-200 size-full object-contain absolute inset-0"
alt="product-background"
/>
<li class="w-full">
<NuxtLink :to="'/product/' + id">
<div class="@container">
<div
v-if="darkLayer"
class="bg-linear-to-t inset-0 from-black/50 to-transparent to-55% absolute z-10 size-full"
/>
<div
class="flex justify-between items-center absolute px-4 @[280px]:px-6 pt-4 @[280px]:pt-6 top-0 w-full inset-x-0"
>
<Rate v-if="rate" :rate="rate" />
<Tag v-if="tag">
{{ tag }}
</Tag>
</div>
<div
:class="
colorObject?.isLight && !darkLayer
? 'text-black'
: 'text-white'
"
class="absolute inset-x-0 bottom-0 pb-4 @[280px]:pb-6 px-4 @[280px]:px-6 flex flex-row-reverse justify-between items-end z-10"
class="group relative size-full aspect-square rounded-xl @[280px]:rounded-2xl bg-white brightness-[98%] overflow-hidden p-6"
>
<img
:id="`product-image-${id}`"
:src="picture"
class="group-hover:scale-105 transition-transform duration-200 size-full object-contain absolute inset-0"
alt="product-background"
/>
<div class="flex flex-col gap-2 items-start w-full">
<span class="@max-[280px]:hidden typo-sub-h-md @[280px]:typo-sub-h-lg truncate w-full">
{{ title }}
</span>
<div class="flex items-center justify-between w-full mt-1">
<div class="flex items-center gap-2 @[280px]:mt-1">
<ColorCircle
v-for="color in colors"
:key="color"
:style="{ backgroundColor: color }"
class="!size-5 @[280px]:!size-6"
/>
</div>
<span class="@max-[280px]:hidden typo-p-xs @[280px]:typo-p-md !font-semibold whitespace-nowrap">
{{ price }}
<div
v-if="darkLayer"
class="bg-linear-to-t inset-0 from-black/50 to-transparent to-55% absolute z-10 size-full"
/>
<div
class="flex justify-between items-center absolute px-4 @[280px]:px-6 pt-4 @[280px]:pt-6 top-0 w-full inset-x-0"
>
<Rate v-if="rate" :rate="rate" />
<Tag v-if="tag">
{{ tag }}
</Tag>
</div>
<div
:class="
colorObject?.isLight && !darkLayer
? 'text-black'
: 'text-white'
"
class="absolute inset-x-0 bottom-0 pb-4 @[280px]:pb-6 px-4 @[280px]:px-6 flex flex-row-reverse justify-between items-end z-10"
>
<div class="flex flex-col gap-2 items-start w-full">
<span
class="@max-[280px]:hidden typo-sub-h-md @[280px]:typo-sub-h-lg truncate w-full"
>
{{ title }}
</span>
<div
class="flex items-center justify-between w-full mt-1"
>
<div
class="flex items-center gap-2 @[280px]:mt-1"
>
<ColorCircle
v-for="color in colors"
:key="color"
:style="{ backgroundColor: color }"
class="!size-5 @[280px]:!size-6"
/>
</div>
<span
class="@max-[280px]:hidden typo-p-xs @[280px]:typo-p-md !font-semibold whitespace-nowrap"
>
{{ price }}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="flex flex-col gap-1 px-2 items-start w-full text-black mt-4 @[280px]:hidden">
<span class="typo-sub-h-sm w-full truncate">
{{ title }}
</span>
<div class="@[280px]:hidden flex items-center justify-between w-full mt-1">
<span class="typo-p-xs !font-semibold whitespace-nowrap">
{{ price }}
<div
class="flex flex-col gap-1 px-2 items-start w-full text-black mt-4 @[280px]:hidden"
>
<span class="typo-sub-h-sm w-full truncate">
{{ title }}
</span>
<div
class="@[280px]:hidden flex items-center justify-between w-full mt-1"
>
<span
class="typo-p-xs !font-semibold whitespace-nowrap"
>
{{ price }}
</span>
</div>
</div>
</div>
</div>
</NuxtLink>
</NuxtLink>
</li>
</template>