feat: Implement event and questionnaire management features

- 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.
This commit is contained in:
miguel
2025-08-12 20:00:21 -06:00
parent 5b0f0ad6bf
commit be8f207ecd
35 changed files with 2091 additions and 642 deletions
+101
View File
@@ -0,0 +1,101 @@
'use client';
import { GetEventoWithCuestionariosWithCupos } from '@/types/evento';
import axiosInstance from '@/utils/api-config';
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
ReactNode,
} from 'react';
interface EventoContextType {
evento: GetEventoWithCuestionariosWithCupos | null;
loading: boolean;
error: string | null;
refetch: () => void;
updateEvento: (
eventoData: Partial<GetEventoWithCuestionariosWithCupos>
) => void;
setEventoData: (evento: GetEventoWithCuestionariosWithCupos) => void;
}
const EventoContext = createContext<EventoContextType | undefined>(undefined);
interface EventoProviderProps {
children: ReactNode;
id_evento: string;
}
export function EventoProvider({ children, id_evento }: EventoProviderProps) {
const [evento, setEvento] =
useState<GetEventoWithCuestionariosWithCupos | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchEvento = useCallback(async () => {
console.log('Fetching evento with ID:', id_evento);
try {
setLoading(true);
setError(null);
const response =
await axiosInstance.get<GetEventoWithCuestionariosWithCupos>(
`/evento/${id_evento}/cuestionarios`
);
setEvento(response.data);
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Error al cargar el evento';
setError(errorMessage);
console.error('Error fetching evento:', error);
} finally {
setLoading(false);
}
}, [id_evento]);
useEffect(() => {
if (id_evento) {
fetchEvento();
}
}, [id_evento, fetchEvento]);
const refetch = () => {
fetchEvento();
};
const updateEvento = useCallback(
(eventoData: Partial<GetEventoWithCuestionariosWithCupos>) => {
setEvento((prev) => (prev ? { ...prev, ...eventoData } : null));
},
[]
);
const setEventoData = useCallback(
(newEvento: GetEventoWithCuestionariosWithCupos) => {
setEvento(newEvento);
},
[]
);
const value: EventoContextType = {
evento,
loading,
error,
refetch,
updateEvento,
setEventoData,
};
return (
<EventoContext.Provider value={value}>{children}</EventoContext.Provider>
);
}
export function useEvento() {
const context = useContext(EventoContext);
if (context === undefined) {
throw new Error('useEvento must be used within an EventoProvider');
}
return context;
}
+1
View File
@@ -0,0 +1 @@
export * from './evento-context';
+1
View File
@@ -0,0 +1 @@
export * from './evento';