ldc-showroom/app.vue
2025-07-09 14:38:52 +02:00

165 lines
5.1 KiB
Vue

<template>
<div
class="app-component"
@mousemove="setTimeout"
@mousedown="setTimeout"
@mouseup="setTimeout"
@focus="setTimeout"
@keyup="setTimeout"
@keydown="setTimeout"
@touchstart="setTimeout"
>
<template v-if="!loading">
<AppHeader :active-brand="activeBrand" :active-range="activeRange" />
<div class="container-fluid overflow-auto p-0">
<NuxtPage :page-key="(route: RouteLocation) => route.fullPath" />
</div>
<NavigationMenu v-if="showNavigation" />
<AppFooter v-if="showFooter" :active-brand="activeBrand" :active-range="activeRange" />
<ToastContainer />
</template>
<template v-else>
{{ t('loading') }}
</template>
<ChickenRun :run-animation="chickenRun" />
</div>
</template>
<script lang="ts">
// import Modal from "bootstrap/js/dist/modal";
import KonamiCode from "konami-code-js";
// import Swal from "sweetalert2";
import { defineComponent } from "vue";
import type { RouteLocationNormalizedLoaded } from "vue-router";
import ToolboxHelper from "./classes/ToolboxHelper";
import { useAppStore } from "~/stores/useAppStore";
// import data from "data/test.json";
export default defineComponent({
name: "IndexPage",
data(): {
timeout: NodeJS.Timeout|undefined;
loading: boolean;
route: RouteLocationNormalizedLoaded;
activeBrand: TypeBrand|null;
activeRange: TypeRange|null;
chickenRun: boolean;
konami: KonamiCode|null;
} {
return {
timeout: undefined,
loading: true,
route: useRoute(),
activeBrand: null,
activeRange: null,
chickenRun: false,
konami: null,
};
},
computed: {
showFooter(): boolean {
return this.route.name?.toString().startsWith("index") !== true;
},
showNavigation(): boolean {
return ["ranges-slug"].find(routeName => this.route.name?.toString().startsWith(routeName)) !== undefined &&
this.brandWithMultipleRanges;
},
brandWithMultipleRanges(): boolean {
if(!this.activeBrand) {
return false;
}
return this.activeBrand.ranges.length > 1;
}
},
watch: {
$route() {
this.setTimeout();
this.activeBrand = useAppStore().activeBrand;
this.activeRange = useAppStore().activeRange;
},
},
beforeMount() {
// * INIT STATES
window.ipcRendererObject.getJsonData().then((dataJson) => {
useAppStore().setupAppData(dataJson, this.$i18n.locale, String(this.$i18n.fallbackLocale));
this.loading = false;
this.setTimeout();
dataJson.fonts.forEach(font => this.injectFontFace(font.font_name, font.font));
this.redirectIfOneBrand(dataJson.items);
});
},
mounted() {
this.konami = new KonamiCode(() => {
this.$nextTick(() => {
this.chickenRun = true;
setTimeout(() => {this.chickenRun = false;}, 12000);
});
});
},
beforeUnmount() {
clearTimeout(this.timeout);
},
methods: {
t(text: string, params: Record<string,string> = {}, localeToUse: string|null = null): string {
return ToolboxHelper.trans(text, params, localeToUse);
},
transField(model: Typei18nModel, field: Typei18nFieldList) {
return ToolboxHelper.getTranslatableField(model, field);
},
injectFontFace(fontName: string, fontPath: string|null) {
const newStyle = document.createElement("style");
if(fontPath) {
newStyle.appendChild(document.createTextNode(`@font-face { font-family: '${fontName}'; src: url('/data/${fontPath}');}`));
newStyle.appendChild(document.createTextNode(`.f-${fontName} { font-family: '${fontName}' !important; }`));
} else {
newStyle.appendChild(document.createTextNode(`.f-${fontName} { font-family: ${fontName} !important; }`));
}
document.head.appendChild(newStyle);
},
/** Redirect to ranges.index if there is only one brand. */
redirectIfOneBrand(brands: Array<TypeBrand>): void {
if (brands.length === 1) {
useAppStore().setActiveBrand(brands[0]);
this.activeBrand = brands[0];
navigateTo(useLocaleRoute()({"name": "brands-slug", "params": {"slug": this.transField(brands[0], "slug")}}));
} else {
useAppStore().setActiveBrand(null);
this.activeBrand = null;
}
},
/** Prolong le timer pour revenir au home screen. */
setTimeout(): void {
if(this.timeout) {
clearTimeout(this.timeout);
}
this.$nextTick(() => {
this.timeout = setTimeout(() => {
useAppStore().setActiveRange(null);
window.ipcRendererObject.getJsonData().then((dataJson) => {
this.redirectIfOneBrand(dataJson.items);
});
navigateTo(useLocaleRoute()({"name": "index"}));
}, useAppStore().getSettings().home_timeout * 1000);
});
},
}
});
</script>
<style lang="postcss">
@import "~/assets/scss/style.scss";
@import "@fortawesome/fontawesome-svg-core/styles.css";
</style>
<style lang="scss">
.page-enter-active,
.page-leave-active {
transition: all 0.2s;
}
.page-enter-from,
.page-leave-to {
opacity: 0;
filter: blur(1rem);
}
</style>