Files
vf_react/src/hooks/useFollowingEvents.js
2025-12-15 18:28:35 +08:00

109 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/hooks/useFollowingEvents.js
// 关注事件管理自定义 Hook
import { useState, useCallback } from 'react';
import { useToast } from '@chakra-ui/react';
import { logger } from '../utils/logger';
import { getApiBase } from '../utils/apiConfig';
const EVENTS_PAGE_SIZE = 8;
/**
* 关注事件管理 Hook
* 提供事件加载、分页、取消关注等功能
*
* @returns {{
* followingEvents: Array,
* eventsLoading: boolean,
* eventsPage: number,
* setEventsPage: Function,
* EVENTS_PAGE_SIZE: number,
* loadFollowingEvents: Function,
* handleUnfollowEvent: Function
* }}
*/
export const useFollowingEvents = () => {
const toast = useToast();
const [followingEvents, setFollowingEvents] = useState([]);
const [eventsLoading, setEventsLoading] = useState(false);
const [eventsPage, setEventsPage] = useState(1);
// 加载关注的事件
const loadFollowingEvents = useCallback(async () => {
try {
setEventsLoading(true);
const base = getApiBase();
const resp = await fetch(base + '/api/account/events/following', {
credentials: 'include',
cache: 'no-store'
});
if (resp.ok) {
const data = await resp.json();
if (data && data.success && Array.isArray(data.data)) {
// 合并重复的事件(用最新的数据)
const eventMap = new Map();
for (const evt of data.data) {
if (evt && evt.id) {
eventMap.set(evt.id, evt);
}
}
const merged = Array.from(eventMap.values());
// 按创建时间降序排列(假设事件有 created_at 或 id
if (merged.length > 0 && merged[0].created_at) {
merged.sort((a, b) => new Date(b.created_at || 0) - new Date(a.created_at || 0));
} else {
merged.sort((a, b) => (b.id || 0) - (a.id || 0));
}
setFollowingEvents(merged);
} else {
setFollowingEvents([]);
}
} else {
setFollowingEvents([]);
}
} catch (e) {
logger.warn('useFollowingEvents', '加载关注事件失败', {
error: e.message
});
setFollowingEvents([]);
} finally {
setEventsLoading(false);
}
}, []);
// 取消关注事件
const handleUnfollowEvent = useCallback(async (eventId) => {
try {
const base = getApiBase();
const resp = await fetch(base + `/api/events/${eventId}/follow`, {
method: 'POST',
credentials: 'include'
});
const data = await resp.json().catch(() => ({}));
if (resp.ok && data && data.success !== false) {
setFollowingEvents((prev) => {
const updated = (prev || []).filter((x) => x.id !== eventId);
const newMaxPage = Math.max(1, Math.ceil((updated.length || 0) / EVENTS_PAGE_SIZE));
setEventsPage((p) => Math.min(p, newMaxPage));
return updated;
});
toast({ title: '已取消关注该事件', status: 'info', duration: 1500 });
} else {
toast({ title: '操作失败', status: 'error', duration: 2000 });
}
} catch (e) {
toast({ title: '网络错误,操作失败', status: 'error', duration: 2000 });
}
}, [toast]);
return {
followingEvents,
eventsLoading,
eventsPage,
setEventsPage,
EVENTS_PAGE_SIZE,
loadFollowingEvents,
handleUnfollowEvent
};
};