diff --git a/components/MemberCard.vue b/components/MemberCard.vue
index 1ec249f..1c10e15 100644
--- a/components/MemberCard.vue
+++ b/components/MemberCard.vue
@@ -74,7 +74,7 @@
- {{ member.FullName || `${member.first_name} ${member.last_name}` }}
+ {{ displayName }}
@@ -223,6 +223,13 @@ const memberInitials = computed(() => {
return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();
});
+const displayName = computed(() => {
+ // Try FullName first, then build from first_name + last_name, then fallback
+ return props.member.FullName ||
+ `${props.member.first_name || ''} ${props.member.last_name || ''}`.trim() ||
+ 'New Member';
+});
+
const avatarColor = computed(() => {
// Generate consistent color based on member ID using high-contrast colors
const colors = ['red', 'blue', 'green', 'orange', 'purple', 'teal', 'indigo', 'pink', 'brown'];
diff --git a/server/api/members/index.post.ts b/server/api/members/index.post.ts
index 83bd68d..20eaaac 100644
--- a/server/api/members/index.post.ts
+++ b/server/api/members/index.post.ts
@@ -63,23 +63,24 @@ export default defineEventHandler(async (event) => {
console.log('[api/members.post] DIAGNOSTIC - Raw created member:', JSON.stringify(rawNewMember, null, 2));
console.log('[api/members.post] DIAGNOSTIC - Raw member fields:', Object.keys(rawNewMember));
- // Apply field normalization (same as in get members API)
+ // Apply EXACT SAME processing pipeline as GET API
+ // 1. Apply field normalization (same as in get members API)
const normalizedMember = normalizeFieldsFromNocoDB(rawNewMember);
console.log('[api/members.post] Applied field normalization');
- console.log('[api/members.post] DIAGNOSTIC - Normalized first_name:', normalizedMember.first_name);
- console.log('[api/members.post] DIAGNOSTIC - Normalized last_name:', normalizedMember.last_name);
+ console.log('[api/members.post] DIAGNOSTIC - Normalized first_name:', `"${normalizedMember.first_name}"`);
+ console.log('[api/members.post] DIAGNOSTIC - Normalized last_name:', `"${normalizedMember.last_name}"`);
- // Add computed fields (same as in get members API)
- const fullName = `${normalizedMember.first_name || ''} ${normalizedMember.last_name || ''}`.trim();
+ // 2. Add computed fields (EXACT SAME as GET API)
const processedMember = {
...normalizedMember,
- FullName: fullName,
+ FullName: `${normalizedMember.first_name || ''} ${normalizedMember.last_name || ''}`.trim(),
FormattedPhone: formatPhoneNumber(normalizedMember.phone)
};
console.log('[api/members.post] DIAGNOSTIC - Final FullName:', `"${processedMember.FullName}"`);
console.log('[api/members.post] DIAGNOSTIC - FullName calculation:',
- `"${normalizedMember.first_name || ''}" + " " + "${normalizedMember.last_name || ''}" = "${fullName}"`);
+ `"${normalizedMember.first_name || ''}" + " " + "${normalizedMember.last_name || ''}" = "${processedMember.FullName}"`);
+ console.log('[api/members.post] DIAGNOSTIC - Final processed member keys:', Object.keys(processedMember));
return {
success: true,
diff --git a/server/utils/nocodb.ts b/server/utils/nocodb.ts
index 2114cad..051f36a 100644
--- a/server/utils/nocodb.ts
+++ b/server/utils/nocodb.ts
@@ -102,59 +102,33 @@ export const formatNationalitiesAsString = (nationalities: string[]): string =>
export const normalizeFieldsFromNocoDB = (data: any): Member => {
console.log('[normalizeFieldsFromNocoDB] Input data keys:', Object.keys(data));
+ // Since NocoDB schema uses snake_case directly, no complex mapping needed
const normalized: any = { ...data };
- // Field mapping for display names to snake_case (READ operations)
- const readFieldMap: Record = {
- 'First Name': 'first_name',
- 'Last Name': 'last_name',
- 'Email': 'email',
- 'Email Address': 'email',
- 'Phone': 'phone',
- 'Phone Number': 'phone',
- 'Date of Birth': 'date_of_birth',
- 'Nationality': 'nationality',
- 'Address': 'address',
- 'Membership Status': 'membership_status',
- 'Member Since': 'member_since',
- 'Member ID': 'member_id', // Added field mapping for member_id
- 'Current Year Dues Paid': 'current_year_dues_paid',
- 'Membership Date Paid': 'membership_date_paid',
- 'Payment Due Date': 'payment_due_date',
- 'Keycloak ID': 'keycloak_id',
- 'keycloak_id': 'keycloak_id',
- // Also handle reverse mapping in case data comes in snake_case already
- 'first_name': 'first_name',
- 'last_name': 'last_name',
- 'email': 'email',
- 'phone': 'phone',
- 'date_of_birth': 'date_of_birth',
- 'nationality': 'nationality',
- 'address': 'address',
- 'membership_status': 'membership_status',
- 'member_since': 'member_since',
- 'member_id': 'member_id',
- 'current_year_dues_paid': 'current_year_dues_paid',
- 'membership_date_paid': 'membership_date_paid',
- 'payment_due_date': 'payment_due_date'
- };
+ // Ensure all expected fields exist with proper fallbacks
+ const requiredFields = [
+ 'first_name', 'last_name', 'email', 'phone', 'nationality',
+ 'address', 'date_of_birth', 'membership_status', 'member_since',
+ 'member_id', 'current_year_dues_paid', 'membership_date_paid',
+ 'payment_due_date', 'keycloak_id'
+ ];
- // Apply field mapping
- for (const [sourceKey, targetKey] of Object.entries(readFieldMap)) {
- if (sourceKey in data && data[sourceKey] !== undefined && data[sourceKey] !== null) {
- normalized[targetKey] = data[sourceKey];
- console.log(`[normalizeFieldsFromNocoDB] Mapped "${sourceKey}" -> "${targetKey}":`, data[sourceKey]);
+ // Initialize missing fields as empty strings (except booleans)
+ requiredFields.forEach(field => {
+ if (!(field in normalized) || normalized[field] === null || normalized[field] === undefined) {
+ if (field === 'current_year_dues_paid') {
+ normalized[field] = 'false'; // Boolean field default
+ } else if (field === 'membership_status') {
+ normalized[field] = 'Pending'; // Enum field default
+ } else {
+ normalized[field] = ''; // String field default
+ }
}
- }
-
- // Ensure required fields exist with fallbacks
- normalized.first_name = normalized.first_name || normalized['First Name'] || '';
- normalized.last_name = normalized.last_name || normalized['Last Name'] || '';
- normalized.email = normalized.email || normalized['Email'] || normalized['Email Address'] || '';
+ });
console.log('[normalizeFieldsFromNocoDB] Normalized member fields:', Object.keys(normalized));
- console.log('[normalizeFieldsFromNocoDB] Final first_name:', normalized.first_name);
- console.log('[normalizeFieldsFromNocoDB] Final last_name:', normalized.last_name);
+ console.log('[normalizeFieldsFromNocoDB] Final first_name:', `"${normalized.first_name}"`);
+ console.log('[normalizeFieldsFromNocoDB] Final last_name:', `"${normalized.last_name}"`);
return normalized as Member;
};