Merge branch '20-settings-page' into 'main'

Resolve "settings page"

Closes #20

See merge request htwk-software/htwkalender-pwa!12
This commit is contained in:
Elmar Kresse
2024-07-02 10:08:36 +00:00
10 changed files with 103 additions and 52 deletions

View File

@ -21,8 +21,13 @@ import MenuBar from "./components/MenuBar.vue";
import { RouteRecordName, RouterView } from "vue-router";
import CalendarPreview from "./components/CalendarPreview.vue";
import moduleStore from "./store/moduleStore.ts";
import { provide, ref } from "vue";
import { onMounted, provide, ref } from "vue";
import { VueQueryDevtools } from "@tanstack/vue-query-devtools";
import settingsStore from "@/store/settingsStore.ts";
import { setTheme } from "@/helpers/theme.ts";
import { usePrimeVue } from "primevue/config";
const primeVue = usePrimeVue();
const disabledPages = [
"room-finder",
@ -33,7 +38,7 @@ const disabledPages = [
"edit-calendar",
"rooms",
"free-rooms",
"room-schedule",
"room-schedule"
];
const store = moduleStore();
@ -49,14 +54,26 @@ const updateMobile = () => {
};
updateMobile();
window.addEventListener("resize", updateMobile);
const settings = settingsStore();
const emit = defineEmits(["dark-mode-toggled"]);
onMounted(() => {
// set theme matching browser preference
settings.setDarkMode(window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches)
setTheme(settings, primeVue, emit);
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
settings.setDarkMode(e.matches)
setTheme(settings, primeVue, emit);
});
});
</script>
<template>
<MenuBar />
<RouterView v-slot="{ Component, route }">
<transition name="scale" mode="out-in">
<transition mode="out-in" name="scale">
<div :key="route.name ?? ''" class="origin-near-top">
<component :is="Component" />
</div>

View File

