Add click-to-edit pattern across all admin tables
Replace Actions columns with clickable rows that open edit modals directly. Delete is now an inline two-step confirm button in the edit modal footer. Games modal links to routes/bosses detail, route modal links to encounters, and boss modal has an Edit Team button. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { AdminTable, type Column } from '../../components/admin/AdminTable'
|
||||
import { GameFormModal } from '../../components/admin/GameFormModal'
|
||||
import { DeleteConfirmModal } from '../../components/admin/DeleteConfirmModal'
|
||||
import { useGames } from '../../hooks/useGames'
|
||||
import { useCreateGame, useUpdateGame, useDeleteGame } from '../../hooks/useAdmin'
|
||||
import { exportGames } from '../../api/admin'
|
||||
@@ -10,7 +8,6 @@ import { downloadJson } from '../../utils/download'
|
||||
import type { Game, CreateGameInput, UpdateGameInput } from '../../types'
|
||||
|
||||
export function AdminGames() {
|
||||
const navigate = useNavigate()
|
||||
const { data: games = [], isLoading } = useGames()
|
||||
const createGame = useCreateGame()
|
||||
const updateGame = useUpdateGame()
|
||||
@@ -18,7 +15,6 @@ export function AdminGames() {
|
||||
|
||||
const [showCreate, setShowCreate] = useState(false)
|
||||
const [editing, setEditing] = useState<Game | null>(null)
|
||||
const [deleting, setDeleting] = useState<Game | null>(null)
|
||||
|
||||
const columns: Column<Game>[] = [
|
||||
{ header: 'Name', accessor: (g) => g.name },
|
||||
@@ -26,25 +22,6 @@ export function AdminGames() {
|
||||
{ header: 'Region', accessor: (g) => g.region, sortKey: (g) => g.region },
|
||||
{ header: 'Gen', accessor: (g) => g.generation, sortKey: (g) => g.generation },
|
||||
{ header: 'Year', accessor: (g) => g.releaseYear ?? '-', sortKey: (g) => g.releaseYear ?? 0 },
|
||||
{
|
||||
header: 'Actions',
|
||||
accessor: (g) => (
|
||||
<div className="flex gap-2" onClick={(e) => e.stopPropagation()}>
|
||||
<button
|
||||
onClick={() => setEditing(g)}
|
||||
className="text-blue-600 hover:text-blue-800 dark:text-blue-400 text-sm"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setDeleting(g)}
|
||||
className="text-red-600 hover:text-red-800 dark:text-red-400 text-sm"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
@@ -75,7 +52,7 @@ export function AdminGames() {
|
||||
data={games}
|
||||
isLoading={isLoading}
|
||||
emptyMessage="No games yet. Add one to get started."
|
||||
onRowClick={(g) => navigate(`/admin/games/${g.id}`)}
|
||||
onRowClick={(g) => setEditing(g)}
|
||||
keyFn={(g) => g.id}
|
||||
/>
|
||||
|
||||
@@ -102,20 +79,13 @@ export function AdminGames() {
|
||||
}
|
||||
onClose={() => setEditing(null)}
|
||||
isSubmitting={updateGame.isPending}
|
||||
/>
|
||||
)}
|
||||
|
||||
{deleting && (
|
||||
<DeleteConfirmModal
|
||||
title={`Delete ${deleting.name}?`}
|
||||
message="This will permanently delete the game and all its routes. Games with existing runs cannot be deleted."
|
||||
onConfirm={() =>
|
||||
deleteGame.mutate(deleting.id, {
|
||||
onSuccess: () => setDeleting(null),
|
||||
onDelete={() =>
|
||||
deleteGame.mutate(editing.id, {
|
||||
onSuccess: () => setEditing(null),
|
||||
})
|
||||
}
|
||||
onCancel={() => setDeleting(null)}
|
||||
isDeleting={deleteGame.isPending}
|
||||
detailUrl={`/admin/games/${editing.id}`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user