DigitalConsumer.ISS/src/iss-components/loading-modal/loading-modal.vue
2025-12-11 10:44:44 -05:00

213 lines
5.9 KiB
Vue

<template>
<div
v-if="showModalContent"
class="container-fluid modal-loader">
<div class="modal-loader-background"></div>
<div class="modal-loader-content">
<div class="modal-loader-content-container">
<div class="modal-loader-spinner-container">
<div class="modal-loader-text">
Processing...
</div>
<div
class="modal-loader-spinner"
role="status">
<img
src="~@/assets/img/heritage-loader-blue.gif"
alt="Loading spinner" />
</div>
</div>
<div
v-if="showTextCarouselContent"
class="row modal-loader-text-container">
<div class="col">
<div class="text-container slide">
<p
v-for="text in textSlides"
:key="text">
{{ text }}
<span class="dot-1">.</span>
<span class="dot-2">.</span>
<span class="dot-3">.</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'loading-modal',
props: {
showLoader: {
type: Boolean,
default: false
},
showTextCarousel: {
type: Boolean,
default: false
},
textSlides: {
type: Array,
default: () => []
}
},
data() {
return {
isModalVisible: false,
isModalTextCarouselVisible: false
};
},
computed: {
showModalContent() {
return this.isModalVisible || this.showLoader;
},
showTextCarouselContent() {
return this.isModalTextCarouselVisible || this.showTextCarousel;
}
},
methods: {
showModal(showTextCarousel = true) {
// Display modal
this.isModalTextCarouselVisible = showTextCarousel;
this.isModalVisible = true;
// Force page reload on back button
window.addEventListener(
'pageshow',
(evt) => {
if (evt.persisted) {
setTimeout(() => {
window.location.reload();
}, 10);
}
},
false
);
},
hideModal() {
this.isModalVisible = false;
}
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/ux-variables-svg-strings.scss";
.modal-loader {
.modal-loader-background,
.modal-loader-content {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
outline: 0;
}
.modal-loader-background {
z-index: 1057;
background: #000;
opacity: 0.5;
}
.modal-loader-content {
z-index: 1058;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
@include media-breakpoint-up(xs) {
padding-top: 5rem;
}
@include media-breakpoint-up(md) {
padding-top: 7rem;
}
.modal-loader-content-container {
min-width: 15rem; // 240px
min-height: 15rem; // 240px
font-weight: 600;
padding: 1rem 0;
display: flex;
align-items: flex-start;
justify-content: center;
background-color: #fff;
background-clip: padding-box;
outline: 0;
border: 1px solid rgba(0, 0, 0, .2);
border-radius: 0.375rem;
box-shadow: 0 .375rem 11rem rgba(0, 0, 0, .5);
.modal-loader-spinner-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #1574a1;
font-weight: 600;
.modal-loader-spinner {
margin-top: 0.75rem;
}
}
}
.tagbg {
background-image: url($svg-loading-modal-image);
background-repeat: no-repeat;
background-position: center center;
background-size: 96px;
display: flex;
justify-content: center;
align-items: center;
}
.text-container {
display: flex;
width: 350px;
overflow: hidden;
white-space: nowrap;
margin: 0 auto;
position: relative;
&:after {
content: "";
background: rgb(245, 245, 245);
background: linear-gradient(
270deg,
rgba(245, 245, 245, 1) 0%,
rgba(245, 245, 245, 0) 5%,
rgba(245, 245, 245, 0) 95%,
rgba(245, 245, 245, 1) 100%
);
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
&.slide p {
animation: slide-in 20s ease-in-out 1s forwards 1;
}
p {
margin: 0 175px;
transform: translateX(180px);
}
}
}
}
</style>