be8f207ecd
- Added event creation page with form handling and validation. - Introduced layout for event management with context provider. - Created event listing page with active and recent events display. - Developed questionnaire creation page linked to events. - Implemented breadcrumb navigation for better user experience. - Added reusable components for event and questionnaire cards. - Integrated API calls for fetching and managing event data. - Enhanced slugify utility for better URL handling. - Established context for managing event state across components.
167 lines
6.1 KiB
TypeScript
167 lines
6.1 KiB
TypeScript
import { GetEventoWithCuestionariosWithCupos } from '@/types/evento';
|
|
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import React, { useState } from 'react';
|
|
import MarkdownRenderer from './markdown-render';
|
|
import { formatearRangoFechas } from '@/utils/date-utils';
|
|
|
|
export default function EventoCard({
|
|
evento,
|
|
user = 'public',
|
|
}: {
|
|
evento: GetEventoWithCuestionariosWithCupos;
|
|
user?: 'public' | 'administrador' | 'staff';
|
|
}) {
|
|
const [verMas, setVerMas] = useState(false);
|
|
const descripcion = evento.descripcion_evento ?? '';
|
|
const limite = 100;
|
|
|
|
const descripcionRecortada =
|
|
descripcion.length > limite && !verMas
|
|
? `${descripcion.slice(0, limite)}...`
|
|
: descripcion;
|
|
|
|
return (
|
|
<div className="card card-blog d-flex flex-column justify-content-between">
|
|
<div>
|
|
<div className="card-image scale-hover-1">
|
|
<Link
|
|
href={
|
|
user === 'administrador' || user === 'staff'
|
|
? `/${user}/evento/${evento.id_evento}`
|
|
: `/evento/${evento.nombre_evento.split(' ').join('_')}/${
|
|
evento.id_evento
|
|
}/${evento.cuestionarios[0].id_cuestionario}`
|
|
}
|
|
>
|
|
<Image
|
|
width={400}
|
|
height={300}
|
|
className="img-fluid"
|
|
src={`${process.env.NEXT_PUBLIC_API_URL}/banners/${evento.banner}`}
|
|
alt="Banner formulario"
|
|
/>
|
|
<div className="card-caption">{evento.nombre_evento}</div>
|
|
</Link>
|
|
</div>
|
|
<div className="card-body">
|
|
<div className="card-description mb-0">
|
|
<MarkdownRenderer markdown={descripcionRecortada} />
|
|
{descripcion.length > limite && (
|
|
<button
|
|
onClick={() => setVerMas(!verMas)}
|
|
className="btn btn-link btn-sm p-0 ms-1 align-baseline"
|
|
style={{ fontSize: '0.875rem' }}
|
|
>
|
|
{verMas ? 'Ver menos' : 'Ver más'}
|
|
</button>
|
|
)}
|
|
</div>
|
|
{evento.cuestionarios.length > 0 ? (
|
|
<>
|
|
<h2 className="my-2 fs-3">Formularios</h2>
|
|
<table className="table table-white">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Nombre</th>
|
|
<th scope="col">Inscritos</th>
|
|
<th scope="col">Capacidad total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{evento.cuestionarios.map((cuestionario) => (
|
|
<tr key={cuestionario.id_cuestionario}>
|
|
<td>
|
|
<Link
|
|
href={
|
|
user === 'administrador' || user === 'staff'
|
|
? `/${user}/evento/${evento.id_evento}/formulario/${cuestionario.id_cuestionario}`
|
|
: `/evento/${evento.nombre_evento
|
|
.split(' ')
|
|
.join('_')}/${evento.id_evento}/${
|
|
cuestionario.id_cuestionario
|
|
}`
|
|
}
|
|
>
|
|
{cuestionario.nombre_form}
|
|
</Link>
|
|
</td>
|
|
{cuestionario.cupo_maximo ? (
|
|
<>
|
|
<td>{cuestionario.cupos_usados}</td>
|
|
<td>{cuestionario.cupo_maximo}</td>
|
|
</>
|
|
) : (
|
|
<td colSpan={2} className="text-center">
|
|
Sin límite
|
|
</td>
|
|
)}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</>
|
|
) : (
|
|
<div className="text-center px-4 py-3 border rounded bg-light my-3">
|
|
<i className="bi bi-clipboard-x fs-1 text-muted mb-3"></i>
|
|
<p className="text-muted mb-3">
|
|
Este evento no tiene formularios disponibles.
|
|
</p>
|
|
{(user === 'administrador' || user === 'staff') && (
|
|
<Link
|
|
href={`/${user}/evento/${evento.id_evento}/formularios/crear`}
|
|
className="btn btn-primary"
|
|
>
|
|
<i className="bi bi-plus-circle me-2"></i>
|
|
Crear formulario
|
|
</Link>
|
|
)}
|
|
</div>
|
|
)}
|
|
<span className="badge fs-6 w-100 bg-primary">
|
|
Evento {formatearRangoFechas(evento.fecha_inicio, evento.fecha_fin)}
|
|
</span>
|
|
|
|
{/* Botón único del evento */}
|
|
<div className="mt-2">
|
|
{user === 'administrador' || user === 'staff' ? (
|
|
<Link
|
|
href={`/${user}/evento/${evento.id_evento}`}
|
|
className="btn w-100 btn-outline-primary"
|
|
>
|
|
Ver/Editar evento
|
|
</Link>
|
|
) : evento.cuestionarios.length === 0 ? (
|
|
<button className="btn w-100 btn-outline-secondary" disabled>
|
|
Sin formularios disponibles
|
|
</button>
|
|
) : evento.cuestionarios.some(
|
|
(cuestionario) =>
|
|
cuestionario.cupos_disponibles === 0 &&
|
|
cuestionario.cupo_maximo !== null
|
|
) &&
|
|
evento.cuestionarios.every(
|
|
(cuestionario) =>
|
|
cuestionario.cupos_disponibles === 0 &&
|
|
cuestionario.cupo_maximo !== null
|
|
) ? (
|
|
<button className="btn w-100 btn-outline-secondary" disabled>
|
|
Cupo lleno
|
|
</button>
|
|
) : (
|
|
<Link
|
|
href={`/evento/${evento.nombre_evento.split(' ').join('_')}/${
|
|
evento.id_evento
|
|
}/${evento.cuestionarios[0]?.id_cuestionario || ''}`}
|
|
className="btn w-100 btn-outline-primary"
|
|
>
|
|
Registro
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|