implemented cancelled event visualization
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -34,4 +34,5 @@ export interface CalendarEventShort {
|
|||||||
start: Date;
|
start: Date;
|
||||||
end: Date;
|
end: Date;
|
||||||
color: string;
|
color: string;
|
||||||
|
cancelled: boolean;
|
||||||
}
|
}
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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 },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user