feat: replace emoji icons with Heroicons SVG set

Install @heroicons/react and replace all emoji usage across stats, history,
search, and team pages with proper SVG icons (outline style, w-3 to w-4).
SectionTitle in stats page refactored to accept an icon component prop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-14 21:23:38 +02:00
parent a6111d7beb
commit c3ddb6e874
6 changed files with 8133 additions and 22 deletions
+22 -13
View File
@@ -3,6 +3,10 @@ import { useQuery, gql } from '@/lib/graphql/hooks'
import { useEffect } from 'react'
import Link from 'next/link'
import { TeamFlag } from '@/components/team-flag'
import {
ChartBarIcon, StarIcon, TrophyIcon, ClockIcon, BoltIcon,
FireIcon, SparklesIcon, ArrowPathIcon, GlobeEuropeAfricaIcon, TableCellsIcon,
} from '@heroicons/react/24/outline'
const STATS_QUERY = gql`
query Stats {
@@ -36,8 +40,13 @@ const STATS_QUERY = gql`
}
`
function SectionTitle({ children }: { children: React.ReactNode }) {
return <h2 className="text-[11px] font-bold tracking-[0.14em] uppercase text-[#2a5c35] mb-4">{children}</h2>
function SectionTitle({ children, icon: Icon }: { children: React.ReactNode; icon: React.ComponentType<{ className?: string }> }) {
return (
<h2 className="flex items-center gap-1.5 text-[11px] font-bold tracking-[0.14em] uppercase text-[#2a5c35] mb-4">
<Icon className="w-3.5 h-3.5 flex-shrink-0" />
{children}
</h2>
)
}
function Card({ children, className = '' }: { children: React.ReactNode; className?: string }) {
@@ -92,7 +101,7 @@ export default function StatsPage() {
{/* ── Goals per tournament bar chart ── */}
{tournaments.length > 0 && (
<div className="mb-12">
<SectionTitle> Goals Scored per Tournament</SectionTitle>
<SectionTitle icon={ChartBarIcon}>Goals Scored per Tournament</SectionTitle>
<Card>
<div className="px-3 pt-4 pb-0 sm:px-7 sm:pt-7">
<div className="flex items-end gap-[2px] sm:gap-[3px] h-[170px]">
@@ -125,7 +134,7 @@ export default function StatsPage() {
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-12">
{/* ── All-time top scorers ── */}
<div>
<SectionTitle>🏅 All-Time Top Scorers</SectionTitle>
<SectionTitle icon={StarIcon}>All-Time Top Scorers</SectionTitle>
<Card>
{scorers.map((s, i) => (
<Link key={s.playerName} href={`/players/${encodeURIComponent(s.playerName)}`}>
@@ -149,7 +158,7 @@ export default function StatsPage() {
{/* ── World Cup titles ── */}
<div>
<SectionTitle>🏆 World Cup Titles by Nation</SectionTitle>
<SectionTitle icon={TrophyIcon}>World Cup Titles by Nation</SectionTitle>
<Card>
{titlesByNation.map((t, i) => (
<Link key={t.name} href={`/teams/${t.slug}`}>
@@ -160,7 +169,7 @@ export default function StatsPage() {
<div className="flex-1 min-w-0 text-sm font-semibold text-[#dff5e8] truncate">{t.name}</div>
<div className="hidden sm:flex gap-0.5 flex-shrink-0">
{Array.from({ length: t.stats?.titles ?? 0 }).map((_, j) => (
<span key={j} className="text-sm">🏆</span>
<TrophyIcon key={j} className="w-4 h-4 text-[#22c55e]" />
))}
</div>
<span className="font-['Bebas_Neue'] text-[28px] text-[#22c55e] flex-shrink-0">{t.stats?.titles}</span>
@@ -174,7 +183,7 @@ export default function StatsPage() {
{/* ── Goals by minute heatmap ── */}
{minuteBuckets.length > 0 && (
<div className="mb-12">
<SectionTitle> Goals by Minute (All-Time)</SectionTitle>
<SectionTitle icon={ClockIcon}>Goals by Minute (All-Time)</SectionTitle>
<Card>
<div className="px-3 py-4 sm:p-6">
<div className="flex items-end gap-1 sm:gap-3 h-24">
@@ -197,7 +206,7 @@ export default function StatsPage() {
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-12">
{/* ── Biggest wins ── */}
<div>
<SectionTitle>💥 Biggest Victories</SectionTitle>
<SectionTitle icon={BoltIcon}>Biggest Victories</SectionTitle>
<Card>
{biggestWins.map(m => (
<Link key={m.id} href={`/tournaments/${m.year}#match-${m.id}`}>
@@ -220,7 +229,7 @@ export default function StatsPage() {
{/* ── Highest scoring matches ── */}
<div>
<SectionTitle>🔥 Highest Scoring Matches</SectionTitle>
<SectionTitle icon={FireIcon}>Highest Scoring Matches</SectionTitle>
<Card>
{highScoring.map(m => (
<Link key={m.id} href={`/tournaments/${m.year}#match-${m.id}`}>
@@ -245,7 +254,7 @@ export default function StatsPage() {
{/* ── Hat-tricks ── */}
{hatTricks.length > 0 && (
<div className="mb-12">
<SectionTitle>🎩 Hat-Tricks</SectionTitle>
<SectionTitle icon={SparklesIcon}>Hat-Tricks</SectionTitle>
<div className="grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] gap-3">
{hatTricks.map((h, i) => (
<div key={i} className="rounded-xl p-4" style={{ background: '#0a1810', border: '1px solid rgba(34,197,94,0.12)' }}>
@@ -270,7 +279,7 @@ export default function StatsPage() {
{/* ── ET & Penalty stats ── */}
{etStats && (
<div className="mb-12">
<SectionTitle> Extra Time & Penalty Shootouts</SectionTitle>
<SectionTitle icon={ArrowPathIcon}>Extra Time & Penalty Shootouts</SectionTitle>
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
{[
{ label: 'Knockout Matches', value: etStats.totalKnockoutMatches },
@@ -290,7 +299,7 @@ export default function StatsPage() {
{/* ── Confederation stats ── */}
{confStats.length > 0 && (
<div className="mb-12">
<SectionTitle>🌍 Performance by Confederation</SectionTitle>
<SectionTitle icon={GlobeEuropeAfricaIcon}>Performance by Confederation</SectionTitle>
<Card>
<table className="w-full">
<thead>
@@ -319,7 +328,7 @@ export default function StatsPage() {
{/* ── All-time team table ── */}
{teams.length > 0 && (
<div>
<SectionTitle>📊 All-Time Team Table</SectionTitle>
<SectionTitle icon={TableCellsIcon}>All-Time Team Table</SectionTitle>
<Card>
<div className="overflow-x-auto">
<table className="w-full" style={{ minWidth: '560px' }}>