Use type PNG badges instead of colored text spans

Replace inline typeColors maps in PokemonCard and StatusChangeModal
with a shared TypeBadge component that renders the type icon PNGs
from /types/{type}.png.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 21:12:45 +01:00
parent 14ce0c1ce7
commit 6d77fb731e
23 changed files with 22 additions and 56 deletions

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-rkyc
title: Dupes Clause & Shiny Clause enforcement
status: todo
status: completed
type: feature
priority: low
created_at: 2026-02-05T12:25:19Z
updated_at: 2026-02-07T19:52:42Z
updated_at: 2026-02-07T20:11:59Z
---
Implement active enforcement for Dupes Clause and Shiny Clause in the encounter flow.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,4 +1,5 @@
import type { EncounterDetail } from '../types'
import { TypeBadge } from './TypeBadge'
interface PokemonCardProps {
encounter: EncounterDetail
@@ -6,27 +7,6 @@ interface PokemonCardProps {
onClick?: () => void
}
const typeColors: Record<string, string> = {
normal: 'bg-gray-400',
fire: 'bg-red-500',
water: 'bg-blue-500',
electric: 'bg-yellow-400',
grass: 'bg-green-500',
ice: 'bg-cyan-300',
fighting: 'bg-red-700',
poison: 'bg-purple-500',
ground: 'bg-amber-600',
flying: 'bg-indigo-300',
psychic: 'bg-pink-500',
bug: 'bg-lime-500',
rock: 'bg-amber-700',
ghost: 'bg-purple-700',
dragon: 'bg-indigo-600',
dark: 'bg-gray-700',
steel: 'bg-gray-400',
fairy: 'bg-pink-300',
}
export function PokemonCard({ encounter, showFaintLevel, onClick }: PokemonCardProps) {
const { pokemon, currentPokemon, route, nickname, catchLevel, faintLevel, deathCause } = encounter
const isDead = faintLevel !== null
@@ -68,12 +48,7 @@ export function PokemonCard({ encounter, showFaintLevel, onClick }: PokemonCardP
<div className="flex gap-1 mt-1">
{displayPokemon.types.map((type) => (
<span
key={type}
className={`px-1.5 py-0.5 rounded text-[10px] font-medium text-white ${typeColors[type] ?? 'bg-gray-500'}`}
>
{type}
</span>
<TypeBadge key={type} type={type} />
))}
</div>

View File

@@ -1,6 +1,7 @@
import { useState } from 'react'
import type { EncounterDetail, UpdateEncounterInput } from '../types'
import { useEvolutions } from '../hooks/useEncounters'
import { TypeBadge } from './TypeBadge'
interface StatusChangeModalProps {
encounter: EncounterDetail
@@ -13,27 +14,6 @@ interface StatusChangeModalProps {
region?: string
}
const typeColors: Record<string, string> = {
normal: 'bg-gray-400',
fire: 'bg-red-500',
water: 'bg-blue-500',
electric: 'bg-yellow-400',
grass: 'bg-green-500',
ice: 'bg-cyan-300',
fighting: 'bg-red-700',
poison: 'bg-purple-500',
ground: 'bg-amber-600',
flying: 'bg-indigo-300',
psychic: 'bg-pink-500',
bug: 'bg-lime-500',
rock: 'bg-amber-700',
ghost: 'bg-purple-700',
dragon: 'bg-indigo-600',
dark: 'bg-gray-700',
steel: 'bg-gray-400',
fairy: 'bg-pink-300',
}
function formatEvolutionMethod(evo: { trigger: string; minLevel: number | null; item: string | null; heldItem: string | null; condition: string | null }): string {
const parts: string[] = []
if (evo.trigger === 'level-up' && evo.minLevel) {
@@ -149,12 +129,7 @@ export function StatusChangeModal({
)}
<div className="flex gap-1 mt-1">
{displayPokemon.types.map((type) => (
<span
key={type}
className={`px-1.5 py-0.5 rounded text-[10px] font-medium text-white ${typeColors[type] ?? 'bg-gray-500'}`}
>
{type}
</span>
<TypeBadge key={type} type={type} />
))}
</div>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1">

View File

@@ -0,0 +1,15 @@
interface TypeBadgeProps {
type: string
size?: 'sm' | 'md'
}
export function TypeBadge({ type, size = 'sm' }: TypeBadgeProps) {
const height = size === 'md' ? 'h-5' : 'h-4'
return (
<img
src={`/types/${type}.png`}
alt={type}
className={`${height} w-auto`}
/>
)
}

View File

@@ -13,3 +13,4 @@ export { RuleToggle } from './RuleToggle'
export { RulesConfiguration } from './RulesConfiguration'
export { StatCard } from './StatCard'
export { StepIndicator } from './StepIndicator'
export { TypeBadge } from './TypeBadge'