feat: Refactor carousel component and add new event card

- Updated ClientCarousel to accept props for dynamic image rendering.
- Changed CarouselProps interface to export for better type usage.
- Enhanced Carousel component to handle default images and improved styling.
- Introduced EventoCard component for displaying event details with dynamic data.
- Added MarkdownRenderer for rendering markdown content in EventoCard.
- Removed old Formulario component and replaced it with FormularioRegistro for better structure.
- Implemented prefetching logic in FormularioRegistro to auto-fill user data based on account info.
- Created PrefetchAbiertaCorta component for handling short answer questions with pre-filled data.
- Added useGetApi hook for simplified API data fetching.
- Updated plantillas data to include validation types for new form fields.
- Introduced new types for event and questionnaire handling in TypeScript.
- Enhanced styles for better UI/UX, including carousel controls and required field indicators.
This commit is contained in:
miguel
2025-06-16 18:25:12 -06:00
parent e275b33131
commit f00bd8ac5e
21 changed files with 2110 additions and 599 deletions
+13 -13
View File
@@ -1,7 +1,7 @@
import Image from 'next/image';
import React from 'react';
interface CarouselProps {
export interface CarouselProps {
id?: string;
images?: {
src: string;
@@ -9,15 +9,9 @@ interface CarouselProps {
}[];
}
export default function Carousel({
id = 'carouselExample',
images = [
{
src: '/feriasex.png',
alt: 'Imagen de ejemplo',
},
],
}: CarouselProps) {
export default function Carousel({ id, images }: CarouselProps) {
console.log('Carousel images:', images);
if (!images || images.length === 0) {
return <div>No hay imágenes para mostrar</div>;
}
@@ -31,11 +25,17 @@ export default function Carousel({
className={`carousel-item ${index === 0 ? 'active' : ''}`}
>
<Image
src={img.src}
width={1600}
height={535}
src={img.src ? img.src : '/default-banner.png'}
width={1200}
height={400}
alt="Ejemplo de banner"
className="d-block w-100 rounded-3 img-fluid"
style={{
height: '400px',
objectFit: 'cover',
objectPosition: 'center',
maxHeight: '400px',
}}
/>
</div>
))}
+65
View File
@@ -0,0 +1,65 @@
import { GetEventoWithCuestionarios } from '@/types/evento';
import Image from 'next/image';
import Link from 'next/link';
import React, { useState } from 'react';
import MarkdownRenderer from './markdown-render';
export default function EventoCard({
evento,
}: {
evento: GetEventoWithCuestionarios;
}) {
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={`/evento/${evento.id_evento}`}>
<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 className="ripple-cont"></div>
</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 &&
evento.cuestionarios.map((cuestionario) => (
<div key={cuestionario.id_cuestionario} className="">
<Link
href={`/evento/${evento.nombre_evento.split(' ').join('_')}/${evento.id_evento}/${cuestionario.id_cuestionario}`}
className="btn mt-2 w-100 btn-outline-primary"
>
{cuestionario.nombre_form}
</Link>
</div>
))}
</div>
</div>
</div>
);
}
+18
View File
@@ -0,0 +1,18 @@
import React from 'react';
import ReactMarkdown from 'react-markdown';
type MarkdownRendererProps = {
markdown: string;
};
const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ markdown }) => (
<ReactMarkdown
components={{
p: ({ ...props }) => <p style={{ margin: 0 }} {...props} />,
}}
>
{markdown}
</ReactMarkdown>
);
export default MarkdownRenderer;