feat: plans page

This commit is contained in:
2026-06-11 19:49:12 +03:30
parent 1988480ff6
commit e802abb12f
6 changed files with 208 additions and 1 deletions

BIN
public/images/basic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
public/images/pro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
public/images/standard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -0,0 +1,30 @@
---
import ActionLink from "@/components/landing/ActionLink.astro";
import { LucideIcon } from "@/components/ui/lucide-icon";
---
<div
class="glass-surface flex flex-col gap-6 p-6 md:flex-row md:items-center md:justify-between md:p-8"
>
<div class="flex items-center gap-4">
<span class="contact-icon size-12 rounded-xl">
<LucideIcon name="headset" className="size-6" />
</span>
<div>
<p class="font-semibold text-foreground">به یک پلن اختصاصی نیاز دارید؟</p>
<p class="mt-1 text-sm text-muted-foreground">
تیم ما به شما کمک می‌کند پلنی متناسب با نیازهای مجموعه‌تان داشته باشید.
</p>
</div>
</div>
<ActionLink
href="#contact-form"
variant="outline"
size="lg"
class="shrink-0 rounded-lg px-6 [&_svg]:ms-1"
>
تماس با پشتیبانی
<LucideIcon name="arrowLeft" className="size-4" />
</ActionLink>
</div>

View File

@@ -4,6 +4,7 @@ import {
Bell, Bell,
BicepsFlexed, BicepsFlexed,
Building2, Building2,
Calendar,
Check, Check,
Cloud, Cloud,
Dumbbell, Dumbbell,
@@ -20,6 +21,7 @@ import {
UserCircle, UserCircle,
Users, Users,
Wallet, Wallet,
X,
type LucideIcon as LucideIconComponent, type LucideIcon as LucideIconComponent,
} from "lucide-react" } from "lucide-react"
@@ -48,6 +50,8 @@ export const landingIcons = {
thumbsUp: ThumbsUp, thumbsUp: ThumbsUp,
star: Star, star: Star,
check: Check, check: Check,
calendar: Calendar,
x: X,
} as const satisfies Record<string, LucideIconComponent> } as const satisfies Record<string, LucideIconComponent>
export type LandingIconName = keyof typeof landingIcons export type LandingIconName = keyof typeof landingIcons

View File

@@ -1,9 +1,182 @@
--- ---
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import { LucideIcon } from "@/components/ui/lucide-icon";
import ContactBanner from "@/components/contact/ContactBanner.astro";
const plans = [
{
title: "پلن ساده",
description: "بهترین انتخاب برای باشگاه‌های تازه به راه افتاده.",
userCount: 50,
coachCount: 5,
pricePerMonth: 2_500_000,
time: 30,
accessToPublicMovments: true,
accessToPublicMeals: false,
imageUrl: "/images/basic.png",
popular: false,
},
{
title: "پلن استاندارد",
description: "ایده‌آل برای باشگاه‌های در حال رشد با اعضای فعال.",
userCount: 100,
coachCount: 10,
pricePerMonth: 3_500_000,
time: 30,
accessToPublicMovments: true,
accessToPublicMeals: true,
imageUrl: "/images/standard.png",
popular: true,
},
{
title: "پلن حرفه ای",
description:
"مناسب برای باشگاه‌های بزرگ که به دسترسی کامل و انعطاف‌پذیری بالا نیاز دارند.",
userCount: Infinity,
coachCount: Infinity,
pricePerMonth: 4_500_000,
time: 90,
accessToPublicMovments: true,
accessToPublicMeals: true,
imageUrl: "/images/pro.png",
popular: false,
},
];
function formatLimit(value: number) {
return value === Infinity ? "نامحدود" : String(value);
}
--- ---
<Layout title="پلن‌ها | نکستا"> <Layout title="پلن‌ها | نکستا">
<section class="mx-auto max-w-7xl px-6 py-16 lg:px-8"> <section class="mx-auto max-w-7xl px-6 py-16 lg:px-8">
<h1 class="text-3xl font-bold text-foreground">پلن‌ها</h1> <h1 class="text-3xl text-center font-bold text-foreground">
پلن
<span class="text-primary"> متناسب </span>
با باشگاه شما
</h1>
<section class="mt-10 grid grid-cols-1 gap-6 md:grid-cols-3">
{
plans.map(
({
accessToPublicMeals,
description,
coachCount,
pricePerMonth,
imageUrl,
accessToPublicMovments,
time,
title,
userCount,
popular,
}) => (
<article class="relative flex flex-col rounded-xl border border-primary bg-card p-5">
<img src={imageUrl} alt="" class="w-full rounded-lg" />
<div class="flex justify-between pt-5">
<div class="text-xl text-primary">{title}</div>
<div>
<span class="font-medium">
{pricePerMonth.toLocaleString("fa-IR")}
</span>
<span class="text-xs">تومان / ماهانه</span>
</div>
</div>
<p class="mt-2 text-sm text-muted-foreground">{description}</p>
<ul class="mt-8 flex flex-1 flex-col gap-4">
<li class="flex items-center justify-between text-sm">
<span class="flex items-center gap-2">
<LucideIcon name="users" className="size-4 text-primary" />
محدودیت اعضا
</span>
<span class="text-foreground">{formatLimit(userCount)}</span>
</li>
<hr />
<li class="flex items-center justify-between text-sm">
<span class="flex items-center gap-2">
<LucideIcon
name="userCircle"
className="size-4 text-primary"
/>
محدودیت مربیان
</span>
<span class="text-foreground">{formatLimit(coachCount)}</span>
</li>
<hr />
<li class="flex items-center justify-between text-sm">
<span class="flex items-center gap-2">
<LucideIcon
name="calendar"
className="size-4 text-primary"
/>
مدت زمان
</span>
<span class="text-foreground">{time} روز</span>
</li>
<hr />
<li class="flex items-center justify-between text-sm">
<span>دسترسی به حرکات عمومی</span>
{accessToPublicMovments ? (
<span class="flex size-5 shrink-0 items-center justify-center rounded-full border border-primary">
<LucideIcon
name="check"
className="size-3 text-primary"
/>
</span>
) : (
<span class="flex size-5 shrink-0 items-center justify-center rounded-full border border-muted-foreground/50">
<LucideIcon
name="x"
className="size-3 text-muted-foreground"
/>
</span>
)}
</li>
<hr />
<li class="flex items-center justify-between text-sm">
<span>دسترسی به وعده‌های عمومی</span>
{accessToPublicMeals ? (
<span class="flex size-5 shrink-0 items-center justify-center rounded-full border border-primary">
<LucideIcon
name="check"
className="size-3 text-primary"
/>
</span>
) : (
<span class="flex size-5 shrink-0 items-center justify-center rounded-full border border-muted-foreground/50">
<LucideIcon
name="x"
className="size-3 text-muted-foreground"
/>
</span>
)}
</li>
</ul>
<div class="mt-6 relative">
{popular && (
<span class="mb-3 absolute -top-6 right-1/2 translate-x-1/2 block w-fit rounded-t-lg border border-primary px-3 py-1 text-xs text-primary">
محبوب‌ترین
</span>
)}
<button
type="button"
class:list={[
"w-full cursor-pointer rounded-full py-2.5 text-sm font-medium transition-colors",
popular
? "bg-primary text-primary-foreground hover:bg-primary/80"
: "border border-primary bg-transparent text-primary hover:bg-primary/10",
]}
>
خرید
</button>
</div>
</article>
),
)
}
</section>
<div class="mt-12 md:mt-16">
<ContactBanner />
</div>
</section> </section>
</Layout> </Layout>