136 lines
5.2 KiB
TypeScript
136 lines
5.2 KiB
TypeScript
import { getMembers, handleNocoDbError, normalizeFieldsFromNocoDB } from '~/server/utils/nocodb';
|
|
import type { Member } from '~/utils/types';
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
console.log('[api/members.get] =========================');
|
|
console.log('[api/members.get] GET /api/members - List all members');
|
|
console.log('[api/members.get] Request from:', getClientIP(event));
|
|
|
|
try {
|
|
// Get query parameters
|
|
const query = getQuery(event);
|
|
const limit = parseInt(query.limit as string) || 1000;
|
|
const searchTerm = query.search as string;
|
|
const nationality = query.nationality as string;
|
|
const membershipStatus = query.status as string;
|
|
const duesPaid = query.duesPaid as string;
|
|
|
|
console.log('[api/members.get] Query parameters:', {
|
|
limit,
|
|
searchTerm,
|
|
nationality,
|
|
membershipStatus,
|
|
duesPaid
|
|
});
|
|
|
|
// Fetch members from NocoDB
|
|
const result = await getMembers();
|
|
|
|
let members = result.list || [];
|
|
console.log('[api/members.get] Fetched members count:', members.length);
|
|
|
|
// DIAGNOSTIC: Log processing pipeline
|
|
if (members.length > 0) {
|
|
const sampleMember = members[0];
|
|
console.log('[api/members.get] DIAGNOSTIC - Raw member from getMembers:', JSON.stringify(sampleMember, null, 2));
|
|
console.log('[api/members.get] DIAGNOSTIC - Member field check:');
|
|
console.log(' - sampleMember.first_name:', sampleMember.first_name);
|
|
console.log(' - sampleMember.last_name:', sampleMember.last_name);
|
|
console.log(' - sampleMember["First Name"]:', (sampleMember as any)['First Name']);
|
|
console.log(' - sampleMember["Last Name"]:', (sampleMember as any)['Last Name']);
|
|
console.log(' - typeof sampleMember.first_name:', typeof sampleMember.first_name);
|
|
console.log(' - typeof sampleMember.last_name:', typeof sampleMember.last_name);
|
|
}
|
|
|
|
// Apply field normalization to handle schema mismatches
|
|
members = members.map(member => {
|
|
const normalized = normalizeFieldsFromNocoDB(member);
|
|
return normalized;
|
|
});
|
|
|
|
console.log('[api/members.get] Applied field normalization to', members.length, 'members');
|
|
|
|
// Apply client-side filtering since NocoDB filtering can be complex
|
|
if (searchTerm) {
|
|
const search = searchTerm.toLowerCase();
|
|
members = members.filter(member =>
|
|
member.first_name?.toLowerCase().includes(search) ||
|
|
member.last_name?.toLowerCase().includes(search) ||
|
|
member.email?.toLowerCase().includes(search)
|
|
);
|
|
console.log('[api/members.get] After search filter:', members.length);
|
|
}
|
|
|
|
if (nationality) {
|
|
members = members.filter(member => member.nationality === nationality);
|
|
console.log('[api/members.get] After nationality filter:', members.length);
|
|
}
|
|
|
|
if (membershipStatus) {
|
|
members = members.filter(member => member.membership_status === membershipStatus);
|
|
console.log('[api/members.get] After status filter:', members.length);
|
|
}
|
|
|
|
if (duesPaid === 'true' || duesPaid === 'false') {
|
|
members = members.filter(member => member.current_year_dues_paid === duesPaid);
|
|
console.log('[api/members.get] After dues filter:', members.length);
|
|
}
|
|
|
|
// Add computed fields
|
|
const processedMembers = members.map(member => {
|
|
const fullName = `${member.first_name || ''} ${member.last_name || ''}`.trim();
|
|
return {
|
|
...member,
|
|
FullName: fullName,
|
|
FormattedPhone: formatPhoneNumber(member.phone)
|
|
};
|
|
});
|
|
|
|
// DIAGNOSTIC: Log processed member data
|
|
if (processedMembers.length > 0) {
|
|
const sampleProcessed = processedMembers[0];
|
|
console.log('[api/members.get] DIAGNOSTIC - Processed member FullName:', `"${sampleProcessed.FullName}"`);
|
|
console.log('[api/members.get] DIAGNOSTIC - FullName calculation result:',
|
|
`"${sampleProcessed.first_name || ''}" + " " + "${sampleProcessed.last_name || ''}" = "${sampleProcessed.FullName}"`);
|
|
console.log('[api/members.get] DIAGNOSTIC - Processed member keys:', Object.keys(sampleProcessed));
|
|
}
|
|
|
|
console.log('[api/members.get] ✅ Successfully processed', processedMembers.length, 'members');
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
list: processedMembers,
|
|
totalCount: processedMembers.length,
|
|
filters: {
|
|
searchTerm,
|
|
nationality,
|
|
membershipStatus,
|
|
duesPaid: duesPaid ? duesPaid === 'true' : undefined
|
|
}
|
|
}
|
|
};
|
|
|
|
} catch (error: any) {
|
|
console.error('[api/members.get] ❌ Error fetching members:', error);
|
|
handleNocoDbError(error, 'getMembers', 'Members');
|
|
}
|
|
});
|
|
|
|
// Utility function to format phone numbers
|
|
function formatPhoneNumber(phone: string): string {
|
|
if (!phone) return '';
|
|
|
|
// Remove all non-digits
|
|
const cleaned = phone.replace(/\D/g, '');
|
|
|
|
// Format based on length
|
|
if (cleaned.length === 10) {
|
|
return `(${cleaned.substring(0, 3)}) ${cleaned.substring(3, 6)}-${cleaned.substring(6)}`;
|
|
} else if (cleaned.length === 11 && cleaned.startsWith('1')) {
|
|
return `+1 (${cleaned.substring(1, 4)}) ${cleaned.substring(4, 7)}-${cleaned.substring(7)}`;
|
|
}
|
|
|
|
return phone; // Return original if we can't format it
|
|
}
|