salons section
This commit is contained in:
@@ -20,6 +20,10 @@
|
||||
"title": "دسته بندی ها",
|
||||
"description": "از بین صدها مرکز زیبایی، دقیقا همونی که میخای رو پیدا کن."
|
||||
},
|
||||
"Salons": {
|
||||
"title": "سالن ها و کلینیک های زیبایی",
|
||||
"description": "از بین صدها مرکز، دقیقا همونی که میخای رو پیدا کن."
|
||||
},
|
||||
"Reservation": {
|
||||
"title": "رزرو خدمات زیبایی، ساده\u200Cتر از همیشه",
|
||||
"stations": "مراکز معتبر",
|
||||
|
||||
BIN
public/images/salons/salon.jpg
Normal file
BIN
public/images/salons/salon.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
@@ -68,7 +68,7 @@ export function CarouselComponent({ title, description }: Props) {
|
||||
{categories.map((category) => (
|
||||
<CarouselItem
|
||||
key={category.id}
|
||||
className="after:bg-border relative after:absolute after:top-1/2 after:left-2 after:h-[50%] after:w-px after:-translate-y-1/2 after:content-[''] last:after:hidden md:basis-1/5 lg:basis-1/7"
|
||||
className="after:bg-border relative after:absolute after:top-1/2 after:left-2 after:h-[50%] after:w-px after:-translate-y-1/2 after:content-[''] last:after:hidden md:basis-1/3 lg:basis-1/6"
|
||||
>
|
||||
<motion.div variants={itemVariants} className="p-1">
|
||||
<motion.div
|
||||
|
||||
124
src/components/Home/Desktop/Salons/CarouselComponent.tsx
Normal file
124
src/components/Home/Desktop/Salons/CarouselComponent.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent } from "@/components/UI/card";
|
||||
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/UI/Carousel";
|
||||
import {salons} from "@/data/mockCategories";
|
||||
import Image from "next/image";
|
||||
import { easeOut, motion } from "framer-motion";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const containerVariants = {
|
||||
hidden: {},
|
||||
show: {
|
||||
transition: {
|
||||
staggerChildren: 0.08,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
y: 30,
|
||||
scale: 0.95,
|
||||
},
|
||||
show: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
scale: 1,
|
||||
transition: {
|
||||
duration: 0.4,
|
||||
ease: easeOut,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function CarouselComponent({ title, description }: Props) {
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
<Carousel dir="rtl" className="w-full" opts={{ direction: "rtl" }}>
|
||||
{/* 🔥 Animated Header */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 40 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="my-5 flex h-full w-full items-center justify-between"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-x-2">
|
||||
<motion.div
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: 64 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="bg-primary-100 w-4 rounded-2xl rounded-tr-none"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-lg font-semibold">{title}</p>
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
</span>
|
||||
</motion.div>
|
||||
|
||||
{/* 🔥 Animated Carousel Items */}
|
||||
<motion.div variants={containerVariants} initial="hidden" animate="show">
|
||||
<CarouselContent>
|
||||
{salons.map((category) => (
|
||||
<CarouselItem
|
||||
key={category.id}
|
||||
className="after:bg-border relative after:absolute after:top-1/2 after:left-2 after:h-[60%] after:w-px after:-translate-y-1/2 after:content-[''] last:after:hidden md:basis-1/3 lg:basis-1/5"
|
||||
>
|
||||
<motion.div variants={itemVariants} className="p-1">
|
||||
<motion.div
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
y: -5,
|
||||
}}
|
||||
transition={{ type: "spring", stiffness: 300 }}
|
||||
>
|
||||
<Card dir="rtl" className="cursor-pointer transition-shadow hover:shadow-xl">
|
||||
<CardContent className="flex h-30 flex-col items-center justify-center gap-3 ">
|
||||
<motion.div
|
||||
whileHover={{ rotate: 5 }}
|
||||
transition={{ type: "spring", stiffness: 200 }}
|
||||
className="h-full"
|
||||
>
|
||||
<Image
|
||||
src={category.image}
|
||||
alt={category.salon_name}
|
||||
width={200}
|
||||
height={500}
|
||||
className="rounded-xl"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<p className="text-text-muted font-semibold">{category.salon_name}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
</motion.div>
|
||||
|
||||
{/* 🔥 Animated Controls */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="absolute top-10 left-16 flex gap-2"
|
||||
>
|
||||
<motion.div whileTap={{ scale: 0.85 }}>
|
||||
<CarouselPrevious />
|
||||
</motion.div>
|
||||
<motion.div whileTap={{ scale: 0.85 }}>
|
||||
<CarouselNext />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</Carousel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
src/components/Home/Desktop/Salons/index.tsx
Normal file
14
src/components/Home/Desktop/Salons/index.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { CarouselComponent } from "./CarouselComponent";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const Salons = () => {
|
||||
const t = useTranslations("Salons");
|
||||
|
||||
return (
|
||||
<div className="container mx-auto my-16">
|
||||
<CarouselComponent title={t("title")} description={t("description")} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Salons;
|
||||
@@ -1,6 +1,7 @@
|
||||
import BannerComponent from "./Banner";
|
||||
import Categories from "@/components/Home/Desktop/Categories";
|
||||
import Reservation from "@/components/Home/Desktop/Reservation";
|
||||
import Categories from "./Categories";
|
||||
import Reservation from "./Reservation";
|
||||
import Salons from "./Salons";
|
||||
|
||||
export default function DesktopHome() {
|
||||
return (
|
||||
@@ -8,6 +9,7 @@ export default function DesktopHome() {
|
||||
<BannerComponent />
|
||||
<Categories />
|
||||
<Reservation />
|
||||
<Salons />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,3 +45,59 @@ export const categories = [
|
||||
image: "/images/categories/ژل.jpg",
|
||||
},
|
||||
];
|
||||
export const salons = [
|
||||
{
|
||||
id: 1,
|
||||
salon_name: "سالن همارو",
|
||||
rate : "4",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
salon_name: "سالن بیوتی",
|
||||
rate : "4",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
rate : "4",
|
||||
salon_name: "سالن عروس",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
rate : "4",
|
||||
salon_name: "سالن فیشیال",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
rate : "4",
|
||||
salon_name: "سالن زیبایی",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
rate : "4",
|
||||
salon_name: "سالن همارو",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
rate : "4",
|
||||
salon_name: "سالن عروس",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
rate : "4",
|
||||
salon_name: "سالن بیوتی",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
rate : "4",
|
||||
salon_name: "سالن بیوتی",
|
||||
image: "/images/salons/salon.jpg",
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user