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 @@ + + + + + + + + + mdi-account-group + + + Member Directory + + mdi-account-multiple + {{ stats.total }} total members • {{ stats.active }} active + + + + + + + Add New Member + + + + + + + + + + + + + {{ stat.icon }} + + + + {{ stat.changeType === 'increase' ? 'mdi-trending-up' : 'mdi-trending-down' }} + + {{ stat.change }} + + + {{ stat.value }} + {{ stat.title }} + + + + + + + + + + + + + + + + + + + + + + + mdi-all-inclusive + All Members + + + mdi-check-circle + Active + + + mdi-clock-alert + Dues Pending + + + mdi-new-box + New This Month + + + + + mdi-filter-variant + Advanced Filters + + + + mdi-download + Export + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Showing {{ filteredMembers.length }} of {{ members.length }} members + + + + Cards + + + Table + + + + + + + + + + + + + {{ member.first_name }} {{ member.last_name }} + + + {{ member.member_id || 'Pending ID' }} + + + + + + + mdi-email + {{ member.email }} + + + + + mdi-flag + + + + + + mdi-calendar + Since {{ formatDate(member.join_date) }} + + + + + + + {{ member.status === 'active' ? 'mdi-check' : 'mdi-close' }} + + {{ member.status }} + + + + mdi-cash + {{ member.dues_paid_this_year ? 'Dues Paid' : 'Dues Pending' }} + + + + {{ member.membership_type }} + + + + + + + + mdi-check + Mark Dues Paid + + + + + View + + + + + Edit + + + + + Email + + + + + + + + + + + viewMember(item)" + > + + + + + + {{ item.first_name }} {{ item.last_name }} + + + {{ item.member_id || 'Pending ID' }} + + + + + + + + + mdi-email + + {{ item.email }} + + + + mdi-phone + {{ item.phone }} + + + + + + + + + + + + {{ item.membership_type }} + + + Since {{ formatDate(item.join_date) }} + + + + + + + + {{ item.status }} + + + {{ item.dues_paid_this_year ? 'Paid' : 'Due' }} + + + + + + + + + + + + + + + + mdi-email + + Send Email + + + + mdi-check + + Mark Dues Paid + + + + mdi-history + + Payment History + + + + + + {{ item.status === 'active' ? 'mdi-account-off' : 'mdi-account-check' }} + + + + {{ item.status === 'active' ? 'Deactivate' : 'Activate' }} + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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'
+ mdi-account-multiple + {{ stats.total }} total members • {{ stats.active }} active +