Merge remote-tracking branch 'origin/main'

This commit is contained in:
marzban-dev
2024-12-28 21:07:17 +03:30
18 changed files with 562 additions and 45 deletions
+46
View File
@@ -120,14 +120,60 @@
--breakpoint-xs: 480px;
/* ANIMATIONS */
<<<<<<< HEAD
--animate-marquee: marquee 3s linear infinite;
--animate-slide-down: slideDown 300ms ease-out;
--animate-slide-up: slideUp 300ms ease-out;
--animate-overlay-show: overlayShow 150ms ease-in;
--animate-content-show: contentShow 150ms ease-in;
=======
--animate-marquee: marquee 25s linear infinite;
--animate-marquee-reverse: marquee 25s linear infinite reverse;
>>>>>>> be4fa509843c81855f5ffc118150196c94a7b17b
@keyframes marquee {
to {
transform: translateX(50%);
}
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--reka-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--reka-accordion-content-height);
}
to {
height: 0;
}
}
@keyframes overlayShow {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes contentShow {
from {
opacity: 0;
transform: translate(-50%, -48%) scale(0.96);
}
to {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
}
/* CONTAINER */
@@ -0,0 +1,61 @@
<script setup lang="ts">
// types
type Highlight = {
icon: string;
title: string;
description: string;
};
// state
const highlights = ref<Highlight[]>([
{
icon: "ci:headset",
title: "خدمات مشتری",
description: "پشتیبانی استثنایی، راه‌حل‌های پایدار",
},
{
icon: "ci:delivery",
title: "ارسال سریع و رایگان",
description: "ارسال رایگان برای سفارش‌های بالای ۱۵۰ دلار",
},
{
icon: "ci:users",
title: "معرفی به دوستان",
description: "دوستان خود را معرفی کنید و هر دو ۱۵٪ تخفیف بگیرید",
},
{
icon: "ci:shield-done",
title: "پرداخت امن",
description: "اطلاعات پرداخت شما به‌صورت امن پردازش می‌شود",
},
]);
</script>
<template>
<section 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">
<div class="size-[1.5rem] flex-center">
<Icon :name="highlight.icon" />
</div>
<div class="w-full flex-col-center gap-[.25rem]">
<span class="typo-sub-h-md text-black text-center">
{{ highlight.title }}
</span>
<p class="text-slate-500 typo-p-md text-center">
{{ highlight.description }}
</p>
</div>
</div>
<div
class="w-[1px] h-[5rem] bg-slate-200"
v-if="index + 1 != highlights.length"
/>
</template>
</section>
</template>
<style scoped></style>
@@ -27,7 +27,7 @@ const onSwiper = (swiper: SwiperClass) => {
</script>
<template>
<div class="w-full flex flex-col gap-[4rem] py-[5rem] container">
<section class="w-full flex flex-col gap-[4rem] py-[5rem] container">
<div class="w-full flex justify-between items-center">
<span class="text-black typo-h-3">
{{ title }}
@@ -90,7 +90,7 @@ const onSwiper = (swiper: SwiperClass) => {
</SwiperSlide>
</Swiper>
</div>
</div>
</section>
</template>
<style scoped></style>
@@ -0,0 +1,132 @@
<template>
<div class="w-full flex flex-col">
<AccordionRoot
class="w-full last:border-b last:border-slate-200"
default-value="item-1"
type="single"
:collapsible="true"
>
<AccordionItem value="item-1" class="overflow-hidden">
<AccordionHeader
class="border-t border-slate-200 py-[1.5rem] flex justify-between items-center"
>
<span class="typo-sub-h-md text-black">مشخصات</span>
<AccordionTrigger class="group">
<Icon
name="ci:plus"
size="24"
class="group-data-[state=open]:rotate-45 transition-transform"
/>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent
class="data-[state=open]:animate-slide-down pb-[1.5rem] data-[state=closed]:animate-slide-up overflow-hidden"
>
<div
class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[1rem]"
>
<div
v-for="i in 4"
class="flex flex-col gap-y-[1.5rem]"
>
<span
class="typo-sub-h-lg text-black w-full pt-[1.5rem]"
>صفحه نمایش</span
>
<ul class="list-disc w-full ps-5">
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
</ul>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2" class="overflow-hidden">
<AccordionHeader
class="border-t border-slate-200 py-[1.5rem] flex justify-between items-center"
>
<span class="typo-sub-h-md text-black">مشخصات</span>
<AccordionTrigger class="group">
<Icon
name="ci:plus"
size="24"
class="group-data-[state=open]:rotate-45 transition-transform"
/>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent
class="data-[state=open]:animate-slide-down pb-[1.5rem] data-[state=closed]:animate-slide-up overflow-hidden"
>
<div
class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[1rem]"
>
<div
v-for="i in 4"
class="flex flex-col gap-y-[1.5rem]"
>
<span
class="typo-sub-h-lg text-black w-full pt-[1.5rem]"
>صفحه نمایش</span
>
<ul class="list-disc w-full ps-5">
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
</ul>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3" class="overflow-hidden">
<AccordionHeader
class="border-t border-slate-200 py-[1.5rem] flex justify-between items-center"
>
<span class="typo-sub-h-md text-black">مشخصات</span>
<AccordionTrigger class="group">
<Icon
name="ci:plus"
size="24"
class="group-data-[state=open]:rotate-45 transition-transform"
/>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent
class="data-[state=open]:animate-slide-down pb-[1.5rem] data-[state=closed]:animate-slide-up overflow-hidden"
>
<div
class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[1rem]"
>
<div
v-for="i in 4"
class="flex flex-col gap-y-[1.5rem]"
>
<span
class="typo-sub-h-lg text-black w-full pt-[1.5rem]"
>صفحه نمایش</span
>
<ul class="list-disc w-full ps-5">
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
<li class="text-slate-500 typo-p-md">
روشنایی :3000mn
</li>
</ul>
</div>
</div>
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</div>
</template>
<script setup lang="ts"></script>
<style scoped></style>
@@ -0,0 +1,38 @@
<template>
<section class="w-full p-[5rem] flex flex-col gap-y-[1.5rem]">
<div class="w-full flex">
<span class="text-black typo-h-3"> جزيات محصول </span>
</div>
<div class="w-full flex items-start justify-between gap-[3rem]">
<div class="w-8/12">
<Accordion />
</div>
<div class="w-4/12">
<div
class="w-full bg-slate-50 rounded-xl flex-col-center p-[5rem] gap-[1.5rem]"
>
<span>داخل جعبه چیه؟</span>
<div
class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[3rem]"
>
<div
v-for="i in 4"
class="w-full flex-col-center gap-[.75rem]"
>
<div
class="size-[6.25rem] rounded-full border-slate-200 bg-white flex-center"
>
<Icon name="ci:flag" size="44" />
</div>
<span class="text-black typo-p-md">Headphones</span>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts"></script>
<style scoped></style>
@@ -1,7 +1,7 @@
<script lang="ts" setup></script>
<template>
<div class="h-[95svh] w-full relative bg-black mt-[5rem]">
<section class="h-[95svh] w-full relative bg-black mt-[5rem]">
<img src="/img/product-3.jpg" class="object-cover absolute size-full" />
<div class="size-full absolute inset-0 bg-black/60" />
<StickyCard
@@ -11,5 +11,5 @@
title="نام محصول"
class="absolute right-6 bottom-6"
/>
</div>
</section>
</template>
@@ -0,0 +1,78 @@
<script setup lang="ts"></script>
<template>
<DialogRoot modal>
<DialogTrigger>
<Button
end-icon="ci:filter"
variant="secondary"
class="rounded-full"
>
فیلتر محصولات
</Button>
</DialogTrigger>
<DialogPortal to="#teleports">
<DialogOverlay
class="bg-black/60 backdrop-blur-sm data-[state=open]:animate-overlay-show fixed inset-0 z-30"
/>
<DialogContent
class="data-[state=open]:animate-content-show absolute top-1/2 left-1/2 max-h-[85vh] w-[90vw] max-w-[450px] -translate-x-1/2 -translate-y-1/2 rounded-[6px] bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none z-[100]"
>
<DialogTitle
class="flex items-center typo-h-4 text-black font-semibold"
>
Edit profile
</DialogTitle>
<DialogDescription
class="text-mauve11 mt-[10px] mb-5 text-sm leading-normal"
>
Make changes to your profile here. Click save when you're
done.
</DialogDescription>
<fieldset class="mb-[15px] flex items-center gap-5">
<label
class="text-black w-[90px] text-right text-sm"
for="name"
>
Name
</label>
<input
id="name"
class="text-black bg-stone-50 shadow-green7 focus:shadow-gray-100 inline-flex h-[35px] w-full flex-1 items-center justify-center rounded-lg px-[10px] text-sm leading-none shadow-[0_0_0_1px] outline-none focus:shadow-[0_0_0_2px]"
defaultValue="Pedro Duarte"
/>
</fieldset>
<fieldset class="mb-[15px] flex items-center gap-5">
<label
class="text-black w-[90px] text-right text-sm"
for="username"
>
Username
</label>
<input
id="username"
class="text-black bg-stone-50 shadow-green7 focus:shadow-gray-100 inline-flex h-[35px] w-full flex-1 items-center justify-center rounded-lg px-[10px] text-sm leading-none shadow-[0_0_0_1px] outline-none focus:shadow-[0_0_0_2px]"
defaultValue="@peduarte"
/>
</fieldset>
<div class="mt-[25px] flex justify-end">
<DialogClose as-child>
<button
class="bg-green4 text-green11 text-sm hover:bg-green5 focus:shadow-green7 inline-flex h-[35px] items-center justify-center rounded-lg px-[15px] font-semibold leading-none focus:shadow-[0_0_0_2px] focus:outline-none"
>
Save changes
</button>
</DialogClose>
</div>
<DialogClose
class="text-black hover:bg-green4 focus:shadow-green7 absolute top-[10px] right-[10px] inline-flex h-[25px] w-[25px] appearance-none items-center justify-center rounded-full focus:shadow-[0_0_0_2px] focus:outline-none"
aria-label="Close"
>
<Icon name="ci:close" />
</DialogClose>
</DialogContent>
</DialogPortal>
</DialogRoot>
</template>
<style lang="scss" scoped></style>
+13
View File
@@ -0,0 +1,13 @@
FROM node:20-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:20-alpine as production-stage
WORKDIR /app
COPY --from=build-stage /app /app
EXPOSE 3000
ENV NODE_ENV=production
CMD ["npm", "run", "start"]
+8 -2
View File
@@ -11,11 +11,17 @@
</script>
<template>
<div class="w-full flex flex-col-center persian-number font-yekan-bakh" dir="rtl">
<div
class="w-full flex flex-col-center persian-number font-yekan-bakh"
dir="rtl"
>
<Header />
<main class="w-full overflow-x-hidden">
<slot />
</main>
<Footer />
<div class="w-full flex-col flex">
<ServiceHighlights />
<Footer />
</div>
</div>
</template>
+7 -4
View File
@@ -1,8 +1,11 @@
<script lang="ts" setup></script>
<template>
<ProductHero />
<Video />
<Comments />
<RelatedProducts title="محصولات مشابه" />
<div class="w-full flex flex-col">
<ProductHero />
<ProductVideo />
<ProductComments />
<ProductDetails />
<RelatedProducts title="محصولات مشابه" />
</div>
</template>
+35
View File
@@ -0,0 +1,35 @@
<script setup lang="ts"></script>
<template>
<div class="w-full container flex flex-col">
<div class="w-full flex justify-between items-center py-[5rem]">
<div class="flex flex-col items-start gap-[1.5rem] text-black">
<div class="flex-center gap-[.75rem]">
<span>خانه</span>
<span>/</span>
<span>محصولات</span>
<span>/</span>
<span>همه</span>
</div>
<h1 class="typo-hero-2">همه محصولات</h1>
</div>
<FilterButton />
</div>
<ul class="w-full grid grid-cols-3 gap-[1.5rem]">
<li v-for="i in 9" :key="i">
<ProductCard
brand="Samsung"
title="Galaxy S20 Ultra"
picture="/assets/img/product-1.jpg"
:colors="['#0000ff', '#00ff00', 'red']"
:price="599"
:rate="2.4"
tag="New"
/>
</li>
</ul>
</div>
</template>
<style scoped></style>