'use client'; import React, { useMemo } from 'react'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Story } from '@/types/project'; import { FileText, FolderKanban, Clock, CheckSquare } from 'lucide-react'; interface StoryCardProps { story: Story; epicName?: string; taskCount?: number; } export const StoryCard = React.memo(function StoryCard({ story, epicName, taskCount }: StoryCardProps) { const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: story.id }); const style = { transform: CSS.Transform.toString(transform), transition, }; const priorityColors = { Low: 'bg-gray-100 text-gray-700 border-gray-300', Medium: 'bg-blue-100 text-blue-700 border-blue-300', High: 'bg-orange-100 text-orange-700 border-orange-300', Critical: 'bg-red-100 text-red-700 border-red-300', }; const statusColors = { Backlog: 'bg-gray-100 text-gray-600', Todo: 'bg-blue-100 text-blue-600', InProgress: 'bg-yellow-100 text-yellow-700', Done: 'bg-green-100 text-green-700', }; // Get assignee initials const assigneeInitials = useMemo(() => { if (!story.assigneeId) return null; // For now, just use first two letters. In real app, fetch user data return story.assigneeId.substring(0, 2).toUpperCase(); }, [story.assigneeId]); // Calculate progress (if both estimated and actual hours exist) const hoursDisplay = useMemo(() => { if (story.estimatedHours) { if (story.actualHours) { return `${story.actualHours}/${story.estimatedHours}h`; } return `0/${story.estimatedHours}h`; } return null; }, [story.estimatedHours, story.actualHours]); return ( {/* Header: Story icon + Task count */}
Story
{taskCount !== undefined && taskCount > 0 && ( {taskCount} {taskCount === 1 ? 'task' : 'tasks'} )}
{/* Epic breadcrumb */} {epicName && (
{epicName}
)} {/* Title */}

{story.title}

{/* Description (if available) */} {story.description && (

{story.description}

)} {/* Footer: Priority, Hours, Assignee */}
{story.priority} {story.status}
{/* Hours display */} {hoursDisplay && (
{hoursDisplay}
)} {/* Assignee avatar */} {assigneeInitials && ( {assigneeInitials} )}
); });