Replace circular with linear loading indicator

This commit is contained in:
2022-10-03 14:28:40 +02:00
parent 257f665ce6
commit 2e4039cd70
5 changed files with 75 additions and 40 deletions

View File

@ -4,7 +4,7 @@ import TitleBar from "./components/titlebar-element.vue";
import BottomNavbar from "./components/bottom-navbar.vue";
import DateSelector from "./components/date-selector.vue";
import LoadingElement from "./components/loading-element.vue";
import { loading, theme } from "./store";
import { loading, loadingProgress, theme } from "./store";
import { computed, ref } from "vue";
const autoThemes = { true: "dark", false: "light" };
@ -31,10 +31,10 @@ const isDataView = computed(() => {
:class="theme == 'auto' ? `theme-${autoTheme}` : `theme-${theme}`"
>
<TitleBar />
<DateSelector v-show="isDataView" />
<LoadingElement :active="loading" :progress="loadingProgress" />
<div class="center">
<main>
<LoadingElement :active="loading" v-show="isDataView" />
<DateSelector v-show="isDataView" />
<RouterView />
</main>
</div>

View File

@ -16,6 +16,7 @@
--bottomnav-active-color: #7ca74b;
--bottomnav-shadow: 5px 7px 19px 0px rgba(0, 0, 0, 0.25);
--loader-color: #7ca74b;
--loader-error-color: #a54a4a;
--substitution-background-change: #095079;
--substitution-background-cancellation: #7d2b2d;
--substitution-background-addition: #375c1d;
@ -42,7 +43,8 @@
--bottomnav-icon-active-color: #456c47;
--bottomnav-active-color: #99b677;
--bottomnav-shadow: 5px 7px 19px 0px rgba(0, 0, 0, 0.25);
--loader-color: #7ca74b;
--loader-color: #8bab7c;
--loader-error-color: #db5a5a;
--substitution-background-change: #9bb7c7;
--substitution-background-cancellation: #e4a7a9;
--substitution-background-addition: #b0d396;

View File

@ -26,7 +26,11 @@ const loadedDates = ref([
// Load left or right date on slide change
function slideChange(swiper) {
selectedDate.value = loadedDates.value[swiper.activeIndex];
// Only trigger data refresh if date is different
const newSelectedDate = loadedDates.value[swiper.activeIndex];
if (selectedDate.value.getTime() != newSelectedDate.getTime())
selectedDate.value = newSelectedDate;
const activeSlide = swiper.activeIndex;
if (activeSlide == loadedDates.value.length - 1) {
const lastDate = loadedDates.value[loadedDates.value.length - 1];

View File

@ -1,54 +1,73 @@
<script setup>
defineProps({
import { ref, watch } from "vue";
const props = defineProps({
active: {
required: true,
type: Boolean,
},
progress: {
default: 0,
type: Number,
},
error: {
default: false,
type: Boolean,
},
});
const computedProgress = ref(0);
const visible = ref(true);
var hideTimeout;
watch(
() => props.progress,
() => {
if (visible.value) computedProgress.value = props.progress;
}
);
watch(
() => props.active,
() => {
if (hideTimeout) {
clearTimeout(hideTimeout);
hideTimeout = undefined;
}
if (props.active) {
visible.value = true;
computedProgress.value = props.progress;
} else {
hideTimeout = setTimeout(() => {
if (!props.active) {
visible.value = false;
computedProgress.value = 0;
}
}, 500);
}
}
);
</script>
<template>
<div class="container" :class="active ? 'active' : ''">
<span class="loader"></span>
</div>
<div
class="bar"
:class="(active ? 'active' : '') + (error ? ' error' : '')"
:style="`width: ${computedProgress * 100}%;`"
></div>
</template>
<style scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-color: var(--bg-color);
height: 0px;
margin: 0px;
.bar {
width: 0%;
opacity: 0;
transition: all 0.8s;
transition-delay: 0.2s;
background-color: var(--loader-color);
height: 5px;
transition: 0.5s;
transition-property: width opacity background-color;
}
.container.active {
height: 100px;
.bar.active {
opacity: 1;
}
.loader {
width: 48px;
height: 48px;
border: 5px solid;
border-color: var(--loader-color) transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
.bar.error {
background-color: var(--loader-error-color);
}
</style>

View File

@ -5,6 +5,7 @@ import i18n from "./main";
export const lastRoute = ref();
export const loading = ref(false);
export const loadingProgress = ref(0);
export const classFilter = ref(localStorage.getItem("classFilter") || "none");
export const timetableGroups = ref(
@ -45,9 +46,12 @@ if (selectedDay.value == -1)
// Load new data if date changes
watch(selectedDate, async () => {
loadingProgress.value = 0.1;
loading.value = true;
await fetchSubstitutions();
loadingProgress.value = 1 / 2;
await fetchHistory();
loadingProgress.value = 1;
loading.value = false;
});
@ -124,16 +128,22 @@ export const possibleTimetableGroups = computed(() => {
const baseUrl = import.meta.env.VITE_API_ENDPOINT || "/api";
export async function fetchData() {
loadingProgress.value = 0.1;
loading.value = true;
const checkResponse = await fetch(`${baseUrl}/check`);
if (checkResponse.status != 200) router.push("/login");
loadingProgress.value = 1 / 5;
await fetchClassList();
loadingProgress.value = 2 / 5;
await fetchTimetable();
loadingProgress.value = 3 / 5;
await fetchSubstitutions();
loadingProgress.value = 4 / 5;
await fetchHistory();
loadingProgress.value = 1;
loading.value = false;
}