Files

226 lines
6.9 KiB
TypeScript

"use client";
import { Check, ChevronsUpDown, X } from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { cn } from "@/lib/utils";
interface Feature {
name: string;
values: (boolean | null | string)[];
}
interface FeatureSection {
category: string;
features: Feature[];
}
interface Plan {
name: string;
ctaText: string;
ctaHref?: string;
ctaVariant?: "default" | "outline" | "secondary";
}
interface Pricing42Props {
plans?: Plan[];
featureSections?: FeatureSection[];
className?: string;
}
const CATEGORY_LABELS: Record<string, string> = {
Usage: "میزان استفاده",
Features: "امکانات",
Support: "پشتیبانی",
};
const Pricing42 = ({
plans = [
{
name: "رایگان",
ctaText: "شروع رایگان",
ctaHref: "#",
ctaVariant: "outline",
},
{
name: "استارتاپ",
ctaText: "شروع رایگان",
ctaHref: "#",
ctaVariant: "outline",
},
{
name: "سازمانی",
ctaText: "درخواست دمو",
ctaHref: "#",
ctaVariant: "outline",
},
],
featureSections = [
{
category: "Usage",
features: [
{
name: "اعضا",
values: ["نامحدود", "نامحدود", "نامحدود"],
},
{
name: "تراکنش‌ها",
values: ["۲۵۰", "نامحدود", "نامحدود"],
},
{ name: "تیم‌ها", values: ["۲", "نامحدود", "نامحدود"] },
],
},
{
category: "Features",
features: [
{ name: "گزارش‌دهی", values: [true, true, true] },
{ name: "تحلیل‌ها", values: [true, true, true] },
{ name: "ورود و خروج داده", values: [true, true, true] },
{ name: "یکپارچه‌سازی‌ها", values: [true, true, true] },
{ name: "دستیار هوش مصنوعی", values: [null, true, true] },
{ name: "نقش‌های مدیریتی", values: [null, null, true] },
{ name: "گزارش ممیزی", values: [null, null, true] },
],
},
{
category: "Support",
features: [
{ name: "پشتیبانی اولویت‌دار", values: [true, true, true] },
{ name: "مدیر حساب", values: [null, null, true] },
{ name: "SLA آپتایم", values: [null, null, true] },
],
},
],
className,
}: Pricing42Props) => {
const [selectedPlan, setSelectedPlan] = useState(1);
const renderFeatureValue = (value: boolean | null | string) => {
if (value === true) {
return <Check className="size-5" />;
}
if (value === false) {
return <X className="size-5" />;
}
if (value === null) {
return null;
}
return (
<div className="flex items-center gap-2">
<Check className="size-4 shrink-0" />
<span className="text-muted-foreground">{value}</span>
</div>
);
};
return (
<section className={cn("pb-28 lg:py-32", className)}>
<div className="container">
{/* Plan Headers */}
<div>
{/* Mobile View */}
<div className="md:hidden">
<Collapsible className="">
<>
<div className="flex items-center justify-between border-b py-4">
<CollapsibleTrigger className="flex items-center gap-2">
<h3 className="text-xl font-semibold">
{plans[selectedPlan].name}
</h3>
<ChevronsUpDown
className={cn("size-5 transition-transform")}
/>
</CollapsibleTrigger>
<Button
variant={plans[selectedPlan].ctaVariant || "outline"}
className="w-fit"
asChild
>
<a href={plans[selectedPlan].ctaHref || "#"}>
{plans[selectedPlan].ctaText}
</a>
</Button>
</div>
<CollapsibleContent className="flex flex-col space-y-2 p-2">
{plans.map(
(plan, index) =>
index !== selectedPlan && (
<Button
size="lg"
variant="secondary"
key={index}
onClick={() => setSelectedPlan(index)}
>
{plan.name}
</Button>
),
)}
</CollapsibleContent>
</>
</Collapsible>
</div>
{/* Desktop View */}
<div className="grid grid-cols-4 gap-4 max-md:hidden">
<div className="col-span-1 max-md:hidden" />
{plans.map((plan, index) => (
<div key={index}>
<h3 className="mb-3 text-xl font-semibold">{plan.name}</h3>
<Button variant={plan.ctaVariant || "outline"} asChild>
<a href={plan.ctaHref || "#"}>{plan.ctaText}</a>
</Button>
</div>
))}
</div>
</div>
{/* Feature Sections */}
{featureSections.map((section, sectionIndex) => (
<div key={sectionIndex}>
<div className="border-b border-primary/40 py-4">
<h3 className="text-lg font-semibold">
{CATEGORY_LABELS[section.category] ?? section.category}
</h3>
</div>
{section.features.map((feature, featureIndex) => (
<div
key={featureIndex}
className="grid grid-cols-2 font-medium text-foreground max-md:border-b md:grid-cols-4"
>
<span className="inline-flex items-center py-4">
{feature.name}
</span>
{/* Mobile View - Only Selected Plan */}
<div className="md:hidden">
<div className="flex items-center gap-1 py-4 md:border-b">
{renderFeatureValue(feature.values[selectedPlan])}
</div>
</div>
{/* Desktop View - All Plans */}
<div className="hidden md:col-span-3 md:grid md:grid-cols-3 md:gap-4">
{feature.values.map((value, i) => (
<div
key={i}
className="flex items-center gap-1 border-b py-4"
>
{renderFeatureValue(value)}
</div>
))}
</div>
</div>
))}
</div>
))}
</div>
</section>
);
};
export { Pricing42 };