195 lines
7.3 KiB
TypeScript
195 lines
7.3 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const formatPrice = (value: string | number) =>
|
|
`${(typeof value === "string" ? Number(value) : value).toLocaleString("fa-IR")} ریال`;
|
|
|
|
interface Pricing35Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Pricing35 = ({ className }: Pricing35Props) => {
|
|
const pricingPlans = [
|
|
{
|
|
id: "standard",
|
|
type: "standard",
|
|
prices: {
|
|
quarterly: 150000,
|
|
yearly: 12,
|
|
},
|
|
isCustom: false,
|
|
isDark: false,
|
|
hasToggle: true,
|
|
badge: null,
|
|
ctaText: "شروع با طرح استاندارد",
|
|
description:
|
|
"مناسب افراد یا فریلنسرهایی که تازه شروع کردهاند. نیازی به کارت اعتباری نیست.",
|
|
},
|
|
{
|
|
id: "premium",
|
|
type: "premium",
|
|
prices: {
|
|
quarterly: null,
|
|
yearly: null,
|
|
},
|
|
isCustom: true,
|
|
isDark: true,
|
|
hasToggle: false,
|
|
badge: "۱۰ از ۳۰۰ جایگاه باقی مانده",
|
|
ctaText: "عضویت VIP",
|
|
description:
|
|
"مناسب افراد یا فریلنسرهایی که تازه شروع کردهاند. نیازی به کارت اعتباری نیست.",
|
|
},
|
|
];
|
|
|
|
const [billingPeriods, setBillingPeriods] = useState({
|
|
standard: "quarterly",
|
|
premium: "quarterly",
|
|
});
|
|
|
|
const updateBillingPeriod = (
|
|
planId: string,
|
|
period: "quarterly" | "yearly",
|
|
) => {
|
|
setBillingPeriods((prev) => ({
|
|
...prev,
|
|
[planId]: period,
|
|
}));
|
|
};
|
|
|
|
const formatDisplayPrice = (
|
|
price: number | null,
|
|
isCustom: boolean,
|
|
) => {
|
|
if (isCustom || price === null) {
|
|
return "سفارشی";
|
|
}
|
|
return `${formatPrice(price)} در ماه`;
|
|
};
|
|
|
|
return (
|
|
<section className={cn("bg-background", className)}>
|
|
<div className="container py-32">
|
|
<header className="mb-10 flex flex-col items-center gap-6 md:mb-20">
|
|
<h1 className="text-center text-2xll font-bold tracking-tighter text-foreground md:text-2xll">
|
|
طرحهای تعرفه انعطافپذیر
|
|
</h1>
|
|
<p className="w-full max-w-lg px-4 text-center text-base font-normal tracking-tight text-muted-foreground opacity-70 md:px-0 md:text-lg">
|
|
طرحی را انتخاب کنید که با نیازها و بودجه شما هماهنگ باشد.
|
|
</p>
|
|
</header>
|
|
|
|
<div className="flex flex-col justify-center gap-8 px-4 md:flex-row">
|
|
{pricingPlans.map((plan) => {
|
|
const currentPeriod = billingPeriods[
|
|
plan.id as keyof typeof billingPeriods
|
|
] as "quarterly" | "yearly";
|
|
|
|
return (
|
|
<Card
|
|
key={plan.id}
|
|
className={`h-auto w-full overflow-hidden rounded-4xl border border-border shadow-sm ${plan.isDark ? "bg-foreground text-background" : "bg-background text-foreground"} md:max-w-md`}
|
|
>
|
|
<CardContent className="p-6">
|
|
<div className="mt-8 mb-8 md:mt-10 md:mb-10">
|
|
<div className="flex items-end">
|
|
<span className="w-full text-center text-2xll font-semibold tracking-tighter md:text-2xll">
|
|
{formatDisplayPrice(
|
|
plan.prices[currentPeriod],
|
|
plan.isCustom,
|
|
)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mb-8 flex items-center gap-4 md:mb-10">
|
|
<div className="h-px flex-1 bg-muted" />
|
|
<span className="text-center text-xs font-normal whitespace-nowrap uppercase opacity-50">
|
|
{!plan.isCustom && currentPeriod === "quarterly"
|
|
? "صورتحساب سهماهه"
|
|
: !plan.isCustom && currentPeriod === "yearly"
|
|
? "صورتحساب سالانه"
|
|
: "صورتحساب انعطافپذیر"}
|
|
</span>
|
|
<div className="h-px flex-1 bg-muted" />
|
|
</div>
|
|
|
|
<div className="mb-8 flex justify-center md:mb-10">
|
|
{plan.hasToggle ? (
|
|
<ToggleGroup
|
|
type="single"
|
|
value={currentPeriod}
|
|
onValueChange={(value) => {
|
|
if (value)
|
|
updateBillingPeriod(
|
|
plan.id,
|
|
value as "quarterly" | "yearly",
|
|
);
|
|
}}
|
|
className="rounded-xl bg-muted p-1"
|
|
>
|
|
<ToggleGroupItem
|
|
value="quarterly"
|
|
className="h-8 w-20 rounded-lg data-[state=on]:bg-background"
|
|
>
|
|
<span className="text-center text-xs font-semibold text-foreground">
|
|
سهماهه
|
|
</span>
|
|
</ToggleGroupItem>
|
|
<ToggleGroupItem
|
|
value="yearly"
|
|
className="h-8 w-20 rounded-lg data-[state=on]:bg-background"
|
|
>
|
|
<span className="text-center text-xs font-semibold text-foreground">
|
|
سالانه
|
|
</span>
|
|
</ToggleGroupItem>
|
|
</ToggleGroup>
|
|
) : plan.badge ? (
|
|
<Badge
|
|
className={`rounded-xl border bg-muted/20 ${plan.isDark ? "text-background" : "text-foreground"} px-3 py-2 text-xs font-semibold`}
|
|
>
|
|
{plan.badge}
|
|
</Badge>
|
|
) : null}
|
|
</div>
|
|
|
|
<div className="mb-8 flex justify-center md:mb-10">
|
|
<span className="text-center text-xs font-normal whitespace-nowrap opacity-50">
|
|
{currentPeriod === "yearly"
|
|
? "با صورتحساب سالانه ۲۰٪ صرفهجویی میکنید"
|
|
: "با طرح سالانه ۲۰٪ تخفیف بگیرید"}
|
|
</span>
|
|
</div>
|
|
|
|
<p className="mb-8 w-full text-center text-sm font-normal tracking-tight md:mb-10 md:text-base">
|
|
{plan.description}
|
|
</p>
|
|
|
|
<Button
|
|
variant={plan.isDark ? "secondary" : "default"}
|
|
className="h-10 w-full"
|
|
>
|
|
<span className="text-center text-sm font-normal md:text-base">
|
|
{plan.ctaText}
|
|
</span>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Pricing35 };
|