102 lines
3.2 KiB
TypeScript
102 lines
3.2 KiB
TypeScript
import { createNocoDBEventsClient } from '~/server/utils/nocodb-events';
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
try {
|
|
// Get member statistics using the same pattern as other APIs
|
|
const { getMembers } = await import('~/server/utils/nocodb');
|
|
const allMembers = await getMembers();
|
|
|
|
if (!allMembers?.list) {
|
|
return {
|
|
success: true,
|
|
data: {
|
|
totalMembers: 0,
|
|
activeMembers: 0,
|
|
upcomingMeetings: 0,
|
|
pendingActions: 0,
|
|
dataSource: 'unavailable'
|
|
}
|
|
};
|
|
}
|
|
|
|
const totalMembers = allMembers.list.length;
|
|
const activeMembers = allMembers.list.filter((member: any) =>
|
|
member.membership_status === 'Active'
|
|
).length;
|
|
|
|
// Get real upcoming meetings count from events
|
|
let upcomingMeetings = 0;
|
|
let eventsSource = 'unavailable';
|
|
|
|
try {
|
|
const eventsClient = createNocoDBEventsClient();
|
|
const now = new Date();
|
|
const thirtyDaysFromNow = new Date();
|
|
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
|
|
|
|
const eventsResponse = await eventsClient.findAll({
|
|
limit: 200 // Increased limit to get all events
|
|
});
|
|
|
|
// Handle different possible response structures
|
|
const eventsList = (eventsResponse as any)?.list || [];
|
|
if (eventsList && Array.isArray(eventsList)) {
|
|
// Count meetings in the next 30 days
|
|
upcomingMeetings = eventsList.filter((event: any) => {
|
|
if (!event.start_datetime) return false;
|
|
const eventDate = new Date(event.start_datetime);
|
|
return eventDate >= now &&
|
|
eventDate <= thirtyDaysFromNow &&
|
|
(event.event_type === 'meeting' ||
|
|
event.title?.toLowerCase().includes('meeting') ||
|
|
event.title?.toLowerCase().includes('board'));
|
|
}).length;
|
|
eventsSource = 'live';
|
|
console.log(`[board-stats] Found ${upcomingMeetings} upcoming meetings from live data`);
|
|
}
|
|
} catch (error) {
|
|
console.error('[board-stats] Error fetching events:', error);
|
|
// Keep upcomingMeetings as 0 instead of using fallback
|
|
upcomingMeetings = 0;
|
|
eventsSource = 'error';
|
|
}
|
|
|
|
// Get overdue dues count for pending actions
|
|
let pendingActions = 0;
|
|
let duesSource = 'unavailable';
|
|
try {
|
|
const overdueResponse: any = await $fetch('/api/members/overdue-count');
|
|
pendingActions = overdueResponse?.data?.count || 0;
|
|
duesSource = 'live';
|
|
} catch (error) {
|
|
console.error('[board-stats] Error fetching overdue count:', error);
|
|
pendingActions = 0;
|
|
duesSource = 'error';
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
totalMembers,
|
|
activeMembers,
|
|
upcomingMeetings,
|
|
pendingActions,
|
|
// Add metadata about data sources
|
|
dataSources: {
|
|
members: 'live',
|
|
events: eventsSource,
|
|
dues: duesSource
|
|
}
|
|
}
|
|
};
|
|
|
|
} catch (error: any) {
|
|
console.error('[board-stats] Error:', error);
|
|
|
|
throw createError({
|
|
statusCode: error.statusCode || 500,
|
|
statusMessage: error.message || 'Failed to fetch board statistics'
|
|
});
|
|
}
|
|
});
|