trello_fake/components/dashboard/project-detail.tsx

273 lines
11 KiB
TypeScript

"use client";
import { ArrowLeft, Calendar, DollarSign, TrendingUp, FileText, Building2 } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { ProjectStatusBadge } from '@/components/ui/project-status-badge';
import { Project } from '@/types/project';
interface ProjectDetailProps {
project: Project;
}
// Función para generar iniciales
function getInitials(name: string): string {
return name
.split(' ')
.map(word => word[0])
.join('')
.toUpperCase()
.slice(0, 2);
}
/**
* Componente de detalle completo de un proyecto
* Muestra toda la información disponible del proyecto
*/
export default function ProjectDetail({ project }: ProjectDetailProps) {
const router = useRouter();
const initials = getInitials(project.name);
return (
<div className="min-h-screen bg-background">
{/* Header */}
<div className="bg-card border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<Button
variant="ghost"
onClick={() => router.back()}
className="mb-4"
>
<ArrowLeft className="w-4 h-4 mr-2" />
Volver
</Button>
<div className="flex items-start gap-6">
<Avatar className="w-20 h-20">
<AvatarFallback className="bg-gradient-to-br from-blue-500 to-purple-600 text-white font-semibold text-2xl">
{initials}
</AvatarFallback>
</Avatar>
<div className="flex-1">
<div className="flex items-start justify-between">
<div>
<h1 className="text-3xl font-bold mb-2">{project.name}</h1>
<p className="text-muted-foreground mb-3">{project.ref}</p>
<ProjectStatusBadge status={project.status} className="text-base px-4 py-1" />
</div>
</div>
</div>
</div>
</div>
</div>
{/* Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Main Content */}
<div className="lg:col-span-2 space-y-6">
{/* Descripción */}
{project.description && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="w-5 h-5" />
Descripción
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground whitespace-pre-wrap">{project.description}</p>
</CardContent>
</Card>
)}
{/* Progreso */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<TrendingUp className="w-5 h-5" />
Progreso del Proyecto
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm font-medium text-muted-foreground">Avance Total</span>
<span className="text-2xl font-bold">{project.progress}%</span>
</div>
<div className="w-full bg-muted rounded-full h-4">
<div
className="bg-gradient-to-r from-blue-500 to-purple-600 h-4 rounded-full transition-all duration-500"
style={{ width: `${project.progress}%` }}
/>
</div>
<div className="grid grid-cols-2 gap-4 pt-4">
<div className="text-center p-4 bg-muted/50 rounded-lg">
<p className="text-sm text-muted-foreground mb-1">Estado</p>
<p className="text-lg font-semibold">
{project.status === '0' ? 'Borrador' : project.status === '1' ? 'En Progreso' : 'Finalizado'}
</p>
</div>
<div className="text-center p-4 bg-muted/50 rounded-lg">
<p className="text-sm text-muted-foreground mb-1">Completado</p>
<p className="text-lg font-semibold">
{project.progress === 100 ? 'Sí' : 'No'}
</p>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Presupuesto */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<DollarSign className="w-5 h-5" />
Información Financiera
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<p className="text-sm text-muted-foreground">Presupuesto Total</p>
<p className="text-3xl font-bold">
€{project.budget.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</p>
</div>
<div className="space-y-2">
<p className="text-sm text-muted-foreground">Estimado Gastado</p>
<p className="text-3xl font-bold text-blue-600 dark:text-blue-400">
€{project.spent.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</p>
</div>
</div>
<Separator className="my-4" />
<div className="flex items-center justify-between p-4 bg-muted/50 rounded-lg">
<span className="text-sm font-medium text-muted-foreground">Restante</span>
<span className="text-xl font-bold text-green-600 dark:text-green-400">
€{(project.budget - project.spent).toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</span>
</div>
</CardContent>
</Card>
</div>
{/* Sidebar */}
<div className="space-y-6">
{/* Información General */}
<Card>
<CardHeader>
<CardTitle className="text-lg">Información General</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* Cliente */}
{project.client !== 'Sin cliente' && (
<div className="flex items-start gap-3">
<Building2 className="w-5 h-5 text-muted-foreground mt-0.5" />
<div>
<p className="text-sm text-muted-foreground">Cliente</p>
<p className="font-medium">{project.client}</p>
</div>
</div>
)}
<Separator />
{/* Fecha de Inicio */}
<div className="flex items-start gap-3">
<Calendar className="w-5 h-5 text-muted-foreground mt-0.5" />
<div>
<p className="text-sm text-muted-foreground">Fecha de Inicio</p>
<p className="font-medium">
{new Date(project.startDate).toLocaleDateString('es-ES', {
day: 'numeric',
month: 'long',
year: 'numeric'
})}
</p>
</div>
</div>
<Separator />
{/* Fecha de Fin */}
<div className="flex items-start gap-3">
<Calendar className="w-5 h-5 text-muted-foreground mt-0.5" />
<div>
<p className="text-sm text-muted-foreground">Fecha de Fin</p>
<p className="font-medium">
{new Date(project.endDate).toLocaleDateString('es-ES', {
day: 'numeric',
month: 'long',
year: 'numeric'
})}
</p>
</div>
</div>
<Separator />
{/* Duración */}
<div className="flex items-start gap-3">
<Calendar className="w-5 h-5 text-muted-foreground mt-0.5" />
<div>
<p className="text-sm text-muted-foreground">Duración</p>
<p className="font-medium">
{Math.ceil((new Date(project.endDate).getTime() - new Date(project.startDate).getTime()) / (1000 * 60 * 60 * 24))} días
</p>
</div>
</div>
</CardContent>
</Card>
{/* Metadatos */}
<Card>
<CardHeader>
<CardTitle className="text-lg">Metadatos</CardTitle>
</CardHeader>
<CardContent className="space-y-3 text-sm">
<div>
<p className="text-muted-foreground">ID del Proyecto</p>
<p className="font-mono">{project.id}</p>
</div>
<Separator />
<div>
<p className="text-muted-foreground">Referencia</p>
<p className="font-mono">{project.ref}</p>
</div>
<Separator />
<div>
<p className="text-muted-foreground">Creado</p>
<p>
{new Date(project.createdAt).toLocaleDateString('es-ES', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</p>
</div>
<Separator />
<div>
<p className="text-muted-foreground">Última Actualización</p>
<p>
{new Date(project.updatedAt).toLocaleDateString('es-ES', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</p>
</div>
</CardContent>
</Card>
</div>
</div>
</main>
</div>
);
}