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 # nuzlocke-tracker-rkyc
title: Dupes Clause & Shiny Clause enforcement title: Dupes Clause & Shiny Clause enforcement
status: todo status: completed
type: feature type: feature
priority: low priority: low
created_at: 2026-02-05T12:25:19Z 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. 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 type { EncounterDetail } from '../types'
import { TypeBadge } from './TypeBadge'
interface PokemonCardProps { interface PokemonCardProps {
encounter: EncounterDetail encounter: EncounterDetail
@@ -6,27 +7,6 @@ interface PokemonCardProps {
onClick?: () => void 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) { export function PokemonCard({ encounter, showFaintLevel, onClick }: PokemonCardProps) {
const { pokemon, currentPokemon, route, nickname, catchLevel, faintLevel, deathCause } = encounter const { pokemon, currentPokemon, route, nickname, catchLevel, faintLevel, deathCause } = encounter
const isDead = faintLevel !== null const isDead = faintLevel !== null
@@ -68,12 +48,7 @@ export function PokemonCard({ encounter, showFaintLevel, onClick }: PokemonCardP
<div className="flex gap-1 mt-1"> <div className="flex gap-1 mt-1">
{displayPokemon.types.map((type) => ( {displayPokemon.types.map((type) => (
<span <TypeBadge key={type} type={type} />
key={type}
className={`px-1.5 py-0.5 rounded text-[10px] font-medium text-white ${typeColors[type] ?? 'bg-gray-500'}`}
>
{type}
</span>
))} ))}
</div> </div>

View File

@@ -1,6 +1,7 @@
import { useState } from 'react' import { useState } from 'react'
import type { EncounterDetail, UpdateEncounterInput } from '../types' import type { EncounterDetail, UpdateEncounterInput } from '../types'
import { useEvolutions } from '../hooks/useEncounters' import { useEvolutions } from '../hooks/useEncounters'
import { TypeBadge } from './TypeBadge'
interface StatusChangeModalProps { interface StatusChangeModalProps {
encounter: EncounterDetail encounter: EncounterDetail
@@ -13,27 +14,6 @@ interface StatusChangeModalProps {
region?: string 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 { function formatEvolutionMethod(evo: { trigger: string; minLevel: number | null; item: string | null; heldItem: string | null; condition: string | null }): string {
const parts: string[] = [] const parts: string[] = []
if (evo.trigger === 'level-up' && evo.minLevel) { if (evo.trigger === 'level-up' && evo.minLevel) {
@@ -149,12 +129,7 @@ export function StatusChangeModal({
)} )}
<div className="flex gap-1 mt-1"> <div className="flex gap-1 mt-1">
{displayPokemon.types.map((type) => ( {displayPokemon.types.map((type) => (
<span <TypeBadge key={type} type={type} />
key={type}
className={`px-1.5 py-0.5 rounded text-[10px] font-medium text-white ${typeColors[type] ?? 'bg-gray-500'}`}
>
{type}
</span>
))} ))}
</div> </div>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1"> <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 { RulesConfiguration } from './RulesConfiguration'
export { StatCard } from './StatCard' export { StatCard } from './StatCard'
export { StepIndicator } from './StepIndicator' export { StepIndicator } from './StepIndicator'
export { TypeBadge } from './TypeBadge'