Spaces:
Running
Running
| import React, { useState } from 'react'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { useNavigate } from 'react-router-dom'; | |
| import { useTranslation } from 'react-i18next'; | |
| import { PenTool, MoreVertical, Clock, ExternalLink, Trash2 } from 'lucide-react'; | |
| const ProjectCard = ({ project, onDelete }) => { | |
| const navigate = useNavigate(); | |
| const [showMenu, setShowMenu] = useState(false); | |
| const { t } = useTranslation(); | |
| return ( | |
| <motion.div | |
| whileHover={{ y: -5, rotate: 0.5 }} | |
| className="bg-surface-container-lowest p-6 rough-border rough-shadow cursor-pointer group flex flex-col gap-4 relative" | |
| onClick={() => navigate(`/canvas/${project.id}`)} | |
| > | |
| <div className="flex justify-between items-start"> | |
| <div className={`w-12 h-12 rounded-lg bg-primary/10 rough-border flex items-center justify-center`}> | |
| <PenTool size={24} className="text-primary" /> | |
| </div> | |
| <div className="relative"> | |
| <button | |
| onClick={(e) => { e.stopPropagation(); setShowMenu(!showMenu); }} | |
| className="text-on-surface-variant hover:text-primary p-1 rounded-full hover:bg-surface-variant" | |
| > | |
| <MoreVertical size={20} /> | |
| </button> | |
| <AnimatePresence> | |
| {showMenu && ( | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.9, y: -10 }} | |
| animate={{ opacity: 1, scale: 1, y: 0 }} | |
| exit={{ opacity: 0, scale: 0.9, y: -10 }} | |
| className="absolute right-0 mt-2 w-48 bg-surface-container-lowest rough-border rough-shadow z-50 overflow-hidden" | |
| > | |
| <button | |
| onClick={(e) => { e.stopPropagation(); navigate(`/canvas/${project.id}`); }} | |
| className="w-full text-left px-4 py-3 flex items-center gap-3 hover:bg-surface-variant transition-colors text-on-surface font-bold border-b-2 border-primary/5" | |
| > | |
| <ExternalLink size={18} /> {t('dashboard.open_sketch', 'Open Sketch')} | |
| </button> | |
| <button | |
| onClick={(e) => { e.stopPropagation(); onDelete(project.id); setShowMenu(false); }} | |
| className="w-full text-left px-4 py-3 flex items-center gap-3 hover:bg-red-500/10 text-red-500 transition-colors font-bold" | |
| > | |
| <Trash2 size={18} /> {t('dashboard.delete')} | |
| </button> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </div> | |
| </div> | |
| <div> | |
| <h3 className="text-3xl font-display-lg text-primary line-clamp-1">{project.title}</h3> | |
| <p className="text-sm text-on-surface-variant flex items-center gap-1 mt-1"> | |
| <Clock size={14} /> {new Date(project.createdAt).toLocaleDateString()} | |
| </p> | |
| </div> | |
| <div className="mt-2"> | |
| <p className="text-sm text-on-surface-variant line-clamp-2 italic opacity-70"> | |
| {project.description || t('dashboard.no_description', 'No description provided...')} | |
| </p> | |
| </div> | |
| </motion.div> | |
| ); | |
| }; | |
| export default ProjectCard; | |