Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -0,0 +1,73 @@
|
|||||||
|
@layer base {
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/IRANYekanX-UltraLight.woff2");
|
||||||
|
font-weight: 200;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Light.woff2");
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Regular.woff2");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Medium.woff2");
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-SemiBold.woff2");
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Bold.woff2");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-ExtraBold.woff2");
|
||||||
|
font-weight: 800;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Black.woff2");
|
||||||
|
font-weight: 900;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Morabba";
|
||||||
|
src: url("/fonts/Morabba/Morabba-Heavy.woff2");
|
||||||
|
font-weight: 1000;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@layer base {
|
||||||
|
@font-face {
|
||||||
|
font-family: "YekanBakh";
|
||||||
|
src: url("/fonts/YekanBakh/YekanBakh-Thin.woff");
|
||||||
|
font-weight: 100;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "YekanBakh";
|
||||||
|
src: url("/fonts/YekanBakh/YekanBakh-Light.woff");
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "YekanBakh";
|
||||||
|
src: url("/fonts/YekanBakh/YekanBakh-Regular.woff");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "YekanBakh";
|
||||||
|
src: url("/fonts/YekanBakh/YekanBakh-SemiBold.woff");
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "YekanBakh";
|
||||||
|
src: url("/fonts/YekanBakh/YekanBakh-Bold.woff");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
@utility persian-number {
|
@utility persian-number {
|
||||||
-moz-font-feature-settings: "ss02";
|
-moz-font-feature-settings: "ss07";
|
||||||
-webkit-font-feature-settings: "ss02";
|
-webkit-font-feature-settings: "ss07";
|
||||||
font-feature-settings: "ss02";
|
font-feature-settings: "ss07";
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility text-gradient {
|
@utility text-gradient {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
@import "./typo.utils.css";
|
@import "./typo.utils.css";
|
||||||
@import "./button.comp.css";
|
@import "./button.comp.css";
|
||||||
@import "./input.comp.css";
|
@import "./input.comp.css";
|
||||||
@import "./fonts/iran-yekan-x.css"
|
@import "./fonts/iran-yekan-x.css";
|
||||||
|
@import "./fonts/morabba.css";
|
||||||
|
@import "./fonts/yekan-bakh.css";
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
/* COLORS */
|
/* COLORS */
|
||||||
@@ -109,19 +111,21 @@
|
|||||||
--font-inter: "Inter", sans-serif;
|
--font-inter: "Inter", sans-serif;
|
||||||
--font-dmsans: "DM Sans", sans-serif;
|
--font-dmsans: "DM Sans", sans-serif;
|
||||||
--font-iran-yekan-x: "IRANYekanXVF", "sans-serif";
|
--font-iran-yekan-x: "IRANYekanXVF", "sans-serif";
|
||||||
|
--font-yekan-bakh: "YekanBakh", "sans-serif";
|
||||||
|
--font-morabba: "Morabba", "sans-serif";
|
||||||
|
|
||||||
/* BREAKPOINTS */
|
/* BREAKPOINTS */
|
||||||
--breakpoint-3xl: 1700px;
|
--breakpoint-3xl: 1700px;
|
||||||
--breakpoint-2xs: 400px;
|
--breakpoint-2xs: 400px;
|
||||||
--breakpoint-xs: 480px;
|
--breakpoint-xs: 480px;
|
||||||
|
|
||||||
|
|
||||||
/* ANIMATIONS */
|
/* ANIMATIONS */
|
||||||
--animate-marquee: marquee 3s linear infinite;
|
--animate-marquee: marquee 25s linear infinite;
|
||||||
|
--animate-marquee-reverse: marquee 25s linear infinite reverse;
|
||||||
|
|
||||||
@keyframes marquee {
|
@keyframes marquee {
|
||||||
to {
|
to {
|
||||||
transform: translateY(-50%);
|
transform: translateX(50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,6 +133,7 @@
|
|||||||
/* CONTAINER */
|
/* CONTAINER */
|
||||||
|
|
||||||
@utility container {
|
@utility container {
|
||||||
|
@apply mx-auto;
|
||||||
padding-inline: 3rem;
|
padding-inline: 3rem;
|
||||||
@screen xl {
|
@screen xl {
|
||||||
padding-inline: 5rem;
|
padding-inline: 5rem;
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
/* TYPO HERO */
|
/* TYPO HERO */
|
||||||
@utility typo-hero-1 {
|
@utility typo-hero-1 {
|
||||||
@apply text-[96px] leading-[96px] font-bold ;
|
@apply text-[96px] leading-[96px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-hero-2 {
|
@utility typo-hero-2 {
|
||||||
@apply text-[72px] leading-[72px] font-bold ;
|
@apply text-[72px] leading-[72px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TYPE HEADING */
|
/* TYPE HEADING */
|
||||||
@utility typo-h-1 {
|
@utility typo-h-1 {
|
||||||
@apply text-[64px] leading-[72px] font-bold ;
|
@apply text-[64px] leading-[72px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-h-2 {
|
@utility typo-h-2 {
|
||||||
@apply text-[56px] leading-[64px] font-bold ;
|
@apply text-[56px] leading-[64px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-h-3 {
|
@utility typo-h-3 {
|
||||||
@apply text-[48px] leading-[56px] font-bold ;
|
@apply text-[48px] leading-[56px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-h-4 {
|
@utility typo-h-4 {
|
||||||
@apply text-[40px] leading-[52px] font-bold ;
|
@apply text-[40px] leading-[52px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-h-5 {
|
@utility typo-h-5 {
|
||||||
@apply text-[32px] leading-[40px] font-bold ;
|
@apply text-[32px] leading-[40px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility typo-h-6 {
|
@utility typo-h-6 {
|
||||||
@apply text-[24px] leading-[32px] font-bold ;
|
@apply text-[24px] leading-[32px] font-semibold ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TYPE SUBHEADING */
|
/* TYPE SUBHEADING */
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
tag: string;
|
||||||
|
date: string;
|
||||||
|
comments: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
link: string;
|
||||||
|
variant?: "sm" | "lg";
|
||||||
|
}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
variant: "lg"
|
||||||
|
});
|
||||||
|
const {} = toRefs(props);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="variant === 'lg' ? 'rounded-150 overflow-hidden' : ''"
|
||||||
|
class="max-h-[700px] h-[700px] relative"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Tag
|
||||||
|
v-if="variant === 'lg'"
|
||||||
|
class="bg-success-500 absolute left-10 top-10 z-20"
|
||||||
|
>
|
||||||
|
اسپیکر
|
||||||
|
</Tag>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="variant === 'sm'"
|
||||||
|
class="h-[350px] rounded-150 overflow-hidden relative"
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
class="bg-success-500 absolute z-20 left-6 top-6"
|
||||||
|
>
|
||||||
|
اسپیکر
|
||||||
|
</Tag>
|
||||||
|
|
||||||
|
<img
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
class="absolute size-full object-cover z-10"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
:class="variant === 'lg' ? 'absolute px-10' : 'invert mt-8'"
|
||||||
|
class="bottom-10 flex flex-col gap-6 z-20"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-6">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Icon
|
||||||
|
name="ci:comment"
|
||||||
|
size="18"
|
||||||
|
class="**:stroke-white"
|
||||||
|
/>
|
||||||
|
<span class="typo-p-sm text-white">
|
||||||
|
۰ نظر
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Icon
|
||||||
|
name="ci:calendar"
|
||||||
|
size="18"
|
||||||
|
class="**:stroke-white"
|
||||||
|
/>
|
||||||
|
<span class="typo-p-sm text-white">
|
||||||
|
۳۱ مهر ۱۴۰۳
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex gap-4 flex-col">
|
||||||
|
<span
|
||||||
|
:class="variant === 'lg' ? 'typo-h-4' : 'typo-h-6'"
|
||||||
|
class="text-white"
|
||||||
|
>
|
||||||
|
برسی آیفون ۱۶ پرومکس
|
||||||
|
</span>
|
||||||
|
<p
|
||||||
|
:class="variant === 'lg' ? 'typo-h-4' : 'typo-h-6 text-slate-500'"
|
||||||
|
class="typo-p-md text-white text-justify"
|
||||||
|
>
|
||||||
|
نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد.
|
||||||
|
نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد.
|
||||||
|
کتابهای زیادی در شصت و سه درصد گذشته.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="underline text-white typo-p-md">
|
||||||
|
بیشتر بخوانید...
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-if="variant === 'lg'"
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
class="absolute size-full object-cover z-10"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="variant === 'lg'"
|
||||||
|
class="w-full h-full bg-linear-to-t from-black to-transparent absolute inset-0 z-15"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
// brands: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const {} = toRefs(props);
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const { $gsap: gsap } = useNuxtApp();
|
||||||
|
|
||||||
|
// lifecycle
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
gsap.to("#marquee-text-container", {
|
||||||
|
xPercent: -50, // Adjust based on content width
|
||||||
|
duration: 10, // Adjust for desired speed
|
||||||
|
ease: "none",
|
||||||
|
repeat: -1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative w-full flex flex-col justify-center h-[350px]">
|
||||||
|
|
||||||
|
<div class="-rotate-z-2 z-20">
|
||||||
|
<div
|
||||||
|
class="bg-warning-500 flex pr-20 gap-20 py-2 w-max animate-marquee-reverse"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="i in 10"
|
||||||
|
class="text-[50px] text-white whitespace-nowrap font-semibold"
|
||||||
|
>
|
||||||
|
TEST {{ i }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-for="i in 10"
|
||||||
|
class="text-[50px] text-white whitespace-nowrap font-semibold"
|
||||||
|
>
|
||||||
|
TEST {{ i }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rotate-z-2 z-10">
|
||||||
|
<div
|
||||||
|
class="bg-slate-50 flex pr-20 gap-20 py-2 w-max animate-marquee"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="i in 10"
|
||||||
|
class="text-[50px] text-slate-300 whitespace-nowrap font-semibold"
|
||||||
|
>
|
||||||
|
TEST {{ i }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-for="i in 10"
|
||||||
|
class="text-[50px] text-slate-300 whitespace-nowrap font-semibold"
|
||||||
|
>
|
||||||
|
TEST {{ i }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
category: string;
|
||||||
|
count: number;
|
||||||
|
description: string;
|
||||||
|
picture: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative rounded-150 overflow-hidden w-full h-[500px]">
|
||||||
|
<img
|
||||||
|
class="absolute object-cover size-full"
|
||||||
|
:src="picture"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div class="bg-linear-to-t from-black/80 to-transparent absolute z-10 size-full" />
|
||||||
|
|
||||||
|
<div class="absolute z-20 bottom-0 p-6 flex items-end justify-between w-full">
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2 text-white">
|
||||||
|
<div class="typo-s-h-md">
|
||||||
|
تمام دسته ها
|
||||||
|
<span class="typo-p-xs -translate-y-1 inline-block mr-1">
|
||||||
|
24
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span class="typo-p-md">محصولات ما را مشاهده کنید</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
size="24"
|
||||||
|
name="ci:arrow-left"
|
||||||
|
class="**:stroke-white mb-1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -35,7 +35,7 @@ const nav_links = ref<NavLink[]>([
|
|||||||
<template>
|
<template>
|
||||||
<header class="w-full bg-white flex-center">
|
<header class="w-full bg-white flex-center">
|
||||||
<div
|
<div
|
||||||
class="w-full flex items-center justify-between container py-[2.25rem]"
|
class="size-full flex items-center justify-between container py-[2.25rem]"
|
||||||
>
|
>
|
||||||
<div class="w-2/12 flex items-center justify-start">
|
<div class="w-2/12 flex items-center justify-start">
|
||||||
<span class="size-[2rem] bg-black rounded-full"></span>
|
<span class="size-[2rem] bg-black rounded-full"></span>
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
<Icon name="ci:check" class="size-4 **:stroke-white"/>
|
<Icon name="ci:check" class="size-4 **:stroke-white"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="typo-label-sm whitespace-nowrap">Pick up from Store</span>
|
<span class="typo-label-sm whitespace-nowrap">دریافت حضوری فروشگاه</span>
|
||||||
<span class="typo-p-sm whitespace-nowrap">Usually ready in 2 hours</span>
|
<span class="typo-p-sm whitespace-nowrap">معمولا طی ۲ ساعت اماده میشود</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="typo-p-xs">
|
<span class="typo-p-xs">
|
||||||
Check availability at other stores
|
برسی موجودی در فروشگاه های دیگر
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// imports
|
||||||
|
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
|
import type { SwiperClass } from "swiper/react";
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const swiper_instance = ref<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const onSwiper = (swiper: SwiperClass) => {
|
||||||
|
swiper_instance.value = swiper;
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div 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 }}
|
||||||
|
</span>
|
||||||
|
<div class="flex-center gap-[.5rem]">
|
||||||
|
<button
|
||||||
|
@click="swiper_instance?.slidePrev()"
|
||||||
|
:disabled="swiper_instance?.isBeginning"
|
||||||
|
:class="
|
||||||
|
swiper_instance?.isBeginning
|
||||||
|
? 'border-slate-200 cursor-not-allowed'
|
||||||
|
: 'border-black cursor-pointer'
|
||||||
|
"
|
||||||
|
class="size-[2.75rem] rounded-full border-[1.5px] click-effect flex-center"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="ci:chevron-right"
|
||||||
|
:class="
|
||||||
|
swiper_instance?.isBeginning
|
||||||
|
? '**:stroke-slate-200'
|
||||||
|
: '**:stroke-black'
|
||||||
|
"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="swiper_instance?.slideNext()"
|
||||||
|
:disabled="swiper_instance?.isEnd"
|
||||||
|
:class="
|
||||||
|
swiper_instance?.isEnd
|
||||||
|
? 'border-slate-200 cursor-not-allowed'
|
||||||
|
: 'border-black cursor-pointer'
|
||||||
|
"
|
||||||
|
class="size-[2.75rem] rounded-full border-[1.5px] click-effect flex-center"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="ci:chevron-left"
|
||||||
|
:class="
|
||||||
|
swiper_instance?.isEnd
|
||||||
|
? '**:stroke-slate-200'
|
||||||
|
: '**:stroke-black'
|
||||||
|
"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<Swiper :slides-per-view="3" :space-between="24" @swiper="onSwiper">
|
||||||
|
<SwiperSlide v-for="i in 4" :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"
|
||||||
|
/>
|
||||||
|
</SwiperSlide>
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="typo-p-sm">
|
|
||||||
5.0
|
|
||||||
</span>
|
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<Icon
|
<Icon
|
||||||
name="ci:star-solid"
|
name="ci:star-solid"
|
||||||
@@ -29,5 +26,8 @@
|
|||||||
class="size-4.5 **:fill-yellow-500"
|
class="size-4.5 **:fill-yellow-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="typo-p-sm">
|
||||||
|
5.0
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
// types
|
// types
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
maxQuantity: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,16 +14,19 @@ defineProps<Props>();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2 w-full items-end">
|
<div class="flex flex-col gap-2 w-full">
|
||||||
<p class="typo-p-sm text-slate-500">
|
<p class="typo-p-sm text-slate-500">
|
||||||
Hurry, only
|
سریع باش فقط
|
||||||
<span class="text-black">
|
<span class="text-black">
|
||||||
{{ quantity }}
|
{{ maxQuantity }}
|
||||||
</span>
|
</span>
|
||||||
items left in stock
|
عدد از این محصول باقی مانده
|
||||||
</p>
|
</p>
|
||||||
<div class="h-2 rounded-full relative bg-slate-200 w-full">
|
<div class="h-2 rounded-full relative bg-slate-200 w-full">
|
||||||
<div class="w-[85%] h-full absolute left-0 rounded-full bg-black" />
|
<div
|
||||||
|
:style="{ width: `${quantity * (100 / maxQuantity)}%` }"
|
||||||
|
class="h-full absolute right-0 rounded-full bg-black transition-all ease-out"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-6">
|
<div class="flex items-center gap-6">
|
||||||
<span class="typo-p-md text-black">
|
<span class="typo-p-md text-black">
|
||||||
Share:
|
اشتراک گذاری:
|
||||||
</span>
|
</span>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<NuxtLink>
|
<NuxtLink>
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
selectedSlide: number;
|
||||||
|
slides: {
|
||||||
|
id: number;
|
||||||
|
picture: string;
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const { slides, selectedSlide } = toRefs(props);
|
||||||
|
|
||||||
|
// emit
|
||||||
|
const emit = defineEmits(["update:selectedSlide"]);
|
||||||
|
|
||||||
|
// computed
|
||||||
|
|
||||||
|
const selectedSlideDetail = computed(() => {
|
||||||
|
return slides.value.find((item) => {
|
||||||
|
return item.id === selectedSlide.value;
|
||||||
|
})!;
|
||||||
|
});
|
||||||
|
|
||||||
|
// method
|
||||||
|
|
||||||
|
const changeSlide = (id: number) => {
|
||||||
|
emit("update:selectedSlide", id);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col relative gap-4">
|
||||||
|
<div class="bg-red-300 w-full relative aspect-square overflow-hidden rounded-200">
|
||||||
|
<img
|
||||||
|
class="size-full absolute object-cover"
|
||||||
|
:src="selectedSlideDetail.picture"
|
||||||
|
:alt="String(selectedSlideDetail.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between gap-4">
|
||||||
|
<div
|
||||||
|
@click="changeSlide(slide.id)"
|
||||||
|
v-for="slide in slides"
|
||||||
|
:class="selectedSlide === slide.id ? 'ring-black' : 'ring-transparent'"
|
||||||
|
class="cursor-pointer aspect-square w-[108px] ring-2 ring-offset-4 rounded-200 w-full overflow-hidden relative"
|
||||||
|
:key="slide.id"
|
||||||
|
>
|
||||||
|
<img class="absolute object-cover size-full" :src="slide.picture" :alt="String(slide.id)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full p-12 rounded-150 bg-white border-[0.5px] border-slate-200 flex flex-col gap-6">
|
||||||
|
<div class="flex justify-between items-start w-full">
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<span class="typo-h-6 text-black">
|
||||||
|
خیلی محصول خوبی بودددد
|
||||||
|
</span>
|
||||||
|
<span class="typo-p-sm text-slate-500">
|
||||||
|
منصور مرزبان در ۱۴۰۳/۱۲/۲ ساعت ۱۲:۳۴
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Rating />
|
||||||
|
</div>
|
||||||
|
<div class="typo-p-md">
|
||||||
|
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون
|
||||||
|
بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرد گذشته.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
+13
-11
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
// import
|
// import
|
||||||
|
|
||||||
import Tag from "~/components/ui/Tag.vue";
|
import Tag from "~/components/ui/Tag.vue";
|
||||||
@@ -16,22 +15,25 @@ type Props = {
|
|||||||
picture: string;
|
picture: string;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
rate?: number;
|
rate?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
// props
|
// props
|
||||||
|
|
||||||
defineProps<Props>();
|
defineProps<Props>();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative h-[500px] w-[400px] rounded-2xl bg-black/10 overflow-hidden p-6">
|
<div
|
||||||
|
class="relative size-full min-h-[31.25rem] rounded-2xl bg-black/10 overflow-hidden p-6"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src="~/assets/img/product-2.jpg"
|
src="~/assets/img/product-2.jpg"
|
||||||
class="size-full object-cover absolute inset-0"
|
class="size-full object-cover absolute inset-0"
|
||||||
alt="product-background"
|
alt="product-background"
|
||||||
/>
|
/>
|
||||||
<div class="flex justify-between items-center absolute px-6 pt-6 top-0 w-full inset-x-0">
|
<div
|
||||||
|
class="flex justify-between items-center absolute px-6 pt-6 top-0 w-full inset-x-0"
|
||||||
|
>
|
||||||
<Rate v-if="rate">
|
<Rate v-if="rate">
|
||||||
{{ rate }}
|
{{ rate }}
|
||||||
</Rate>
|
</Rate>
|
||||||
@@ -39,12 +41,12 @@ defineProps<Props>();
|
|||||||
{{ tag }}
|
{{ tag }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute inset-x-0 bottom-0 pb-6 px-6 flex justify-between items-center">
|
<div
|
||||||
<span class="typo-p-md">
|
class="absolute inset-x-0 bottom-0 pb-6 px-6 flex justify-between items-center"
|
||||||
${{ price }}
|
>
|
||||||
</span>
|
<span class="typo-p-md"> ${{ price }} </span>
|
||||||
<div class="flex flex-col gap-2 items-end">
|
<div class="flex flex-col gap-2 items-end">
|
||||||
<span class="typo-p-md ">
|
<span class="typo-p-md">
|
||||||
{{ brand }}
|
{{ brand }}
|
||||||
</span>
|
</span>
|
||||||
<span class="typo-sub-h-md">
|
<span class="typo-sub-h-md">
|
||||||
@@ -54,7 +56,7 @@ defineProps<Props>();
|
|||||||
<ColorCircle
|
<ColorCircle
|
||||||
v-for="color in colors"
|
v-for="color in colors"
|
||||||
:key="color"
|
:key="color"
|
||||||
:style="{backgroundColor: color}"
|
:style="{ backgroundColor: color }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
picture: string;
|
||||||
|
title: string;
|
||||||
|
color: string;
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const { picture, price, title, color } = toRefs(props);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="max-w-[500px] w-full h-[116px] flex items-center justify-between py-2 pe-6 ps-2 bg-white rounded-150">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="relative size-[100px] rounded-100 overflow-hidden border-[0.5px] border-slate-200">
|
||||||
|
<img :src="picture" :alt="title" class="object-cover absolute" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<span class="typo-sub-h-md text-black">{{ title }}</span>
|
||||||
|
<span class="typo-p-sm text-slate-500">{{ color }}</span>
|
||||||
|
<span class="typo-p-md text-black">{{ price }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button class="rounded-full">
|
||||||
|
افزودن به سبد
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
|
import type { SwiperClass } from "swiper/react";
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const {} = toRefs(props);
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const swiper_instance = ref<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
const slides = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "TEST"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const onSwiper = (swiper: SwiperClass) => {
|
||||||
|
swiper_instance.value = swiper;
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full my-20 relative">
|
||||||
|
<Swiper
|
||||||
|
:slides-per-view="3.65"
|
||||||
|
:space-between="20"
|
||||||
|
:slides-offset-after="125"
|
||||||
|
:slides-offset-before="125"
|
||||||
|
@swiper="onSwiper"
|
||||||
|
>
|
||||||
|
<SwiperSlide
|
||||||
|
v-for="slide in slides"
|
||||||
|
:key="slide.id"
|
||||||
|
>
|
||||||
|
<CategoryCard
|
||||||
|
category="یک دسته بندی تست"
|
||||||
|
picture="/img/product-1.jpg"
|
||||||
|
:count="20"
|
||||||
|
description="یک دسته بندی تستasdasd"
|
||||||
|
/>
|
||||||
|
</SwiperSlide>
|
||||||
|
</Swiper>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!swiper_instance?.isBeginning"
|
||||||
|
@click="swiper_instance?.slidePrev()"
|
||||||
|
class="absolute z-20 right-20 shadow-lg cursor-pointer shadow-black/25 bottom-[50%] bg-white rounded-full size-11.5 flex justify-center items-center"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="ci:arrow-right"
|
||||||
|
class="**:stroke-black"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!swiper_instance?.isEnd"
|
||||||
|
@click="swiper_instance?.slideNext()"
|
||||||
|
class="absolute z-20 left-20 shadow-lg cursor-pointer shadow-black/25 bottom-[50%] bg-white rounded-full size-11.5 flex justify-center items-center"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="ci:arrow-left"
|
||||||
|
class="**:stroke-black"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// import
|
||||||
|
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
|
import type { SwiperClass } from "swiper/react";
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const swiper_instance = ref<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
const slides = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "TEST"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const onSwiper = (swiper: SwiperClass) => {
|
||||||
|
swiper_instance.value = swiper;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (swiper: SwiperClass) => {
|
||||||
|
console.log(swiper.activeIndex, swiper.realIndex, swiper.snapIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full mb-20">
|
||||||
|
<div
|
||||||
|
class="relative"
|
||||||
|
>
|
||||||
|
<Swiper
|
||||||
|
:slides-per-view="1.2"
|
||||||
|
:loop="true"
|
||||||
|
:space-between="40"
|
||||||
|
:centered-slides="true"
|
||||||
|
@swiper="onSwiper"
|
||||||
|
@slide-change="onChange"
|
||||||
|
>
|
||||||
|
<SwiperSlide
|
||||||
|
v-for="slide in slides"
|
||||||
|
:key="slide.id"
|
||||||
|
>
|
||||||
|
<div class="relative w-full rounded-200 h-[80svh] overflow-hidden">
|
||||||
|
<img
|
||||||
|
class="absolute inset-0 size-full object-cover"
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div class="size-full absolute z-10 bg-linear-to-t from-black to-transparent" />
|
||||||
|
<div class="px-20 absolute z-10 w-full bottom-36">
|
||||||
|
<div class="border-b border-white/10 pb-6">
|
||||||
|
<h3 class="typo-hero-1 text-white">
|
||||||
|
Samsung {{ slide.id }}
|
||||||
|
</h3>
|
||||||
|
<div class="flex justify-between items-end">
|
||||||
|
<span class="typo-p-lg text-white">
|
||||||
|
توضیحات درمورد این محصول خاص
|
||||||
|
</span>
|
||||||
|
<Button class="invert rounded-full hover:bg-transparent">
|
||||||
|
خرید Samsung
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
</Swiper>
|
||||||
|
<div class="absolute w-full bottom-20 left-[50%] translate-x-[-50%] z-100">
|
||||||
|
<div class="container h-full">
|
||||||
|
<div class="h-full flex items-center justify-between px-20">
|
||||||
|
<button @click="swiper_instance?.slidePrev()">
|
||||||
|
<Icon
|
||||||
|
class="**:stroke-white cursor-pointer"
|
||||||
|
name="ci:arrow-right"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<div class="flex items-center justify-center gap-3 text-white">
|
||||||
|
<div
|
||||||
|
v-for="(slide, index) in slides"
|
||||||
|
:class="swiper_instance?.realIndex === index ? 'bg-white' : 'bg-transparent'"
|
||||||
|
class="border border-white size-3 rounded-full transition-all duration-200"
|
||||||
|
@click="swiper_instance?.slideTo(index)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button>
|
||||||
|
<Icon
|
||||||
|
@click="swiper_instance?.slideNext()"
|
||||||
|
class="**:stroke-white cursor-pointer"
|
||||||
|
name="ci:arrow-left"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const {} = toRefs(props);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="h-[100svh] mt-20 px-20">
|
||||||
|
<div class="flex items-center justify-between mb-20">
|
||||||
|
<span class="typo-h-4 text-black">
|
||||||
|
مقالات اخیر سایت
|
||||||
|
</span>
|
||||||
|
<Button variant="outlined" class="rounded-full" start-icon="ci:paper">
|
||||||
|
نمایش همه
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-12">
|
||||||
|
<div class="flex-1 flex flex-col gap-12">
|
||||||
|
<BlogPost
|
||||||
|
description="aaasd"
|
||||||
|
title="asd"
|
||||||
|
:comments="2"
|
||||||
|
link="#"
|
||||||
|
date="2020-06-10"
|
||||||
|
tag="asdsa"
|
||||||
|
/>
|
||||||
|
<BlogPost
|
||||||
|
description="aaasd"
|
||||||
|
title="asd"
|
||||||
|
:comments="2"
|
||||||
|
link="#"
|
||||||
|
date="2020-06-10"
|
||||||
|
tag="asdsa"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex-[0.8] flex flex-col">
|
||||||
|
<BlogPost
|
||||||
|
description="aaasd"
|
||||||
|
title="asd"
|
||||||
|
:comments="2"
|
||||||
|
link="#"
|
||||||
|
date="2020-06-10"
|
||||||
|
tag="asdsa"
|
||||||
|
variant="sm"
|
||||||
|
/>
|
||||||
|
<BlogPost
|
||||||
|
description="aaasd"
|
||||||
|
title="asd"
|
||||||
|
:comments="2"
|
||||||
|
link="#"
|
||||||
|
date="2020-06-10"
|
||||||
|
tag="asdsa"
|
||||||
|
variant="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// import
|
||||||
|
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
|
import type { SwiperClass } from "swiper/react";
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const {} = toRefs(props);
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const swiper_instance = ref<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const onSwiper = (swiper: SwiperClass) => {
|
||||||
|
swiper_instance.value = swiper;
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative max-h-[700px] flex justify-center items-center h-svh w-full">
|
||||||
|
<img
|
||||||
|
class="absolute size-full object-cover"
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div class="absolute bg-black/60 size-full z-10" />
|
||||||
|
|
||||||
|
<div class="w-full relative z-10">
|
||||||
|
<Swiper
|
||||||
|
:slides-per-view="1"
|
||||||
|
:loop="true"
|
||||||
|
:space-between="40"
|
||||||
|
:centered-slides="true"
|
||||||
|
:grab-cursor="true"
|
||||||
|
@swiper="onSwiper"
|
||||||
|
>
|
||||||
|
<SwiperSlide
|
||||||
|
v-for="i in 6"
|
||||||
|
:key="i"
|
||||||
|
>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<div class="max-w-[900px] px-4 text-white flex flex-col items-center gap-4">
|
||||||
|
<Icon name="ci:instagram" size="28" class="**:stroke-white" />
|
||||||
|
<p class="typo-h-5 leading-[150%] text-center">
|
||||||
|
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با
|
||||||
|
استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله
|
||||||
|
در ستون و سطرآنچنان که لازم.
|
||||||
|
</p>
|
||||||
|
<span class="typo-p-xl text-center">
|
||||||
|
- منصور مرزبان
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
</Swiper>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center gap-3 text-white mt-6 relative z-10">
|
||||||
|
<div
|
||||||
|
v-for="(i, index) in 6"
|
||||||
|
:class="swiper_instance?.realIndex === index ? 'bg-white' : 'bg-transparent'"
|
||||||
|
class="border border-white size-2 rounded-full transition-all duration-200"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
// import
|
||||||
|
|
||||||
|
import { useDraggable } from "@vueuse/core";
|
||||||
|
|
||||||
|
// state
|
||||||
|
|
||||||
|
const clipPathPercent = ref(49);
|
||||||
|
|
||||||
|
const draggableEl = ref<HTMLElement | null>(null);
|
||||||
|
const previewContainerEl = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const { x: dragAxisX } = useDraggable(draggableEl, {
|
||||||
|
initialValue: { x: 0, y: 0 },
|
||||||
|
axis: "x"
|
||||||
|
});
|
||||||
|
|
||||||
|
// watch
|
||||||
|
|
||||||
|
watch(() => dragAxisX.value, (newValue) => {
|
||||||
|
const clientRect = previewContainerEl.value?.getBoundingClientRect()!;
|
||||||
|
const percent = clientRect.width / 100;
|
||||||
|
const clipPercent = (newValue - clientRect.x - 8) / percent;
|
||||||
|
if (clipPercent >= 5 && clipPercent <= 95) {
|
||||||
|
clipPathPercent.value = clipPercent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="flex flex-col items-center gap-3 mb-16">
|
||||||
|
<span class="typo-p-md text-slate-500">یک متن تست لورم</span>
|
||||||
|
<span class="typo-h-3 text-black">تفاوت محصول را ببینید در اینجا</span>
|
||||||
|
</div>
|
||||||
|
<div ref="previewContainerEl" class="rounded-200 overflow-hidden h-[90svh] relative">
|
||||||
|
|
||||||
|
<img
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
class="select-none absolute size-full object-cover"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="absolute size-full right-0 w-full"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/img/hero-bg.jpg"
|
||||||
|
class="overlay-image select-none absolute object-cover size-full hue-rotate-200 brightness-35"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
left: `${clipPathPercent}%`
|
||||||
|
}"
|
||||||
|
ref="draggableEl"
|
||||||
|
class="select-none w-2 h-full bg-white absolute left-0 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cursor-grab hover:scale-115 transition-transform rounded-full absolute bg-white size-11 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<Icon name="ci:arrows" size="24" class="**:stroke-black" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="absolute bottom-0 p-10 w-full flex justify-between items-end bg-linear-to-t from-black/55 to-transparent">
|
||||||
|
<div class="flex flex-col gap-2 text-white">
|
||||||
|
<span class="typo-p-md">رنگ محصول</span>
|
||||||
|
<span class="typo-h-3">نارنجی</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col justify-start gap-2 text-white">
|
||||||
|
<span class="typo-p-md">رنگ محصول</span>
|
||||||
|
<span class="typo-h-3">سفید</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.overlay-image {
|
||||||
|
clip-path: polygon(
|
||||||
|
v-bind('clipPathPercent + "%"') 0,
|
||||||
|
100% 0,
|
||||||
|
100% 100%,
|
||||||
|
v-bind('clipPathPercent + "%"') 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="bg-slate-50 p-20">
|
||||||
|
<div class="flex gap-12 my-42 container">
|
||||||
|
<div class="flex flex-col gap-6 min-w-fit">
|
||||||
|
<h3 class="typo-h-3">
|
||||||
|
نظرات کاربران
|
||||||
|
</h3>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<Rating />
|
||||||
|
<span class="typo-p-sm">
|
||||||
|
بر اساس ۴ نظر
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Button class="rounded-full">
|
||||||
|
نظر بنویسید
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-12">
|
||||||
|
<Comment />
|
||||||
|
<Comment />
|
||||||
|
<Comment />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
// state
|
||||||
|
const quantity = ref(1);
|
||||||
|
const maxQuantity = ref(10);
|
||||||
|
|
||||||
|
const selectedSlide = ref(0);
|
||||||
|
const slides = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
picture: "/img/product-1.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
picture: "/img/product-2.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
picture: "/img/product-3.jpg",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-12 container pt-[5rem]">
|
||||||
|
<Slider
|
||||||
|
class="flex-1"
|
||||||
|
v-model:selectedSlide="selectedSlide"
|
||||||
|
:slides="slides"
|
||||||
|
/>
|
||||||
|
<div class="flex-1 flex flex-col gap-3 mt-12">
|
||||||
|
<span class="typo-label-sm"> سامسونگ </span>
|
||||||
|
<h1 class="typo-h-2">موبایل Nova</h1>
|
||||||
|
<div class="flex w-full items-center justify-between">
|
||||||
|
<span class="typo-p-2xl"> $689.00 </span>
|
||||||
|
<Rating />
|
||||||
|
</div>
|
||||||
|
<p class="typo-p-md text-slate-500 text-justify">
|
||||||
|
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با
|
||||||
|
استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله
|
||||||
|
در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد
|
||||||
|
نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد.
|
||||||
|
کتابهای زیادی در شصت و سه درصد گذشته.
|
||||||
|
</p>
|
||||||
|
<div class="w-full flex flex-col gap-6 mt-4">
|
||||||
|
<RemainQuantity
|
||||||
|
:maxQuantity="maxQuantity"
|
||||||
|
:quantity="quantity"
|
||||||
|
/>
|
||||||
|
<div class="w-full flex gap-3 flex-col">
|
||||||
|
<div class="w-full flex gap-3">
|
||||||
|
<Button class="w-full rounded-full" end-icon="ci:plus">
|
||||||
|
افزودن به سبد خرید
|
||||||
|
</Button>
|
||||||
|
<QuantityCounter
|
||||||
|
v-model="quantity"
|
||||||
|
:max="maxQuantity"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button class="w-full rounded-full" variant="outlined">
|
||||||
|
همین الان بخر
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<InfoCard />
|
||||||
|
<Share />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
|
|
||||||
// state
|
|
||||||
const quantity = ref(1);
|
|
||||||
const maxQuantity = ref(10);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex gap-12">
|
|
||||||
<div class="w-[800px] flex flex-col items-end gap-3 mt-12">
|
|
||||||
<span class="typo-label-sm">
|
|
||||||
Nova
|
|
||||||
</span>
|
|
||||||
<h1 class="typo-h-2">
|
|
||||||
Nova
|
|
||||||
</h1>
|
|
||||||
<div class="flex w-full items-center justify-between">
|
|
||||||
<Rating />
|
|
||||||
<span class="typo-p-2xl">
|
|
||||||
$689.00
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p class="typo-p-md text-slate-500 text-left">
|
|
||||||
Compact, stylish, and engineered for the future, Eco Tunes are more than just headphones; they're a
|
|
||||||
statement. Hear the future, save the planet.
|
|
||||||
</p>
|
|
||||||
<div class="w-full flex flex-col gap-6 mt-4">
|
|
||||||
<RemainQuantity :quantity="maxQuantity" />
|
|
||||||
<div class="w-full flex gap-3 flex-col">
|
|
||||||
<div class="w-full flex gap-3">
|
|
||||||
<Button
|
|
||||||
class="w-full"
|
|
||||||
end-icon="ci:plus"
|
|
||||||
>
|
|
||||||
Add to cart
|
|
||||||
</Button>
|
|
||||||
<QuantityCounter v-model="quantity" :max="maxQuantity" />
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
class="w-full"
|
|
||||||
variant="outlined"
|
|
||||||
>
|
|
||||||
Buy it now
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<InfoCard />
|
|
||||||
<Share />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bg-red-300 w-full h-[500px] rounded-200">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div 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
|
||||||
|
color="سبز"
|
||||||
|
:price="240000"
|
||||||
|
picture="/img/product-1.jpg"
|
||||||
|
title="نام محصول"
|
||||||
|
class="absolute right-6 bottom-6"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// types
|
// types
|
||||||
import Tooltip from "~/components/Tooltip.vue";
|
import Tooltip from "~/components/ui/Tooltip.vue";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variant?: "solid" | "outlined";
|
variant?: "solid" | "outlined";
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full flex flex-col-center font-iran-yekan-x" dir="rtl">
|
<div class="w-full flex flex-col-center persian-number font-yekan-bakh" dir="rtl">
|
||||||
<Header />
|
<Header />
|
||||||
<main class="w-full overflow-x-hidden container">
|
<main class="w-full overflow-x-hidden">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
+17
-15
@@ -3,22 +3,20 @@ export default defineNuxtConfig({
|
|||||||
compatibilityDate: "2024-11-01",
|
compatibilityDate: "2024-11-01",
|
||||||
ssr: false,
|
ssr: false,
|
||||||
devtools: { enabled: false },
|
devtools: { enabled: false },
|
||||||
css: [
|
css: ["~/assets/css/tailwind.css", "swiper/css"],
|
||||||
"~/assets/css/tailwind.css",
|
|
||||||
],
|
|
||||||
|
|
||||||
postcss: {
|
postcss: {
|
||||||
plugins: {
|
plugins: {
|
||||||
"@tailwindcss/postcss": {},
|
"@tailwindcss/postcss": {},
|
||||||
autoprefixer: {}
|
autoprefixer: {},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
components: [
|
components: [
|
||||||
{
|
{
|
||||||
path: "~/components",
|
path: "~/components",
|
||||||
pathPrefix: false
|
pathPrefix: false,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
icon: {
|
icon: {
|
||||||
@@ -26,20 +24,24 @@ export default defineNuxtConfig({
|
|||||||
customCollections: [
|
customCollections: [
|
||||||
{
|
{
|
||||||
prefix: "ci",
|
prefix: "ci",
|
||||||
dir: "./public/icons"
|
dir: "./public/icons",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [[
|
modules: [
|
||||||
|
[
|
||||||
"@nuxtjs/google-fonts",
|
"@nuxtjs/google-fonts",
|
||||||
{
|
{
|
||||||
families: {
|
families: {
|
||||||
"DM Sans": "100..900",
|
"DM Sans": "100..900",
|
||||||
Inter: "100..900",
|
Inter: "100..900",
|
||||||
download: true,
|
download: true,
|
||||||
inject: false
|
inject: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
], "@nuxt/icon", "reka-ui/nuxt"]
|
],
|
||||||
|
"@nuxt/icon",
|
||||||
|
"reka-ui/nuxt",
|
||||||
|
],
|
||||||
});
|
});
|
||||||
Generated
+20
@@ -15,6 +15,7 @@
|
|||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
"nuxt": "^3.14.1592",
|
"nuxt": "^3.14.1592",
|
||||||
"reka-ui": "^1.0.0-alpha.6",
|
"reka-ui": "^1.0.0-alpha.6",
|
||||||
|
"swiper": "^11.1.15",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vue-scrollto": "^2.20.0",
|
"vue-scrollto": "^2.20.0",
|
||||||
@@ -8957,6 +8958,25 @@
|
|||||||
"url": "https://opencollective.com/svgo"
|
"url": "https://opencollective.com/svgo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swiper": {
|
||||||
|
"version": "11.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.15.tgz",
|
||||||
|
"integrity": "sha512-IzWeU34WwC7gbhjKsjkImTuCRf+lRbO6cnxMGs88iVNKDwV+xQpBCJxZ4bNH6gSrIbbyVJ1kuGzo3JTtz//CBw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/swiperjs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "open_collective",
|
||||||
|
"url": "http://opencollective.com/swiper"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/system-architecture": {
|
"node_modules/system-architecture": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
"nuxt": "^3.14.1592",
|
"nuxt": "^3.14.1592",
|
||||||
"reka-ui": "^1.0.0-alpha.6",
|
"reka-ui": "^1.0.0-alpha.6",
|
||||||
|
"swiper": "^11.1.15",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vue-scrollto": "^2.20.0",
|
"vue-scrollto": "^2.20.0",
|
||||||
|
|||||||
+11
-19
@@ -1,26 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import Categories from "~/components/home/Categories.vue";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full h-screen p-8 flex gap-8 justify-start items-start">
|
<div class="w-full">
|
||||||
<Product
|
<Hero />
|
||||||
brand="Samsung"
|
<Preview />
|
||||||
title="Galaxy S20 Ultra"
|
<Categories />
|
||||||
picture="/assets/img/product-1.jpg"
|
<ProductsSlider title="یک عنوان تستی" />
|
||||||
:colors="['#0000ff', '#00ff00','red']"
|
<Brands />
|
||||||
:price="599"
|
<ProductHero />
|
||||||
:rate="2.4"
|
<MostRecentComments />
|
||||||
tag="New"
|
<LatestStories />
|
||||||
/>
|
|
||||||
<Product
|
|
||||||
brand="Samsung"
|
|
||||||
title="Galaxy S20 Ultra"
|
|
||||||
picture="/assets/img/product-1.jpg"
|
|
||||||
:colors="['#0000ff', '#00ff00','red']"
|
|
||||||
:price="599"
|
|
||||||
:rate="2.4"
|
|
||||||
tag="New"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ProductView />
|
<ProductHero />
|
||||||
|
<Video />
|
||||||
|
<Comments />
|
||||||
|
<RelatedProducts title="محصولات مشابه" />
|
||||||
</template>
|
</template>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 5.2 MiB |
Reference in New Issue
Block a user