76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
import { useNavigate } from 'react-router-dom';
|
|
import type { Project } from '@/types';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Badge } from '@/components/ui/badge';
|
|
|
|
interface ProjectsWidgetProps {
|
|
projects: Project[];
|
|
}
|
|
|
|
const statusColors: Record<string, string> = {
|
|
not_started: 'bg-gray-500/10 text-gray-500 border-gray-500/20',
|
|
in_progress: 'bg-accent/10 text-accent border-accent/20',
|
|
completed: 'bg-green-500/10 text-green-500 border-green-500/20',
|
|
blocked: 'bg-red-500/10 text-red-500 border-red-500/20',
|
|
review: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/20',
|
|
on_hold: 'bg-orange-500/10 text-orange-500 border-orange-500/20',
|
|
};
|
|
|
|
export default function ProjectsWidget({ projects }: ProjectsWidgetProps) {
|
|
const navigate = useNavigate();
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Active Projects</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{projects.length === 0 ? (
|
|
<p className="text-sm text-muted-foreground text-center py-8">
|
|
No active projects. Create one to get started!
|
|
</p>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{projects.map((project) => {
|
|
const completedTasks = project.tasks?.filter((t) => t.status === 'completed').length || 0;
|
|
const totalTasks = project.tasks?.length || 0;
|
|
const progress = totalTasks > 0 ? (completedTasks / totalTasks) * 100 : 0;
|
|
|
|
return (
|
|
<div
|
|
key={project.id}
|
|
className="p-3 rounded-lg border bg-card hover:bg-accent/5 transition-colors cursor-pointer"
|
|
onClick={() => navigate(`/projects/${project.id}`)}
|
|
>
|
|
<div className="flex items-start justify-between mb-2">
|
|
<p className="font-medium">{project.name}</p>
|
|
<Badge className={statusColors[project.status]}>
|
|
{project.status.replace('_', ' ')}
|
|
</Badge>
|
|
</div>
|
|
{totalTasks > 0 && (
|
|
<div>
|
|
<div className="flex justify-between text-xs text-muted-foreground mb-1">
|
|
<span>Progress</span>
|
|
<span>
|
|
{completedTasks}/{totalTasks} tasks
|
|
</span>
|
|
</div>
|
|
<div className="h-2 bg-secondary rounded-full overflow-hidden">
|
|
<div
|
|
className="h-full bg-accent transition-all"
|
|
style={{ width: `${progress}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|