Add pinwheel, encounters link, and boss position columns to admin tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-13 14:10:28 +01:00
parent 29a5c84651
commit 867ded8fa2
4 changed files with 69 additions and 4 deletions

View File

@@ -43,9 +43,11 @@ import type { CreateBossBattleInput, UpdateBossBattleInput } from '../../types/a
function SortableRouteRow({
route,
gameId,
onClick,
}: {
route: GameRoute
gameId: number
onClick: (r: GameRoute) => void
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
@@ -83,15 +85,31 @@ function SortableRouteRow({
</td>
<td className="px-4 py-3 text-sm whitespace-nowrap w-16">{route.order}</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">{route.name}</td>
<td className="px-4 py-3 text-sm whitespace-nowrap text-center">
{route.pinwheelZone != null ? route.pinwheelZone : '\u2014'}
</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">
<Link
to={`/admin/games/${gameId}/routes/${route.id}`}
onClick={(e) => e.stopPropagation()}
className="text-blue-600 dark:text-blue-400 hover:underline"
>
Encounters
</Link>
</td>
</tr>
)
}
function SortableBossRow({
boss,
routes,
onPositionChange,
onClick,
}: {
boss: BossBattle
routes: GameRoute[]
onPositionChange: (bossId: number, afterRouteId: number | null) => void
onClick: (b: BossBattle) => void
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
@@ -137,6 +155,24 @@ function SortableBossRow({
</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">{boss.section ?? '\u2014'}</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">{boss.location}</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">
<select
value={boss.afterRouteId ?? ''}
onClick={(e) => e.stopPropagation()}
onChange={(e) => {
const value = e.target.value === '' ? null : Number(e.target.value)
onPositionChange(boss.id, value)
}}
className="text-sm border border-gray-300 dark:border-gray-600 rounded px-1.5 py-0.5 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 max-w-[180px]"
>
<option value=""></option>
{routes.map((r) => (
<option key={r.id} value={r.id}>
{r.name}
</option>
))}
</select>
</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">{boss.levelCap}</td>
<td className="px-4 py-3 text-sm whitespace-nowrap">{boss.pokemon.length}</td>
</tr>
@@ -314,6 +350,12 @@ export function AdminGameDetail() {
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Name
</th>
<th className="px-4 py-3 text-center text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-24">
Pinwheel
</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-28">
Links
</th>
</tr>
</thead>
<DndContext
@@ -330,6 +372,7 @@ export function AdminGameDetail() {
<SortableRouteRow
key={route.id}
route={route}
gameId={id}
onClick={(r) => setEditing(r)}
/>
))}
@@ -443,6 +486,9 @@ export function AdminGameDetail() {
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Location
</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Position
</th>
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-20">
Lv Cap
</th>
@@ -465,6 +511,13 @@ export function AdminGameDetail() {
<SortableBossRow
key={boss.id}
boss={boss}
routes={routes}
onPositionChange={(bossId, afterRouteId) =>
updateBoss.mutate({
bossId,
data: { afterRouteId } as UpdateBossBattleInput,
})
}
onClick={(b) => setEditingBoss(b)}
/>
))}