@ -17,43 +17,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { toggleTheme } from "@/helpers/theme.ts";
import settingsStore from "@/store/settingsStore.ts";
import { computed } from "vue";
import { usePrimeVue } from "primevue/config";
const PrimeVue = usePrimeVue();
const primeVue = usePrimeVue();
const emit = defineEmits(["dark-mode-toggled"]);
const isDark = ref(true);
const darkTheme = ref("lara-dark-blue"),
lightTheme = ref("lara-light-blue");
const store = settingsStore();
function toggleTheme() {
isDark.value = !isDark.value;
setTheme(isDark.value);
}
const isDark = computed(() => store.isDark);
function setTheme(shouldBeDark: boolean) {
isDark.value = shouldBeDark;
const newTheme = isDark.value ? darkTheme.value : lightTheme.value,
oldTheme = isDark.value ? lightTheme.value : darkTheme.value;
PrimeVue.changeTheme(oldTheme, newTheme, "theme-link", () => {});
emit("dark-mode-toggled", isDark.value);
}
onMounted(() => {
// set theme matching browser preference
setTheme(
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches,
);
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (e) => {
setTheme(e.matches);
});
});
</script>
<template>
@ -63,7 +39,7 @@ onMounted(() => {
class="p-button-rounded md:w-auto"
style="margin-right: 1rem"
:severity="isDark ? 'warning' : 'success'"
@click="toggleTheme()"
@click="toggleTheme(store, primeVue, emit)"
>
<i v-if="isDark" class="pi pi-sun"></i>
<i v-else class="pi pi-moon"></i>

View File

@ -18,7 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
<script lang="ts" setup>
import { computed } from "vue";
import localeStore from "../store/localeStore.ts";
import settingsStore from "../store/settingsStore.ts";
import { useI18n } from "vue-i18n";
import { usePrimeVue } from "primevue/config";
import primeVue_de from "@/i18n/translations/primevue/prime_vue_local_de.json";
@ -43,7 +43,7 @@ function displayCountry(code: string) {
const primeVueConfig = usePrimeVue();
function updateLocale(locale: string) {
localeStore().setLocale(locale);
settingsStore().setLocale(locale);
if (locale === "de") {
primeVueConfig.config.locale = primeVue_de;
@ -54,7 +54,7 @@ function updateLocale(locale: string) {
}
}
updateLocale(localeStore().locale);
updateLocale(settingsStore().locale);
</script>
<template>
<Dropdown

View File

@ -0,0 +1,51 @@
//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
//Copyright (C) 2024 HTWKalender support@htwkalender.de
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU Affero General Public License for more details.
//You should have received a copy of the GNU Affero General Public License
//along with this program. If not, see <https://www.gnu.org/licenses/>.
import { ref } from "vue";
import { Store } from "pinia";
import { PrimeVueChangeTheme } from "primevue/config";
import { EmitFn } from "primevue/ts-helpers";
import { RemovableRef } from "@vueuse/core";
const darkTheme = ref("lara-dark-blue"),
lightTheme = ref("lara-light-blue");
type SettingsStore = Store<"settingsStore", { locale: RemovableRef<string>, isDark: boolean }, NonNullable<unknown>, {
setLocale(locale: string): void,
setDarkMode(isDark: boolean): void,
getDarkMode(): boolean
}>;
export function toggleTheme(
store: SettingsStore,
primeVue: { changeTheme: PrimeVueChangeTheme },
emit: EmitFn<"dark-mode-toggled"[]>,
): void {
store.setDarkMode(!store.isDark);
setTheme(store, primeVue, emit);
}
export function setTheme(
store: SettingsStore,
{ changeTheme }: { changeTheme: PrimeVueChangeTheme },
emit: EmitFn<"dark-mode-toggled"[]>
) {
const isDark = ref(store.isDark);
const newTheme = isDark.value ? darkTheme.value : lightTheme.value,
oldTheme = isDark.value ? lightTheme.value : darkTheme.value;
changeTheme(oldTheme, newTheme, "theme-link", () => { });
emit("dark-mode-toggled", isDark.value);
}

View File

@ -18,7 +18,7 @@ import { createI18n } from "vue-i18n";
import en from "./translations/en.json";
import de from "./translations/de.json";
import ja from "./translations/ja.json";
import localeStore from "../store/localeStore.ts";
import settingsStore from "../store/settingsStore.ts";
// Private instance of VueI18n object
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -27,7 +27,7 @@ let _i18n: any;
function setup() {
_i18n = createI18n({
legacy: false,
locale: localeStore().locale,
locale: settingsStore().locale,
fallbackLocale: "en",
messages: {
en,

View File

@ -70,10 +70,10 @@ app.use(VueQueryPlugin, {
queryClientConfig: {
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
},
refetchOnWindowFocus: false
}
}
}
});
app.use(PrimeVue);

View File

@ -17,17 +17,24 @@
import { defineStore } from "pinia";
import { useLocalStorage } from "@vueuse/core";
const localeStore = defineStore("localeStore", {
const settingsStore = defineStore("settingsStore", {
state: () => {
return {
locale: useLocalStorage("locale", "en"), //useLocalStorage takes in a key of 'count' and default value of 0
isDark: true,
};
},
actions: {
setLocale(locale: string) {
this.locale = locale;
},
setDarkMode(isDark: boolean) {
this.isDark = isDark;
},
getDarkMode(): boolean {
return this.isDark;
}
},
});
export default localeStore;
export default settingsStore;

View File

@ -47,9 +47,9 @@ const hasContent = computed(() => {
class="flex align-items-center justify-content-center gap-3 mx-2 mb-4 transition-rolldown"
:class="{ 'md:mt-8': hideContent }"
>
<h3 class="text-4xl">
<h1 class="text-4xl">
{{ headline }}
</h3>
</h1>
<i v-if="icon" :class="icon" style="font-size: 2rem"></i>
</div>
<div v-if="subTitle" class="flex justify-content-center">

View File

@ -21,9 +21,9 @@ function handleDarkModeToggled(isDarkVar: boolean) {
<div
class="flex align-items-center justify-content-center gap-3 mx-2 mb-4 transition-rolldown md:mt-8"
>
<h3 class="text-4xl">
<h1 class="text-4xl">
{{ $t("settings.headline") }}
</h3>
</h1>
<i v-if="icon" :class="icon" style="font-size: 2rem"></i>
</div>
<div v-if="$t('settings.subTitle')" class="flex justify-content-center">

View File

@ -34,9 +34,9 @@ async function nextStep() {
<template>
<div class="flex flex-column align-items-center w-full mb-7">
<div class="flex align-items-center justify-content-center m-2">
<h3>
<h1>
{{ $t("additionalModules.subTitle") }}
</h3>
</h1>
</div>
<AdditionalModuleTable />
<div