feat(frontend): settings window, i18n, admin UI, books, tasks, calendar, timer
ci / backend (push) Canceled after 0s
ci / frontend (push) Canceled after 0s

- Settings window with tabs: profile (name, email, avatar, password),
  appearance (light/dark/system), language (de/en/zh), background
  (gradient presets, custom URL, blur toggle); persisted server-side
- i18n dictionaries (de/en/zh) applied across nav, sidebar, tasks,
  calendar, time tracking, admin, invites and comments
- Greeting header with time-of-day message, live clock and date; cooler
  theme, cards, kanban, calendar grid and data-table styling
- Shared sidebar: nav, collapsible books with per-book pages, top-level
  pages, search; user chip opens settings
- Tasks kanban with priorities, overdue flags and book/page links;
  calendar month view fed by task deadlines; time view with entries,
  durations and totals; top-right live timer with optional book link
- User discovery autocomplete in the invite card; editor gains tables
  and checklists; standalone theme buttons removed
This commit is contained in:
x3
2026-09-22 13:56:26 +02:00
parent b852583499
commit fb396d313a
30 changed files with 1698 additions and 190 deletions
+28 -5
View File
@@ -1,17 +1,40 @@
<script setup>
import { onMounted } from 'vue';
import { computed, onMounted } from 'vue';
import { useAuthStore } from './stores/auth';
import { useThemeStore } from './stores/theme';
import ThemeToggle from './components/ThemeToggle.vue';
import { useLocaleStore } from './stores/locale';
import { useUiStore } from './stores/ui';
import SettingsWindow from './components/SettingsWindow.vue';
import TimeTrackerButton from './components/TimeTrackerButton.vue';
const auth = useAuthStore();
const theme = useThemeStore();
onMounted(() => theme.apply());
const locale = useLocaleStore();
const ui = useUiStore();
const bgStyle = computed(() => {
const bg = auth.user?.bgImage || '';
if (!bg) return {};
const style = { backgroundImage: bg.startsWith('http') ? `url("${bg}")` : bg };
if (auth.user?.bgBlur !== false) style.filter = 'blur(14px) brightness(0.85)';
return style;
});
onMounted(() => {
locale.set(locale.locale);
theme.apply();
auth.applyPrefs();
});
</script>
<template>
<div>
<div style="position: fixed; top: 12px; right: 12px; z-index: 50">
<ThemeToggle />
<div v-if="bgStyle.backgroundImage" class="bg-layer" :style="bgStyle"></div>
<div v-if="auth.isLoggedIn" class="top-right">
<TimeTrackerButton />
<button class="ghost icon-btn" @click="ui.openSettings()" title="⚙️">⚙️</button>
</div>
<router-view />
<SettingsWindow />
</div>
</template>