This repository has been archived on 2026-05-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tippspiel/frontend/src/components/AchievementBadge.tsx
T
Ronny edf33fa932 feat: premium achievement badges with Material Symbols icons
Backend:
- New /api/achievements endpoint calculating 6 badges:
  Scharfschütze, Serien-Tipper, Tabellenführer, Frühtipper,
  Globetrotter, Diamant
- Each with progress tracking (current/target)

Frontend:
- AchievementBadge component with Stitch-inspired design
- Material Symbols Outlined font (filled icons)
- Unlocked: colored icon with glow + drop-shadow, rank label
- Locked: grayscale, lock overlay, progress bar
- ProfilePage: real badges replacing emoji placeholders
- Progress bar showing X/6 collected
- Mobile: 2-col grid, Desktop: 6-col grid

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:09:25 +02:00

71 lines
2.1 KiB
TypeScript

import { Achievement } from '../api/client';
import styles from './AchievementBadge.module.css';
interface Props {
achievement: Achievement;
}
export default function AchievementBadge({ achievement }: Props) {
const { name, description, icon, color, rankLabel, unlocked, current, target } = achievement;
return (
<div className={`${styles.badge} ${unlocked ? styles.unlocked : styles.locked}`}>
{/* Glow background for unlocked */}
{unlocked && (
<div className={styles.glow} style={{ background: `${color}20` }} />
)}
{/* Lock overlay for locked */}
{!unlocked && (
<div className={styles.lockOverlay}>
<div className={styles.lockCircle}>
<span className="material-symbols-outlined" style={{ fontSize: 18 }}>lock</span>
</div>
</div>
)}
{/* Icon */}
<div className={styles.iconWrap}>
{unlocked && (
<div className={styles.iconGlow} style={{ background: `${color}30` }} />
)}
<span
className={`material-symbols-outlined ${styles.icon}`}
style={{
color: unlocked ? color : 'var(--text-muted)',
fontVariationSettings: "'FILL' 1",
filter: unlocked ? `drop-shadow(0 0 10px ${color}cc)` : 'none',
}}
>
{icon}
</span>
</div>
{/* Name + Description */}
<h3 className={styles.name}>{name}</h3>
<p className={styles.desc}>{description}</p>
{/* Progress or Rank label */}
{unlocked ? (
<div className={styles.rankBadge} style={{
background: `${color}15`,
borderColor: `${color}40`,
color: color,
}}>
{rankLabel}
</div>
) : (
<div className={styles.progress}>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${achievement.progress}%`, background: color }}
/>
</div>
<span className={styles.progressText}>{current}/{target}</span>
</div>
)}
</div>
);
}