implemented cancelled event visualization

This commit is contained in:
2025-11-27 13:40:58 -05:00
parent 941004f913
commit 0b3a95cdc0
5 changed files with 33 additions and 18 deletions

View File

@@ -65,7 +65,7 @@ export async function cancelEvent(eventID: number) {
export async function getShortEventsInRange(startDate: string, endDate: string): Promise<CalendarEventShort[]> { export async function getShortEventsInRange(startDate: string, endDate: string): Promise<CalendarEventShort[]> {
const sql = ` const sql = `
SELECT id, name, start, end, color SELECT id, name, start, end, color, cancelled
FROM calendar_events FROM calendar_events
WHERE start BETWEEN ? AND ? WHERE start BETWEEN ? AND ?
ORDER BY start ASC ORDER BY start ASC

View File

@@ -34,4 +34,5 @@ export interface CalendarEventShort {
start: Date; start: Date;
end: Date; end: Date;
color: string; color: string;
cancelled: boolean;
} }

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { CalendarEvent, CalendarSignup } from '@shared/types/calendar' import type { CalendarEvent, CalendarSignup } from '@shared/types/calendar'
import { Clock, MapPin, User, X } from 'lucide-vue-next'; import { CircleAlert, Clock, MapPin, User, X } from 'lucide-vue-next';
import { computed, onMounted, ref, watch } from 'vue'; import { computed, onMounted, ref, watch } from 'vue';
import ButtonGroup from '../ui/button-group/ButtonGroup.vue'; import ButtonGroup from '../ui/button-group/ButtonGroup.vue';
import Button from '../ui/button/Button.vue'; import Button from '../ui/button/Button.vue';
@@ -92,6 +92,9 @@ async function setAttendance(state: CalendarAttendance) {
</div> </div>
<!-- Body --> <!-- Body -->
<div class="flex-1 flex flex-col items-center min-h-0 overflow-y-auto px-4 py-4 space-y-6 w-full"> <div class="flex-1 flex flex-col items-center min-h-0 overflow-y-auto px-4 py-4 space-y-6 w-full">
<section v-if="activeEvent.cancelled == true" class="w-full">
<div class="flex p-2 rounded-md w-full bg-destructive gap-3"><CircleAlert></CircleAlert> This event has been cancelled</div>
</section>
<section class="w-full"> <section class="w-full">
<ButtonGroup class="flex w-full"> <ButtonGroup class="flex w-full">
<Button variant="outline" <Button variant="outline"

View File

@@ -11,7 +11,7 @@ export function useCalendarEvents(selectedMonth, selectedYear) {
title: e.name, title: e.name,
start: new Date(e.start), start: new Date(e.start),
end: e.end ? new Date(e.end) : undefined, end: e.end ? new Date(e.end) : undefined,
extendedProps: { color: e.color }, extendedProps: { color: e.color, cancelled: !!e.cancelled },
}; };
} }

View File

@@ -29,14 +29,6 @@ function buildFullDate(month: number, year: number): Date {
return new Date(year, month, 1); //default to first of month return new Date(year, month, 1); //default to first of month
} }
type CalEvent = {
id: string
title: string
start: Date
end?: Date
extendedProps?: Record<string, any>
}
const { selectedMonth, selectedYear, years, goPrev, goNext, goToday, onDatesSet, goToSelectedDate } = useCalendarNavigation(api) const { selectedMonth, selectedYear, years, goPrev, goNext, goToday, onDatesSet, goToSelectedDate } = useCalendarNavigation(api)
const { events } = useCalendarEvents(selectedMonth, selectedYear); const { events } = useCalendarEvents(selectedMonth, selectedYear);
@@ -82,7 +74,7 @@ const calendarOptions = ref({
navLinks: false, navLinks: false,
dateClick: onDateClick, dateClick: onDateClick,
eventClick: onEventClick, eventClick: onEventClick,
editable: true, editable: false,
// force block-mode in dayGrid so we can lay it out on one line // force block-mode in dayGrid so we can lay it out on one line
eventDisplay: 'block', eventDisplay: 'block',
@@ -96,13 +88,25 @@ const calendarOptions = ref({
// custom renderer -> one-line pill // custom renderer -> one-line pill
eventContent(arg) { eventContent(arg) {
console.log //debug
// console.log("Rendering event:", {
// id: arg.event.id,
// title: arg.event.title,
// extendedProps: arg.event.extendedProps,
// fullEvent: arg.event
// })
const ext = arg.event.extendedProps || {} const ext = arg.event.extendedProps || {}
const c = ext.color || arg.backgroundColor || arg.borderColor || '' const color = ext.color || arg.backgroundColor || arg.borderColor || ''
const isCancelled = !!ext.cancelled;
const wrap = document.createElement('div') const wrap = document.createElement('div')
wrap.className = 'ev-pill' wrap.className = 'ev-pill'
if (c) wrap.style.setProperty('--ev-color', String(c)) // dot color if (color) wrap.style.setProperty('--ev-color', String(color)) // dot color
if (isCancelled) {
wrap.classList.add('is-cancelled')
}
const dot = document.createElement('span') const dot = document.createElement('span')
dot.className = 'ev-dot' dot.className = 'ev-dot'
@@ -254,6 +258,12 @@ onMounted(() => {
height: 100% !important; height: 100% !important;
} }
:global(.ev-pill.is-cancelled) {
opacity: 0.45;
text-decoration: line-through;
filter: grayscale(100%);
}
.calendar-card { .calendar-card {
background: var(--color-card); background: var(--color-card);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
@@ -427,9 +437,10 @@ onMounted(() => {
transition: background 120ms ease, border-color 120ms ease, transform 120ms ease; transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
} }
.ev-pill:hover { :global(.ev-pill:hover) {
background: color-mix(in oklab, var(--color-primary) 20%, transparent); /* background: color-mix(in oklab, var(--color-primary) 20%, transparent);
border-color: color-mix(in oklab, var(--color-primary) 45%, var(--color-border)); border-color: color-mix(in oklab, var(--color-primary) 45%, var(--color-border)); */
cursor: pointer;
} }
.ev-dot { .ev-dot {