db updates and fixes
All checks were successful
Build And Push Image / docker (push) Successful in 3m59s
All checks were successful
Build And Push Image / docker (push) Successful in 3m59s
This commit is contained in:
@@ -89,7 +89,7 @@
|
||||
Due Date
|
||||
</span>
|
||||
<span class="text-body-2 font-weight-bold text-warning">
|
||||
{{ formatDate(member.nextDueDate || member.payment_due_date) }}
|
||||
{{ formatDate(member.nextDueDate || member.payment_due_date || '') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -151,17 +151,27 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<v-text-field
|
||||
v-model="selectedPaymentDate"
|
||||
label="Payment Date"
|
||||
type="date"
|
||||
variant="outlined"
|
||||
:max="todayDate"
|
||||
prepend-inner-icon="mdi-calendar"
|
||||
hint="Select the date when the payment was received"
|
||||
persistent-hint
|
||||
class="mb-2"
|
||||
/>
|
||||
<div class="date-picker-wrapper">
|
||||
<label class="date-picker-label">Payment Date</label>
|
||||
<VueDatePicker
|
||||
v-model="selectedPaymentModel"
|
||||
:timezone="{
|
||||
timezone: 'Europe/Monaco',
|
||||
emitTimezone: 'UTC'
|
||||
}"
|
||||
:format="'dd/MM/yyyy (Monaco)'"
|
||||
:max-date="new Date()"
|
||||
placeholder="Select payment date"
|
||||
:enable-time-picker="false"
|
||||
auto-apply
|
||||
:clearable="false"
|
||||
:required="true"
|
||||
@update:model-value="handleDateUpdate"
|
||||
/>
|
||||
<div class="text-caption text-medium-emphasis mt-1">
|
||||
Select the date when the payment was received
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-alert
|
||||
v-if="selectedPaymentDate && isDateInFuture"
|
||||
@@ -229,7 +239,16 @@
|
||||
import type { Member } from '~/utils/types';
|
||||
|
||||
// Extended member type for dues management
|
||||
interface DuesMember extends Member {
|
||||
interface DuesMember {
|
||||
Id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
nationality?: string;
|
||||
member_id?: string;
|
||||
FullName?: string;
|
||||
FormattedPhone?: string;
|
||||
overdueDays?: number;
|
||||
overdueReason?: string;
|
||||
daysUntilDue?: number;
|
||||
@@ -247,7 +266,7 @@ interface Props {
|
||||
|
||||
interface Emits {
|
||||
(e: 'mark-paid', member: Member): void;
|
||||
(e: 'view-member', member: Member): void;
|
||||
(e: 'view-member', member: DuesMember): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -259,14 +278,24 @@ const emit = defineEmits<Emits>();
|
||||
// Reactive state for payment date dialog
|
||||
const showPaymentDateDialog = ref(false);
|
||||
const selectedPaymentDate = ref('');
|
||||
const selectedPaymentModel = ref<Date | null>(null);
|
||||
|
||||
// Initialize with today's date when dialog opens
|
||||
watch(showPaymentDateDialog, (isOpen) => {
|
||||
if (isOpen) {
|
||||
const today = new Date();
|
||||
selectedPaymentModel.value = today;
|
||||
selectedPaymentDate.value = todayDate.value;
|
||||
}
|
||||
});
|
||||
|
||||
// Date picker handler
|
||||
const handleDateUpdate = (date: Date | null) => {
|
||||
if (date) {
|
||||
selectedPaymentDate.value = date.toISOString().split('T')[0];
|
||||
}
|
||||
};
|
||||
|
||||
// Computed properties
|
||||
const memberInitials = computed(() => {
|
||||
const firstName = props.member.first_name || '';
|
||||
@@ -458,6 +487,76 @@ const confirmMarkAsPaid = async () => {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
/* Date picker styling to match Vuetify */
|
||||
.date-picker-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date-picker-label {
|
||||
font-size: 16px;
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 0.009375em;
|
||||
margin-bottom: 8px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Style the Vue DatePicker to match Vuetify inputs */
|
||||
:deep(.dp__input) {
|
||||
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
border-radius: 4px;
|
||||
padding: 16px 12px;
|
||||
padding-right: 48px; /* Make room for calendar icon */
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
background: rgb(var(--v-theme-surface));
|
||||
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
|
||||
transition: border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
width: 100%;
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
:deep(.dp__input:hover) {
|
||||
border-color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
|
||||
}
|
||||
|
||||
:deep(.dp__input:focus) {
|
||||
border-color: rgb(var(--v-theme-primary));
|
||||
border-width: 2px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:deep(.dp__input_readonly) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Style the date picker dropdown */
|
||||
:deep(.dp__menu) {
|
||||
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
background: rgb(var(--v-theme-surface));
|
||||
}
|
||||
|
||||
/* Primary color theming for the date picker */
|
||||
:deep(.dp__primary_color) {
|
||||
background-color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
:deep(.dp__primary_text) {
|
||||
color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
:deep(.dp__active_date) {
|
||||
background-color: rgb(var(--v-theme-primary));
|
||||
color: rgb(var(--v-theme-on-primary));
|
||||
}
|
||||
|
||||
:deep(.dp__today) {
|
||||
border: 1px solid rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media (max-width: 600px) {
|
||||
.dues-action-card {
|
||||
|
||||
@@ -260,6 +260,7 @@ function handleEventMount(mountInfo: any) {
|
||||
function transformEventForCalendar(event: Event): FullCalendarEvent {
|
||||
console.log('[EventCalendar] Transforming event:', {
|
||||
id: event.id,
|
||||
event_id: event.event_id,
|
||||
title: event.title,
|
||||
start_datetime: event.start_datetime,
|
||||
end_datetime: event.end_datetime,
|
||||
@@ -277,6 +278,10 @@ function transformEventForCalendar(event: Event): FullCalendarEvent {
|
||||
const colors = eventTypeColors[event.event_type] ||
|
||||
{ bg: '#757575', border: '#424242' };
|
||||
|
||||
// Use event_id as the primary identifier for FullCalendar uniqueness
|
||||
const calendarId = event.event_id || event.id || `temp_${(event as any).Id}_${Date.now()}`;
|
||||
console.log('[EventCalendar] Using calendar ID:', calendarId, 'from event_id:', event.event_id, 'fallback id:', event.id);
|
||||
|
||||
// Ensure dates are properly formatted for FullCalendar
|
||||
let startDate: string | Date;
|
||||
let endDate: string | Date;
|
||||
@@ -287,7 +292,7 @@ function transformEventForCalendar(event: Event): FullCalendarEvent {
|
||||
const endDateObj = new Date(event.end_datetime);
|
||||
|
||||
if (isNaN(startDateObj.getTime()) || isNaN(endDateObj.getTime())) {
|
||||
console.error('[EventCalendar] Invalid date values for event:', event.id, {
|
||||
console.error('[EventCalendar] Invalid date values for event:', calendarId, {
|
||||
start: event.start_datetime,
|
||||
end: event.end_datetime
|
||||
});
|
||||
@@ -299,14 +304,14 @@ function transformEventForCalendar(event: Event): FullCalendarEvent {
|
||||
endDate = endDateObj.toISOString();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[EventCalendar] Date parsing error for event:', event.id, error);
|
||||
console.error('[EventCalendar] Date parsing error for event:', calendarId, error);
|
||||
// Use fallback dates
|
||||
startDate = new Date().toISOString();
|
||||
endDate = new Date(Date.now() + 3600000).toISOString(); // +1 hour
|
||||
}
|
||||
|
||||
const transformedEvent = {
|
||||
id: event.id,
|
||||
id: calendarId, // ✅ Use event_id instead of event.id
|
||||
title: event.title,
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
@@ -325,7 +330,9 @@ function transformEventForCalendar(event: Event): FullCalendarEvent {
|
||||
current_attendees: typeof event.current_attendees === 'string' ? parseInt(event.current_attendees) : (event.current_attendees || 0),
|
||||
user_rsvp: event.user_rsvp,
|
||||
visibility: event.visibility,
|
||||
creator: event.creator
|
||||
creator: event.creator,
|
||||
event_id: event.event_id, // Store for reference
|
||||
database_id: event.id || (event as any).Id
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user