Files
KLC-Website-Frontend/src/components/StatsSection.tsx

133 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-08-28 13:14:51 +05:30
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
2026-03-20 19:43:27 +05:30
import { useAnimatedCounter } from "../redux/hooks/useAnimatedCounter";
interface Stat {
id: string;
number: number;
suffix: string;
label: string;
display_order: number;
}
interface StatsSectionProps {
stats: Stat[];
isLoading?: boolean;
}
2025-08-28 13:14:51 +05:30
interface StatItemProps {
end: number;
suffix: string;
label: string;
duration?: number;
}
function StatItem({ end, suffix, label, duration = 2000 }: StatItemProps) {
const { count, ref } = useAnimatedCounter({ end, suffix, duration });
return (
<div className="mb-0">
2026-03-20 19:43:27 +05:30
<div
2025-08-28 13:14:51 +05:30
className="w-full h-[1px] mb-4"
2026-03-20 19:43:27 +05:30
style={{ backgroundColor: "var(--color-brand-gray-muted)" }}
2025-08-28 13:14:51 +05:30
/>
2026-03-20 19:43:27 +05:30
<span
2025-08-28 13:14:51 +05:30
ref={ref}
className="stats-number mb-3 leading-none"
2026-03-20 19:43:27 +05:30
style={{
color: "var(--color-brand-primary)",
fontFamily: "var(--font-family-base)",
2025-08-28 13:14:51 +05:30
}}
>
{count}
</span>
2026-03-20 19:43:27 +05:30
2025-08-28 13:14:51 +05:30
<div className="flex items-center mb-4">
2026-03-20 19:43:27 +05:30
<div
2025-08-28 13:14:51 +05:30
className="w-2 h-2 mr-3 flex-shrink-0"
2026-03-20 19:43:27 +05:30
style={{ backgroundColor: "var(--color-brand-accent)" }}
2025-08-28 13:14:51 +05:30
/>
2026-03-20 19:43:27 +05:30
<span
2025-08-28 13:14:51 +05:30
className="text-eyebrow"
2026-03-20 19:43:27 +05:30
style={{ color: "var(--color-brand-black)" }}
2025-08-28 13:14:51 +05:30
>
{label}
</span>
</div>
2026-03-20 19:43:27 +05:30
<div
2025-08-28 13:14:51 +05:30
className="w-full h-[1px]"
2026-03-20 19:43:27 +05:30
style={{ backgroundColor: "var(--color-brand-gray-muted)" }}
2025-08-28 13:14:51 +05:30
/>
</div>
);
}
2026-03-20 19:43:27 +05:30
export function StatsSection({ stats = [], isLoading }: StatsSectionProps) {
const sortedStats = [...stats].sort(
(a, b) => a.display_order - b.display_order
);
if (isLoading) return null;
2025-08-28 13:14:51 +05:30
return (
2026-03-20 19:43:27 +05:30
<section
2025-08-28 13:14:51 +05:30
className="py-20"
2026-03-20 19:43:27 +05:30
style={{ backgroundColor: "var(--color-brand-bg-light)" }}
2025-08-28 13:14:51 +05:30
>
<div className="section-margin-x">
<div className="max-w-7xl mx-auto">
<div className="mb-12 lg:mb-16 md:mb-12 sm:mb-8">
2026-03-20 19:43:27 +05:30
<BrandedTag text="Serving Leaders Across Industries" />
2025-08-28 13:14:51 +05:30
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12 items-start">
<div className="lg:col-span-6 md:col-span-8 sm:col-span-12">
<h2 className="text-h2 mb-8">
2026-03-20 19:43:27 +05:30
Your Partner in Leadership, Culture, and Capability Building
2025-08-28 13:14:51 +05:30
</h2>
2026-03-20 19:43:27 +05:30
<PrimaryCTAButton
2025-08-28 13:14:51 +05:30
text="About Us"
2026-03-20 19:43:27 +05:30
onClick={() => console.log("About us clicked")}
2025-08-28 13:14:51 +05:30
ariaLabel="Learn more about KLC"
/>
</div>
2026-03-20 19:43:27 +05:30
{/* Desktop */}
2025-08-28 13:14:51 +05:30
<div className="hidden lg:block lg:col-start-9 lg:col-end-13">
<div className="space-y-6">
2026-03-20 19:43:27 +05:30
{sortedStats.map((stat) => (
<StatItem
key={stat.id}
end={stat.number}
suffix={stat.suffix}
label={stat.label}
/>
))}
2025-08-28 13:14:51 +05:30
</div>
</div>
</div>
2026-03-20 19:43:27 +05:30
{/* Mobile */}
2025-08-28 13:14:51 +05:30
<div className="block lg:hidden mt-12">
2025-09-02 18:48:56 +05:30
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 sm:gap-8">
2026-03-20 19:43:27 +05:30
{sortedStats.map((stat) => (
<StatItem
key={stat.id}
end={stat.number}
suffix={stat.suffix}
label={stat.label}
/>
))}
2025-08-28 13:14:51 +05:30
</div>
</div>
2026-03-20 19:43:27 +05:30
2025-08-28 13:14:51 +05:30
</div>
</div>
</div>
</section>
);
}