"use client" import { Card } from "@/components/ui/card" import { projectTemplates } from "@/lib/data" import { Sandbox } from "@/lib/types" import { AnimatePresence, motion } from "framer-motion" import { Clock, Eye, Globe, Heart, Lock } from "lucide-react" import Image from "next/image" import { useRouter } from "next/navigation" import { memo, useEffect, useMemo, useState } from "react" import ProjectCardDropdown from "./dropdown" import { CanvasRevealEffect } from "./revealEffect" type BaseProjectCardProps = { id: string name: string type: string visibility: "public" | "private" createdAt: Date likeCount: number viewCount: number } type AuthenticatedProjectCardProps = BaseProjectCardProps & { isAuthenticated: true onVisibilityChange: ( sandbox: Pick ) => void onDelete: (sandbox: Pick) => void deletingId: string } type UnauthenticatedProjectCardProps = BaseProjectCardProps & { isAuthenticated: false } type ProjectCardProps = | AuthenticatedProjectCardProps | UnauthenticatedProjectCardProps const StatItem = memo(({ icon: Icon, value }: { icon: any; value: number }) => (
{value}
)) StatItem.displayName = "StatItem" const formatDate = (date: Date): string => { const now = new Date() const diffInMinutes = Math.floor((now.getTime() - date.getTime()) / 60000) if (diffInMinutes < 1) return "Now" if (diffInMinutes < 60) return `${diffInMinutes}m ago` if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)}h ago` return `${Math.floor(diffInMinutes / 1440)}d ago` } const ProjectMetadata = memo( ({ visibility, createdAt, likeCount, viewCount, }: Pick< BaseProjectCardProps, "visibility" | "createdAt" | "likeCount" | "viewCount" >) => { const [date, setDate] = useState() useEffect(() => { setDate(formatDate(new Date(createdAt))) }, [createdAt]) return (
{visibility === "private" ? ( <> Private ) : ( <> Public )}
{date}
) } ) ProjectMetadata.displayName = "ProjectMetadata" function ProjectCardComponent({ id, name, type, visibility, createdAt, likeCount, viewCount, ...props }: ProjectCardProps) { const [hovered, setHovered] = useState(false) const router = useRouter() const projectIcon = useMemo( () => projectTemplates.find((p) => p.id === type)?.icon ?? "/project-icons/node.svg", [type] ) const handleVisibilityChange = () => { if (props.isAuthenticated) { props.onVisibilityChange({ id, name, visibility, }) } } const handleDelete = () => { if (props.isAuthenticated) { props.onDelete({ id, name, }) } } return ( router.push(`/code/${id}`)} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} className={` group/canvas-card p-4 h-48 flex flex-col justify-between items-start hover:border-muted-foreground/50 relative overflow-hidden transition-all ${props.isAuthenticated && props.deletingId === id ? "opacity-50" : ""} `} > {hovered && (
)}
{`${type}
{name}
{props.isAuthenticated && ( )}
) } ProjectCardComponent.displayName = "ProjectCard" const ProjectCard = memo(ProjectCardComponent) export default ProjectCard const colors: { [key: string]: number[][] } = { react: [ [71, 207, 237], [30, 126, 148], ], node: [ [86, 184, 72], [59, 112, 52], ], }