diff --git a/apps/cat-admin-web/src/pages/cat-management.tsx b/apps/cat-admin-web/src/pages/cat-management.tsx new file mode 100644 index 0000000..66b5075 --- /dev/null +++ b/apps/cat-admin-web/src/pages/cat-management.tsx @@ -0,0 +1,233 @@ +import React, { useState, useEffect } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { entities } from '@/lib/nvwa'; +import { Button } from '@/components/ui/button'; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Switch } from '@/components/ui/switch'; +import { Badge } from '@/components/ui/badge'; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Textarea } from '@/components/ui/textarea'; + +interface Cat { + id: number; + name: string; + age: number; + gender: string; + grade: string; + type: string; + is_available: boolean; + description?: string; + image_ids: number[]; + created_at: string; + updated_at: string; +} + +export default function CatManagement() { + const [searchParams] = useSearchParams(); + const editId = searchParams.get('id'); + const [cats, setCats] = useState([]); + const [editingCat, setEditingCat] = useState(null); + const [isDialogOpen, setIsDialogOpen] = useState(false); + + useEffect(() => { + fetchCats(); + }, []); + + useEffect(() => { + if (editId && cats.length > 0) { + const cat = cats.find(c => c.id === parseInt(editId)); + if (cat) { + setEditingCat(cat); + setIsDialogOpen(true); + } + } + }, [editId, cats]); + + const fetchCats = async () => { + const { data, error } = await entities.from('cat').select('*'); + if (error) { + console.error(error); + return; + } + setCats(data || []); + }; + + const toggleAvailability = async (cat: Cat) => { + const { error } = await entities.from('cat').update({ is_available: !cat.is_available }).eq('id', cat.id); + if (error) { + console.error(error); + return; + } + setCats(cats.map(c => c.id === cat.id ? { ...c, is_available: !c.is_available } : c)); + }; + + const openEditDialog = (cat: Cat) => { + setEditingCat(cat); + setIsDialogOpen(true); + }; + + const handleEdit = async () => { + if (!editingCat) return; + const { error } = await entities.from('cat').update({ + name: editingCat.name, + age: editingCat.age, + gender: editingCat.gender, + grade: editingCat.grade, + type: editingCat.type, + description: editingCat.description, + image_ids: editingCat.image_ids, + }).eq('id', editingCat.id); + if (error) { + console.error(error); + return; + } + setCats(cats.map(cat => cat.id === editingCat.id ? editingCat : cat)); + setIsDialogOpen(false); + setEditingCat(null); + }; + + return ( +
+ + + 猫咪管理 + + + + + + 名称 + 年龄 + 性别 + 等级 + 类型 + 可售卖 + 操作 + + + + {cats.map(cat => ( + + {cat.name} + {cat.age} 月 + + + {cat.gender === 'male' ? '雄' : '雌'} + + + + {cat.grade} + + + + {cat.type === 'breeding_male' ? '种公' : cat.type === 'breeding_female' ? '种母' : '幼猫'} + + + + toggleAvailability(cat)} + /> + + + + + + ))} + +
+
+
+ + + + + 编辑猫咪 + + {editingCat && ( +
+
+ + setEditingCat({ ...editingCat, name: e.target.value })} + /> +
+
+ + setEditingCat({ ...editingCat, age: parseInt(e.target.value) })} + /> +
+
+ + +
+
+ + +
+
+ + +
+
+ +