61 lines
1.5 KiB
Vue
61 lines
1.5 KiB
Vue
<template>
|
|
<div
|
|
v-if="showOverlay"
|
|
class="fixed inset-0 bg-black bg-opacity-30 flex items-center justify-center z-[9999] transition-opacity duration-200"
|
|
:class="{ 'opacity-100': showOverlay, 'opacity-0 pointer-events-none': !showOverlay }"
|
|
>
|
|
<div class="bg-white rounded-lg p-6 shadow-xl max-w-sm w-full mx-4 text-center">
|
|
<div class="mb-4">
|
|
<i class="pi pi-spin pi-spinner text-4xl text-blue-500"></i>
|
|
</div>
|
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">Loading</h3>
|
|
<p class="text-gray-600">{{ loadingMessage }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from "vue";
|
|
import { useLoadingStore } from "../../stores/loading";
|
|
|
|
const props = defineProps({
|
|
// Show overlay only for global loading, not component-specific
|
|
globalOnly: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// Minimum display time to prevent flashing
|
|
minDisplayTime: {
|
|
type: Number,
|
|
default: 300,
|
|
},
|
|
});
|
|
|
|
const loadingStore = useLoadingStore();
|
|
|
|
const showOverlay = computed(() => {
|
|
if (props.globalOnly) {
|
|
return loadingStore.isLoading;
|
|
}
|
|
return loadingStore.isAnyLoading;
|
|
});
|
|
|
|
const loadingMessage = computed(() => {
|
|
return loadingStore.loadingMessage;
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Additional styling for better visual appearance */
|
|
.bg-opacity-30 {
|
|
background-color: rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
/* Backdrop blur effect for modern browsers */
|
|
@supports (backdrop-filter: blur(4px)) {
|
|
.fixed.inset-0 {
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
}
|
|
</style>
|