Files
reui-blocks/blocks/pricing23.tsx
T

299 lines
7.7 KiB
TypeScript

"use client";
import { Check, ChevronsUpDown } 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 FeatureSection {
category: string;
features: {
name: string;
free: string | boolean;
startup: string | boolean;
enterprise: string | boolean;
}[];
}
const pricingPlans = [
{
name: "رایگان",
button: {
text: "شروع رایگان",
variant: "outline" as const,
},
},
{
name: "استارتاپ",
button: {
text: "شروع رایگان",
variant: "outline" as const,
},
},
{
name: "سازمانی",
button: {
text: "دریافت دمو",
variant: "outline" as const,
},
},
];
const comparisonFeatures: FeatureSection[] = [
{
category: "میزان استفاده",
features: [
{
name: "اعضا",
free: "نامحدود",
startup: "نامحدود",
enterprise: "نامحدود",
},
{
name: "تراکنش‌ها",
free: "۲۵۰",
startup: "نامحدود",
enterprise: "نامحدود",
},
{
name: "تیم‌ها",
free: "۲",
startup: "نامحدود",
enterprise: "نامحدود",
},
],
},
{
category: "امکانات",
features: [
{
name: "گزارش‌دهی",
free: true,
startup: true,
enterprise: true,
},
{
name: "تحلیل‌ها",
free: true,
startup: true,
enterprise: true,
},
{
name: "ورود و خروج داده",
free: true,
startup: true,
enterprise: true,
},
{
name: "یکپارچه‌سازی‌ها",
free: true,
startup: true,
enterprise: true,
},
{
name: "هوش مصنوعی نوافروش",
free: false,
startup: true,
enterprise: true,
},
{
name: "نقش‌های مدیریتی",
free: false,
startup: false,
enterprise: false,
},
{
name: "گزارش ممیزی",
free: false,
startup: false,
enterprise: false,
},
],
},
{
category: "پشتیبانی",
features: [
{
name: "پشتیبانی اولویت‌دار",
free: true,
startup: true,
enterprise: true,
},
{
name: "مدیر حساب",
free: false,
startup: false,
enterprise: true,
},
{
name: "SLA پایداری",
free: false,
startup: false,
enterprise: true,
},
],
},
];
interface Pricing23Props {
className?: string;
}
const Pricing23 = ({ className }: Pricing23Props) => {
const [selectedPlan, setSelectedPlan] = useState(1);
return (
<section className={cn("py-32", className)}>
<div className="container">
<PlanHeaders
selectedPlan={selectedPlan}
onPlanChange={setSelectedPlan}
/>
<FeatureSections selectedPlan={selectedPlan} />
</div>
</section>
);
};
const PlanHeaders = ({
selectedPlan,
onPlanChange,
}: {
selectedPlan: number;
onPlanChange: (index: number) => void;
}) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="">
{/* Mobile View */}
<div className="md:hidden">
<Collapsible open={isOpen} onOpenChange={setIsOpen} 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">
{pricingPlans[selectedPlan].name}
</h3>
<ChevronsUpDown
className={`size-5 transition-transform ${isOpen ? "rotate-180" : ""}`}
/>
</CollapsibleTrigger>
<Button
variant={pricingPlans[selectedPlan].button.variant}
className="w-fit"
>
{pricingPlans[selectedPlan].button.text}
</Button>
</div>
<CollapsibleContent className="flex flex-col space-y-2 p-2">
{pricingPlans.map(
(plan, index) =>
index !== selectedPlan && (
<Button
size="lg"
variant="secondary"
key={index}
onClick={() => {
onPlanChange(index);
setIsOpen(false);
}}
>
{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"></div>
{pricingPlans.map((plan, index) => (
<div key={index} className="">
<h3 className="mb-3 text-xl font-semibold">{plan.name}</h3>
<Button variant={plan.button.variant} className="">
{plan.button.text}
</Button>
</div>
))}
</div>
</div>
);
};
const FeatureSections = ({ selectedPlan }: { selectedPlan: number }) => (
<>
{comparisonFeatures.map((section, sectionIndex) => (
<div key={sectionIndex} className="">
<div className="border-b border-primary/40 py-4">
<h3 className="text-lg font-semibold">{section.category}</h3>
</div>
{section.features.map((feature, featureIndex) => (
<div
key={featureIndex}
className="grid grid-cols-2 font-medium text-primary 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">
{(() => {
const value = [
feature.free,
feature.startup,
feature.enterprise,
][selectedPlan];
return typeof value === "boolean" ? (
value ? (
<Check className="size-5" />
) : null
) : (
<div className="flex items-center gap-1">
<Check className="size-4 shrink-0" />
<span>{value}</span>
</div>
);
})()}
</div>
</div>
{/* Desktop View - All Plans */}
<div className="hidden md:col-span-3 md:grid md:grid-cols-3 md:gap-4">
{[feature.free, feature.startup, feature.enterprise].map(
(value, i) => (
<div
key={i}
className="flex items-center gap-1 border-b py-4"
>
{typeof value === "boolean" ? (
value ? (
<Check className="size-5" />
) : null
) : (
<div className="flex items-center gap-1">
<Check className="size-4 shrink-0" />
<span>{value}</span>
</div>
)}
</div>
),
)}
</div>
</div>
))}
</div>
))}
</>
);
export { Pricing23 };