- Add navigation with Themes, Puzzles, and Miscellany. - Create "coming soon" pages for Puzzles and Miscellany. - Create a Themes page with cards for various topics. - Implement basic boxy layout. - Prepare for future interactive additions and filtering. - Set up for Netlify deployment.
104 lines
No EOL
3 KiB
TypeScript
104 lines
No EOL
3 KiB
TypeScript
import { Badge } from "@/components/ui/badge";
|
|
import { ArrowRight, Clock, Users } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface InteractiveCardProps {
|
|
title: string;
|
|
description: string;
|
|
tags: string[];
|
|
difficulty?: "Beginner" | "Intermediate" | "Advanced";
|
|
duration?: string;
|
|
participants?: string;
|
|
imageUrl?: string;
|
|
onClick?: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
const InteractiveCard = ({
|
|
title,
|
|
description,
|
|
tags,
|
|
difficulty,
|
|
duration,
|
|
participants,
|
|
imageUrl,
|
|
onClick,
|
|
className
|
|
}: InteractiveCardProps) => {
|
|
const difficultyColors = {
|
|
Beginner: "bg-green-100 text-green-800",
|
|
Intermediate: "bg-yellow-100 text-yellow-800",
|
|
Advanced: "bg-red-100 text-red-800"
|
|
};
|
|
|
|
return (
|
|
<div
|
|
onClick={onClick}
|
|
className={cn(
|
|
"group cursor-pointer bg-surface border border-outline rounded-lg overflow-hidden shadow-card hover:shadow-card-hover transition-all duration-200 hover:-translate-y-1",
|
|
className
|
|
)}
|
|
>
|
|
{imageUrl && (
|
|
<div className="h-48 bg-surface-variant overflow-hidden">
|
|
<img
|
|
src={imageUrl}
|
|
alt={title}
|
|
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<div className="p-6">
|
|
<div className="flex items-start justify-between mb-3">
|
|
<h3 className="text-lg font-semibold text-foreground group-hover:text-accent transition-colors flex-1">
|
|
{title}
|
|
</h3>
|
|
<ArrowRight className="w-5 h-5 text-muted-foreground group-hover:text-accent group-hover:translate-x-1 transition-all flex-shrink-0 ml-2" />
|
|
</div>
|
|
|
|
<p className="text-muted-foreground text-sm leading-relaxed mb-4">
|
|
{description}
|
|
</p>
|
|
|
|
<div className="flex items-center gap-4 mb-4 text-xs text-muted-foreground">
|
|
{duration && (
|
|
<div className="flex items-center gap-1">
|
|
<Clock className="w-3 h-3" />
|
|
<span>{duration}</span>
|
|
</div>
|
|
)}
|
|
{participants && (
|
|
<div className="flex items-center gap-1">
|
|
<Users className="w-3 h-3" />
|
|
<span>{participants}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex flex-wrap gap-2 mb-3">
|
|
{difficulty && (
|
|
<Badge
|
|
variant="secondary"
|
|
className={cn("text-xs", difficultyColors[difficulty])}
|
|
>
|
|
{difficulty}
|
|
</Badge>
|
|
)}
|
|
{tags.slice(0, 3).map((tag) => (
|
|
<Badge key={tag} variant="outline" className="text-xs">
|
|
{tag}
|
|
</Badge>
|
|
))}
|
|
{tags.length > 3 && (
|
|
<Badge variant="outline" className="text-xs">
|
|
+{tags.length - 3}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default InteractiveCard; |