99-Loading-Screens #102
@@ -13,6 +13,7 @@ import DropdownMenuContent from '../ui/dropdown-menu/DropdownMenuContent.vue';
|
||||
import DropdownMenuItem from '../ui/dropdown-menu/DropdownMenuItem.vue';
|
||||
import { Calendar } from 'lucide-vue-next';
|
||||
import MemberCard from '../members/MemberCard.vue';
|
||||
import Spinner from '../ui/spinner/Spinner.vue';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -240,7 +241,8 @@ defineExpose({ forceReload })
|
||||
<MapPin :size="20"></MapPin> {{ activeEvent.location || "Unknown" }}
|
||||
</div>
|
||||
<div class="text-foreground/80 flex gap-3 items-center">
|
||||
<User :size="20"></User> <MemberCard :member-id="activeEvent.creator_id"></MemberCard>
|
||||
<User :size="20"></User>
|
||||
<MemberCard :member-id="activeEvent.creator_id"></MemberCard>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Description -->
|
||||
@@ -289,4 +291,7 @@ defineExpose({ forceReload })
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex justify-center h-full items-center">
|
||||
<Spinner class="size-8"></Spinner>
|
||||
</div>
|
||||
</template>
|
||||
@@ -8,6 +8,7 @@ import PopoverContent from '../ui/popover/PopoverContent.vue';
|
||||
import { cn } from '@/lib/utils.js'
|
||||
import { watch } from 'vue';
|
||||
import { format } from 'path';
|
||||
import Spinner from '../ui/spinner/Spinner.vue';
|
||||
|
||||
|
||||
// Props
|
||||
@@ -91,8 +92,8 @@ function formatDate(date: Date): string {
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-72 p-0 overflow-hidden">
|
||||
<!-- Loading -->
|
||||
<div v-if="loadingFull" class="p-4 text-sm text-muted-foreground">
|
||||
Loading profile…
|
||||
<div v-if="loadingFull" class="p-4 text-sm text-muted-foreground mx-auto flex justify-center my-5">
|
||||
<Spinner></Spinner>
|
||||
</div>
|
||||
|
||||
<!-- Profile -->
|
||||
|
||||
@@ -8,6 +8,7 @@ import Button from '@/components/ui/button/Button.vue';
|
||||
import { CheckIcon, XIcon } from 'lucide-vue-next';
|
||||
import Unauthorized from './Unauthorized.vue';
|
||||
import { ApplicationData, ApplicationFull, ApplicationStatus, CommentRow } from '@shared/types/application';
|
||||
import Spinner from '@/components/ui/spinner/Spinner.vue';
|
||||
|
||||
const appData = ref<ApplicationData>(null);
|
||||
const appID = ref<number | null>(null);
|
||||
@@ -181,5 +182,7 @@ async function handleDeny(id) {
|
||||
|
||||
</div>
|
||||
<!-- TODO: Implement some kinda loading screen -->
|
||||
<div v-else class="flex items-center justify-center h-full">Loading</div>
|
||||
<div v-else class="flex items-center justify-center h-full">
|
||||
<Spinner class="size-8"/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -217,7 +217,7 @@ onMounted(() => {
|
||||
<aside v-if="panelOpen"
|
||||
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' }">
|
||||
<ViewCalendarEvent ref="eventViewRef" @close="() => { router.push('/calendar'); }"
|
||||
<ViewCalendarEvent ref="eventViewRef" :key="currentEventID" @close="() => { router.push('/calendar'); }"
|
||||
@reload="loadEvents()" @edit="(val) => { dialogRef.openDialog(null, 'edit', val) }">
|
||||
</ViewCalendarEvent>
|
||||
</aside>
|
||||
|
||||
@@ -22,6 +22,7 @@ import SelectContent from '@/components/ui/select/SelectContent.vue';
|
||||
import SelectItem from '@/components/ui/select/SelectItem.vue';
|
||||
import Input from '@/components/ui/input/Input.vue';
|
||||
import MemberCard from '@/components/members/MemberCard.vue';
|
||||
import Spinner from '@/components/ui/spinner/Spinner.vue';
|
||||
|
||||
enum sidePanelState { view, create, closed };
|
||||
|
||||
@@ -42,6 +43,7 @@ watch(() => route.params.id, async (newID) => {
|
||||
focusedTrainingReport.value = null;
|
||||
return;
|
||||
}
|
||||
TRLoaded.value = false;
|
||||
viewTrainingReport(Number(route.params.id));
|
||||
})
|
||||
|
||||
@@ -60,6 +62,7 @@ const focusedTrainingTrainers = computed<CourseAttendee[] | null>(() => {
|
||||
})
|
||||
async function viewTrainingReport(id: number) {
|
||||
focusedTrainingReport.value = await getTrainingReport(id);
|
||||
TRLoaded.value = true;
|
||||
}
|
||||
|
||||
async function closeTrainingReport() {
|
||||
@@ -93,6 +96,8 @@ onMounted(async () => {
|
||||
viewTrainingReport(Number(route.params.id))
|
||||
loaded.value = true;
|
||||
})
|
||||
|
||||
const TRLoaded = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -173,7 +178,7 @@ onMounted(async () => {
|
||||
<X></X>
|
||||
</button>
|
||||
</div>
|
||||
<div class="max-h-[70vh] overflow-auto scrollbar-themed my-5">
|
||||
<div v-if="TRLoaded" class="max-h-[70vh] overflow-auto scrollbar-themed my-5">
|
||||
<div class="flex flex-col mb-5 border rounded-lg bg-muted/70 p-2 py-3 px-4">
|
||||
<p class="scroll-m-20 text-xl font-semibold tracking-tight">{{ focusedTrainingReport.course_name }}
|
||||
</p>
|
||||
@@ -184,7 +189,7 @@ onMounted(async () => {
|
||||
:member-id="focusedTrainingReport.created_by" />
|
||||
<p v-else>{{ focusedTrainingReport.created_by_name === null ? "Unknown User" :
|
||||
focusedTrainingReport.created_by_name
|
||||
}}</p>
|
||||
}}</p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -284,6 +289,9 @@ onMounted(async () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex w-full items-center justify-center h-[80%]">
|
||||
<Spinner class="size-8"></Spinner>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="sidePanel == sidePanelState.create" class="pl-7 border-l w-3/5 max-w-5xl">
|
||||
<div class="flex justify-between my-3">
|
||||
|
||||
Reference in New Issue
Block a user