trello_fake/components/project-detail/project-info.tsx

257 lines
9.6 KiB
TypeScript

import {
FileText,
Building2,
Calendar,
Clock,
Hash,
} from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { Progress } from "@/components/ui/progress";
import { Project } from "@/types/project";
interface ProjectInfoProps {
project: Project;
}
// Formatear moneda
function formatCurrency(amount: number): string {
return new Intl.NumberFormat("es-ES", {
style: "currency",
currency: "EUR",
minimumFractionDigits: 2,
}).format(amount);
}
// Formatear fecha
function formatDate(dateString: string): string {
return new Date(dateString).toLocaleDateString("es-ES", {
day: "numeric",
month: "long",
year: "numeric",
});
}
// Calcular duración en días
function getDuration(startDate: string, endDate: string): number {
const start = new Date(startDate);
const end = new Date(endDate);
const diff = end.getTime() - start.getTime();
return Math.ceil(diff / (1000 * 60 * 60 * 24));
}
export function ProjectInfo({ project }: ProjectInfoProps) {
const duration = getDuration(project.startDate, project.endDate);
const budgetUsed = project.budget > 0 ? (project.spent / project.budget) * 100 : 0;
const budgetRemaining = project.budget - project.spent;
return (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Columna principal - 2/3 */}
<div className="lg:col-span-2 space-y-6">
{/* Descripción */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2 text-base">
<FileText className="h-4 w-4 text-muted-foreground" />
Descripción
</CardTitle>
</CardHeader>
<CardContent>
{project.description ? (
<p className="text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed">
{project.description}
</p>
) : (
<p className="text-sm text-muted-foreground italic">
Sin descripción disponible
</p>
)}
</CardContent>
</Card>
{/* Información financiera */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">Información Financiera</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
{/* Barra de progreso del presupuesto */}
<div>
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium">Uso del presupuesto</span>
<span className={`text-sm font-medium ${budgetUsed > 90 ? "text-red-500" : ""}`}>
{budgetUsed.toFixed(1)}%
</span>
</div>
<Progress
value={Math.min(budgetUsed, 100)}
className={`h-2 ${budgetUsed > 100 ? "[&>div]:bg-red-500" : ""}`}
/>
</div>
{/* Desglose */}
<div className="grid grid-cols-3 gap-4">
<div className="text-center p-4 rounded-lg bg-muted/50">
<p className="text-sm text-muted-foreground mb-1">Presupuesto</p>
<p className="text-xl font-bold">{formatCurrency(project.budget)}</p>
</div>
<div className="text-center p-4 rounded-lg bg-muted/50">
<p className="text-sm text-muted-foreground mb-1">Gastado</p>
<p className="text-xl font-bold text-blue-600 dark:text-blue-400">
{formatCurrency(project.spent)}
</p>
</div>
<div className="text-center p-4 rounded-lg bg-muted/50">
<p className="text-sm text-muted-foreground mb-1">Restante</p>
<p className={`text-xl font-bold ${budgetRemaining < 0 ? "text-red-500" : "text-green-600 dark:text-green-400"}`}>
{formatCurrency(budgetRemaining)}
</p>
</div>
</div>
</CardContent>
</Card>
{/* Timeline */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2 text-base">
<Calendar className="h-4 w-4 text-muted-foreground" />
Timeline del Proyecto
</CardTitle>
</CardHeader>
<CardContent>
<div className="relative">
{/* Línea de progreso */}
<div className="absolute top-4 left-0 right-0 h-1 bg-muted rounded-full">
<div
className="h-full bg-gradient-to-r from-blue-500 to-purple-600 rounded-full transition-all"
style={{ width: `${project.progress}%` }}
/>
</div>
{/* Puntos */}
<div className="relative flex justify-between pt-8">
<div className="text-center">
<div className="w-3 h-3 rounded-full bg-blue-500 mx-auto -mt-5 relative z-10" />
<p className="text-xs text-muted-foreground mt-2">Inicio</p>
<p className="text-sm font-medium">{formatDate(project.startDate)}</p>
</div>
<div className="text-center">
<div className={`w-3 h-3 rounded-full mx-auto -mt-5 relative z-10 ${project.progress >= 100 ? "bg-green-500" : "bg-gray-300 dark:bg-gray-600"}`} />
<p className="text-xs text-muted-foreground mt-2">Fin previsto</p>
<p className="text-sm font-medium">{formatDate(project.endDate)}</p>
</div>
</div>
</div>
<div className="mt-6 flex items-center justify-center gap-6 text-sm">
<div className="flex items-center gap-2">
<Clock className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground">Duración:</span>
<span className="font-medium">{duration} días</span>
</div>
<div className="flex items-center gap-2">
<span className="text-muted-foreground">Progreso:</span>
<span className="font-medium">{project.progress}%</span>
</div>
</div>
</CardContent>
</Card>
</div>
{/* Sidebar - 1/3 */}
<div className="space-y-6">
{/* Detalles generales */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">Detalles</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* Cliente */}
{project.client !== "Sin cliente" && (
<>
<div className="flex items-start gap-3">
<Building2 className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Cliente</p>
<p className="text-sm font-medium">{project.client}</p>
</div>
</div>
<Separator />
</>
)}
{/* Referencia */}
<div className="flex items-start gap-3">
<Hash className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Referencia</p>
<p className="text-sm font-medium font-mono">{project.ref}</p>
</div>
</div>
<Separator />
{/* ID */}
<div className="flex items-start gap-3">
<Hash className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">ID del proyecto</p>
<p className="text-sm font-medium font-mono">{project.id}</p>
</div>
</div>
</CardContent>
</Card>
{/* Fechas */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">Fechas</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-start gap-3">
<Calendar className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Fecha de inicio</p>
<p className="text-sm font-medium">{formatDate(project.startDate)}</p>
</div>
</div>
<Separator />
<div className="flex items-start gap-3">
<Calendar className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Fecha de fin</p>
<p className="text-sm font-medium">{formatDate(project.endDate)}</p>
</div>
</div>
<Separator />
<div className="flex items-start gap-3">
<Clock className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Creado</p>
<p className="text-sm font-medium">{formatDate(project.createdAt)}</p>
</div>
</div>
<Separator />
<div className="flex items-start gap-3">
<Clock className="h-4 w-4 text-muted-foreground mt-0.5" />
<div>
<p className="text-xs text-muted-foreground">Última actualización</p>
<p className="text-sm font-medium">{formatDate(project.updatedAt)}</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
);
}