224 lines
7.4 KiB
TypeScript
224 lines
7.4 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { Button } from "@/components/ui/button"
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
DialogTrigger,
|
||
} from "@/components/ui/dialog"
|
||
import { Input } from "@/components/ui/input"
|
||
import { Label } from "@/components/ui/label"
|
||
import { Textarea } from "@/components/ui/textarea"
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectGroup,
|
||
SelectItem,
|
||
SelectLabel,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "@/components/ui/select"
|
||
import { Switch } from "@/components/ui/switch"
|
||
import { Trophy, Loader2 } from "lucide-react"
|
||
import { toast } from "@/components/ui/use-toast"
|
||
import type { Achievement } from "@/lib/api/types"
|
||
|
||
type AddAchievementDialogProps = {
|
||
onAchievementAdded: () => void
|
||
}
|
||
|
||
export function AddAchievementDialog({ onAchievementAdded }: AddAchievementDialogProps) {
|
||
const [open, setOpen] = useState(false)
|
||
const [loading, setLoading] = useState(false)
|
||
const [formData, setFormData] = useState<Partial<Achievement>>({
|
||
name: "",
|
||
description: "",
|
||
category: "互动",
|
||
requirement: "",
|
||
rewardType: "经验值",
|
||
rewardAmount: 100,
|
||
isHidden: false,
|
||
})
|
||
|
||
const handleChange = (field: keyof Achievement, value: any) => {
|
||
setFormData((prev) => ({ ...prev, [field]: value }))
|
||
}
|
||
|
||
const handleSubmit = async () => {
|
||
if (!formData.name || !formData.description || !formData.requirement) {
|
||
toast({
|
||
title: "表单不完整",
|
||
description: "请填写所有必填字段",
|
||
variant: "destructive",
|
||
})
|
||
return
|
||
}
|
||
|
||
setLoading(true)
|
||
|
||
try {
|
||
// 模拟API调用
|
||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||
|
||
toast({
|
||
title: "成就添加成功",
|
||
description: `成就 "${formData.name}" 已成功添加到系统`,
|
||
})
|
||
|
||
setOpen(false)
|
||
setFormData({
|
||
name: "",
|
||
description: "",
|
||
category: "互动",
|
||
requirement: "",
|
||
rewardType: "经验值",
|
||
rewardAmount: 100,
|
||
isHidden: false,
|
||
})
|
||
onAchievementAdded()
|
||
} catch (error) {
|
||
toast({
|
||
title: "添加失败",
|
||
description: "添加成就时发生错误,请重试",
|
||
variant: "destructive",
|
||
})
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={setOpen}>
|
||
<DialogTrigger asChild>
|
||
<Button className="bg-gradient-to-r from-amber-500 to-orange-600 hover:from-amber-600 hover:to-orange-700">
|
||
<Trophy className="mr-2 h-4 w-4" />
|
||
添加成就
|
||
</Button>
|
||
</DialogTrigger>
|
||
<DialogContent className="sm:max-w-[600px]">
|
||
<DialogHeader>
|
||
<DialogTitle className="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-amber-600 to-orange-600">
|
||
添加新成就
|
||
</DialogTitle>
|
||
<DialogDescription>创建新的系统成就和解锁条件</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<div className="grid gap-4 py-4">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="name">成就名称 *</Label>
|
||
<Input
|
||
id="name"
|
||
value={formData.name}
|
||
onChange={(e) => handleChange("name", e.target.value)}
|
||
placeholder="输入成就名称"
|
||
/>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="category">成就类别 *</Label>
|
||
<Select value={formData.category} onValueChange={(value) => handleChange("category", value)}>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="选择类别" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectGroup>
|
||
<SelectLabel>成就类别</SelectLabel>
|
||
<SelectItem value="互动">互动</SelectItem>
|
||
<SelectItem value="好感度">好感度</SelectItem>
|
||
<SelectItem value="收集">收集</SelectItem>
|
||
<SelectItem value="探索">探索</SelectItem>
|
||
<SelectItem value="特殊">特殊</SelectItem>
|
||
<SelectItem value="隐藏">隐藏</SelectItem>
|
||
</SelectGroup>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="description">成就描述 *</Label>
|
||
<Textarea
|
||
id="description"
|
||
value={formData.description}
|
||
onChange={(e) => handleChange("description", e.target.value)}
|
||
placeholder="输入成就描述"
|
||
/>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="requirement">解锁条件 *</Label>
|
||
<Textarea
|
||
id="requirement"
|
||
value={formData.requirement}
|
||
onChange={(e) => handleChange("requirement", e.target.value)}
|
||
placeholder="输入解锁条件"
|
||
/>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="rewardType">奖励类型</Label>
|
||
<Select value={formData.rewardType} onValueChange={(value) => handleChange("rewardType", value)}>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="选择奖励类型" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectGroup>
|
||
<SelectLabel>奖励类型</SelectLabel>
|
||
<SelectItem value="经验值">经验值</SelectItem>
|
||
<SelectItem value="好感度">好感度</SelectItem>
|
||
<SelectItem value="虚拟币">虚拟币</SelectItem>
|
||
<SelectItem value="道具">道具</SelectItem>
|
||
<SelectItem value="服装">服装</SelectItem>
|
||
<SelectItem value="称号">称号</SelectItem>
|
||
</SelectGroup>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="rewardAmount">奖励数量</Label>
|
||
<Input
|
||
id="rewardAmount"
|
||
type="number"
|
||
value={formData.rewardAmount}
|
||
onChange={(e) => handleChange("rewardAmount", Number.parseInt(e.target.value) || 0)}
|
||
min={0}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center space-x-2">
|
||
<Switch
|
||
id="isHidden"
|
||
checked={formData.isHidden}
|
||
onCheckedChange={(checked) => handleChange("isHidden", checked)}
|
||
/>
|
||
<Label htmlFor="isHidden">隐藏成就(用户无法在成就列表中看到)</Label>
|
||
</div>
|
||
</div>
|
||
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setOpen(false)}>
|
||
取消
|
||
</Button>
|
||
<Button
|
||
className="bg-gradient-to-r from-amber-500 to-orange-600 hover:from-amber-600 hover:to-orange-700"
|
||
onClick={handleSubmit}
|
||
disabled={loading}
|
||
>
|
||
{loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Trophy className="mr-2 h-4 w-4" />}
|
||
{loading ? "添加中..." : "添加成就"}
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
)
|
||
}
|