Public Access
Added more details and a landing page
This commit is contained in:
1 parent
950f7d2b80
commit
38976e3240
8 files changed
+654
-40
No files matched your search
@@ -0,0 +1,40 @@
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function useCountUp(target, durationMs = 1600) {
|
||||
const [value, setValue] = useState(0);
|
||||
useEffect(() => {
|
||||
const safeTarget = typeof target === 'number' && Number.isFinite(target) ? target : 0;
|
||||
if (safeTarget === 0) {
|
||||
setValue(0);
|
||||
return;
|
||||
}
|
||||
let raf;
|
||||
let start;
|
||||
const step = (ts) => {
|
||||
if (start === undefined) start = ts;
|
||||
const progress = Math.min((ts - start) / durationMs, 1);
|
||||
setValue(Math.floor(progress * safeTarget));
|
||||
if (progress < 1) raf = requestAnimationFrame(step);
|
||||
};
|
||||
raf = requestAnimationFrame(step);
|
||||
return () => cancelAnimationFrame(raf);
|
||||
}, [target, durationMs]);
|
||||
return value;
|
||||
}
|
||||
|
||||
export default function StatCard({label, value, icon, suffix}) {
|
||||
const animated = useCountUp(value);
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center p-6 bg-white dark:bg-slate-800 rounded-xl shadow-sm border border-slate-200 dark:border-slate-700">
|
||||
{icon && (
|
||||
<i className={`mdi ${icon} text-3xl text-blue-600 dark:text-blue-400 mb-2`}></i>
|
||||
)}
|
||||
<div className="text-4xl font-black text-slate-900 dark:text-white tabular-nums">
|
||||
{animated.toLocaleString()}{suffix ?? ''}
|
||||
</div>
|
||||
<div className="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 mt-2 text-center">
|
||||
{label}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user