reservation style

This commit is contained in:
2026-02-26 10:41:35 +03:30
parent 2d7b48b5b7
commit 632304c271
5 changed files with 178 additions and 0 deletions

View File

@@ -20,6 +20,20 @@
"title": "دسته بندی ها",
"description": "از بین صدها مرکز زیبایی، دقیقا همونی که میخای رو پیدا کن."
},
"Reservation": {
"title": "رزرو خدمات زیبایی، ساده\u200Cتر از همیشه",
"stations" : "مراکز معتبر",
"online_reserve" : "رزرو انلاین سریع",
"start_reserve" : "شروع رزرو",
"customer" : "مشتریان",
"customer_number" : "+100K",
"clinic" : "کلینیک فعال",
"clinic_number" : "+336",
"salon" : "سالن زیبایی",
"salon_number" : "+345",
"score" : "امتیازدهی واقعی کاربران",
"description": "ما این پلتفرم را ساختیم تا بتوانید بهترین سالن\u200Cهای زیبایی و کلینیک\u200Cهای معتبر را به راحتی پیدا کنید.\n مقایسه، رزرو آنلاین و تجربه\u200Cای بی\u200Cدردسر."
},
"Application": {
"title": "دانلود نرم افزار تلفن همراه 141",
"description": "نسخه‌ی تلفن همراه اپلیکیشن مرکز مدیریت راه‌های کشور با قابلیت‌هایی نظیر نمایش تصاویر دوربین‌های، نظارتی در سراسر کشور، مسیریابی همراه با نمایش مسافت و زمان تقریبی و جزئیات مسیر، مشاهده اخبار متنی و شنیداری، کروکی ترافیک استان‌های کشور، دریافت اطلاعیه‌های مربوط به مسیرهای پرتردد و ... آماده دریافت از مارکت‌های مختلف می‌باشد.",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -0,0 +1,160 @@
"use client";
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
import { ArrowTopLeft } from "@/assets";
import Image from "next/image";
export default function Reservation() {
const t = useTranslations("Reservation");
return (
<section className="w-full my-32 lg:my-40">
<div className="container mx-auto px-6">
<motion.div
initial={{ opacity: 0, y: 80 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, ease: "easeOut" }}
className="
relative
bg-primary-50
rounded-tr-[60px] md:rounded-tr-[80px]
rounded-bl-[60px] md:rounded-bl-[80px]
p-8 md:px-12
grid
gap-16
grid-cols-2
items-center
"
>
{/* ================= TEXT CONTENT ================= */}
<motion.div
initial={{ opacity: 0, x: -40 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.3, duration: 0.7 }}
className="text-white space-y-8 order-1 w-full lg:px-10"
>
<h2 className="text-xl md:text-2xl lg:text-3xl font-bold leading-relaxed">
{t("title")}
</h2>
<p className="text-sm md:text-base text-primary-100 leading-8 max-w-xl">
{t("description")}
</p>
{/* Features */}
<div className="flex flex-wrap items-center gap-x-8 gap-y-4 pt-2 text-sm">
{[t("stations"), t("online_reserve"), t("score")].map(
(item, i) => (
<div key={i} className="flex items-center gap-2">
<span className="w-3 h-3 rounded-full bg-primary-200" />
<span className="text-xs md:text-sm">{item}</span>
</div>
)
)}
</div>
{/* Button */}
<motion.button
whileHover={{ scale: 1.07 }}
whileTap={{ scale: 0.95 }}
className="
mt-4
bg-white
flex
items-center
gap-2
text-primary-100
px-6
py-3
rounded-xl
font-medium
shadow-lg
w-fit
"
>
{t("start_reserve")}
<ArrowTopLeft className="size-5" />
</motion.button>
</motion.div>
{/* ================= IMAGE + STATS ================= */}
<motion.div
initial={{ opacity: 0, x: 60 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.4, duration: 0.9 }}
className="relative flex flex-col items-center order-2"
>
{/* Image */}
<div
className="
relative
rounded-full
overflow-hidden
border-8
border-white
shadow-2xl
w-[260px] h-[320px]
md:w-[320px] md:h-[420px]
lg:w-[450px] lg:h-[580px]
"
>
<Image
src="/images/reservation/reservation.jpg"
alt="reservation"
fill
className="object-cover"
/>
</div>
{/* Stats Card */}
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2, duration: 0.6 }}
className="
mt-8
lg:absolute
lg:-bottom-16
bg-card
w-full
max-w-md
rounded-[40px] md:rounded-[60px]
shadow-2xl
px-6
py-6
flex
items-center
justify-between
gap-6
"
>
{[
{ number: t("customer_number"), label: t("customer") },
{ number: t("clinic_number"), label: t("clinic") },
{ number: t("salon_number"), label: t("salon") },
].map((item, i) => (
<div key={i} className="text-center flex-1">
<p className="text-lg md:text-xl font-bold text-text-primary">
{item.number}
</p>
<p className="text-xs md:text-sm text-text-muted mt-1">
{item.label}
</p>
</div>
))}
</motion.div>
</motion.div>
</motion.div>
</div>
</section>
);
}

View File

@@ -1,11 +1,13 @@
import BannerComponent from "./Banner";
import Categories from "@/components/Home/Desktop/Categories";
import Reservation from "@/components/Home/Desktop/Reservation";
export default function DesktopHome() {
return (
<div className="container mx-auto h-full w-full">
<BannerComponent />
<Categories />
<Reservation />
</div>
);
}

View File

@@ -131,6 +131,7 @@ body {
/* =====================
Primary (Purple)
====================== */
--color-primary-50: #140B4E;
--color-primary-100: #7d34b9;
--color-primary-200: #9a5cff;
--color-primary-300: #b38bff;
@@ -191,6 +192,7 @@ body {
--color-text-muted: #9ca3af;
--color-primary-100: #b38bff;
--color-primary-50: #140B4E;
--color-primary-200: #9a5cff;
--color-primary-300: #7d34b9;