simba-index/components/robots-showcase.tsx

201 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useRef, useState, useEffect } from "react"
import Image from "next/image"
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { ChevronLeft, ChevronRight, Info } from "lucide-react"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
export default function RobotsShowcase() {
const scrollContainerRef = useRef<HTMLDivElement>(null)
const [activeIndex, setActiveIndex] = useState(0)
const robots = [
{
id: 1,
name: "初号步兵",
image: "/placeholder.svg?height=400&width=600",
category: "INFANTRY",
description:
"Our flagship defense robot, equipped with advanced armor plating and a 360° rotating turret system.",
specs: ["Weight: 15kg", "Max Speed: 3m/s", "Battery Life: 30min", "Weapon: Launcher"],
},
{
id: 2,
name: "初号英雄",
image: "/placeholder.svg?height=400&width=600",
category: "HERO",
description: "High-mobility attack unit designed for rapid engagement and strategic positioning.",
specs: ["Weight: 12kg", "Max Speed: 4.5m/s", "Battery Life: 25min", "Weapon: Dual Launcher System"],
},
{
id: 3,
name: "零号哨兵",
image: "/placeholder.svg?height=400&width=600",
category: "SENTRY",
description:
"Lightweight reconnaissance drone providing battlefield intelligence and limited attack capabilities.",
specs: ["Weight: 2kg", "Max Speed: 10m/s", "Flight Time: 15min", "Sensors: 4K Camera, Infrared"],
},
{
id: 4,
name: "零号工程",
image: "/placeholder.svg?height=400&width=600",
category: "ENGINEER",
description: "Specialized support unit capable of on-field repairs and resource management during matches.",
specs: ["Weight: 18kg", "Max Speed: 2m/s", "Battery Life: 40min", "Tools: Mechanical Arm, Repair Module"],
},
]
// 创建一个循环数组,用于无限滚动
const displayRobots = [...robots]
const scroll = (direction: "left" | "right") => {
if (scrollContainerRef.current) {
const { current: container } = scrollContainerRef
const cardWidth = container.querySelector(".robot-card")?.clientWidth || 350
// 更新活跃索引
if (direction === "left") {
setActiveIndex((prev) => (prev === 0 ? robots.length - 1 : prev - 1))
} else {
setActiveIndex((prev) => (prev === robots.length - 1 ? 0 : prev + 1))
}
// 滚动到新的活跃卡片
const newScrollPosition = activeIndex * (cardWidth + 24) // 24 是 gap-6
container.scrollTo({
left: newScrollPosition,
behavior: "smooth",
})
}
}
// 使用 useEffect 监听活跃索引变化,滚动到对应位置
useEffect(() => {
if (scrollContainerRef.current) {
const cardWidth = scrollContainerRef.current.querySelector(".robot-card")?.clientWidth || 350
const newScrollPosition = activeIndex * (cardWidth + 24) // 24 是 gap-6
scrollContainerRef.current.scrollTo({
left: newScrollPosition,
behavior: "smooth",
})
}
}, [activeIndex])
return (
<section id="robots" className="py-20 relative overflow-hidden">
<div className="absolute right-0 top-0 bottom-0 red-section z-0" />
<div className="container mx-auto px-4 relative z-10">
<div className="flex flex-col md:flex-row gap-8 mb-12">
<div className="md:w-1/3">
<div className="red-accent pl-4">
<h2 className="text-3xl font-bold mb-2 uppercase"></h2>
<p className="text-xs text-muted-foreground uppercase mb-4 font-mono">ROBOTS</p>
</div>
<div className="diagonal-line mb-8"></div>
<div className="content-overlay">
<p className="text-muted-foreground leading-relaxed">
RoboMaster
</p>
</div>
</div>
</div>
<div className="relative">
<Button
variant="outline"
size="icon"
className="absolute left-0 top-1/2 -translate-y-1/2 z-10 bg-background/80 backdrop-blur-sm border-white/10 button-hover-effect"
onClick={() => scroll("left")}
>
<ChevronLeft className="h-6 w-6" />
</Button>
<div ref={scrollContainerRef} className="flex gap-6 overflow-x-auto scrollbar-hide py-4 px-2">
{displayRobots.map((robot, index) => (
<Card
key={robot.id}
className="min-w-[300px] md:min-w-[350px] border-white/10 bg-background/60 backdrop-blur-sm flex-shrink-0 card-hover-effect robot-card"
>
<CardContent className="p-0">
<div className="relative">
<Image
src={robot.image || "/placeholder.svg"}
alt={robot.name}
width={350}
height={200}
className="w-full h-48 object-cover"
/>
<div className="absolute top-0 right-0 bg-primary text-primary-foreground text-xs px-3 py-1">
{robot.category}
</div>
<div className="absolute bottom-0 left-0 p-2">
<p className="text-xs text-primary font-mono">{`0${index + 1}/0${robots.length}`}</p>
</div>
</div>
<div className="p-4">
<div className="flex justify-between items-start mb-2">
<h3 className="text-xl font-bold">{robot.name}</h3>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="icon" className="h-8 w-8 button-hover-effect">
<Info className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent className="max-w-[250px]">
<div className="space-y-2">
<p className="font-bold">Technical Specifications:</p>
<ul className="text-xs space-y-1">
{robot.specs.map((spec, specIndex) => (
<li key={specIndex}>{spec}</li>
))}
</ul>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<p className="text-sm text-muted-foreground mb-4 leading-relaxed">{robot.description}</p>
<Button variant="outline" size="sm" className="w-full border-white/10 button-hover-effect">
View Details
</Button>
</div>
</CardContent>
</Card>
))}
</div>
<Button
variant="outline"
size="icon"
className="absolute right-0 top-1/2 -translate-y-1/2 z-10 bg-background/80 backdrop-blur-sm border-white/10 button-hover-effect"
onClick={() => scroll("right")}
>
<ChevronRight className="h-6 w-6" />
</Button>
{/* 添加索引指示器 */}
<div className="flex justify-center mt-6 gap-2">
{robots.map((_, index) => (
<button
key={index}
className={`w-2 h-2 rounded-full transition-all ${
activeIndex === index ? "bg-primary w-4" : "bg-gray-500"
}`}
onClick={() => setActiveIndex(index)}
/>
))}
</div>
</div>
</div>
</section>
)
}