Implement dues reminder system with monthly payment cycle
Some checks failed
Build And Push Image / docker (push) Failing after 1m10s
Some checks failed
Build And Push Image / docker (push) Failing after 1m10s
- Add API endpoint and email templates for dues reminders - Change due date calculation from yearly to monthly billing - Add visual status indicators for overdue and due-soon members - Enhance member cards with status stripes and styling
This commit is contained in:
@@ -254,10 +254,10 @@ watch(duesPaid, (newValue) => {
|
||||
} else {
|
||||
form.value['Membership Date Paid'] = '';
|
||||
if (!form.value['Payment Due Date']) {
|
||||
// Set due date to one year from member since date or today
|
||||
// Set due date to one month from member since date or today
|
||||
const memberSince = form.value['Member Since'] || new Date().toISOString().split('T')[0];
|
||||
const dueDate = new Date(memberSince);
|
||||
dueDate.setFullYear(dueDate.getFullYear() + 1);
|
||||
dueDate.setMonth(dueDate.getMonth() + 1);
|
||||
form.value['Payment Due Date'] = dueDate.toISOString().split('T')[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,10 +415,10 @@ watch(duesPaid, (newValue) => {
|
||||
} else {
|
||||
form.value.membership_date_paid = '';
|
||||
if (!form.value.payment_due_date) {
|
||||
// Set due date to one year from member since date or today
|
||||
// Set due date to one month from member since date or today
|
||||
const memberSince = form.value.member_since || new Date().toISOString().split('T')[0];
|
||||
const dueDate = new Date(memberSince);
|
||||
dueDate.setFullYear(dueDate.getFullYear() + 1);
|
||||
dueDate.setMonth(dueDate.getMonth() + 1);
|
||||
form.value.payment_due_date = dueDate.toISOString().split('T')[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
<template>
|
||||
<v-card
|
||||
class="member-card"
|
||||
:class="{ 'member-card--inactive': !isActive }"
|
||||
:class="{
|
||||
'member-card--inactive': !isActive,
|
||||
'member-card--overdue': isOverdue,
|
||||
'member-card--due-soon': isDuesComingDue
|
||||
}"
|
||||
elevation="2"
|
||||
@click="$emit('view', member)"
|
||||
>
|
||||
<!-- Status Stripe -->
|
||||
<div
|
||||
v-if="isOverdue || isDuesComingDue"
|
||||
class="status-stripe"
|
||||
:class="{
|
||||
'status-stripe--overdue': isOverdue,
|
||||
'status-stripe--due-soon': isDuesComingDue
|
||||
}"
|
||||
/>
|
||||
<!-- Member Status Badge -->
|
||||
<div class="member-status-badge">
|
||||
<v-chip
|
||||
@@ -547,4 +560,33 @@ const formatDate = (dateString: string): string => {
|
||||
.text-error {
|
||||
color: rgb(var(--v-theme-error)) !important;
|
||||
}
|
||||
|
||||
/* Status Stripe Styles */
|
||||
.status-stripe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.status-stripe--overdue {
|
||||
background: linear-gradient(180deg, #f44336 0%, #d32f2f 100%);
|
||||
box-shadow: 2px 0 8px rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
.status-stripe--due-soon {
|
||||
background: linear-gradient(180deg, #ff9800 0%, #f57c00 100%);
|
||||
box-shadow: 2px 0 8px rgba(255, 152, 0, 0.3);
|
||||
}
|
||||
|
||||
.member-card--overdue {
|
||||
border-left: 4px solid #f44336;
|
||||
}
|
||||
|
||||
.member-card--due-soon {
|
||||
border-left: 4px solid #ff9800;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user