Replace all mock/placeholder data with real data systems
All checks were successful
Build And Push Image / docker (push) Successful in 2m13s

- Added getUserCount() method to Keycloak admin for real user statistics
- Replaced hardcoded userCount (25) with live Keycloak data in admin stats
- Fixed board meeting API to query real events, removed Jan 15 2025 fallback
- Updated board stats to count real events instead of hardcoded 3
- Created member-tiers service for proper tier determination
- Created dues-calculator service for accurate dues tracking
- Updated auth callback to use member-tiers service
- Updated overdue-count API to use dues-calculator
- Added data quality tracking with confidence levels
- Added proper error handling - returns null/0 instead of fake data
- Included source tracking for all data (live/calculated/fallback)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-31 18:28:38 +02:00
parent 9d93f0ca84
commit 1aef356d78
8 changed files with 954 additions and 121 deletions

View File

@@ -5,14 +5,12 @@ export default defineEventHandler(async (event) => {
// Try to get next meeting from events
const eventsClient = createNocoDBEventsClient();
const now = new Date();
const thirtyDaysFromNow = new Date();
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
let nextMeeting = null;
try {
const eventsResponse = await eventsClient.findAll({
limit: 50
limit: 100 // Increased limit to ensure we get all upcoming events
});
// Handle different possible response structures
@@ -24,8 +22,11 @@ export default defineEventHandler(async (event) => {
.filter((event: any) => {
if (!event.start_datetime) return false;
const eventDate = new Date(event.start_datetime);
// Check if event is in the future and is a meeting
return eventDate >= now &&
(event.event_type === 'meeting' || event.title?.toLowerCase().includes('meeting'));
(event.event_type === 'meeting' ||
event.title?.toLowerCase().includes('meeting') ||
event.title?.toLowerCase().includes('board'));
})
.sort((a: any, b: any) => new Date(a.start_datetime).getTime() - new Date(b.start_datetime).getTime());
@@ -46,8 +47,12 @@ export default defineEventHandler(async (event) => {
minute: '2-digit',
timeZoneName: 'short'
}),
location: meeting.location,
description: meeting.description
location: meeting.location || 'To be announced',
description: meeting.description || '',
// Add additional fields for better UI
isoDate: meeting.start_datetime,
endTime: meeting.end_datetime || null,
eventType: meeting.event_type || 'meeting'
};
}
}
@@ -55,37 +60,34 @@ export default defineEventHandler(async (event) => {
console.error('[next-meeting] Error fetching events:', error);
}
// Fallback if no meetings found
if (!nextMeeting) {
nextMeeting = {
id: null,
title: 'Board Meeting',
date: 'January 15, 2025',
time: '7:00 PM EST',
location: 'TBD',
description: 'Monthly board meeting'
// Return appropriate response based on whether we found a meeting
if (nextMeeting) {
console.log('[next-meeting] Found upcoming meeting:', nextMeeting.title);
return {
success: true,
data: nextMeeting,
source: 'live'
};
} else {
// No meetings found - return null instead of fake data
console.log('[next-meeting] No upcoming meetings found');
return {
success: true,
data: null,
message: 'No upcoming meetings scheduled',
source: 'live'
};
}
return {
success: true,
data: nextMeeting
};
} catch (error: any) {
console.error('[next-meeting] Error:', error);
// Return fallback data
// Return error response instead of fallback data
return {
success: true,
data: {
id: null,
title: 'Board Meeting',
date: 'January 15, 2025',
time: '7:00 PM EST',
location: 'TBD',
description: 'Monthly board meeting'
}
success: false,
data: null,
error: 'Unable to fetch meeting information',
message: 'Please check back later or contact administrator'
};
}
});

View File

@@ -13,7 +13,8 @@ export default defineEventHandler(async (event) => {
totalMembers: 0,
activeMembers: 0,
upcomingMeetings: 0,
pendingActions: 0
pendingActions: 0,
dataSource: 'unavailable'
}
};
}
@@ -23,10 +24,10 @@ export default defineEventHandler(async (event) => {
member.membership_status === 'Active'
).length;
// Get upcoming meetings count - simplified approach since events API might still have issues
let upcomingMeetings = 3; // Default fallback
// Get real upcoming meetings count from events
let upcomingMeetings = 0;
let eventsSource = 'unavailable';
// Try to get real events data but don't fail if it's not working
try {
const eventsClient = createNocoDBEventsClient();
const now = new Date();
@@ -34,32 +35,43 @@ export default defineEventHandler(async (event) => {
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
const eventsResponse = await eventsClient.findAll({
limit: 100
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.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, using fallback:', error);
// Keep the fallback value of 3
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 {
@@ -68,7 +80,13 @@ export default defineEventHandler(async (event) => {
totalMembers,
activeMembers,
upcomingMeetings,
pendingActions
pendingActions,
// Add metadata about data sources
dataSources: {
members: 'live',
events: eventsSource,
dues: duesSource
}
}
};