299 lines
7.7 KiB
TypeScript
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 };
|