onRowClick(row) : undefined}
- className={onRowClick ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800' : ''}
+ className={
+ onRowClick
+ ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800'
+ : ''
+ }
>
{columns.map((col) => (
- Edit Team ({boss?.pokemon.length ?? 0})
-
- ) : undefined}
+ headerExtra={
+ onEditTeam ? (
+
+ ) : undefined
+ }
>
@@ -190,7 +212,9 @@ export function BossBattleFormModal({
{games && games.length > 1 && (
-
+
-
+
-
+
(a[0] ?? '').localeCompare(b[0] ?? ''))
+ const remaining = [...map.entries()].sort((a, b) =>
+ (a[0] ?? '').localeCompare(b[0] ?? '')
+ )
for (const [label, pokemon] of remaining) {
variants.push({ label, pokemon })
}
return variants
}
-export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEditorProps) {
- const [variants, setVariants] = useState(() => groupByVariant(boss))
+export function BossTeamEditor({
+ boss,
+ onSave,
+ onClose,
+ isSaving,
+}: BossTeamEditorProps) {
+ const [variants, setVariants] = useState(() =>
+ groupByVariant(boss)
+ )
const [activeTab, setActiveTab] = useState(0)
const [newVariantName, setNewVariantName] = useState('')
const [showAddVariant, setShowAddVariant] = useState(false)
const activeVariant = variants[activeTab] ?? variants[0]
- const updateVariant = (tabIndex: number, updater: (v: Variant) => Variant) => {
+ const updateVariant = (
+ tabIndex: number,
+ updater: (v: Variant) => Variant
+ ) => {
setVariants((prev) => prev.map((v, i) => (i === tabIndex ? updater(v) : v)))
}
const addSlot = () => {
updateVariant(activeTab, (v) => ({
...v,
- pokemon: [...v.pokemon, { pokemonId: null, pokemonName: '', level: '', order: v.pokemon.length + 1 }],
+ pokemon: [
+ ...v.pokemon,
+ {
+ pokemonId: null,
+ pokemonName: '',
+ level: '',
+ order: v.pokemon.length + 1,
+ },
+ ],
}))
}
const removeSlot = (index: number) => {
updateVariant(activeTab, (v) => ({
...v,
- pokemon: v.pokemon.filter((_, i) => i !== index).map((item, i) => ({ ...item, order: i + 1 })),
+ pokemon: v.pokemon
+ .filter((_, i) => i !== index)
+ .map((item, i) => ({ ...item, order: i + 1 })),
}))
}
- const updateSlot = (index: number, field: string, value: number | string | null) => {
+ const updateSlot = (
+ index: number,
+ field: string,
+ value: number | string | null
+ ) => {
updateVariant(activeTab, (v) => ({
...v,
- pokemon: v.pokemon.map((item, i) => (i === index ? { ...item, [field]: value } : item)),
+ pokemon: v.pokemon.map((item, i) =>
+ i === index ? { ...item, [field]: value } : item
+ ),
}))
}
@@ -92,7 +125,13 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
const name = newVariantName.trim()
if (!name) return
if (variants.some((v) => v.label === name)) return
- setVariants((prev) => [...prev, { label: name, pokemon: [{ pokemonId: null, pokemonName: '', level: '', order: 1 }] }])
+ setVariants((prev) => [
+ ...prev,
+ {
+ label: name,
+ pokemon: [{ pokemonId: null, pokemonName: '', level: '', order: 1 }],
+ },
+ ])
setActiveTab(variants.length)
setNewVariantName('')
setShowAddVariant(false)
@@ -109,8 +148,11 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
e.preventDefault()
const allPokemon: BossPokemonInput[] = []
for (const variant of variants) {
- const conditionLabel = variants.length === 1 && variant.label === null ? null : variant.label
- const validPokemon = variant.pokemon.filter((t) => t.pokemonId != null && t.level)
+ const conditionLabel =
+ variants.length === 1 && variant.label === null ? null : variant.label
+ const validPokemon = variant.pokemon.filter(
+ (t) => t.pokemonId != null && t.level
+ )
for (let i = 0; i < validPokemon.length; i++) {
allPokemon.push({
pokemonId: validPokemon[i].pokemonId!,
@@ -147,7 +189,10 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
{v.label ?? 'Default'}
{v.label !== null && (
{ e.stopPropagation(); removeVariant(i) }}
+ onClick={(e) => {
+ e.stopPropagation()
+ removeVariant(i)
+ }}
className="ml-1.5 text-gray-400 hover:text-red-500 cursor-pointer"
title="Remove variant"
>
@@ -171,13 +216,31 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
type="text"
value={newVariantName}
onChange={(e) => setNewVariantName(e.target.value)}
- onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addVariant() } if (e.key === 'Escape') setShowAddVariant(false) }}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault()
+ addVariant()
+ }
+ if (e.key === 'Escape') setShowAddVariant(false)
+ }}
placeholder="Variant name..."
className="px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600 w-40"
autoFocus
/>
-
-
+
+
)}
@@ -185,7 +248,10 @@ export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEdit
|
- {group.order} |
+
+ {group.order}
+ |
{group.name} |
{group.pinwheelZone != null ? group.pinwheelZone : '\u2014'}
@@ -138,7 +155,9 @@ function SortableRouteGroup({
{child.order}
|
- {'\u2514'}
+
+ {'\u2514'}
+
{child.name}
|
@@ -172,8 +191,14 @@ function SortableBossRow({
onPositionChange: (bossId: number, afterRouteId: number | null) => void
onClick: (b: BossBattle) => void
}) {
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
- useSortable({ id: boss.id })
+ const {
+ attributes,
+ listeners,
+ setNodeRef,
+ transform,
+ transition,
+ isDragging,
+ } = useSortable({ id: boss.id })
const style = {
transform: CSS.Transform.toString(transform),
@@ -208,22 +233,29 @@ function SortableBossRow({
| {boss.order} |
{boss.name}
- {boss.gameId != null && (() => {
- const g = games.find((g) => g.id === boss.gameId)
- return g ? (
-
- {g.name}
-
- ) : null
- })()}
+ {boss.gameId != null &&
+ (() => {
+ const g = games.find((g) => g.id === boss.gameId)
+ return g ? (
+
+ {g.name}
+
+ ) : null
+ })()}
|
{boss.bossType.replace('_', ' ')}
|
- {boss.specialtyType ? : '\u2014'}
+ {boss.specialtyType ? (
+
+ ) : (
+ '\u2014'
+ )}
+ |
+
+ {boss.section ?? '\u2014'}
|
- {boss.section ?? '\u2014'} |
{boss.location} |
|
{boss.levelCap} |
- {boss.pokemon.length} |
+
+ {boss.pokemon.length}
+ |
)
}
@@ -278,16 +312,18 @@ export function AdminGameDetail() {
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
- useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
+ useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
)
- if (isLoading) return Loading...
- if (!game) return Loading...
+ if (!game)
+ return