"use client"; import { useState, useRef } from "react"; import Image from "next/image"; import { Search, MapPin, Plus, Trash2, Image as ImageIcon, Crosshair } from "lucide-react"; import AssetPickerModal from "../AssetPickerModal"; import { Asset, getImageUrl } from "@/lib/api"; interface Hotspot { id: string; x: number; y: number; radius: number; label: string; } interface HotspotBlockProps { id: string; title?: string; description?: string; imageUrl?: string; hotspots?: Hotspot[]; editMode: boolean; courseId: string; onChange: (updates: { title?: string; description?: string; imageUrl?: string; hotspots?: Hotspot[] }) => void; } export default function HotspotBlock({ id, title, description, imageUrl, hotspots = [], editMode, courseId, onChange }: HotspotBlockProps) { const [isAssetPickerOpen, setIsAssetPickerOpen] = useState(false); const containerRef = useRef(null); const handleImageSelect = (asset: Asset) => { const url = asset.storage_path.replace('uploads/', '/assets/'); onChange({ imageUrl: url }); setIsAssetPickerOpen(false); }; const handleImageClick = (e: React.MouseEvent) => { if (!editMode || !containerRef.current || !imageUrl) return; const rect = containerRef.current.getBoundingClientRect(); const x = ((e.clientX - rect.left) / rect.width) * 100; const y = ((e.clientY - rect.top) / rect.height) * 100; const newHotspot: Hotspot = { id: Math.random().toString(36).substr(2, 9), x, y, radius: 5, label: "New Hotspot" }; onChange({ hotspots: [...hotspots, newHotspot] }); }; const updateHotspot = (index: number, updates: Partial) => { const newHotspots = [...hotspots]; newHotspots[index] = { ...newHotspots[index], ...updates }; onChange({ hotspots: newHotspots }); }; const removeHotspot = (index: number) => { const newHotspots = hotspots.filter((_, i) => i !== index); onChange({ hotspots: newHotspots }); }; if (!editMode) { return (

{title || "Image Hunt"}

{description || "Find the hidden spots!"}

{imageUrl ? ( {title ) : (
No image provided.
)}

Interactive Game Preview (Switch to Student View to Play)

); } return (
onChange({ title: e.target.value })} placeholder="e.g. Parts of the Body..." className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2 text-sm font-bold focus:border-amber-500/50 focus:outline-none" />
onChange({ description: e.target.value })} placeholder="e.g. Find and click on the following items..." className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2 text-sm focus:border-amber-500/50 focus:outline-none" />
{!imageUrl ? ( ) : (
Hotspot base
)}
{imageUrl && (
{hotspots.length} Defined
Define Hotspots {hotspots.map((h, idx) => (
{h.label}
))}
{hotspots.length === 0 ? (

Click on the image to add hotspots

) : ( hotspots.map((h, idx) => (
Hotspot #{idx + 1}
updateHotspot(idx, { label: e.target.value })} placeholder="Item name..." className="w-full bg-black/40 border border-white/10 rounded-lg px-3 py-1.5 text-xs font-bold focus:border-amber-500/50 focus:outline-none" />
updateHotspot(idx, { radius: parseInt(e.target.value) })} className="flex-1 accent-amber-500 h-1 bg-white/10 rounded-lg appearance-none cursor-pointer" /> {h.radius}%
)) )}
)}
setIsAssetPickerOpen(false)} courseId={courseId} filterType="image" onSelect={handleImageSelect} />
); }