217 lines
7.3 KiB
TypeScript
217 lines
7.3 KiB
TypeScript
"use client";
|
|
|
|
import NumberFlow from "@number-flow/react";
|
|
import { motion } from "framer-motion";
|
|
import { ArrowLeft } from "lucide-react";
|
|
import React, { useRef, useState } from "react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const numberFlowLocales = "fa-IR-u-nu-latn";
|
|
|
|
const formatNumber = (value: number) => value.toLocaleString("fa-IR");
|
|
|
|
interface Stats15Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Stats15 = ({ className }: Stats15Props) => {
|
|
const ref = useRef(null);
|
|
const IllustrationRef = useRef(null);
|
|
const [selectedYear, setSelectedYear] = useState(2021);
|
|
|
|
const Stats = {
|
|
2021: {
|
|
TotalRevenue: 12.3,
|
|
TotalUsers: 0.3,
|
|
CompanyGrowth: 300,
|
|
NewCustomers: 100,
|
|
BigCorpClients: 10,
|
|
PathHeight: 0,
|
|
},
|
|
2022: {
|
|
TotalRevenue: 105,
|
|
TotalUsers: 50,
|
|
CompanyGrowth: 30,
|
|
NewCustomers: 1.5,
|
|
BigCorpClients: 75,
|
|
PathHeight: 55,
|
|
},
|
|
2023: {
|
|
TotalRevenue: 250,
|
|
TotalUsers: 120,
|
|
CompanyGrowth: 45,
|
|
NewCustomers: 2.8,
|
|
BigCorpClients: 150,
|
|
PathHeight: 105,
|
|
},
|
|
2024: {
|
|
TotalRevenue: 500,
|
|
TotalUsers: 300,
|
|
CompanyGrowth: 65,
|
|
NewCustomers: 4.2,
|
|
BigCorpClients: 250,
|
|
PathHeight: 160,
|
|
},
|
|
};
|
|
|
|
const years = Object.keys(Stats).map(Number);
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
|
|
<div className="container flex flex-col md:flex-row">
|
|
<div className="z-10 md:flex-1">
|
|
<h1 className="font-cal max-w-xl text-2xll font-medium tracking-tighter md:text-2xll">
|
|
مسیر رشد درآمد، سالبهسال
|
|
</h1>
|
|
<p className="mt-4 max-w-xl text-muted-foreground/80">
|
|
کاربران فعال، رشد MRR و حسابهای جدید را در یک نمای زمانی شفاف
|
|
مقایسه کنید.
|
|
</p>
|
|
<div className="my-10 flex gap-4">
|
|
<Button
|
|
variant="secondary"
|
|
className="text-md group flex w-fit items-center justify-center gap-2 rounded-full px-4 py-1 tracking-tight"
|
|
>
|
|
<span>مستندات API</span>
|
|
<ArrowLeft className="size-4 -rotate-45 transition-all ease-out group-hover:ms-3 group-hover:rotate-0" />
|
|
</Button>
|
|
<Button
|
|
variant="default"
|
|
className="text-md group flex w-fit items-center justify-center gap-2 rounded-full px-4 py-1 tracking-tight"
|
|
>
|
|
<span>شروع رایگان</span>
|
|
<ArrowLeft className="size-4 -rotate-45 transition-all ease-out group-hover:ms-3 group-hover:rotate-0" />
|
|
</Button>
|
|
</div>
|
|
<div
|
|
ref={ref}
|
|
className="mt-12 flex max-w-3xl flex-col items-start bg-background md:mt-32 xl:bg-transparent"
|
|
>
|
|
<div className="mt-auto mb-10 grid w-full grid-cols-2 gap-4 md:grid-cols-4">
|
|
<div className="w-full text-start">
|
|
<h2 className="text-xl font-medium lg:text-2xll">
|
|
<NumberFlow
|
|
value={Stats[selectedYear as keyof typeof Stats].TotalUsers}
|
|
locales={numberFlowLocales}
|
|
format={{
|
|
minimumFractionDigits: 1,
|
|
maximumFractionDigits: 1,
|
|
}}
|
|
suffix=" هزار+"
|
|
/>
|
|
</h2>
|
|
<p className="text-sm whitespace-pre text-muted-foreground/70">
|
|
کاربر فعال
|
|
</p>
|
|
</div>
|
|
<div className="w-full text-start">
|
|
<h2 className="text-xl font-medium lg:text-2xll">
|
|
<NumberFlow
|
|
value={
|
|
Stats[selectedYear as keyof typeof Stats].CompanyGrowth
|
|
}
|
|
locales={numberFlowLocales}
|
|
suffix="٪"
|
|
/>
|
|
</h2>
|
|
<p className="text-sm whitespace-pre text-muted-foreground/70">
|
|
رشد MRR
|
|
</p>
|
|
</div>
|
|
<div className="w-full text-start">
|
|
<h2 className="text-xl font-medium lg:text-2xll">
|
|
<NumberFlow
|
|
value={
|
|
Stats[selectedYear as keyof typeof Stats].NewCustomers
|
|
}
|
|
locales={numberFlowLocales}
|
|
format={{
|
|
minimumFractionDigits: 1,
|
|
maximumFractionDigits: 1,
|
|
}}
|
|
suffix=" میلیون"
|
|
/>
|
|
</h2>
|
|
<p className="text-sm whitespace-pre text-muted-foreground/70">
|
|
حساب جدید
|
|
</p>
|
|
</div>
|
|
<div ref={IllustrationRef} className="w-full text-start">
|
|
<h2 className="text-xl font-medium lg:text-2xll">
|
|
<NumberFlow
|
|
value={
|
|
Stats[selectedYear as keyof typeof Stats].BigCorpClients
|
|
}
|
|
locales={numberFlowLocales}
|
|
prefix="~"
|
|
suffix="+"
|
|
/>
|
|
</h2>
|
|
<p className="text-sm whitespace-pre text-muted-foreground/70">
|
|
قرارداد سازمانی
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="relative flex w-fit flex-row flex-wrap gap-2 md:mt-42 md:flex-col">
|
|
{years.map((year) => (
|
|
<div key={year} className="group">
|
|
<button
|
|
onClick={() => setSelectedYear(year)}
|
|
className={`relative rounded-full px-4 py-1 text-sm transition-all ease-out ${
|
|
selectedYear === year
|
|
? "bg-primary text-primary-foreground md:translate-x-8"
|
|
: "bg-muted/70 group-hover:translate-x-4 group-hover:bg-muted"
|
|
}`}
|
|
>
|
|
{formatNumber(year)} - {formatNumber(year + 1)}
|
|
</button>
|
|
</div>
|
|
))}
|
|
<LinkIllustration
|
|
className="absolute bottom-9 -right-14 hidden translate-x-full -translate-y-full text-orange-500 md:block"
|
|
PathHeight={Stats[selectedYear as keyof typeof Stats].PathHeight}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Stats15 };
|
|
|
|
const LinkIllustration = ({ className = "", PathHeight = 0 }) => {
|
|
return (
|
|
<svg
|
|
width="280"
|
|
height="124"
|
|
viewBox="0 0 412 178"
|
|
overflow="visible"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className={className}
|
|
>
|
|
<motion.path
|
|
initial={{ pathLength: 0 }}
|
|
animate={{ pathLength: 1 }}
|
|
transition={{ duration: 1 }}
|
|
key={PathHeight}
|
|
d={`M408.308 ${PathHeight}H294L114.965 274H1`}
|
|
stroke="currentColor"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<motion.path
|
|
d={`M408.308 ${PathHeight}H294L114.965 274H1`}
|
|
stroke="black"
|
|
strokeWidth="1.5"
|
|
opacity="0.1"
|
|
/>
|
|
<circle cx="408.309" cy={PathHeight} r="5" fill="currentColor" />
|
|
<circle cx="2" cy="274" r="5" fill="currentColor" />
|
|
</svg>
|
|
);
|
|
};
|