195 lines
8.2 KiB
TypeScript
195 lines
8.2 KiB
TypeScript
'use client';
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
import { useEffect } from 'react';
|
|
|
|
export function Ecosystem() {
|
|
const t = useTranslations();
|
|
|
|
useEffect(() => {
|
|
const grid = document.getElementById('bentoGrid');
|
|
let obs: IntersectionObserver;
|
|
|
|
if (grid) {
|
|
const bars = grid.querySelectorAll<HTMLElement>('.report-bar');
|
|
const ring = grid.querySelector<SVGElement>('.ring-progress');
|
|
let done = false;
|
|
|
|
obs = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting && !done) {
|
|
done = true;
|
|
bars.forEach((bar, i) => {
|
|
setTimeout(() => {
|
|
if (bar.dataset.w) bar.style.width = bar.dataset.w;
|
|
}, i * 150);
|
|
});
|
|
if (ring && ring.dataset.dash) {
|
|
setTimeout(() => {
|
|
ring.style.strokeDasharray = ring.dataset.dash!;
|
|
}, 200);
|
|
}
|
|
obs.disconnect();
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.35 },
|
|
);
|
|
obs.observe(grid);
|
|
}
|
|
|
|
return () => {
|
|
if (obs) obs.disconnect();
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<section className="ecosystem" id="ecosystem">
|
|
<div className="container">
|
|
<div className="ecosystem-head">
|
|
<h2>{t('Ecosystem.title')}</h2>
|
|
<p>{t('Ecosystem.desc')}</p>
|
|
</div>
|
|
|
|
<div className="bento" id="bentoGrid">
|
|
{/* Ticketing */}
|
|
<div className="bento-card bento-r1">
|
|
<h3>{t('Ecosystem.ticketing.title')}</h3>
|
|
<p>{t('Ecosystem.ticketing.desc')}</p>
|
|
<div className="bento-illustration">
|
|
<div className="ticket-rows">
|
|
<div className="ticket-row">
|
|
<div className="ticket-track drift-a" style={{ marginLeft: '-14px' }}>
|
|
<span className="pill pill-outline">TX24409198-8798</span>
|
|
<span className="pill pill-orange">TX24409198-8797</span>
|
|
<span className="pill pill-lime">TX24409198-8798</span>
|
|
<span className="pill pill-outline">TX24409198-8901</span>
|
|
<span className="pill pill-navy">TX24409198-8811</span>
|
|
</div>
|
|
</div>
|
|
<div className="ticket-row">
|
|
<div className="ticket-track drift-b" style={{ marginLeft: '-32px' }}>
|
|
<span className="pill pill-lime">TX24409198-8801</span>
|
|
<span className="pill pill-outline">TX24409198-8787</span>
|
|
<span className="pill pill-navy">TX24409198-8786</span>
|
|
<span className="pill pill-outline">TX24409198-8901</span>
|
|
<span className="pill pill-outline">TX24409198-8881</span>
|
|
</div>
|
|
</div>
|
|
<div className="ticket-row">
|
|
<div className="ticket-track drift-a" style={{ marginLeft: '-22px', animationDelay: '-1.4s' }}>
|
|
<span className="pill pill-outline">TX24409198-8902</span>
|
|
<span className="pill pill-lime">TX24409198-8788</span>
|
|
<span className="pill pill-outline">TX24409198-8790</span>
|
|
<span className="pill pill-orange">TX24409198-8905</span>
|
|
<span className="pill pill-outline">TX24409198-8812</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Access Management */}
|
|
<div className="bento-card bento-r2">
|
|
<div className="bento-illustration access-illustration">
|
|
<div className="chip-row">
|
|
<div className="chip active">
|
|
<span>{t('Ecosystem.stats.qr')}</span>
|
|
<i className="uil uil-qrcode-scan"></i>
|
|
</div>
|
|
<div className="chip">
|
|
<span>{t('Ecosystem.stats.gate')}</span>
|
|
<i className="uil uil-monitor-heart-rate"></i>
|
|
</div>
|
|
<div className="chip">
|
|
<span>{t('Ecosystem.stats.rfid')}</span>
|
|
<i className="uil uil-rss-interface"></i>
|
|
</div>
|
|
</div>
|
|
<div className="ring-wrap">
|
|
<svg width="140" height="140" viewBox="0 0 100 100">
|
|
<defs>
|
|
<linearGradient id="rainbowGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stopColor="#f66b0e" />
|
|
<stop offset="70%" stopColor="#112b3c" />
|
|
<stop offset="100%" stopColor="#205375" />
|
|
</linearGradient>
|
|
</defs>
|
|
<circle cx="50" cy="50" r="34" fill="none" stroke="#E1E5E3" strokeWidth="9" />
|
|
<circle
|
|
className="ring-progress"
|
|
cx="50"
|
|
cy="50"
|
|
r="34"
|
|
fill="none"
|
|
stroke="url(#rainbowGrad)"
|
|
strokeWidth="9"
|
|
strokeLinecap="round"
|
|
data-dash="166 213.6"
|
|
transform="rotate(-90 50 50)"
|
|
/>
|
|
</svg>
|
|
<div className="ring-text">
|
|
<b>0.4s</b>
|
|
<small>{t('Ecosystem.stats.avg')}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<h3>{t('Ecosystem.access.title')}</h3>
|
|
<p>{t('Ecosystem.access.desc')}</p>
|
|
</div>
|
|
|
|
{/* Visitor Operations */}
|
|
<div className="bento-card bento-r3">
|
|
<div className="bento-illustration visitor-illustration">
|
|
<div className="avatar-row">
|
|
<div className="avatar-stack">
|
|
<div className="avatar" style={{ background: '#b9f001' }}></div>
|
|
<div className="avatar" style={{ background: '#f66b0e' }}></div>
|
|
<div className="avatar" style={{ background: '#112b3c' }}></div>
|
|
<div className="avatar" style={{ background: '#e1e5e3' }}></div>
|
|
</div>
|
|
<span>{t('Ecosystem.stats.queue')}</span>
|
|
</div>
|
|
<div className="zone-grid">
|
|
<div className="zone-cell" style={{ background: '#e1e5e3' }}></div>
|
|
<div className="zone-cell" style={{ background: '#e1e5e3' }}></div>
|
|
<div className="zone-cell" style={{ background: '#205375' }}></div>
|
|
<div className="zone-cell" style={{ background: '#e1e5e3' }}></div>
|
|
<div className="zone-cell" style={{ background: '#e1e5e3' }}></div>
|
|
<div className="zone-cell" style={{ background: '#b9f001' }}></div>
|
|
<div className="zone-cell" style={{ background: '#e1e5e3' }}></div>
|
|
<div className="zone-cell" style={{ background: 'linear-gradient(135deg, #205375, #112b3c)' }}></div>
|
|
</div>
|
|
</div>
|
|
<h3>{t('Ecosystem.visitor.title')}</h3>
|
|
<p>{t('Ecosystem.visitor.desc')}</p>
|
|
</div>
|
|
|
|
{/* Report */}
|
|
<div className="bento-card bento-r4">
|
|
<h3 style={{ marginBottom: '8px' }}>{t('Ecosystem.report.title')}</h3>
|
|
<p style={{ marginBottom: '26px' }}>{t('Ecosystem.report.desc')}</p>
|
|
<div className="report-bars">
|
|
{[
|
|
{ w: '150px', bg: '#b9f001', val: 'Rp32.5M', key: 'Ecosystem.stats.revenue' },
|
|
{ w: '220px', bg: '#f66b0e', val: '1,284', key: 'Ecosystem.stats.visitors' },
|
|
{ w: '300px', bg: '#112b3c', val: '1,120,240', key: 'Ecosystem.stats.checkin' },
|
|
].map((item, idx) => (
|
|
<div className="report-bar-row" key={idx}>
|
|
<div className="report-bar" data-w={item.w} style={{ background: item.bg }}></div>
|
|
<div className="report-bar-value">
|
|
<b>{item.val}</b>
|
|
<small>{(t as any)(item.key)}</small>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|