Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 1x 1x 1x 1x 1x 1x 12x 12x 12x 12x 12x 12x 6x 6x 6x 6x 6x 6x 5x 1x 1x 1x 6x 6x 12x 5x 12x 1x 12x 12x 1x 1x 1x 2x 12x | import { useCallback, useEffect, useState } from 'react';
import { useAuth } from '@/contexts/AuthContext';
import { FavoriteEventItem } from '@/models/favorite';
import { ApiError } from '@/services/api';
import {
listFavoriteEvents,
removeFavorite,
} from '@/services/favoriteService';
export interface FavoriteEventsViewModel {
events: FavoriteEventItem[];
isLoading: boolean;
isRefreshing: boolean;
isLoadingMore: boolean;
hasMore: boolean;
apiError: string | null;
handleRemoveFavorite: (eventId: string) => Promise<void>;
refresh: () => Promise<void>;
loadMore: () => Promise<void>;
}
function getLoadErrorMessage(error: unknown): string {
Iif (error instanceof ApiError && error.status === 401) {
return 'You must be logged in to view favorites.';
}
Eif (error instanceof ApiError) {
return error.message;
}
return 'Failed to load favorite events. Please try again.';
}
function getRemoveErrorMessage(error: unknown): string {
if (error instanceof ApiError && error.status === 401) {
return 'You must be logged in to manage favorites.';
}
if (error instanceof ApiError) {
return error.message;
}
return 'Failed to remove favorite. Please try again.';
}
export function useFavoriteEventsViewModel(): FavoriteEventsViewModel {
const { token } = useAuth();
const [events, setEvents] = useState<FavoriteEventItem[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isRefreshing, setIsRefreshing] = useState(false);
const [apiError, setApiError] = useState<string | null>(null);
const fetchEvents = useCallback(
async (mode: 'initial' | 'refresh') => {
Iif (!token) {
setEvents([]);
setApiError('You must be logged in to view favorites.');
setIsLoading(false);
setIsRefreshing(false);
return;
}
if (mode === 'initial') setIsLoading(true);
if (mode === 'refresh') setIsRefreshing(true);
setApiError(null);
try {
const response = await listFavoriteEvents(token);
setEvents(response.items);
} catch (error) {
Eif (mode === 'initial') {
setEvents([]);
}
setApiError(getLoadErrorMessage(error));
} finally {
if (mode === 'initial') setIsLoading(false);
if (mode === 'refresh') setIsRefreshing(false);
}
},
[token],
);
useEffect(() => {
void fetchEvents('initial');
}, [fetchEvents]);
const refresh = useCallback(async () => {
await fetchEvents('refresh');
}, [fetchEvents]);
const loadMore = useCallback(async () => {
// The favorites endpoint currently returns the full list without cursor pagination.
}, []);
const handleRemoveFavorite = useCallback(
async (eventId: string) => {
Iif (!token) return;
try {
await removeFavorite(eventId, token);
setEvents((prev) => prev.filter((event) => event.id !== eventId));
} catch (error) {
setApiError(getRemoveErrorMessage(error));
}
},
[token],
);
return {
events,
isLoading,
isRefreshing,
isLoadingMore: false,
hasMore: false,
apiError,
handleRemoveFavorite,
refresh,
loadMore,
};
}
|