2026-02-05 18:36:19 +01:00
|
|
|
import { type FormEvent, useState } from 'react'
|
|
|
|
|
import { FormModal } from './FormModal'
|
2026-02-08 20:04:26 +01:00
|
|
|
import { PokemonSelector } from './PokemonSelector'
|
2026-02-08 20:19:16 +01:00
|
|
|
import { METHOD_ORDER, METHOD_CONFIG, getMethodLabel } from '../EncounterMethodBadge'
|
2026-02-05 18:36:19 +01:00
|
|
|
import type { RouteEncounterDetail, CreateRouteEncounterInput, UpdateRouteEncounterInput } from '../../types'
|
|
|
|
|
|
|
|
|
|
interface RouteEncounterFormModalProps {
|
|
|
|
|
encounter?: RouteEncounterDetail
|
|
|
|
|
onSubmit: (data: CreateRouteEncounterInput | UpdateRouteEncounterInput) => void
|
|
|
|
|
onClose: () => void
|
|
|
|
|
isSubmitting?: boolean
|
2026-02-08 13:44:38 +01:00
|
|
|
onDelete?: () => void
|
|
|
|
|
isDeleting?: boolean
|
2026-02-05 18:36:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function RouteEncounterFormModal({
|
|
|
|
|
encounter,
|
|
|
|
|
onSubmit,
|
|
|
|
|
onClose,
|
|
|
|
|
isSubmitting,
|
2026-02-08 13:44:38 +01:00
|
|
|
onDelete,
|
|
|
|
|
isDeleting,
|
2026-02-05 18:36:19 +01:00
|
|
|
}: RouteEncounterFormModalProps) {
|
|
|
|
|
const [pokemonId, setPokemonId] = useState(encounter?.pokemonId ?? 0)
|
2026-02-08 20:19:16 +01:00
|
|
|
|
|
|
|
|
const initialMethod = encounter?.encounterMethod ?? ''
|
|
|
|
|
const isKnownMethod = METHOD_ORDER.includes(initialMethod)
|
|
|
|
|
const [selectedMethod, setSelectedMethod] = useState(isKnownMethod ? initialMethod : initialMethod ? 'other' : '')
|
|
|
|
|
const [customMethod, setCustomMethod] = useState(isKnownMethod ? '' : initialMethod)
|
|
|
|
|
const encounterMethod = selectedMethod === 'other' ? customMethod : selectedMethod
|
|
|
|
|
|
2026-02-05 18:36:19 +01:00
|
|
|
const [encounterRate, setEncounterRate] = useState(String(encounter?.encounterRate ?? ''))
|
|
|
|
|
const [minLevel, setMinLevel] = useState(String(encounter?.minLevel ?? ''))
|
|
|
|
|
const [maxLevel, setMaxLevel] = useState(String(encounter?.maxLevel ?? ''))
|
|
|
|
|
|
|
|
|
|
const handleSubmit = (e: FormEvent) => {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
if (encounter) {
|
|
|
|
|
onSubmit({
|
|
|
|
|
encounterMethod,
|
|
|
|
|
encounterRate: Number(encounterRate),
|
|
|
|
|
minLevel: Number(minLevel),
|
|
|
|
|
maxLevel: Number(maxLevel),
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
onSubmit({
|
|
|
|
|
pokemonId,
|
|
|
|
|
encounterMethod,
|
|
|
|
|
encounterRate: Number(encounterRate),
|
|
|
|
|
minLevel: Number(minLevel),
|
|
|
|
|
maxLevel: Number(maxLevel),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<FormModal
|
|
|
|
|
title={encounter ? 'Edit Route Encounter' : 'Add Pokemon to Route'}
|
|
|
|
|
onClose={onClose}
|
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
|
isSubmitting={isSubmitting}
|
2026-02-08 13:44:38 +01:00
|
|
|
onDelete={onDelete}
|
|
|
|
|
isDeleting={isDeleting}
|
2026-02-05 18:36:19 +01:00
|
|
|
>
|
|
|
|
|
{!encounter && (
|
2026-02-08 20:04:26 +01:00
|
|
|
<PokemonSelector
|
|
|
|
|
label="Pokemon"
|
|
|
|
|
selectedId={pokemonId || null}
|
|
|
|
|
onChange={(id) => setPokemonId(id ?? 0)}
|
|
|
|
|
/>
|
2026-02-05 18:36:19 +01:00
|
|
|
)}
|
|
|
|
|
<div>
|
|
|
|
|
<label className="block text-sm font-medium mb-1">Encounter Method</label>
|
2026-02-08 20:19:16 +01:00
|
|
|
<select
|
2026-02-05 18:36:19 +01:00
|
|
|
required
|
2026-02-08 20:19:16 +01:00
|
|
|
value={selectedMethod}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
setSelectedMethod(e.target.value)
|
|
|
|
|
if (e.target.value !== 'other') setCustomMethod('')
|
|
|
|
|
}}
|
2026-02-05 18:36:19 +01:00
|
|
|
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
2026-02-08 20:19:16 +01:00
|
|
|
>
|
|
|
|
|
<option value="">Select method...</option>
|
|
|
|
|
{METHOD_ORDER.map((m) => (
|
|
|
|
|
<option key={m} value={m}>
|
|
|
|
|
{getMethodLabel(m)}
|
|
|
|
|
</option>
|
|
|
|
|
))}
|
|
|
|
|
<option value="other">Other...</option>
|
|
|
|
|
</select>
|
|
|
|
|
{selectedMethod && selectedMethod !== 'other' && (
|
|
|
|
|
<span
|
|
|
|
|
className={`inline-block mt-1 text-[9px] px-1.5 py-0.5 font-medium rounded-full whitespace-nowrap ${METHOD_CONFIG[selectedMethod]?.color ?? ''}`}
|
|
|
|
|
>
|
|
|
|
|
{getMethodLabel(selectedMethod)}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
{selectedMethod === 'other' && (
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
required
|
|
|
|
|
value={customMethod}
|
|
|
|
|
onChange={(e) => setCustomMethod(e.target.value)}
|
|
|
|
|
placeholder="Custom method name"
|
|
|
|
|
className="w-full mt-2 px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2026-02-05 18:36:19 +01:00
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label className="block text-sm font-medium mb-1">Encounter Rate (%)</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
required
|
|
|
|
|
min={1}
|
|
|
|
|
max={100}
|
|
|
|
|
value={encounterRate}
|
|
|
|
|
onChange={(e) => setEncounterRate(e.target.value)}
|
|
|
|
|
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
|
|
|
<div>
|
|
|
|
|
<label className="block text-sm font-medium mb-1">Min Level</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
required
|
|
|
|
|
min={1}
|
|
|
|
|
max={100}
|
|
|
|
|
value={minLevel}
|
|
|
|
|
onChange={(e) => setMinLevel(e.target.value)}
|
|
|
|
|
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label className="block text-sm font-medium mb-1">Max Level</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
required
|
|
|
|
|
min={1}
|
|
|
|
|
max={100}
|
|
|
|
|
value={maxLevel}
|
|
|
|
|
onChange={(e) => setMaxLevel(e.target.value)}
|
|
|
|
|
className="w-full px-3 py-2 border rounded-md dark:bg-gray-700 dark:border-gray-600"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</FormModal>
|
|
|
|
|
)
|
|
|
|
|
}
|