| <template> | 
 |   <transition name="fade"> | 
 |     <b-progress v-if="!isLoadingComplete"> | 
 |       <b-progress-bar | 
 |         striped | 
 |         animated | 
 |         :value="loadingIndicatorValue" | 
 |         :aria-label="$t('global.ariaLabel.progressBar')" | 
 |       /> | 
 |     </b-progress> | 
 |   </transition> | 
 | </template> | 
 |  | 
 | <script> | 
 | import { useI18n } from 'vue-i18n'; | 
 | export default { | 
 |   data() { | 
 |     return { | 
 |       $t: useI18n().t, | 
 |       loadingIndicatorValue: 0, | 
 |       isLoadingComplete: false, | 
 |       loadingIntervalId: null, | 
 |       timeoutId: null, | 
 |     }; | 
 |   }, | 
 |   created() { | 
 |     this.$root.$on('loader-start', () => { | 
 |       this.startLoadingInterval(); | 
 |     }); | 
 |     this.$root.$on('loader-end', () => { | 
 |       this.endLoadingInterval(); | 
 |     }); | 
 |     this.$root.$on('loader-hide', () => { | 
 |       this.hideLoadingBar(); | 
 |     }); | 
 |   }, | 
 |   methods: { | 
 |     startLoadingInterval() { | 
 |       this.clearLoadingInterval(); | 
 |       this.clearTimeout(); | 
 |       this.loadingIndicatorValue = 0; | 
 |       this.isLoadingComplete = false; | 
 |       this.loadingIntervalId = setInterval(() => { | 
 |         this.loadingIndicatorValue += 1; | 
 |         if (this.loadingIndicatorValue > 100) this.clearLoadingInterval(); | 
 |       }, 100); | 
 |     }, | 
 |     endLoadingInterval() { | 
 |       this.clearLoadingInterval(); | 
 |       this.clearTimeout(); | 
 |       this.loadingIndicatorValue = 100; | 
 |       this.timeoutId = setTimeout(() => { | 
 |         // Let animation complete before hiding | 
 |         // the loading bar | 
 |         this.isLoadingComplete = true; | 
 |       }, 1000); | 
 |     }, | 
 |     hideLoadingBar() { | 
 |       this.clearLoadingInterval(); | 
 |       this.clearTimeout(); | 
 |       this.loadingIndicatorValue = 0; | 
 |       this.isLoadingComplete = true; | 
 |     }, | 
 |     clearLoadingInterval() { | 
 |       if (this.loadingIntervalId) clearInterval(this.loadingIntervalId); | 
 |       this.loadingIntervalId = null; | 
 |     }, | 
 |     clearTimeout() { | 
 |       if (this.timeoutId) clearTimeout(this.timeoutId); | 
 |       this.timeoutId = null; | 
 |     }, | 
 |   }, | 
 | }; | 
 | </script> | 
 |  | 
 | <style lang="scss" scoped> | 
 | .progress { | 
 |   position: absolute; | 
 |   left: 0; | 
 |   right: 0; | 
 |   bottom: -0.4rem; | 
 |   opacity: 1; | 
 |   transition: opacity $duration--moderate-01 $standard-easing--productive; | 
 |   height: 0.4rem; | 
 |  | 
 |   &.fade-enter, // Remove this vue2 based only class when switching to vue3 | 
 |   &.fade-enter-from, // This is vue3 based only class modified from 'fade-enter' | 
 |   &.fade-leave-to { | 
 |     opacity: 0; | 
 |   } | 
 | } | 
 | .progress-bar { | 
 |   background-color: $loading-color; | 
 | } | 
 | </style> |