Calendar-Improvements #57
@@ -156,6 +156,12 @@ function blurAfter() {
|
|||||||
<RouterLink to="/join" @click="blurAfter">Join</RouterLink>
|
<RouterLink to="/join" @click="blurAfter">Join</RouterLink>
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</NavigationMenuItem>
|
</NavigationMenuItem>
|
||||||
|
<!-- Calendar -->
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuLink as-child :class="navigationMenuTriggerStyle()">
|
||||||
|
<RouterLink to="/calendar" @click="blurAfter">Calendar</RouterLink>
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</NavigationMenuItem>
|
||||||
</NavigationMenuList>
|
</NavigationMenuList>
|
||||||
</NavigationMenu>
|
</NavigationMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,22 +14,10 @@ import DropdownMenuItem from '../ui/dropdown-menu/DropdownMenuItem.vue';
|
|||||||
import { Calendar } from 'lucide-vue-next';
|
import { Calendar } from 'lucide-vue-next';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
// const eventID = computed(() => {
|
|
||||||
// const id = route.params.id;
|
|
||||||
// if (typeof id === 'string') return id;
|
|
||||||
// return undefined;
|
|
||||||
// });
|
|
||||||
|
|
||||||
const loaded = ref<boolean>(false);
|
const loaded = ref<boolean>(false);
|
||||||
const activeEvent = ref<CalendarEvent | null>(null);
|
const activeEvent = ref<CalendarEvent | null>(null);
|
||||||
|
|
||||||
// onMounted(async () => {
|
|
||||||
// let eventID = route.params.id;
|
|
||||||
// console.log(eventID);
|
|
||||||
// activeEvent.value = await getCalendarEvent(Number(eventID));
|
|
||||||
// loaded.value = true;
|
|
||||||
// });
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.params.id,
|
() => route.params.id,
|
||||||
async (id) => {
|
async (id) => {
|
||||||
@@ -76,6 +64,7 @@ const viewedState = ref<CalendarAttendance>(CalendarAttendance.Attending);
|
|||||||
|
|
||||||
let user = useUserStore();
|
let user = useUserStore();
|
||||||
const myAttendance = computed<CalendarSignup | null>(() => {
|
const myAttendance = computed<CalendarSignup | null>(() => {
|
||||||
|
if (!user.isLoggedIn) return null;
|
||||||
return activeEvent.value.eventSignups.find(
|
return activeEvent.value.eventSignups.find(
|
||||||
(s) => s.member_id === user.user.id
|
(s) => s.member_id === user.user.id
|
||||||
) || null;
|
) || null;
|
||||||
@@ -88,6 +77,7 @@ async function setAttendance(state: CalendarAttendance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const canEditEvent = computed(() => {
|
const canEditEvent = computed(() => {
|
||||||
|
if (!user.isLoggedIn) return false;
|
||||||
if (user.user.id == activeEvent.value.creator_id)
|
if (user.user.id == activeEvent.value.creator_id)
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -223,7 +213,7 @@ defineExpose({ forceReload })
|
|||||||
<CircleAlert></CircleAlert> This event has been cancelled
|
<CircleAlert></CircleAlert> This event has been cancelled
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section v-if="isPast" class="w-full">
|
<section v-if="isPast && user.isLoggedIn" class="w-full">
|
||||||
<ButtonGroup class="flex w-full">
|
<ButtonGroup class="flex w-full">
|
||||||
<Button variant="outline"
|
<Button variant="outline"
|
||||||
:class="myAttendance?.status === CalendarAttendance.Attending ? 'border-2 border-primary text-primary' : ''"
|
:class="myAttendance?.status === CalendarAttendance.Attending ? 'border-2 border-primary text-primary' : ''"
|
||||||
|
|||||||
@@ -3,15 +3,14 @@ import { ref, watch, nextTick, computed, onMounted } from 'vue'
|
|||||||
import FullCalendar from '@fullcalendar/vue3'
|
import FullCalendar from '@fullcalendar/vue3'
|
||||||
import dayGridPlugin from '@fullcalendar/daygrid'
|
import dayGridPlugin from '@fullcalendar/daygrid'
|
||||||
import interactionPlugin from '@fullcalendar/interaction'
|
import interactionPlugin from '@fullcalendar/interaction'
|
||||||
import { X, Clock, MapPin, User, ListTodo, ChevronLeft, ChevronRight, Plus } from 'lucide-vue-next'
|
import { ChevronLeft, ChevronRight, Plus } from 'lucide-vue-next'
|
||||||
import CreateCalendarEvent from '@/components/calendar/CreateCalendarEvent.vue'
|
import CreateCalendarEvent from '@/components/calendar/CreateCalendarEvent.vue'
|
||||||
import { getCalendarEvent, getMonthCalendarEvents } from '@/api/calendar'
|
import { CalendarEvent } from '@shared/types/calendar'
|
||||||
import { CalendarEvent, CalendarEventShort } from '@shared/types/calendar'
|
|
||||||
import { Calendar } from '@fullcalendar/core'
|
|
||||||
import ViewCalendarEvent from '@/components/calendar/ViewCalendarEvent.vue'
|
import ViewCalendarEvent from '@/components/calendar/ViewCalendarEvent.vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useCalendarEvents } from '@/composables/useCalendarEvents'
|
import { useCalendarEvents } from '@/composables/useCalendarEvents'
|
||||||
import { useCalendarNavigation } from '@/composables/useCalendarNavigation'
|
import { useCalendarNavigation } from '@/composables/useCalendarNavigation'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
const monthLabels = [
|
const monthLabels = [
|
||||||
'January', 'February', 'March', 'April', 'May', 'June',
|
'January', 'February', 'March', 'April', 'May', 'June',
|
||||||
@@ -24,13 +23,14 @@ function api() {
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
function buildFullDate(month: number, year: number): Date {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
const { selectedMonth, selectedYear, years, goPrev, goNext, goToday, onDatesSet, goToSelectedDate } = useCalendarNavigation(api)
|
const { selectedMonth, selectedYear, years, goPrev, goNext, goToday, onDatesSet, goToSelectedDate } = useCalendarNavigation(api)
|
||||||
const { events, loadEvents} = useCalendarEvents(selectedMonth, selectedYear);
|
const { events, loadEvents } = useCalendarEvents(selectedMonth, selectedYear);
|
||||||
|
|
||||||
const panelOpen = ref(false)
|
const panelOpen = ref(false)
|
||||||
const activeEvent = ref<CalendarEvent | null>(null)
|
const activeEvent = ref<CalendarEvent | null>(null)
|
||||||
@@ -48,6 +48,7 @@ const dialogRef = ref<any>(null)
|
|||||||
|
|
||||||
// NEW: handle day/time slot clicks to start creating an event
|
// NEW: handle day/time slot clicks to start creating an event
|
||||||
function onDateClick(arg: { dateStr: string }) {
|
function onDateClick(arg: { dateStr: string }) {
|
||||||
|
if (!userStore.isLoggedIn) return;
|
||||||
dialogRef.value?.openDialog(arg.dateStr);
|
dialogRef.value?.openDialog(arg.dateStr);
|
||||||
// For now, just open the panel with a draft payload.
|
// For now, just open the panel with a draft payload.
|
||||||
// activeEvent.value = {
|
// activeEvent.value = {
|
||||||
@@ -202,7 +203,7 @@ onMounted(() => {
|
|||||||
@click="goToday">
|
@click="goToday">
|
||||||
Today
|
Today
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button v-if="userStore.isLoggedIn"
|
||||||
class="cursor-pointer ml-1 inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:opacity-90"
|
class="cursor-pointer ml-1 inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:opacity-90"
|
||||||
@click="onCreateEvent">
|
@click="onCreateEvent">
|
||||||
<Plus class="h-4 w-4" />
|
<Plus class="h-4 w-4" />
|
||||||
@@ -216,7 +217,8 @@ onMounted(() => {
|
|||||||
<aside v-if="panelOpen"
|
<aside v-if="panelOpen"
|
||||||
class="3xl:w-lg 2xl:w-md border-l bg-card text-foreground flex flex-col overflow-auto scrollbar-themed"
|
class="3xl:w-lg 2xl:w-md border-l bg-card text-foreground flex flex-col overflow-auto scrollbar-themed"
|
||||||
:style="{ height: 'calc(100vh - 61px)', position: 'sticky', top: '64px' }">
|
:style="{ height: 'calc(100vh - 61px)', position: 'sticky', top: '64px' }">
|
||||||
<ViewCalendarEvent ref="eventViewRef" @close="() => { router.push('/calendar'); }" @reload="loadEvents()" @edit="(val) => {dialogRef.openDialog(null, 'edit', val)}">
|
<ViewCalendarEvent ref="eventViewRef" @close="() => { router.push('/calendar'); }"
|
||||||
|
@reload="loadEvents()" @edit="(val) => { dialogRef.openDialog(null, 'edit', val) }">
|
||||||
</ViewCalendarEvent>
|
</ViewCalendarEvent>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ const router = createRouter({
|
|||||||
{ path: '/loa', component: () => import('@/pages/SubmitLOA.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ path: '/loa', component: () => import('@/pages/SubmitLOA.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
{ path: '/transfer', component: () => import('@/pages/Transfer.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ path: '/transfer', component: () => import('@/pages/Transfer.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
|
|
||||||
{ path: '/calendar', component: () => import('@/pages/Calendar.vue'), meta: { requiresAuth: true, memberOnly: true }, },
|
{ path: '/calendar', component: () => import('@/pages/Calendar.vue'), meta: { }, },
|
||||||
{ path: '/calendar/event/:id', component: () => import('@/pages/Calendar.vue'), meta: { requiresAuth: true, memberOnly: true }, },
|
{ path: '/calendar/event/:id', component: () => import('@/pages/Calendar.vue'), meta: { }, },
|
||||||
|
|
||||||
{ path: '/trainingReport', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ path: '/trainingReport', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
{ path: '/trainingReport/new', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ path: '/trainingReport/new', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
|
|||||||
Reference in New Issue
Block a user