Files
2026FIFAWorldCup/platform/web/app/schedule/page.tsx
wooo 80c7a939dc
Some checks failed
2026 World Cup Quant Platform - Production Deployment / Code Quality, Security Gate & Testing (push) Failing after 3m36s
2026 World Cup Quant Platform - Production Deployment / Deploy to Production VM via Gitea CD (push) Has been skipped
feat: fill missing product pages and analytics proxy
2026-06-18 15:10:53 +08:00

37 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from 'next/link';
const ANALYTICS_BACKEND = process.env.ANALYTICS_BACKEND_URL || 'http://127.0.0.1:8000';
async function getMatches() {
const response = await fetch(`${ANALYTICS_BACKEND}/analytics/matches`, { cache: 'no-store' });
if (!response.ok) throw new Error('賽程 API 暫時無法回應');
return response.json();
}
function taipeiDate(value: string) {
return new Intl.DateTimeFormat('zh-TW', { timeZone: 'Asia/Taipei', month: '2-digit', day: '2-digit', weekday: 'short' }).format(new Date(value));
}
function taipeiTime(value: string) {
return new Intl.DateTimeFormat('zh-TW', { timeZone: 'Asia/Taipei', hour: '2-digit', minute: '2-digit', hour12: false }).format(new Date(value));
}
export default async function SchedulePage() {
let matches: any[] = [];
let error = '';
try { matches = await getMatches(); } catch (err) { error = err instanceof Error ? err.message : '賽程暫時無法讀取'; }
const grouped = matches.reduce<Record<string, any[]>>((acc, match) => {
const key = taipeiDate(match.kickoff_utc);
acc[key] = [...(acc[key] ?? []), match];
return acc;
}, {});
return (
<div className="space-y-6">
<section className="rounded-[2rem] border border-[#e7c89b] bg-[#fff8e6]/95 p-6 md:p-8"><p className="dot-matrix text-sm font-bold text-[#b83822]"></p><h1 className="mt-3 text-4xl font-black text-[#3f2f25]"></h1><p className="mt-3 text-sm leading-7 text-[#6f4f3c]">便</p></section>
{error ? <p className="rounded-2xl border border-[#e7a49a] bg-[#fff0e8] p-4 text-sm font-bold text-[#b83822]">{error}</p> : null}
{Object.entries(grouped).map(([date, rows]) => <section key={date} className="rounded-3xl border border-[#eadcb9] bg-white/75 p-5"><h2 className="dot-matrix text-lg font-bold text-[#7d2a15]">{date}{rows.length} </h2><div className="mt-4 grid gap-3">{rows.map((match) => <Link key={match.match_id} href={`/matches/${match.match_id}`} className="rounded-2xl border border-[#eadcb9] bg-[#fff8e6] p-4 transition hover:border-[#b83822]"><p className="font-black text-[#3f2f25]">{taipeiTime(match.kickoff_utc)}{match.home_team} vs {match.away_team}</p><p className="mt-1 text-sm text-[#7a5b46]">{match.status}{match.home_score ?? '-'} : {match.away_score ?? '-'}{match.venue_city ?? '場地待定'}</p></Link>)}</div></section>)}
</div>
);
}