"use client" import type React from "react" import { useState } from "react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Card, CardContent } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Upload, FileText, Scale, BookOpen, Gavel, FolderOpen, Download, Eye, X, Edit2, Filter, Grid3x3, List, } from "lucide-react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" // Tipos export type TipoAdjunto = "modelo" | "normativa" | "bibliografia" | "jurisprudencia" | "interno" export interface Adjunto { id: string tipo: TipoAdjunto titulo: string archivo?: File url?: string tamanio: number // en bytes fecha: string // ISO date string } interface AdjuntosManagerProps { adjuntos: Adjunto[] onUpload: (tipo: TipoAdjunto, titulo: string, archivo: File) => void onDelete: (id: string) => void onRename: (id: string, nuevoTitulo: string) => void onFilterByTipo: (tipo: TipoAdjunto | "todos") => void readOnly?: boolean } const tiposAdjuntoConfig: Record< TipoAdjunto, { label: string; icon: typeof FileText; color: string; bgColor: string } > = { modelo: { label: "Modelo", icon: FileText, color: "text-blue-500", bgColor: "bg-blue-500/10", }, normativa: { label: "Normativa", icon: Scale, color: "text-purple-500", bgColor: "bg-purple-500/10", }, bibliografia: { label: "Bibliografía", icon: BookOpen, color: "text-green-500", bgColor: "bg-green-500/10", }, jurisprudencia: { label: "Jurisprudencia", icon: Gavel, color: "text-amber-500", bgColor: "bg-amber-500/10", }, interno: { label: "Interno", icon: FolderOpen, color: "text-slate-500", bgColor: "bg-slate-500/10", }, } export function AdjuntosManager({ adjuntos, onUpload, onDelete, onRename, onFilterByTipo, readOnly = false, }: AdjuntosManagerProps) { const [isDragging, setIsDragging] = useState(false) const [nuevoTipo, setNuevoTipo] = useState("interno") const [nuevoTitulo, setNuevoTitulo] = useState("") const [filtroTipo, setFiltroTipo] = useState("todos") const [vistaActual, setVistaActual] = useState<"grid" | "list">("grid") const [editandoId, setEditandoId] = useState(null) const [tituloEditado, setTituloEditado] = useState("") // Filtrar adjuntos const adjuntosFiltrados = filtroTipo === "todos" ? adjuntos : adjuntos.filter((a) => a.tipo === filtroTipo) // Handlers de drag & drop const handleDragOver = (e: React.DragEvent) => { e.preventDefault() setIsDragging(true) } const handleDragLeave = () => { setIsDragging(false) } const handleDrop = (e: React.DragEvent) => { e.preventDefault() setIsDragging(false) const files = Array.from(e.dataTransfer.files) files.forEach((file) => { const titulo = nuevoTitulo || file.name onUpload(nuevoTipo, titulo, file) }) setNuevoTitulo("") } const handleFileInput = (e: React.ChangeEvent) => { const files = Array.from(e.target.files || []) files.forEach((file) => { const titulo = nuevoTitulo || file.name onUpload(nuevoTipo, titulo, file) }) setNuevoTitulo("") } // Handler de filtro const handleFiltroChange = (tipo: TipoAdjunto | "todos") => { setFiltroTipo(tipo) onFilterByTipo(tipo) } // Handler de renombrar const iniciarEdicion = (adjunto: Adjunto) => { setEditandoId(adjunto.id) setTituloEditado(adjunto.titulo) } const confirmarEdicion = () => { if (editandoId && tituloEditado.trim()) { onRename(editandoId, tituloEditado.trim()) setEditandoId(null) setTituloEditado("") } } const cancelarEdicion = () => { setEditandoId(null) setTituloEditado("") } // Formatear tamaño de archivo const formatearTamanio = (bytes: number): string => { if (bytes < 1024) return `${bytes} B` if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB` return `${(bytes / (1024 * 1024)).toFixed(1)} MB` } // Formatear fecha const formatearFecha = (fecha: string): string => { return new Date(fecha).toLocaleDateString("es-AR", { day: "2-digit", month: "2-digit", year: "numeric", }) } // Handler de descarga const handleDescargar = (adjunto: Adjunto) => { console.log("[v0] Descargar adjunto:", adjunto.id) // Implementación real de descarga if (adjunto.archivo) { const url = URL.createObjectURL(adjunto.archivo) const a = document.createElement("a") a.href = url a.download = adjunto.titulo a.click() URL.revokeObjectURL(url) } else if (adjunto.url) { window.open(adjunto.url, "_blank") } } // Handler de ver const handleVer = (adjunto: Adjunto) => { console.log("[v0] Ver adjunto:", adjunto.id) // Implementación real de vista previa if (adjunto.archivo) { const url = URL.createObjectURL(adjunto.archivo) window.open(url, "_blank") } else if (adjunto.url) { window.open(adjunto.url, "_blank") } } return (
{/* Zona de Upload (solo si no es readOnly) */} {!readOnly && (
{/* Controles de tipo y título */}
setNuevoTitulo(e.target.value)} />
{/* Zona de Drag & Drop */}

Arrastre archivos aquí o haga clic para seleccionar

Se subirán como tipo: {tiposAdjuntoConfig[nuevoTipo].label}

)} {/* Barra de controles */}
{/* Lista/Grid de Adjuntos */} {adjuntosFiltrados.length === 0 ? (

{filtroTipo === "todos" ? "No hay adjuntos" : `No hay adjuntos de tipo ${tiposAdjuntoConfig[filtroTipo as TipoAdjunto]?.label}`}

) : vistaActual === "grid" ? ( // Vista Grid
{adjuntosFiltrados.map((adjunto) => { const config = tiposAdjuntoConfig[adjunto.tipo] const Icon = config.icon return (
{/* Ícono y tipo */}
{/* Información */}

{adjunto.titulo}

{!readOnly && ( )}
{config.label}
{formatearTamanio(adjunto.tamanio)} {formatearFecha(adjunto.fecha)}
{/* Acciones */}
{!readOnly && ( )}
) })}
) : ( // Vista Lista
{adjuntosFiltrados.map((adjunto) => { const config = tiposAdjuntoConfig[adjunto.tipo] const Icon = config.icon return (
{/* Ícono */}
{/* Información */}

{adjunto.titulo}

{!readOnly && ( )}
{config.label} {formatearTamanio(adjunto.tamanio)} {formatearFecha(adjunto.fecha)}
{/* Acciones */}
{!readOnly && ( )}
) })}
)} {/* Modal de Edición de Título */} !open && cancelarEdicion()}> Renombrar Archivo Ingrese el nuevo título para el archivo
setTituloEditado(e.target.value)} placeholder="Nuevo título..." onKeyDown={(e) => { if (e.key === "Enter") confirmarEdicion() if (e.key === "Escape") cancelarEdicion() }} />
) }