fix, and animations
This commit is contained in:
@@ -1,39 +1,46 @@
|
||||
'use client';
|
||||
|
||||
import FormularioCard from '@/components/formulario-card';
|
||||
import { GetCuestionario } from '@/types/cuestionario';
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
async function getEventos(): Promise<GetCuestionario[]> {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/cuestionario`, {
|
||||
method: 'GET',
|
||||
cache: 'no-store', // para que no lo cachee ni en build ni entre requests
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
export default function Page() {
|
||||
const [eventos, setEventos] = useState<GetCuestionario[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
useEffect(() => {
|
||||
async function getEventos() {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/cuestionario`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
|
||||
const data: GetCuestionario[] = await res.json();
|
||||
setEventos(data);
|
||||
} catch (err) {
|
||||
console.error('Error en getEventos:', err);
|
||||
setError('Error al cargar los eventos');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const data: GetCuestionario[] = await res.json();
|
||||
getEventos();
|
||||
}, []);
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error en getEventos:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Page() {
|
||||
let eventos;
|
||||
|
||||
try {
|
||||
eventos = await getEventos();
|
||||
} catch (error) {
|
||||
console.error('Error al cargar los eventos:', error);
|
||||
return <div>Error al cargar los eventos</div>;
|
||||
}
|
||||
if (loading) return <div>Cargando formularios...</div>;
|
||||
if (error) return <div>{error}</div>;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -25,34 +25,38 @@ export default function Page() {
|
||||
|
||||
if (username === 'user-admin' && password === '@dm1nP@ss') {
|
||||
Cookies.set('token', 'staff1');
|
||||
router.push('/staff');
|
||||
router.push('/administrador');
|
||||
} else {
|
||||
setError('Usuario o contraseña incorrectos');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='d-flex flex-column justify-content-center align-items-center'>
|
||||
<h1 className='text-dorado'>Iniciar sesión</h1>
|
||||
<h2 className='text-azul'>Administradores</h2>
|
||||
<div className="d-flex flex-column justify-content-center align-items-center">
|
||||
<h1 className="text-dorado">Iniciar sesión</h1>
|
||||
<h2 className="text-azul">Administradores</h2>
|
||||
|
||||
<form className='w-300px' onSubmit={handleOnSubmit}>
|
||||
<form className="w-300px" onSubmit={handleOnSubmit}>
|
||||
<Input
|
||||
name='username'
|
||||
label='Usuario'
|
||||
name="username"
|
||||
label="Usuario"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<Input
|
||||
name='password'
|
||||
type='password'
|
||||
label='Contraseña'
|
||||
name="password"
|
||||
type="password"
|
||||
label="Contraseña"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
{error && <div className='alert alert-danger text-center' role='alert'>{error}</div>}
|
||||
<div className='mb-3'>
|
||||
<Button className='w-100' type='submit'>
|
||||
{error && (
|
||||
<div className="alert alert-danger text-center" role="alert">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
<div className="mb-3">
|
||||
<Button className="w-100" type="submit">
|
||||
Iniciar sesión
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
+53
-41
@@ -1,71 +1,83 @@
|
||||
'use client';
|
||||
|
||||
import ClientCarousel from '@/client-components/client-carousel';
|
||||
import FormularioCard from '@/components/formulario-card';
|
||||
import { GetCuestionario } from '@/types/cuestionario';
|
||||
import React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
async function getEventos(): Promise<GetCuestionario[]> {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/cuestionario`, {
|
||||
method: 'GET',
|
||||
cache: 'no-store', // para que no lo cachee ni en build ni entre requests
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
export default function Page() {
|
||||
const [eventos, setEventos] = useState<GetCuestionario[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
useEffect(() => {
|
||||
async function getEventos() {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/cuestionario`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Error ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
|
||||
const data: GetCuestionario[] = await res.json();
|
||||
setEventos(data);
|
||||
} catch (err) {
|
||||
console.error('Error en getEventos:', err);
|
||||
setError('No se pudieron cargar los cuestionarios.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const data: GetCuestionario[] = await res.json();
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error en getEventos:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Page() {
|
||||
let eventos;
|
||||
|
||||
try {
|
||||
eventos = await getEventos();
|
||||
} catch (error) {
|
||||
console.error('Error al cargar los eventos:', error);
|
||||
return <div>Error al cargar los eventos</div>;
|
||||
}
|
||||
getEventos();
|
||||
}, []);
|
||||
|
||||
function slugify(text: string): string {
|
||||
return text
|
||||
.toString()
|
||||
.normalize('NFD') // Quita tildes
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9]+/g, '-') // Reemplaza cualquier cosa que no sea alfanumérica por guiones
|
||||
.replace(/^-+|-+$/g, ''); // Quita guiones al inicio o final
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '');
|
||||
}
|
||||
|
||||
if (loading) return <div>Cargando cuestionarios...</div>;
|
||||
if (error) return <div>{error}</div>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mx-auto my-5">
|
||||
<div className="mx-auto my-5 fade-in-down-bounce">
|
||||
<ClientCarousel />
|
||||
</div>
|
||||
<div className="cards-1 mt-5">
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{eventos.map((cuestionario) => {
|
||||
const slug = slugify(cuestionario.nombre_form); // Asumiendo que el nombre del evento está en `nombre`
|
||||
{eventos.map((cuestionario, index) => {
|
||||
const slug = slugify(cuestionario.nombre_form);
|
||||
const url = `/registro/${slug}-${cuestionario.id_cuestionario}`;
|
||||
const fadeClass = `delay-${(index % 5) + 1}`;
|
||||
|
||||
return (
|
||||
<FormularioCard
|
||||
<div
|
||||
className={`col-md-4 my-4 fade-in-up-bounce ${fadeClass}`}
|
||||
key={cuestionario.id_cuestionario}
|
||||
cuestionario={cuestionario}
|
||||
link={url}
|
||||
button_message="Registrarse"
|
||||
/>
|
||||
>
|
||||
<FormularioCard
|
||||
cuestionario={cuestionario}
|
||||
link={url}
|
||||
button_message="Registrarse"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -29,50 +29,48 @@ export default function FormularioCard({
|
||||
: descripcion;
|
||||
|
||||
return (
|
||||
<div className="col-md-4 my-4">
|
||||
<div className="card card-blog d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div className="card-image">
|
||||
<Link href={link}>
|
||||
<Image
|
||||
width={400}
|
||||
height={300}
|
||||
className="img"
|
||||
src="/feriasex.jpg"
|
||||
alt="Banner formulario"
|
||||
/>
|
||||
<div className="card-caption">{cuestionario.nombre_form}</div>
|
||||
</Link>
|
||||
<div className="ripple-cont"></div>
|
||||
</div>
|
||||
<div className="card card-blog d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div className="card-image">
|
||||
<Link href={link}>
|
||||
<Image
|
||||
width={400}
|
||||
height={300}
|
||||
className="img"
|
||||
src="/feriasex.jpg"
|
||||
alt="Banner formulario"
|
||||
/>
|
||||
<div className="card-caption">{cuestionario.nombre_form}</div>
|
||||
</Link>
|
||||
<div className="ripple-cont"></div>
|
||||
</div>
|
||||
|
||||
<div className="table px-3 pt-3 mb-0">
|
||||
<h6 className="category text-info">
|
||||
{cuestionario.id_tipo_cuestionario === 1 ? 'Feria' : 'Evento'}
|
||||
</h6>
|
||||
<p className="card-description mb-0">
|
||||
{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>
|
||||
)}
|
||||
</p>
|
||||
{button_message && (
|
||||
<Button
|
||||
onClick={() => router.push(link)}
|
||||
outline
|
||||
className="mt-3 w-100 py-1 rounded"
|
||||
variant="primary"
|
||||
<div className="table px-3 pt-3 mb-0">
|
||||
<h6 className="category text-info">
|
||||
{cuestionario.id_tipo_cuestionario === 1 ? 'Feria' : 'Evento'}
|
||||
</h6>
|
||||
<p className="card-description mb-0">
|
||||
{descripcionRecortada}
|
||||
{descripcion.length > limite && (
|
||||
<button
|
||||
onClick={() => setVerMas(!verMas)}
|
||||
className="btn btn-link btn-sm p-0 ms-1 align-baseline"
|
||||
style={{ fontSize: '0.875rem' }}
|
||||
>
|
||||
{button_message}
|
||||
</Button>
|
||||
{verMas ? 'Ver menos' : 'Ver más'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</p>
|
||||
{button_message && (
|
||||
<Button
|
||||
onClick={() => router.push(link)}
|
||||
outline
|
||||
className="mt-3 w-100 py-1 rounded"
|
||||
variant="primary"
|
||||
>
|
||||
{button_message}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInScale {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRotate {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: rotate(-5deg) scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: rotate(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUpBounce {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translateY(-5px); // se pasa ligeramente hacia arriba
|
||||
}
|
||||
80% {
|
||||
transform: translateY(3px); // rebota hacia abajo
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0); // posición final
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDownBounce {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translateY(5px); // se pasa un poco hacia abajo
|
||||
}
|
||||
80% {
|
||||
transform: translateY(-3px); // rebota hacia arriba
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0); // se estabiliza
|
||||
}
|
||||
}
|
||||
|
||||
// Clase base para aplicar la animación
|
||||
.fade-in {
|
||||
animation: fadeIn 1s ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-up {
|
||||
animation: fadeInUp 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-down {
|
||||
animation: fadeInDown 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-scale {
|
||||
animation: fadeInScale 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.slide-in-left {
|
||||
animation: slideInLeft 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.slide-in-right {
|
||||
animation: slideInRight 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-rotate {
|
||||
animation: fadeInRotate 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-up-bounce {
|
||||
animation: fadeInUpBounce 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.fade-in-down-bounce {
|
||||
animation: fadeInDownBounce 0.8s ease-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
// Variantes con delays más suaves
|
||||
@for $i from 1 through 5 {
|
||||
.delay-#{$i} {
|
||||
animation-delay: #{($i * 0.3)}s;
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -27,6 +27,7 @@ $theme-colors: map-merge($theme-colors, $custom-colors);
|
||||
@import 'sidebar';
|
||||
@import 'hover';
|
||||
@import 'tabs';
|
||||
@import 'animation';
|
||||
|
||||
//Add additional custom code here
|
||||
|
||||
|
||||
Reference in New Issue
Block a user