correciones al formulario osp
This commit is contained in:
@@ -16,7 +16,16 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@repo/shadcn/components/ui/dialog';
|
||||
import { X } from 'lucide-react';
|
||||
import { ScrollArea } from '@repo/shadcn/components/ui/scroll-area';
|
||||
import { Separator } from '@repo/shadcn/components/ui/separator';
|
||||
import {
|
||||
ExternalLink,
|
||||
Factory,
|
||||
MapPin,
|
||||
Package,
|
||||
Wrench,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import React, { useState } from 'react';
|
||||
import { TrainingSchema } from '../schemas/training';
|
||||
|
||||
@@ -37,235 +46,447 @@ export function TrainingViewModal({
|
||||
|
||||
const DetailItem = ({ label, value }: { label: string; value: any }) => (
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm font-medium text-muted-foreground">{label}</p>
|
||||
<p className="text-sm font-semibold">{value || 'N/A'}</p>
|
||||
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||
{label}
|
||||
</p>
|
||||
<p className="text-sm font-semibold text-foreground break-words">
|
||||
{value !== null && value !== undefined && value !== '' ? value : 'N/A'}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Section = ({
|
||||
title,
|
||||
icon: Icon,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
icon?: React.ElementType;
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<Card className="mb-4">
|
||||
<CardHeader className="py-3">
|
||||
<CardTitle className="text-lg">{title}</CardTitle>
|
||||
<Card className="overflow-hidden border-l-4 border-l-primary/20">
|
||||
<CardHeader className="py-3 bg-muted/30">
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
{Icon && <Icon className="h-5 w-5 text-primary" />}
|
||||
{title}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-4 gap-y-6 pt-4">
|
||||
{children}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
const BooleanBadge = ({ value }: { value?: boolean }) => (
|
||||
<Badge variant={value ? 'default' : 'secondary'}>
|
||||
{value ? 'Sí' : 'No'}
|
||||
</Badge>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||
<DialogContent className="sm:max-w-[800px] overflow-y-auto [&>button:last-child]:hidden">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-2xl font-bold">
|
||||
Detalle de la Organización Socioproductiva
|
||||
<DialogContent className="sm:max-w-[1000px] max-h-[90vh] p-0 flex flex-col">
|
||||
<DialogHeader className="px-6 py-4 border-b">
|
||||
<DialogTitle className="text-2xl font-bold flex items-center gap-2">
|
||||
<Factory className="h-6 w-6" />
|
||||
{data.ospName}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="sr-only">
|
||||
Resumen detallado de la información de la organización
|
||||
socioproductiva incluyendo ubicación, responsable y registro
|
||||
fotográfico.
|
||||
<DialogDescription>
|
||||
{data.ospType} • {data.ospRif} •{' '}
|
||||
<span
|
||||
className={
|
||||
data.currentStatus === 'ACTIVA'
|
||||
? 'text-green-600 font-medium'
|
||||
: 'text-red-600'
|
||||
}
|
||||
>
|
||||
{data.currentStatus}
|
||||
</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="mt-4 space-y-6">
|
||||
{/* 1. Datos de la visita */}
|
||||
<Section title="1. Datos de la visita">
|
||||
<DetailItem
|
||||
label="Nombre del Coordinador"
|
||||
value={data.firstname}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Apellido del Coordinador"
|
||||
value={data.lastname}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Fecha y hora de la visita"
|
||||
value={
|
||||
data.visitDate
|
||||
? new Date(data.visitDate).toLocaleString()
|
||||
: 'N/A'
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
<ScrollArea className="flex-1 px-6 py-6">
|
||||
<div className="space-y-8">
|
||||
{/* 1. Datos de la Visita */}
|
||||
<Section title="Datos de la Visita">
|
||||
<DetailItem
|
||||
label="Coordinador"
|
||||
value={`${data.firstname} ${data.lastname}`}
|
||||
/>
|
||||
<DetailItem label="Teléfono Coord." value={data.coorPhone} />
|
||||
<DetailItem
|
||||
label="Fecha Visita"
|
||||
value={
|
||||
data.visitDate
|
||||
? new Date(data.visitDate).toLocaleString()
|
||||
: 'N/A'
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
{/* 2. Datos de la OSP */}
|
||||
<Section title="2. Datos de la OSP">
|
||||
<DetailItem label="Nombre" value={data.ospName} />
|
||||
<DetailItem label="RIF" value={data.ospRif} />
|
||||
<DetailItem label="Tipo" value={data.ospType} />
|
||||
<DetailItem
|
||||
label="Actividad Productiva"
|
||||
value={data.productiveActivity}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Estatus"
|
||||
value={
|
||||
<Badge
|
||||
variant={
|
||||
data.currentStatus === 'ACTIVA' ? 'default' : 'secondary'
|
||||
}
|
||||
>
|
||||
{data.currentStatus}
|
||||
</Badge>
|
||||
}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Año de Constitución"
|
||||
value={data.companyConstitutionYear}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Cant. Productores"
|
||||
value={data.producerCount}
|
||||
/>
|
||||
<DetailItem label="Cant. Productos" value={data.productCount} />
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-3">
|
||||
{/* 2. Sectores y Actividad */}
|
||||
<Section title="Sectores Económicos">
|
||||
<DetailItem label="Sector Económico" value={data.ecoSector} />
|
||||
<DetailItem
|
||||
label="Descripción del Producto"
|
||||
value={data.productDescription}
|
||||
label="Sector Productivo"
|
||||
value={data.productiveSector}
|
||||
/>
|
||||
</div>
|
||||
<DetailItem
|
||||
label="Capacidad Instalada"
|
||||
value={data.installedCapacity}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Capacidad Operativa"
|
||||
value={data.operationalCapacity}
|
||||
/>
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-3">
|
||||
<DetailItem
|
||||
label="Requerimiento Financiero"
|
||||
value={data.financialRequirementDescription}
|
||||
label="Actividad Central"
|
||||
value={data.centralProductiveActivity}
|
||||
/>
|
||||
</div>
|
||||
{data.paralysisReason && (
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-3">
|
||||
<DetailItem
|
||||
label="Actividad Principal"
|
||||
value={data.mainProductiveActivity}
|
||||
/>
|
||||
<div className="col-span-full">
|
||||
<DetailItem
|
||||
label="Razones de paralización"
|
||||
value={data.paralysisReason}
|
||||
label="Actividad Específica"
|
||||
value={data.productiveActivity}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Section>
|
||||
</Section>
|
||||
|
||||
{/* 3. Ubicación */}
|
||||
<Section title="3. Detalles de la ubicación">
|
||||
<DetailItem
|
||||
label="Código SITUR Comuna"
|
||||
value={data.siturCodeCommune}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Consejo Comunal"
|
||||
value={data.communalCouncil}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Código SITUR Consejo Comunal"
|
||||
value={data.siturCodeCommunalCouncil}
|
||||
/>
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-3">
|
||||
<DetailItem label="Dirección OSP" value={data.ospAddress} />
|
||||
</div>
|
||||
</Section>
|
||||
{/* 3. Infraestructura y Ubicación */}
|
||||
<Section title="Infraestructura y Ubicación" icon={MapPin}>
|
||||
<DetailItem
|
||||
label="Año Constitución"
|
||||
value={data.companyConstitutionYear}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Infraestructura (m²)"
|
||||
value={data.infrastructureMt2}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Tipo Estructura"
|
||||
value={data.structureType}
|
||||
/>
|
||||
|
||||
{/* 4. Responsable */}
|
||||
<Section title="4. Datos del Responsable">
|
||||
<DetailItem
|
||||
label="Nombre Completo"
|
||||
value={data.ospResponsibleFullname}
|
||||
/>
|
||||
<DetailItem label="Cédula" value={data.ospResponsibleCedula} />
|
||||
<DetailItem label="RIF" value={data.ospResponsibleRif} />
|
||||
<DetailItem label="Estado Civil" value={data.civilState} />
|
||||
<DetailItem label="Teléfono" value={data.ospResponsiblePhone} />
|
||||
<DetailItem label="Email" value={data.ospResponsibleEmail} />
|
||||
<DetailItem label="Carga Familiar" value={data.familyBurden} />
|
||||
<DetailItem
|
||||
label="Número de Hijos"
|
||||
value={data.numberOfChildren}
|
||||
/>
|
||||
</Section>
|
||||
<DetailItem
|
||||
label="Posee Transporte"
|
||||
value={<BooleanBadge value={data.hasTransport} />}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Espacio Abierto"
|
||||
value={<BooleanBadge value={data.isOpenSpace} />}
|
||||
/>
|
||||
|
||||
{/* 5. Observaciones */}
|
||||
<Card>
|
||||
<CardHeader className="py-3">
|
||||
<CardTitle className="text-lg">
|
||||
5. Observaciones Generales
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm whitespace-pre-wrap">
|
||||
{data.generalObservations || 'Sin observaciones'}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 6. Registro fotográfico */}
|
||||
<Card>
|
||||
<CardHeader className="py-3">
|
||||
<CardTitle className="text-lg">
|
||||
6. Registro fotográfico
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{[data.photo1, data.photo2, data.photo3].map(
|
||||
(photo, idx) =>
|
||||
photo && (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative aspect-video rounded-md overflow-hidden cursor-pointer hover:opacity-90 transition-opacity bg-muted"
|
||||
onClick={() => setSelectedImage(photo)}
|
||||
>
|
||||
<img
|
||||
src={`${process.env.NEXT_PUBLIC_API_URL}${photo}`}
|
||||
alt={`Registro ${idx + 1}`}
|
||||
className="object-cover w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
{![data.photo1, data.photo2, data.photo3].some(Boolean) && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
No hay registro fotográfico
|
||||
<div className="col-span-full space-y-4 mt-2">
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-medium text-muted-foreground uppercase">
|
||||
Dirección
|
||||
</p>
|
||||
<p className="text-sm font-medium">{data.ospAddress}</p>
|
||||
</div>
|
||||
{data.ospGoogleMapsLink && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
asChild
|
||||
className="gap-2"
|
||||
>
|
||||
<a
|
||||
href={data.ospGoogleMapsLink}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<MapPin className="h-4 w-4" />
|
||||
Ver en Google Maps
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<DialogFooter className="mt-6">
|
||||
<Button onClick={onClose} variant="outline" className="w-32">
|
||||
{/* 4. LISTAS DETALLADAS (Lo nuevo) */}
|
||||
|
||||
{/* PRODUCTOS */}
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<Package className="h-5 w-5" />
|
||||
Productos y Mano de Obra
|
||||
<Badge variant="secondary" className="ml-2">
|
||||
{data.productList?.length || 0}
|
||||
</Badge>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-4">
|
||||
{data.productList?.map((prod: any, idx: number) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="bg-muted/40 p-4 rounded-lg border text-sm"
|
||||
>
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<h4 className="font-bold text-base text-primary">
|
||||
{prod.productName}
|
||||
</h4>
|
||||
<Badge variant="outline">
|
||||
Mano de obra:{' '}
|
||||
{Number(prod.menCount || 0) +
|
||||
Number(prod.womenCount || 0)}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-muted-foreground mb-3">
|
||||
{prod.description}
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-3">
|
||||
<DetailItem label="Diario" value={prod.dailyCount} />
|
||||
<DetailItem label="Semanal" value={prod.weeklyCount} />
|
||||
<DetailItem label="Mensual" value={prod.monthlyCount} />
|
||||
<DetailItem
|
||||
label="Hombres / Mujeres"
|
||||
value={`${prod.menCount || 0} / ${prod.womenCount || 0}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Detalles de distribución si existen */}
|
||||
{(prod.internalQuantity || prod.externalQuantity) && (
|
||||
<>
|
||||
<Separator className="my-2" />
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{prod.internalQuantity && (
|
||||
<div>
|
||||
<span className="text-xs font-bold text-muted-foreground block mb-1">
|
||||
DISTRIBUCIÓN INTERNA
|
||||
</span>
|
||||
<p>Cant: {prod.internalQuantity}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{prod.internalDescription}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{prod.externalQuantity && (
|
||||
<div>
|
||||
<span className="text-xs font-bold text-muted-foreground block mb-1">
|
||||
EXPORTACIÓN ({prod.externalCountry})
|
||||
</span>
|
||||
<p>Cant: {prod.externalQuantity}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{prod.externalDescription}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{(!data.productList || data.productList.length === 0) && (
|
||||
<p className="text-sm text-muted-foreground italic">
|
||||
No hay productos registrados.
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* EQUIPAMIENTO Y PRODUCCIÓN */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<Wrench className="h-5 w-5" />
|
||||
Equipamiento
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{data.equipmentList?.map((eq: any, idx: number) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="flex justify-between items-center p-2 rounded bg-muted/40 border"
|
||||
>
|
||||
<div>
|
||||
<p className="font-medium">{eq.machine}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{eq.specifications}
|
||||
</p>
|
||||
</div>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-sm font-bold h-8 w-8 flex items-center justify-center rounded-full"
|
||||
>
|
||||
{eq.quantity}
|
||||
</Badge>
|
||||
</div>
|
||||
))}
|
||||
{(!data.equipmentList ||
|
||||
data.equipmentList.length === 0) && (
|
||||
<p className="text-sm text-muted-foreground italic">
|
||||
No hay equipamiento registrado.
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<Factory className="h-5 w-5" />
|
||||
Materia Prima
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{data.productionList?.map((mat: any, idx: number) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="flex justify-between items-center p-2 rounded bg-muted/40 border"
|
||||
>
|
||||
<div>
|
||||
<p className="font-medium">{mat.rawMaterial}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{mat.supplyType}
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="secondary">Cant: {mat.quantity}</Badge>
|
||||
</div>
|
||||
))}
|
||||
{(!data.productionList ||
|
||||
data.productionList.length === 0) && (
|
||||
<p className="text-sm text-muted-foreground italic">
|
||||
No hay materia prima registrada.
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 5. Comuna y Responsable */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<Section title="Datos de la Comuna">
|
||||
<DetailItem label="Comuna" value={data.communeName} />
|
||||
<DetailItem
|
||||
label="Código SITUR"
|
||||
value={data.siturCodeCommune}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Vocero"
|
||||
value={data.communeSpokespersonName}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Teléfono"
|
||||
value={data.communeSpokespersonPhone}
|
||||
/>
|
||||
<div className="col-span-full border-t pt-4 mt-2">
|
||||
<DetailItem
|
||||
label="Consejo Comunal"
|
||||
value={data.communalCouncil}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Vocero C.C."
|
||||
value={data.communalCouncilSpokespersonName}
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Responsable OSP">
|
||||
<DetailItem
|
||||
label="Nombre"
|
||||
value={data.ospResponsibleFullname}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Cédula"
|
||||
value={data.ospResponsibleCedula}
|
||||
/>
|
||||
<DetailItem
|
||||
label="Teléfono"
|
||||
value={data.ospResponsiblePhone}
|
||||
/>
|
||||
<DetailItem label="Email" value={data.ospResponsibleEmail} />
|
||||
<DetailItem
|
||||
label="Carga Familiar"
|
||||
value={data.familyBurden}
|
||||
/>
|
||||
<DetailItem label="Hijos" value={data.numberOfChildren} />
|
||||
</Section>
|
||||
</div>
|
||||
|
||||
{/* 6. Observaciones */}
|
||||
{(data.generalObservations || data.paralysisReason) && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Observaciones</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{data.generalObservations && (
|
||||
<div>
|
||||
<p className="text-xs font-bold text-muted-foreground uppercase mb-1">
|
||||
Generales
|
||||
</p>
|
||||
<p className="text-sm">{data.generalObservations}</p>
|
||||
</div>
|
||||
)}
|
||||
{data.paralysisReason && (
|
||||
<div className="p-3 bg-red-50 dark:bg-red-900/20 rounded-md border border-red-200 dark:border-red-900">
|
||||
<p className="text-xs font-bold text-red-600 dark:text-red-400 uppercase mb-1">
|
||||
Motivo Paralización
|
||||
</p>
|
||||
<p className="text-sm">{data.paralysisReason}</p>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* 7. Fotos */}
|
||||
<Section title="Registro Fotográfico">
|
||||
{[data.photo1, data.photo2, data.photo3].some(Boolean) ? (
|
||||
<div className="col-span-full grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
{[data.photo1, data.photo2, data.photo3].map(
|
||||
(photo, idx) =>
|
||||
photo && (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative aspect-video rounded-lg overflow-hidden cursor-zoom-in border hover:shadow-lg transition-all"
|
||||
onClick={() => setSelectedImage(photo)}
|
||||
>
|
||||
<img
|
||||
src={`${process.env.NEXT_PUBLIC_API_URL}${photo}`}
|
||||
alt={`Evidencia ${idx + 1}`}
|
||||
className="object-cover w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground col-span-full">
|
||||
No hay imágenes cargadas.
|
||||
</p>
|
||||
)}
|
||||
</Section>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
<DialogFooter className="px-6 py-4 border-t bg-muted/20">
|
||||
<Button
|
||||
onClick={onClose}
|
||||
variant="outline"
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
Cerrar
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Lightbox */}
|
||||
{/* Lightbox para imágenes */}
|
||||
<Dialog
|
||||
open={!!selectedImage}
|
||||
onOpenChange={() => setSelectedImage(null)}
|
||||
>
|
||||
<DialogContent className="max-w-[95vw] max-h-[95vh] p-0 overflow-hidden bg-black/90 border-none [&>button:last-child]:hidden">
|
||||
<DialogContent className="max-w-[95vw] max-h-[95vh] p-0 overflow-hidden bg-black/95 border-none">
|
||||
<DialogHeader className="sr-only">
|
||||
<DialogTitle>Vista ampliada de la imagen</DialogTitle>
|
||||
<DialogDescription>
|
||||
Imagen ampliada del registro fotográfico de la organización.
|
||||
</DialogDescription>
|
||||
<DialogTitle>Imagen Ampliada</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="relative w-full h-full flex items-center justify-center p-4">
|
||||
<DialogDescription></DialogDescription>
|
||||
<div className="relative w-full h-full flex items-center justify-center p-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute top-2 right-2 text-white hover:bg-white/20 z-10"
|
||||
className="absolute top-4 right-4 text-white hover:bg-white/20 rounded-full z-50"
|
||||
onClick={() => setSelectedImage(null)}
|
||||
>
|
||||
<X className="h-6 w-6" />
|
||||
@@ -273,8 +494,8 @@ export function TrainingViewModal({
|
||||
{selectedImage && (
|
||||
<img
|
||||
src={`${process.env.NEXT_PUBLIC_API_URL}${selectedImage}`}
|
||||
alt="Expanded view"
|
||||
className="max-w-full max-h-[90vh] object-contain"
|
||||
alt="Vista ampliada"
|
||||
className="max-w-full max-h-[90vh] object-contain rounded-md"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user