'use client' import { useState } from 'react' import { useTranslations } from 'next-intl' import { useAuth } from '@/hooks/useAuth' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { LegacyAvatar } from '@/components/ui/avatar' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Copy, Download, Calendar, Check } from 'lucide-react' import { formatDistanceToNow } from 'date-fns' import { PromptDetailModal } from './PromptDetailModal' interface Prompt { id: string name: string content: string description: string | null createdAt: string user: { id: string username: string | null avatar: string | null } tags: Array<{ id: string name: string color: string }> versions: Array<{ content: string version: number createdAt: string }> stats?: { viewCount: number likeCount: number rating: number | null ratingCount: number } | null _count: { versions: number } } interface PromptCardProps { prompt: Prompt onViewIncrement: (promptId: string) => void } export function PromptCard({ prompt, onViewIncrement }: PromptCardProps) { const t = useTranslations('plaza') const { user } = useAuth() const [copied, setCopied] = useState(false) const [duplicating, setDuplicating] = useState(false) const [viewIncremented, setViewIncremented] = useState(false) const [isDetailModalOpen, setIsDetailModalOpen] = useState(false) const latestVersion = prompt.versions[0] const handleCopy = async () => { try { await navigator.clipboard.writeText(latestVersion?.content || prompt.content) setCopied(true) setTimeout(() => setCopied(false), 2000) } catch (error) { console.error('Failed to copy:', error) } } const handleDuplicate = async () => { if (!user) { // Redirect to sign in window.location.href = '/signin' return } setDuplicating(true) try { const requestData = { name: `${prompt.name} (Copy)`, content: latestVersion?.content || prompt.content, description: prompt.description, permissions: 'private', userId: user.id, tags: prompt.tags.map(tag => tag.name), } console.log('Duplicating prompt with data:', requestData) const response = await fetch('/api/prompts', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestData), }) if (response.ok) { // Create a temporary success notification const notification = document.createElement('div') notification.className = 'fixed top-4 right-4 bg-green-500 text-white px-4 py-2 rounded-md shadow-lg z-50 transition-all duration-300' notification.textContent = t('promptDuplicated') document.body.appendChild(notification) setTimeout(() => { notification.style.opacity = '0' setTimeout(() => { if (document.body.contains(notification)) { document.body.removeChild(notification) } }, 300) }, 2000) } else { // Create error notification console.error('API response error:', response.status, response.statusText) let errorMessage = 'Failed to duplicate prompt' try { const errorData = await response.json() console.error('Error data:', errorData) errorMessage = errorData.error || `HTTP ${response.status}: ${response.statusText}` } catch (e) { console.error('Failed to parse error response:', e) errorMessage = `HTTP ${response.status}: ${response.statusText}` } const notification = document.createElement('div') notification.className = 'fixed top-4 right-4 bg-red-500 text-white px-4 py-2 rounded-md shadow-lg z-50 transition-all duration-300' notification.textContent = errorMessage document.body.appendChild(notification) setTimeout(() => { notification.style.opacity = '0' setTimeout(() => { if (document.body.contains(notification)) { document.body.removeChild(notification) } }, 300) }, 3000) } } catch (error) { console.error('Failed to duplicate:', error) // Create error notification for network/other errors const notification = document.createElement('div') notification.className = 'fixed top-4 right-4 bg-red-500 text-white px-4 py-2 rounded-md shadow-lg z-50 transition-all duration-300' notification.textContent = 'Network error. Please try again.' document.body.appendChild(notification) setTimeout(() => { notification.style.opacity = '0' setTimeout(() => { if (document.body.contains(notification)) { document.body.removeChild(notification) } }, 300) }, 3000) } finally { setDuplicating(false) } } const handleCardClick = () => { if (!viewIncremented) { onViewIncrement(prompt.id) setViewIncremented(true) } setIsDetailModalOpen(true) } return ( <>
{prompt.name}
{prompt.description && ( {prompt.description} )}
{/* Content Preview */}

{latestVersion?.content || prompt.content}

{/* Tags */} {prompt.tags.length > 0 && (
{prompt.tags.slice(0, 3).map((tag) => ( {tag.name} ))} {prompt.tags.length > 3 && ( +{prompt.tags.length - 3} )}
)} {/* Author & Meta */}
{prompt.user.username || 'Anonymous'}
{formatDistanceToNow(new Date(prompt.createdAt), { addSuffix: true })}
{/* Actions */}
{/* Detail Modal */} setIsDetailModalOpen(false)} /> ) }