267 lines
8.4 KiB
TypeScript
267 lines
8.4 KiB
TypeScript
"use client";
|
|
import type { LucideIcon } from "lucide-react";
|
|
import {
|
|
ArrowRight,
|
|
Bell,
|
|
Book,
|
|
Brush,
|
|
CalendarCheck2,
|
|
CheckSquare,
|
|
ClipboardList,
|
|
Code,
|
|
Database,
|
|
FileText,
|
|
GitBranch,
|
|
GitPullRequest,
|
|
LayoutGrid,
|
|
LifeBuoy,
|
|
MonitorSmartphone,
|
|
PhoneCall,
|
|
Server,
|
|
Settings2,
|
|
Slack,
|
|
Users,
|
|
Zap,
|
|
} from "lucide-react";
|
|
import { useState } from "react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Switch } from "@/components/ui/switch";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const formatPrice = (value: string | number) =>
|
|
`${(typeof value === "string" ? Number(value) : value).toLocaleString("fa-IR")} ریال`;
|
|
|
|
interface FeatureItem {
|
|
icon: LucideIcon;
|
|
text: string;
|
|
}
|
|
|
|
interface PricingPlan {
|
|
name: string;
|
|
priceMonthly: number;
|
|
priceYearly: number;
|
|
description: string;
|
|
bestFor: string;
|
|
features?: FeatureItem[];
|
|
mostPopular?: boolean;
|
|
cta: {
|
|
text: string;
|
|
href: string;
|
|
};
|
|
}
|
|
|
|
const PLANS: PricingPlan[] = [
|
|
{
|
|
name: "شروع",
|
|
priceMonthly: 90000,
|
|
priceYearly: 900000,
|
|
description: "عالی برای توسعهدهندگان مستقل",
|
|
bestFor: "فریلنسرهای تازهکار",
|
|
features: [
|
|
{ icon: Code, text: "دسترسی به کامپوننتهای اصلی" },
|
|
{ icon: LayoutGrid, text: "بلاکهای چیدمان پایه" },
|
|
{ icon: MonitorSmartphone, text: "قالبهای طراحی واکنشگرا" },
|
|
{ icon: FileText, text: "مستندات مقدماتی" },
|
|
{ icon: GitBranch, text: "تاریخچه نسخهها" },
|
|
{ icon: LifeBuoy, text: "پشتیبانی انجمن" },
|
|
{ icon: Book, text: "راهنمای رابط کاربری بهصورت پیدیاف" },
|
|
],
|
|
cta: {
|
|
text: "شروع رایگان",
|
|
href: "#",
|
|
},
|
|
},
|
|
{
|
|
name: "حرفهای",
|
|
mostPopular: true,
|
|
priceMonthly: 290000,
|
|
priceYearly: 290000,
|
|
description: "بهترین گزینه برای تیمهای در حال رشد",
|
|
bestFor: "تیمهای کوچک توسعه و استارتاپها",
|
|
features: [
|
|
{ icon: Code, text: "کتابخانه پیشرفته بلاک رابط کاربری" },
|
|
{ icon: Brush, text: "پشتیبانی از تمهای سفارشی" },
|
|
{ icon: Settings2, text: "ابزارهای سیستم طراحی" },
|
|
{ icon: CheckSquare, text: "شامل تست کامپوننتها" },
|
|
{ icon: Zap, text: "بهبودهای عملکرد" },
|
|
{ icon: Server, text: "میزبانی کامپوننتهای مشترک" },
|
|
{ icon: PhoneCall, text: "پشتیبانی ایمیل و چت" },
|
|
],
|
|
cta: {
|
|
text: "شروع رایگان",
|
|
href: "#",
|
|
},
|
|
},
|
|
{
|
|
name: "تیم",
|
|
priceMonthly: 590000,
|
|
priceYearly: 590000,
|
|
description: "همکاری و رشد سریع",
|
|
bestFor: "تیمهای محصول با چند پروژه",
|
|
features: [
|
|
{ icon: Users, text: "کنترل دسترسی تیمی" },
|
|
{ icon: GitPullRequest, text: "ادغام و بازبینی بلاکهای رابط کاربری" },
|
|
{ icon: CalendarCheck2, text: "نقشه راه اولویتدار" },
|
|
{ icon: Bell, text: "اعلان بهروزرسانیها" },
|
|
{ icon: Database, text: "تحلیل استفاده از کامپوننتها" },
|
|
{ icon: Slack, text: "یکپارچهسازی پیامرسان تیمی" },
|
|
{ icon: ClipboardList, text: "کتابخانه قالبهای پروژه" },
|
|
],
|
|
cta: {
|
|
text: "شروع رایگان",
|
|
href: "#",
|
|
},
|
|
},
|
|
{
|
|
name: "تجاری",
|
|
priceMonthly: 990000,
|
|
priceYearly: 990000,
|
|
description: "کنترل و پشتیبانی کامل",
|
|
bestFor: "آژانسها و تیمهای بزرگ",
|
|
cta: {
|
|
text: "شروع رایگان",
|
|
href: "#",
|
|
},
|
|
},
|
|
{
|
|
name: "سازمانی",
|
|
priceMonthly: 199000,
|
|
priceYearly: 1990000,
|
|
description: "راهکارهای سفارشی در مقیاس بزرگ",
|
|
bestFor: "سازمانهای بزرگ و پلتفرمهای SaaS",
|
|
cta: {
|
|
text: "شروع رایگان",
|
|
href: "#",
|
|
},
|
|
},
|
|
];
|
|
|
|
interface Pricing32Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Pricing32 = ({ className }: Pricing32Props) => {
|
|
const [checked, setChecked] = useState(true);
|
|
|
|
return (
|
|
<section className={cn("py-32", className)}>
|
|
<div className="container">
|
|
<div className="flex flex-col items-center justify-center gap-9.5">
|
|
<h1 className="text-center font-serif text-2xll leading-none text-foreground md:text-2xll lg:text-2xll">
|
|
طرحی برای هر پروژهای که شروع میکنید
|
|
</h1>
|
|
<div className="flex flex-col items-center gap-4">
|
|
<div className="flex items-center justify-center gap-4">
|
|
<Label
|
|
htmlFor="plan-duration"
|
|
className={cn(
|
|
"text-sm transition-colors",
|
|
!checked ? "text-foreground" : "text-muted-foreground",
|
|
)}
|
|
>
|
|
سالانه
|
|
</Label>
|
|
<span dir="rtl" className="inline-flex shrink-0 items-center">
|
|
<Switch
|
|
id="plan-duration"
|
|
checked={checked}
|
|
onCheckedChange={setChecked}
|
|
aria-label="تغییر دوره صورتحساب"
|
|
/>
|
|
</span>
|
|
<Label
|
|
htmlFor="plan-duration"
|
|
className={cn(
|
|
"text-sm transition-colors",
|
|
checked ? "text-foreground" : "text-muted-foreground",
|
|
)}
|
|
>
|
|
ماهانه
|
|
</Label>
|
|
</div>
|
|
<div className="text-center text-green-600">
|
|
تا ۴۰٪ تخفیف با صورتحساب سالانه
|
|
</div>
|
|
</div>
|
|
<div className="mt-3 grid w-full grid-cols-1 gap-5 lg:grid-cols-6">
|
|
{PLANS.map((plan, index) => (
|
|
<PlanCard
|
|
key={index}
|
|
plan={plan}
|
|
monthly={checked}
|
|
className={
|
|
index > PLANS.length - 3 ? "lg:col-span-3" : "lg:col-span-2"
|
|
}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="m-9.5 flex items-center justify-center">
|
|
<Button size="lg">مقایسه همه طرحها</Button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
const PlanCard = ({
|
|
plan,
|
|
monthly,
|
|
className,
|
|
}: {
|
|
plan: PricingPlan;
|
|
monthly: boolean;
|
|
className?: string;
|
|
}) => {
|
|
return (
|
|
<div
|
|
className={`relative h-full w-full rounded-lg border px-6 py-5 ${className} ${plan?.mostPopular ? "border-primary" : "border-border"} bg-background`}
|
|
>
|
|
<div className="text-xl">{plan.name}</div>
|
|
<div className="h-[2.875rem] overflow-hidden">
|
|
<div
|
|
className={`text-[2.875rem] leading-none font-semibold transition-transform duration-500 ${monthly ? "translate-y-0" : "translate-y-[-3rem]"}`}
|
|
>
|
|
<div>{formatPrice(plan.priceMonthly)}</div>
|
|
<div>{formatPrice(plan.priceYearly)}</div>
|
|
</div>
|
|
</div>
|
|
<div className="text-xs text-foreground/60">
|
|
<div>به ازای هر نفر در {monthly ? "ماه" : "سال"}</div>
|
|
<div>{plan.bestFor}</div>
|
|
</div>
|
|
<div className="mt-4 mb-6 text-lg font-medium text-foreground">
|
|
{plan.description}
|
|
</div>
|
|
<Button
|
|
asChild
|
|
className="w-full"
|
|
variant={plan.mostPopular ? "default" : "outline"}
|
|
size="lg"
|
|
>
|
|
<a href={plan.cta.href}>
|
|
{plan.cta.text}
|
|
<ArrowRight className="ms-2 size-4 rtl:rotate-180" />
|
|
</a>
|
|
</Button>
|
|
<div className="mt-6 flex flex-col gap-4">
|
|
{plan.features?.map((feature, index) => (
|
|
<div key={index} className="flex items-center gap-3 text-foreground">
|
|
<feature.icon className="size-5 stroke-1" />
|
|
{feature.text}
|
|
</div>
|
|
))}
|
|
</div>
|
|
{plan.mostPopular && (
|
|
<div className="absolute start-1/2 top-0 w-fit -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary px-4 py-1 text-xs font-medium text-primary-foreground">
|
|
محبوبترین
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { Pricing32 };
|