fixes
Build And Push Image / docker (push) Successful in 3m41s Details

This commit is contained in:
Matt 2025-08-13 15:35:53 +02:00
parent 62fb84d25e
commit db19eb2708
4 changed files with 95 additions and 34 deletions

View File

@ -92,10 +92,12 @@
placeholder="Select start date and time" placeholder="Select start date and time"
:enable-time-picker="true" :enable-time-picker="true"
:is-24="true" :is-24="true"
auto-apply :auto-apply="false"
:action-row="{ showSelect: true, showCancel: true, showNow: false, showPreview: true }"
:clearable="false" :clearable="false"
:required="true" :required="true"
@update:model-value="handleStartDateUpdate" @update:model-value="handleStartDateUpdate"
@closed="onDatePickerClosed"
/> />
</div> </div>
</v-col> </v-col>
@ -113,11 +115,13 @@
placeholder="Select end date and time" placeholder="Select end date and time"
:enable-time-picker="true" :enable-time-picker="true"
:is-24="true" :is-24="true"
auto-apply :auto-apply="false"
:action-row="{ showSelect: true, showCancel: true, showNow: false, showPreview: true }"
:clearable="false" :clearable="false"
:required="true" :required="true"
:min-date="startDateModel" :min-date="startDateModel"
@update:model-value="handleEndDateUpdate" @update:model-value="handleEndDateUpdate"
@closed="onDatePickerClosed"
/> />
</div> </div>
</v-col> </v-col>
@ -487,6 +491,11 @@ const handleEndDateUpdate = (date: Date | null) => {
} }
}; };
const onDatePickerClosed = () => {
console.log('[CreateEventDialog] Date picker closed');
// This handler ensures the date picker behaves correctly on mobile and desktop
};
// Methods // Methods
const resetForm = () => { const resetForm = () => {
eventData.title = ''; eventData.title = '';

View File

@ -170,7 +170,7 @@
<!-- Error Snackbar --> <!-- Error Snackbar -->
<v-snackbar <v-snackbar
v-model="showError" v-model="showErrorSnackbar"
color="error" color="error"
:timeout="5000" :timeout="5000"
> >
@ -178,7 +178,7 @@
<template #actions> <template #actions>
<v-btn <v-btn
variant="text" variant="text"
@click="showError = false" @click="showErrorSnackbar = false"
> >
Close Close
</v-btn> </v-btn>
@ -187,7 +187,7 @@
<!-- Success Snackbar --> <!-- Success Snackbar -->
<v-snackbar <v-snackbar
v-model="showSuccess" v-model="showSuccessSnackbar"
color="success" color="success"
:timeout="3000" :timeout="3000"
> >
@ -195,7 +195,7 @@
<template #actions> <template #actions>
<v-btn <v-btn
variant="text" variant="text"
@click="showSuccess = false" @click="showSuccessSnackbar = false"
> >
Close Close
</v-btn> </v-btn>
@ -244,8 +244,8 @@ const filters = reactive<EventFilters>({
}); });
// Notification state // Notification state
const showError = ref(false); const showErrorSnackbar = ref(false);
const showSuccess = ref(false); const showSuccessSnackbar = ref(false);
const errorMessage = ref(''); const errorMessage = ref('');
const successMessage = ref(''); const successMessage = ref('');
@ -378,35 +378,46 @@ const handleDateClick = (dateInfo: any) => {
// Debug: Log the date format being passed // Debug: Log the date format being passed
console.log('[Events] Date clicked:', dateInfo); console.log('[Events] Date clicked:', dateInfo);
// Ensure proper ISO format for datetime-local inputs // Create proper ISO datetime strings (full format)
let formattedDate = ''; let formattedDate = '';
let formattedEndDate = ''; let formattedEndDate = '';
if (dateInfo.date) { if (dateInfo.date) {
// Convert to local datetime-local format: YYYY-MM-DDTHH:mm // Convert to proper Date object and set default time
const clickedDate = new Date(dateInfo.date); const clickedDate = new Date(dateInfo.date);
// Set default time to 6 PM in the user's local timezone
clickedDate.setHours(18, 0, 0, 0); // Default to 6 PM clickedDate.setHours(18, 0, 0, 0); // Default to 6 PM
formattedDate = clickedDate.toISOString().slice(0, 16); formattedDate = clickedDate.toISOString(); // Full ISO string
// Set end date 2 hours later if not provided // Set end date 2 hours later if not provided
if (dateInfo.endDate) { if (dateInfo.endDate) {
formattedEndDate = new Date(dateInfo.endDate).toISOString().slice(0, 16); const endDate = new Date(dateInfo.endDate);
endDate.setHours(20, 0, 0, 0); // Default to 8 PM for end date
formattedEndDate = endDate.toISOString();
} else { } else {
const endDate = new Date(clickedDate); const endDate = new Date(clickedDate);
endDate.setHours(20, 0, 0, 0); // Default to 8 PM endDate.setHours(20, 0, 0, 0); // Default to 8 PM (2 hours later)
formattedEndDate = endDate.toISOString().slice(0, 16); formattedEndDate = endDate.toISOString();
} }
} }
prefilledDate.value = formattedDate; // Clear previous values first to trigger watchers properly
prefilledEndDate.value = formattedEndDate; prefilledDate.value = '';
prefilledEndDate.value = '';
console.log('[Events] Prefilled dates:', { // Set new values
date: formattedDate, nextTick(() => {
endDate: formattedEndDate prefilledDate.value = formattedDate;
prefilledEndDate.value = formattedEndDate;
console.log('[Events] Prefilled dates set:', {
date: formattedDate,
endDate: formattedEndDate
});
showCreateDialog.value = true;
}); });
showCreateDialog.value = true;
} }
}; };
@ -482,12 +493,12 @@ const subscribeCalendar = async () => {
const showErrorMessage = (message: string) => { const showErrorMessage = (message: string) => {
errorMessage.value = message; errorMessage.value = message;
showError.value = true; showErrorSnackbar.value = true;
}; };
const showSuccessMessage = (message: string) => { const showSuccessMessage = (message: string) => {
successMessage.value = message; successMessage.value = message;
showSuccess.value = true; showSuccessSnackbar.value = true;
}; };
// Lifecycle // Lifecycle

View File

@ -34,6 +34,14 @@ export default defineEventHandler(async (event) => {
console.log('[api/events.get] ✅ Valid session found for user:', session.user.email); console.log('[api/events.get] ✅ Valid session found for user:', session.user.email);
console.log('[api/events.get] User tier:', session.user.tier); console.log('[api/events.get] User tier:', session.user.tier);
// Get member record to find the member_id needed for RSVP lookup
const { getMemberByKeycloakId } = await import('~/server/utils/nocodb');
const member = await getMemberByKeycloakId(session.user.id);
const memberIdentifier = member?.member_id || member?.Id || session.user.id;
console.log('[api/events.get] Using member identifier for RSVP lookup:', memberIdentifier);
console.log('[api/events.get] Member details:', { member_id: member?.member_id, database_id: member?.Id });
const eventsClient = createNocoDBEventsClient(); const eventsClient = createNocoDBEventsClient();
// Build filters with user role // Build filters with user role
@ -56,8 +64,8 @@ export default defineEventHandler(async (event) => {
console.log('[api/events.get] Fetching events with filters:', filters); console.log('[api/events.get] Fetching events with filters:', filters);
// Get events from database // Get events from database using the member identifier (not Keycloak ID)
const response = await eventsClient.findUserEvents(session.user.id, filters); const response = await eventsClient.findUserEvents(memberIdentifier, filters);
console.log('[api/events.get] ✅ Successfully fetched', response.list.length, 'events'); console.log('[api/events.get] ✅ Successfully fetched', response.list.length, 'events');

View File

@ -412,28 +412,61 @@ export function createNocoDBEventsClient() {
}, },
/** /**
* Get events for a specific user (simplified version) * Get events for a specific user with RSVP status loaded
*/ */
async findUserEvents(memberId: string, filters?: EventFilters) { async findUserEvents(memberId: string, filters?: EventFilters) {
console.log('[nocodb-events] Finding events for member:', memberId); console.log('[nocodb-events] Finding events for member:', memberId);
try { try {
// For now, just get all visible events using the working findAll method // First get all events using the working findAll method
// Remove complex filtering temporarily to fix the 422 errors
const simpleFilters = { const simpleFilters = {
status: filters?.status, status: filters?.status,
limit: (filters as any)?.limit, limit: (filters as any)?.limit,
offset: (filters as any)?.offset offset: (filters as any)?.offset
}; };
console.log('[nocodb-events] Using simplified filters to avoid 422 errors:', simpleFilters); console.log('[nocodb-events] Using simplified filters:', simpleFilters);
const events = await this.findAll(simpleFilters); const eventsResponse = await this.findAll(simpleFilters);
if (!eventsResponse.list || eventsResponse.list.length === 0) {
console.log('[nocodb-events] No events found');
return eventsResponse;
}
console.log('[nocodb-events] Found', eventsResponse.list.length, 'events, now loading RSVPs for member:', memberId);
// Load RSVPs for each event for this user
const eventsWithRSVPs = await Promise.all(
eventsResponse.list.map(async (event) => {
try {
// Use event_id if available, otherwise fall back to database Id
const eventIdentifier = event.event_id || event.id || (event as any).Id;
console.log('[nocodb-events] Loading RSVP for event:', event.title, 'identifier:', eventIdentifier);
const userRSVP = await this.findUserRSVP(eventIdentifier, memberId);
if (userRSVP) {
console.log('[nocodb-events] ✅ Found RSVP for event', event.title, ':', userRSVP.rsvp_status);
return {
...event,
user_rsvp: userRSVP
};
} else {
console.log('[nocodb-events] No RSVP found for event:', event.title);
return event;
}
} catch (rsvpError) {
console.log('[nocodb-events] ⚠️ Error loading RSVP for event', event.title, ':', rsvpError);
return event; // Return event without RSVP if lookup fails
}
})
);
console.log('[nocodb-events] ✅ Loaded RSVPs for all events');
// TODO: Add RSVP lookup from separate table
// For now, return events without RSVP status
return { return {
list: events.list || [], list: eventsWithRSVPs,
PageInfo: events.PageInfo PageInfo: eventsResponse.PageInfo
}; };
} catch (error: any) { } catch (error: any) {
console.error('[nocodb-events] Error finding user events:', error); console.error('[nocodb-events] Error finding user events:', error);