102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useParams } from 'react-router-dom';
|
|
import {
|
|
fetchEvent,
|
|
EventData,
|
|
FetchEventError,
|
|
FetchEventErrorCode,
|
|
} from '../services/eventApi';
|
|
|
|
type EventDataStatus = 'loading' | 'ready' | 'error';
|
|
|
|
interface UseEventDataResult {
|
|
event: EventData | null;
|
|
status: EventDataStatus;
|
|
loading: boolean;
|
|
error: string | null;
|
|
errorCode: FetchEventErrorCode | null;
|
|
token: string | null;
|
|
}
|
|
|
|
const NO_TOKEN_ERROR_MESSAGE = 'Es wurde kein Einladungscode übergeben.';
|
|
const eventCache = new Map<string, EventData>();
|
|
|
|
export function useEventData(): UseEventDataResult {
|
|
const { token } = useParams<{ token: string }>();
|
|
const cachedEvent = token ? eventCache.get(token) ?? null : null;
|
|
const [event, setEvent] = useState<EventData | null>(cachedEvent);
|
|
const [status, setStatus] = useState<EventDataStatus>(token ? (cachedEvent ? 'ready' : 'loading') : 'error');
|
|
const [errorMessage, setErrorMessage] = useState<string | null>(token ? null : NO_TOKEN_ERROR_MESSAGE);
|
|
const [errorCode, setErrorCode] = useState<FetchEventErrorCode | null>(token ? null : 'invalid_token');
|
|
|
|
useEffect(() => {
|
|
if (!token) {
|
|
setEvent(null);
|
|
setStatus('error');
|
|
setErrorCode('invalid_token');
|
|
setErrorMessage(NO_TOKEN_ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
let cancelled = false;
|
|
|
|
const loadEvent = async () => {
|
|
const cached = eventCache.get(token) ?? null;
|
|
if (!cached) {
|
|
setStatus('loading');
|
|
}
|
|
setErrorCode(null);
|
|
setErrorMessage(null);
|
|
|
|
try {
|
|
const eventData = await fetchEvent(token);
|
|
if (cancelled) {
|
|
return;
|
|
}
|
|
|
|
eventCache.set(token, eventData);
|
|
setEvent(eventData);
|
|
setStatus('ready');
|
|
} catch (err) {
|
|
if (cancelled) {
|
|
return;
|
|
}
|
|
|
|
if (cached) {
|
|
setEvent(cached);
|
|
setStatus('ready');
|
|
return;
|
|
}
|
|
setEvent(null);
|
|
setStatus('error');
|
|
|
|
if (err instanceof FetchEventError) {
|
|
setErrorCode(err.code);
|
|
setErrorMessage(err.message);
|
|
} else if (err instanceof Error) {
|
|
setErrorCode('unknown');
|
|
setErrorMessage(err.message || 'Event konnte nicht geladen werden.');
|
|
} else {
|
|
setErrorCode('unknown');
|
|
setErrorMessage('Event konnte nicht geladen werden.');
|
|
}
|
|
}
|
|
};
|
|
|
|
loadEvent();
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [token]);
|
|
|
|
return {
|
|
event,
|
|
status,
|
|
loading: status === 'loading',
|
|
error: errorMessage,
|
|
errorCode,
|
|
token: token ?? null,
|
|
};
|
|
}
|