From 12469a7952ad14a08169f37bf29771f7368905dd Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 5 Sep 2025 16:26:59 +0200 Subject: [PATCH] Fix member management issues and add refined view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sort dues management cards alphabetically by last name - Change 'Invalid Date' display to 'N/A' in formatDate functions - Add new refined member management view with modern UI design - Glassmorphism effects and gradient accents - Enhanced stat cards with progress indicators - Improved search and filter interface - Better card and table layouts - Smooth animations and transitions 🤖 Generated with Claude Code Co-Authored-By: Claude --- components/BoardDuesManagement.vue | 17 +- components/ViewMemberDialog.vue | 6 +- pages/admin/members-refined.vue | 996 +++++++++++++++++++++++++++++ pages/admin/members/index.vue | 5 +- 4 files changed, 1019 insertions(+), 5 deletions(-) create mode 100644 pages/admin/members-refined.vue diff --git a/components/BoardDuesManagement.vue b/components/BoardDuesManagement.vue index cfaee36..7fa0d09 100644 --- a/components/BoardDuesManagement.vue +++ b/components/BoardDuesManagement.vue @@ -150,8 +150,21 @@ const loadDuesData = async () => { }>('/api/members/dues-status'); if (response.success) { - overdueMembers.value = response.data.overdue || []; - upcomingMembers.value = response.data.upcoming || []; + // Sort members alphabetically by last name, then first name + const sortByName = (a: Member, b: Member) => { + const aLastName = (a.last_name || '').toLowerCase(); + const bLastName = (b.last_name || '').toLowerCase(); + const aFirstName = (a.first_name || '').toLowerCase(); + const bFirstName = (b.first_name || '').toLowerCase(); + + const lastNameCompare = aLastName.localeCompare(bLastName); + if (lastNameCompare !== 0) return lastNameCompare; + + return aFirstName.localeCompare(bFirstName); + }; + + overdueMembers.value = (response.data.overdue || []).sort(sortByName); + upcomingMembers.value = (response.data.upcoming || []).sort(sortByName); } } catch (error) { console.error('Error loading dues data:', error); diff --git a/components/ViewMemberDialog.vue b/components/ViewMemberDialog.vue index 839dd99..fff7d9e 100644 --- a/components/ViewMemberDialog.vue +++ b/components/ViewMemberDialog.vue @@ -570,8 +570,10 @@ const getMembershipColor = (type: string) => { }; const formatDate = (date: string) => { - if (!date) return null; - return new Date(date).toLocaleDateString('en-US', { + if (!date) return 'N/A'; + const parsedDate = new Date(date); + if (isNaN(parsedDate.getTime())) return 'N/A'; + return parsedDate.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' diff --git a/pages/admin/members-refined.vue b/pages/admin/members-refined.vue new file mode 100644 index 0000000..a4f230e --- /dev/null +++ b/pages/admin/members-refined.vue @@ -0,0 +1,996 @@ + + + + + \ No newline at end of file diff --git a/pages/admin/members/index.vue b/pages/admin/members/index.vue index ae78e4d..ed3d54c 100644 --- a/pages/admin/members/index.vue +++ b/pages/admin/members/index.vue @@ -607,7 +607,10 @@ const getDuesColor = (status: string) => { }; const formatDate = (date: string) => { - return new Date(date).toLocaleDateString('en-US', { + if (!date) return 'N/A'; + const parsedDate = new Date(date); + if (isNaN(parsedDate.getTime())) return 'N/A'; + return parsedDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric'