mirror of
https://github.com/Spythere/srjp-td2.git
synced 2026-05-03 13:38:12 +00:00
chore: settings card; language button
This commit is contained in:
+13
@@ -11,15 +11,18 @@ import MainContainer from './components/App/MainContainer.vue';
|
|||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import { useApiStore } from './stores/api.store';
|
import { useApiStore } from './stores/api.store';
|
||||||
import { useGlobalStore } from './stores/global.store';
|
import { useGlobalStore } from './stores/global.store';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const originalDocumentTitle = document.title;
|
const originalDocumentTitle = document.title;
|
||||||
|
|
||||||
const apiStore = useApiStore();
|
const apiStore = useApiStore();
|
||||||
const globalStore = useGlobalStore();
|
const globalStore = useGlobalStore();
|
||||||
|
const i18n = useI18n();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
apiStore.setupAPIData();
|
apiStore.setupAPIData();
|
||||||
|
|
||||||
|
setupLocale();
|
||||||
setupDarkMode();
|
setupDarkMode();
|
||||||
loadStorageTimetables();
|
loadStorageTimetables();
|
||||||
setupAfterPrintClose();
|
setupAfterPrintClose();
|
||||||
@@ -45,4 +48,14 @@ function setupAfterPrintClose() {
|
|||||||
document.title = originalDocumentTitle;
|
document.title = originalDocumentTitle;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupLocale() {
|
||||||
|
if (window.localStorage.getItem('locale') == null) {
|
||||||
|
const browserLang = window.navigator.language;
|
||||||
|
if (browserLang == 'pl-PL') i18n.locale.value = browserLang == 'pl-PL' ? 'pl' : 'en';
|
||||||
|
window.localStorage.setItem('locale', i18n.locale.value);
|
||||||
|
} else {
|
||||||
|
i18n.locale.value = window.localStorage.getItem('locale')!;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,18 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav class="bg-zinc-900 w-full p-1 print:hidden flex justify-between items-center">
|
<nav class="bg-zinc-900 w-full p-1 print:hidden flex justify-between items-center relative">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img src="/favicon.svg" class="size-8 inline" />
|
<img src="/favicon.svg" class="size-8 inline" />
|
||||||
<b class="ml-2 text-lg"
|
<b class="ml-2 text-lg"
|
||||||
>Rozkładownik TD2 <sup class="font-semibold text-zinc-300">{{ version }}</sup></b
|
>Rozkładownik TD2 <sup class="font-semibold text-zinc-300">{{ version }}</sup></b
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="apiMode == 'mocking'"><ExclamationTriangleIcon class="size-6 inline mr-1 text-yellow-400" /> API mocking</div>
|
|
||||||
|
<div>
|
||||||
|
<button class="bg-slate-600 p-1 px-2 rounded-md hover:bg-slate-500 flex items-center" @click="changeLang()">
|
||||||
|
<LanguageIcon class="size-5 inline-block align-middle mr-2" /> {{ i18n.locale.value == 'pl' ? 'POL' : 'ENG' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- <div v-if="apiMode == 'mocking'"><ExclamationTriangleIcon class="size-6 inline mr-1 text-yellow-400" /> API mocking</div> -->
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { LanguageIcon } from '@heroicons/vue/16/solid';
|
||||||
import { version } from '../../../package.json';
|
import { version } from '../../../package.json';
|
||||||
import { ExclamationTriangleIcon } from '@heroicons/vue/16/solid';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const apiMode = import.meta.env.VITE_API_MODE;
|
const i18n = useI18n();
|
||||||
|
|
||||||
|
function changeLang(locale?: string) {
|
||||||
|
i18n.locale.value = locale ?? i18n.locale.value == 'pl' ? 'en' : 'pl';
|
||||||
|
window.localStorage.setItem('locale', i18n.locale.value);
|
||||||
|
}
|
||||||
|
// const apiMode = import.meta.env.VITE_API_MODE;
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fixed top-0 left-0 w-screen h-screen z-10 bg-black bg-opacity-70" v-if="globalStore.showSettings" @click="globalStore.showSettings = false">
|
||||||
|
<!-- <div class="fixed top-0 left-0 w-screen h-screen z-10" v-show="showSettings" @click="showSettings = false"></div> -->
|
||||||
|
|
||||||
|
<!-- <div class="absolute mt-2 top-full right-0 p-1 rounded-md bg-slate-600 w-full z-20 max-w-[250px]" v-show="showSettings"></div> -->
|
||||||
|
|
||||||
|
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] bg-zinc-800 p-2 h-[500px] z-20">
|
||||||
|
<div class="grid grid-cols-2 gap-2">
|
||||||
|
<button
|
||||||
|
class="bg-slate-900 p-1 rounded-md hover:bg-slate-800"
|
||||||
|
:class="{ 'font-bold text-yellow-400': i18n.locale.value == 'pl' }"
|
||||||
|
@click="chooseLang('pl')"
|
||||||
|
>
|
||||||
|
POLSKI
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="bg-slate-900 p-1 rounded-md hover:bg-slate-800"
|
||||||
|
:class="{ 'font-bold text-yellow-400': i18n.locale.value == 'en' }"
|
||||||
|
@click="chooseLang('en')"
|
||||||
|
>
|
||||||
|
ENGLISH
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useGlobalStore } from '../../stores/global.store';
|
||||||
|
|
||||||
|
const i18n = useI18n();
|
||||||
|
const globalStore = useGlobalStore();
|
||||||
|
|
||||||
|
function chooseLang(locale: string) {
|
||||||
|
i18n.locale.value = locale;
|
||||||
|
window.localStorage.setItem('locale', i18n.locale.value);
|
||||||
|
globalStore.showSettings = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
v-if="globalStore.viewMode == 'storage'"
|
v-if="globalStore.viewMode == 'storage'"
|
||||||
class="bg-zinc-800 p-1 rounded-md print:hidden w-full"
|
class="bg-zinc-800 p-1 rounded-md print:hidden w-full"
|
||||||
:placeholder="$t('train-select-placeholder')"
|
:placeholder="$t('train-search-placeholder')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button class="bg-zinc-800 p-1 rounded-md hover:bg-zinc-700" @click="toggleDarkMode">
|
<button class="bg-zinc-800 p-1 rounded-md hover:bg-zinc-700" @click="toggleDarkMode">
|
||||||
|
|||||||
+14
-2
@@ -1,4 +1,4 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, type Directive } from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
|
|
||||||
@@ -7,4 +7,16 @@ import i18n from './i18n';
|
|||||||
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
|
||||||
createApp(App).use(i18n).use(pinia).mount('#app');
|
const clickOutsideDirective: Directive = {
|
||||||
|
mounted(el, binding) {
|
||||||
|
el.clickOutsideEvent = (event: Event) => {
|
||||||
|
if (!(el == event.target || el.contains(event.target))) {
|
||||||
|
binding.value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('click', el.clickOutsideEvent);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
createApp(App).use(i18n).use(pinia).directive('click-outside', clickOutsideDirective).mount('#app');
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
|
|
||||||
generatedDate: null as Date | null,
|
generatedDate: null as Date | null,
|
||||||
generatedMs: 0,
|
generatedMs: 0,
|
||||||
|
|
||||||
|
showSettings: false,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
activeTimetableTrains() {
|
activeTimetableTrains() {
|
||||||
|
|||||||
Reference in New Issue
Block a user