'use client' import { useState, useEffect, useCallback } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Button } from '@/components/ui/button' import { Header } from '@/components/layout/header' import { LevelList } from '@/components/levels/level-list' import { LevelDialog } from '@/components/levels/level-dialog' import { Spinner } from '@/components/ui/spinner' import { Level, LevelFormData } from '@/types' import { Plus } from 'lucide-react' import { apiFetch } from '@/lib/api' export default function LevelsPage() { const queryClient = useQueryClient() const [isDialogOpen, setIsDialogOpen] = useState(false) const [editingLevel, setEditingLevel] = useState(null) const [deleteConfirmId, setDeleteConfirmId] = useState(null) // Fetch levels const { data: levels, isLoading, error } = useQuery({ queryKey: ['levels'], queryFn: async () => { const res = await apiFetch('/api/levels') if (!res.ok) throw new Error('Failed to fetch levels') return res.json() }, }) // Create level mutation const createMutation = useMutation({ mutationFn: async (data: LevelFormData) => { const res = await apiFetch('/api/levels', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) if (!res.ok) { const error = await res.json() throw new Error(error.error || 'Failed to create level') } return res.json() }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['levels'] }) }, }) // Update level mutation const updateMutation = useMutation({ mutationFn: async ({ id, data }: { id: string; data: LevelFormData }) => { const res = await apiFetch('/api/levels', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id, ...data }), }) if (!res.ok) { const error = await res.json() throw new Error(error.error || 'Failed to update level') } return res.json() }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['levels'] }) }, }) // Delete level mutation const deleteMutation = useMutation({ mutationFn: async (id: string) => { const res = await apiFetch(`/api/levels?id=${id}`, { method: 'DELETE', }) if (!res.ok) { const error = await res.json() throw new Error(error.error || 'Failed to delete level') } return res.json() }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['levels'] }) setDeleteConfirmId(null) }, }) // Reorder mutation const reorderMutation = useMutation({ mutationFn: async (orders: { id: string; sortOrder: number }[]) => { const res = await apiFetch('/api/levels/reorder', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ orders }), }) if (!res.ok) { const error = await res.json() throw new Error(error.error || 'Failed to reorder levels') } return res.json() }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['levels'] }) }, }) const handleOpenCreate = () => { setEditingLevel(null) setIsDialogOpen(true) } const handleOpenEdit = (level: Level) => { setEditingLevel(level) setIsDialogOpen(true) } const handleDelete = (id: string) => { if (deleteConfirmId === id) { deleteMutation.mutate(id) } else { setDeleteConfirmId(id) // Reset after 3 seconds setTimeout(() => setDeleteConfirmId(null), 3000) } } const handleSubmit = async (data: LevelFormData) => { if (editingLevel) { await updateMutation.mutateAsync({ id: editingLevel.id, data }) } else { await createMutation.mutateAsync(data) } } const handleReorder = useCallback( (orders: { id: string; sortOrder: number }[]) => { reorderMutation.mutate(orders) }, [reorderMutation] ) if (isLoading) { return (
) } if (error) { return (

加载失败

) } return (

关卡配置

共 {levels?.length || 0} 个关卡

) }