// ======================================== // PromptCard Component // ======================================== // Card component for displaying prompt history items import * as React from 'react'; import { useIntl } from 'react-intl'; import { cn } from '@/lib/utils'; import { Card, CardContent, CardHeader } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { Button } from '@/components/ui/Button'; import { Checkbox } from '@/components/ui/Checkbox'; import { QualityBadge } from '@/components/shared/QualityBadge'; import { Copy, Trash2, ChevronDown, ChevronUp, Clock, Tag, Calendar, } from 'lucide-react'; import type { Prompt } from '@/types/store'; export interface PromptCardProps { /** Prompt data */ prompt: Prompt; /** Called when delete action is triggered */ onDelete?: (id: string) => void; /** Optional className */ className?: string; /** Disabled state for actions */ actionsDisabled?: boolean; /** Default expanded state */ defaultExpanded?: boolean; /** Selection state for batch operations */ selected?: boolean; /** Called when selection state changes */ onSelectChange?: (id: string, selected: boolean) => void; /** Whether selection mode is active */ selectionMode?: boolean; } /** * Format date to readable string */ function formatDate(dateString: string): string { const date = new Date(dateString); return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', }); } /** * Format content length */ function formatContentLength(length: number): string { if (length >= 1000) { return `${(length / 1000).toFixed(1)}k chars`; } return `${length} chars`; } /** * PromptCard component for displaying prompt history items */ export function PromptCard({ prompt, onDelete, className, actionsDisabled = false, defaultExpanded = false, selected = false, onSelectChange, selectionMode = false, }: PromptCardProps) { const { formatMessage } = useIntl(); const [expanded, setExpanded] = React.useState(defaultExpanded); const [copied, setCopied] = React.useState(false); const handleCopy = async (e: React.MouseEvent) => { e.stopPropagation(); try { await navigator.clipboard.writeText(prompt.content); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { console.error('Failed to copy prompt'); } }; const handleDelete = (e: React.MouseEvent) => { e.stopPropagation(); onDelete?.(prompt.id); }; const toggleExpanded = () => { setExpanded((prev) => !prev); }; const handleSelectionChange = (checked: boolean) => { onSelectChange?.(prompt.id, checked); }; const handleCardClick = (e: React.MouseEvent) => { if (selectionMode && (e.target as HTMLElement).closest('.prompt-card-checkbox')) { return; } if (selectionMode) { handleSelectionChange(!selected); } }; return (
{/* Checkbox for selection mode */} {selectionMode && (
)} {/* Title and metadata */}

{prompt.title || formatMessage({ id: 'prompts.card.untitled' })}

{prompt.category && ( {prompt.category} )}
{/* Metadata */}
{formatDate(prompt.createdAt)} {formatContentLength(prompt.content.length)} {prompt.useCount !== undefined && prompt.useCount > 0 && ( {formatMessage({ id: 'prompts.card.used' }, { count: prompt.useCount })} )}
{/* Tags */} {prompt.tags && prompt.tags.length > 0 && (
{prompt.tags.slice(0, 3).map((tag) => ( {tag} ))} {prompt.tags.length > 3 && ( +{prompt.tags.length - 3} )}
)}
{/* Actions */}
{copied && (

{formatMessage({ id: 'prompts.actions.copied' })}

)}
{/* Expanded content */} {expanded && (
              {prompt.content}
            
)}
); } export default PromptCard;