diff --git a/components/BoardDuesManagement.vue b/components/BoardDuesManagement.vue index 25eb6d0..89e5555 100644 --- a/components/BoardDuesManagement.vue +++ b/components/BoardDuesManagement.vue @@ -42,7 +42,7 @@ :member="member" status="overdue" @mark-paid="handleMarkPaid" - @view-member="$emit('view-member', member)" + @view-member="handleViewMember" :loading="loading[member.Id]" /> @@ -69,7 +69,7 @@ :member="member" status="upcoming" @mark-paid="handleMarkPaid" - @view-member="$emit('view-member', member)" + @view-member="handleViewMember" :loading="loading[member.Id]" /> @@ -99,6 +99,13 @@ View All Members + + + @@ -125,6 +132,10 @@ const upcomingMembers = ref([]); const loading = ref>({}); const refreshLoading = ref(false); +// View member dialog state +const showViewDialog = ref(false); +const selectedMember = ref(null); + // Load dues data const loadDuesData = async () => { refreshLoading.value = true; @@ -184,6 +195,20 @@ const handleMarkPaid = async (member: Member) => { } }; +// Handle view member +const handleViewMember = (member: Member) => { + selectedMember.value = member; + showViewDialog.value = true; +}; + +// Handle edit member (from the view dialog) +const handleEditMember = (member: Member) => { + // Close the view dialog first + showViewDialog.value = false; + // Emit the view-member event which should trigger the edit dialog in the parent component + emit('view-member', member); +}; + // Refresh data const refreshData = () => { loadDuesData(); diff --git a/components/DuesActionCard.vue b/components/DuesActionCard.vue index 066100f..9e2ddf9 100644 --- a/components/DuesActionCard.vue +++ b/components/DuesActionCard.vue @@ -125,7 +125,7 @@ variant="elevated" size="small" :loading="loading" - @click="$emit('mark-paid', member)" + @click="showPaymentDateDialog = true" block > mdi-check-circle @@ -133,6 +133,71 @@ + + + + + mdi-calendar-check + Mark Dues as Paid + + + + + + {{ member.FullName || `${member.first_name} ${member.last_name}` }} + + + Select the date when the dues payment was received: + + + + + + + mdi-information + Future dates are not allowed. Please select today or an earlier date. + + + + + + + Cancel + + + mdi-check-circle + Confirm Payment + + + + + (), { loading: false }); -defineEmits(); +const emit = defineEmits(); + +// Reactive state for payment date dialog +const showPaymentDateDialog = ref(false); +const selectedPaymentDate = ref(''); + +// Initialize with today's date when dialog opens +watch(showPaymentDateDialog, (isOpen) => { + if (isOpen) { + selectedPaymentDate.value = todayDate.value; + } +}); // Computed properties const memberInitials = computed(() => { @@ -195,6 +271,21 @@ const memberInitials = computed(() => { return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase(); }); +const todayDate = computed(() => { + return new Date().toISOString().split('T')[0]; // YYYY-MM-DD format +}); + +const isDateInFuture = computed(() => { + if (!selectedPaymentDate.value) return false; + + const selectedDate = new Date(selectedPaymentDate.value); + const today = new Date(); + today.setHours(0, 0, 0, 0); // Reset time to start of day + selectedDate.setHours(0, 0, 0, 0); // Reset time to start of day + + return selectedDate > today; +}); + const avatarColor = computed(() => { const colors = ['red', 'blue', 'green', 'orange', 'purple', 'teal', 'indigo', 'pink']; const idNumber = parseInt(props.member.Id) || 0; @@ -239,6 +330,41 @@ const formatDate = (dateString: string): string => { return dateString; } }; + +const cancelPaymentDialog = () => { + showPaymentDateDialog.value = false; + selectedPaymentDate.value = ''; +}; + +const confirmMarkAsPaid = async () => { + if (!selectedPaymentDate.value || isDateInFuture.value) return; + + try { + // Call the API with the selected payment date + const response = await $fetch<{ + success: boolean; + data: Member; + message?: string; + }>(`/api/members/${props.member.Id}/mark-dues-paid`, { + method: 'post', + body: { + paymentDate: selectedPaymentDate.value + } + }); + + if (response?.success && response.data) { + // Emit the mark-paid event with the updated member data + emit('mark-paid', response.data); + + // Close the dialog and reset + showPaymentDateDialog.value = false; + selectedPaymentDate.value = ''; + } + } catch (error: any) { + console.error('Error marking dues as paid:', error); + // You could show an error message here if needed + } +};
+ Select the date when the dues payment was received: +