import { useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { GameGrid, RulesConfiguration, StepIndicator } from '../components' import { useGames, useGameRoutes } from '../hooks/useGames' import { useCreateRun, useRuns, useNamingCategories } from '../hooks/useRuns' import type { Game, NuzlockeRules, RunVisibility } from '../types' import { DEFAULT_RULES } from '../types' import { RULE_DEFINITIONS } from '../types/rules' const DEFAULT_COLOR = '#6366f1' export function NewRun() { const navigate = useNavigate() const { data: games, isLoading, error } = useGames() const { data: runs } = useRuns() const createRun = useCreateRun() const { data: namingCategories } = useNamingCategories() const [step, setStep] = useState(1) const [selectedGame, setSelectedGame] = useState(null) const [rules, setRules] = useState(DEFAULT_RULES) const [runName, setRunName] = useState('') const [namingScheme, setNamingScheme] = useState(null) const [visibility, setVisibility] = useState('public') const { data: routes } = useGameRoutes(selectedGame?.id ?? null) const hiddenRules = useMemo(() => { const hidden = new Set() const hasPinwheelZones = routes?.some((r) => r.pinwheelZone != null) if (!hasPinwheelZones) { hidden.add('pinwheelClause') } return hidden.size > 0 ? hidden : undefined }, [routes]) const handleGameSelect = (game: Game) => { if (selectedGame?.id === game.id) { setSelectedGame(null) return } setSelectedGame(game) if (!runName || runName === `${selectedGame?.name} Nuzlocke`) { setRunName(`${game.name} Nuzlocke`) } } const handleCreate = () => { if (!selectedGame) return createRun.mutate( { gameId: selectedGame.id, name: runName, rules, namingScheme, visibility }, { onSuccess: (data) => navigate(`/runs/${data.id}`) } ) } const visibleRuleKeys = RULE_DEFINITIONS.filter((r) => !hiddenRules?.has(r.key)).map((r) => r.key) const enabledRuleCount = visibleRuleKeys.filter((k) => rules[k]).length const totalRuleCount = visibleRuleKeys.length return (

New Nuzlocke Run

Set up your run in a few steps.

{step === 1 && (

Choose a Game

{selectedGame ? (

{selectedGame.name}

{selectedGame.region.charAt(0).toUpperCase() + selectedGame.region.slice(1)}

) : (

Select a game to continue

)}
{isLoading && (
)} {error && (
Failed to load games. Please try again.
)} {games && ( )}
)} {step === 2 && (
)} {step === 3 && (

Name Your Run

setRunName(e.target.value)} className="w-full px-3 py-2 rounded-lg border border-border-default bg-surface-2 text-text-primary focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-transparent" placeholder="My Nuzlocke Run" />
{namingCategories && namingCategories.length > 0 && (

Get nickname suggestions from a themed word list when catching Pokemon.

)}

{visibility === 'private' ? 'Only you will be able to see this run' : 'Anyone can view this run'}

Summary

Game
{selectedGame?.name}
Region
{selectedGame && selectedGame.region.charAt(0).toUpperCase() + selectedGame.region.slice(1)}
Rules
{enabledRuleCount} of {totalRuleCount} enabled
Naming Scheme
{namingScheme ? namingScheme.charAt(0).toUpperCase() + namingScheme.slice(1) : 'None'}
Visibility
{visibility}
{createRun.error && (
Failed to create run. Please try again.
)}
)}
) } function SelectedGameThumb({ game }: { game: Game }) { const [imgIdx, setImgIdx] = useState(0) const backgroundColor = game.color ?? DEFAULT_COLOR const boxArtSrcs = [`/boxart/${game.slug}.png`, `/boxart/${game.slug}.jpg`] if (imgIdx >= boxArtSrcs.length) { return (
{game.name.replace('Pokemon ', '').slice(0, 3)}
) } return ( {game.name} setImgIdx((i) => i + 1)} /> ) }