155 lines
5.9 KiB
TypeScript
155 lines
5.9 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import type { Dance } from "@/lib/api/types"
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogFooter,
|
|
} from "@/components/ui/dialog"
|
|
import { Badge } from "@/components/ui/badge"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Clock, Music, Calendar, User, BarChart, Video, Play, Pause } from "lucide-react"
|
|
|
|
interface DanceDetailDialogProps {
|
|
dance: Dance
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}
|
|
|
|
export function DanceDetailDialog({ dance, open, onOpenChange }: DanceDetailDialogProps) {
|
|
const [isPlaying, setIsPlaying] = useState(false)
|
|
|
|
const togglePlay = () => {
|
|
setIsPlaying(!isPlaying)
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
|
|
<DialogHeader>
|
|
<DialogTitle className="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-purple-600 to-pink-600">
|
|
{dance.name}
|
|
</DialogTitle>
|
|
<DialogDescription>舞蹈ID: {dance.id}</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
|
|
<div className="space-y-4">
|
|
<div className="relative aspect-video bg-gray-100 rounded-lg flex items-center justify-center group overflow-hidden">
|
|
{dance.coverUrl ? (
|
|
<img
|
|
src={dance.coverUrl || "/placeholder.svg"}
|
|
alt={dance.name}
|
|
className="w-full h-full object-cover rounded-lg"
|
|
onError={(e) => {
|
|
// 如果图片加载失败,使用占位符
|
|
e.currentTarget.src = "/placeholder.svg?height=300&width=400"
|
|
}}
|
|
/>
|
|
) : (
|
|
<div className="text-gray-400 flex flex-col items-center">
|
|
<Video className="h-10 w-10 mb-2" />
|
|
<span>舞蹈封面</span>
|
|
</div>
|
|
)}
|
|
<div
|
|
className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center cursor-pointer"
|
|
onClick={togglePlay}
|
|
>
|
|
{isPlaying ? <Pause className="h-12 w-12 text-white" /> : <Play className="h-12 w-12 text-white" />}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
{dance.tags?.map((tag, index) => (
|
|
<Badge key={index} variant="outline" className="bg-purple-50 text-purple-700">
|
|
{tag}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="flex items-center gap-2">
|
|
<User className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">编舞者:</span>
|
|
<span className="font-medium">{dance.choreographer || "未知"}</span>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Clock className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">时长:</span>
|
|
<span className="font-medium">{dance.duration || "未知"}</span>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<BarChart className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">难度:</span>
|
|
<span className="font-medium">{dance.difficulty || "未知"}</span>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Music className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">分类:</span>
|
|
<span className="font-medium">{dance.category || "未分类"}</span>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Calendar className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">创建时间:</span>
|
|
<span className="font-medium">
|
|
{dance.createdAt ? new Date(dance.createdAt).toLocaleDateString() : "未知"}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Calendar className="h-4 w-4 text-purple-500" />
|
|
<span className="text-sm text-gray-500">更新时间:</span>
|
|
<span className="font-medium">
|
|
{dance.updatedAt ? new Date(dance.updatedAt).toLocaleDateString() : "未知"}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500 mb-2">动作文件:</h3>
|
|
<div className="p-2 bg-gray-50 rounded border border-gray-200">
|
|
{dance.motionFile || "未上传动作文件"}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500 mb-2">舞蹈描述:</h3>
|
|
<div className="p-3 bg-gray-50 rounded border border-gray-200 text-sm">
|
|
{dance.description || "暂无描述"}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter className="mt-6">
|
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
关闭
|
|
</Button>
|
|
<Button
|
|
className="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600"
|
|
onClick={() => {
|
|
// 这里可以添加查看更多详情的逻辑
|
|
onOpenChange(false)
|
|
// 可以导航到详情页
|
|
// router.push(`/dances/${dance.id}`)
|
|
}}
|
|
>
|
|
查看更多详情
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|