diff --git a/src/app/globals.css b/src/app/globals.css index 3aebe8c..146f1b9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -967,35 +967,45 @@ h3 { color: var(--weekly-text); } -/* Action Buttons Styling */ +/* Action Buttons Styling - Float above task on hover to avoid overlap */ .task-actions { display: flex; align-items: center; gap: 2px; position: absolute; right: 0; - top: 0; - bottom: 0; - z-index: 10; - padding-left: 8px; - padding-right: 4px; + top: -26px; /* Position above the task item */ + background: var(--weekly-bg, white); + border: 1px solid var(--weekly-border, #e0e0e0); + border-radius: 6px; + box-shadow: 0 2px 8px rgba(0,0,0,0.12); + z-index: 100; + padding: 2px 4px; flex-wrap: nowrap; + pointer-events: auto; } -/* Time-grid tasks: show actions below task text as a dropdown toolbar */ +/* Time-grid tasks: show actions above task text as a floating toolbar on hover */ .time-slot-task > .task-actions { position: absolute; - top: auto; - bottom: auto; + top: -28px; /* Float above the task */ left: 0; right: auto; margin-top: 0; background: var(--weekly-bg, white); border: 1px solid var(--weekly-border, #e0e0e0); border-radius: 6px; - box-shadow: 0 2px 8px rgba(0,0,0,0.12); + box-shadow: 0 4px 12px rgba(0,0,0,0.15); padding: 2px 4px; - z-index: 20; + z-index: 100; /* Ensure it stays above everything */ + display: flex !important; /* Force flex even if default is hidden */ + pointer-events: auto; +} + +/* Ensure actions don't get clipped by the scrolling container */ +.time-slots-container { + overflow-y: auto; + overflow-x: visible; } .dark .time-slot-task > .task-actions { diff --git a/src/components/GridTaskBlock.tsx b/src/components/GridTaskBlock.tsx index c242328..a56dafd 100644 --- a/src/components/GridTaskBlock.tsx +++ b/src/components/GridTaskBlock.tsx @@ -331,8 +331,8 @@ export function GridTaskBlock({ )} diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index 022cfa6..304ad52 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -5854,7 +5854,7 @@ function TaskItem({ -
+
{/* Complete */}
diff --git a/src/lib/apple-calendar.ts b/src/lib/apple-calendar.ts index c7c905a..ea431f9 100644 --- a/src/lib/apple-calendar.ts +++ b/src/lib/apple-calendar.ts @@ -11,6 +11,7 @@ export interface AppleCalendarEvent { endDate: string; description?: string; location?: string; + url?: string; } export interface AppleCalendar { @@ -165,7 +166,8 @@ export const getUpcomingEvents = async ( startDate: exIsAllDay ? exStart.toISOString().slice(0, 10) : exStart.toISOString(), endDate: exIsAllDay ? exEnd.toISOString().slice(0, 10) : exEnd.toISOString(), description: exEvent.description, - location: exEvent.location + location: exEvent.location, + url: exVevent.getFirstPropertyValue('url')?.toString() || undefined }); } }); @@ -197,7 +199,8 @@ export const getUpcomingEvents = async ( startDate: isAllDayRecurring ? occStart.toISOString().slice(0, 10) : occStart.toISOString(), endDate: isAllDayRecurring ? occEnd.toISOString().slice(0, 10) : occEnd.toISOString(), description: event.description, - location: event.location + location: event.location, + url: vevent.getFirstPropertyValue('url')?.toString() || undefined }); } } catch (expandErr: any) { @@ -217,7 +220,8 @@ export const getUpcomingEvents = async ( startDate: isAllDay ? start.toISOString().slice(0, 10) : start.toISOString(), endDate: isAllDay ? end.toISOString().slice(0, 10) : end.toISOString(), description: event.description, - location: event.location + location: event.location, + url: vevent.getFirstPropertyValue('url')?.toString() || undefined }); } }); @@ -338,7 +342,8 @@ END:VCALENDAR`; startDate: eventData.start.dateTime || eventData.start.date || '', endDate: eventData.end.dateTime || eventData.end.date || '', description: eventData.description, - location: eventData.location + location: eventData.location, + url: eventData.url }; } catch (error) { console.error('[APPLE CALENDAR] Error creating event:', error); @@ -553,7 +558,8 @@ export const updateEvent = async ( startDate: event.startDate.toString(), endDate: event.endDate.toString(), description: event.description, - location: event.location + location: event.location, + url: vevent.getFirstPropertyValue('url')?.toString() || undefined }; } catch (error) { diff --git a/src/lib/calendar-events.ts b/src/lib/calendar-events.ts index 847eebb..27441be 100644 --- a/src/lib/calendar-events.ts +++ b/src/lib/calendar-events.ts @@ -56,9 +56,9 @@ function toOutlookRecurrence(recurrence?: string, startDate?: Date): any { case 'daily': return { pattern: { type: 'daily', interval: 1 }, range }; case 'weekly': - return { pattern: { type: 'weekly', interval: 1, daysOfWeek: [['sunday','monday','tuesday','wednesday','thursday','friday','saturday'][start.getDay()]] }, range }; + return { pattern: { type: 'weekly', interval: 1, daysOfWeek: [['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'][start.getDay()]] }, range }; case 'biweekly': - return { pattern: { type: 'weekly', interval: 2, daysOfWeek: [['sunday','monday','tuesday','wednesday','thursday','friday','saturday'][start.getDay()]] }, range }; + return { pattern: { type: 'weekly', interval: 2, daysOfWeek: [['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'][start.getDay()]] }, range }; case 'monthly': return { pattern: { type: 'absoluteMonthly', interval: 1, dayOfMonth: start.getDate() }, range }; case 'yearly': @@ -360,6 +360,7 @@ export const getCalendarEvents = async ( date: startIsAllDay ? event.endDate : undefined, }, location: event.location, + url: event.url, source: 'apple' as const, calendarId, calendarTitle: calendars.find(c => c.id === calendarId)?.title || 'Apple Calendar', @@ -751,6 +752,7 @@ export const updateCalendarEvent = async ( start: { dateTime: updatedEvent.startDate }, end: { dateTime: updatedEvent.endDate }, location: updatedEvent.location, + url: updatedEvent.url, source: 'apple', calendarId, calendarTitle: '',