119 lines
3.8 KiB
Vue
119 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import {
|
|
Moon,
|
|
Sun,
|
|
Check,
|
|
Globe2,
|
|
Palette,
|
|
ShieldCheck,
|
|
} from "lucide-vue-next";
|
|
const { locale, setLocale, t } = useI18n();
|
|
useHead({ title: computed(() => `${t("general.title")} · Webka`) });
|
|
const theme = useCookie("webka_theme", { default: () => "dark" });
|
|
const accent = useCookie("webka_accent", { default: () => "#c3f66b" });
|
|
const colors = [
|
|
{ color: "#c3f66b", key: "lime" },
|
|
{ color: "#91c9ff", key: "blue" },
|
|
{ color: "#c9afff", key: "violet" },
|
|
{ color: "#ffc899", key: "peach" },
|
|
];
|
|
</script>
|
|
<template>
|
|
<div class="page settings-page narrow">
|
|
<div class="page-heading">
|
|
<div>
|
|
<div class="eyebrow">{{ $t("general.eyebrow") }}</div>
|
|
<h1>{{ $t("general.title") }}<span class="heading-dot">.</span></h1>
|
|
<p class="muted">{{ $t("general.subtitle") }}</p>
|
|
</div>
|
|
</div>
|
|
<section class="content-panel">
|
|
<div class="section-heading">
|
|
<h2><Palette :size="21" />{{ $t("general.appearance") }}</h2>
|
|
</div>
|
|
<div class="theme-options">
|
|
<button :class="{ selected: theme === 'dark' }" @click="theme = 'dark'">
|
|
<div class="theme-preview dark-preview"><span /><span /><span /></div>
|
|
<span
|
|
><Moon :size="18" />{{ $t("general.dark")
|
|
}}<Check v-if="theme === 'dark'" :size="17"
|
|
/></span></button
|
|
><button
|
|
:class="{ selected: theme === 'light' }"
|
|
@click="theme = 'light'"
|
|
>
|
|
<div class="theme-preview light-preview">
|
|
<span /><span /><span />
|
|
</div>
|
|
<span
|
|
><Sun :size="18" />{{ $t("general.light")
|
|
}}<Check v-if="theme === 'light'" :size="17"
|
|
/></span>
|
|
</button>
|
|
</div>
|
|
<div class="setting-row">
|
|
<div>
|
|
<h3>{{ $t("general.accent") }}</h3>
|
|
<p>{{ $t("general.accentHint") }}</p>
|
|
</div>
|
|
<div class="swatches">
|
|
<button
|
|
v-for="color in colors"
|
|
:key="color.color"
|
|
:style="{ background: color.color }"
|
|
:aria-label="$t(`colors.${color.key}`)"
|
|
:aria-pressed="accent === color.color"
|
|
@click="accent = color.color"
|
|
>
|
|
<Check v-if="accent === color.color" :size="19" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section class="content-panel">
|
|
<div class="section-heading">
|
|
<h2><Globe2 :size="21" />{{ $t("general.language") }}</h2>
|
|
</div>
|
|
<div class="setting-row">
|
|
<div>
|
|
<h3>{{ $t("general.displayLanguage") }}</h3>
|
|
<p>{{ $t("general.languageHint") }}</p>
|
|
</div>
|
|
<select
|
|
:value="locale"
|
|
:aria-label="$t('general.language')"
|
|
@change="
|
|
setLocale(
|
|
($event.target as HTMLSelectElement).value as 'en' | 'ru' | 'es',
|
|
)
|
|
"
|
|
>
|
|
<option value="en">English</option>
|
|
<option value="ru">Русский</option>
|
|
<option value="es">Español</option>
|
|
</select>
|
|
</div>
|
|
</section>
|
|
<section class="content-panel">
|
|
<div class="section-heading">
|
|
<h2><ShieldCheck :size="21" />{{ $t("general.privacy") }}</h2>
|
|
</div>
|
|
<div class="setting-row">
|
|
<div>
|
|
<h3>{{ $t("general.loginRequired") }}</h3>
|
|
<p>{{ $t("general.loginHint") }}</p>
|
|
</div>
|
|
<span class="role-tag admin">{{ $t("general.alwaysOn") }}</span>
|
|
</div>
|
|
<div class="setting-row">
|
|
<div>
|
|
<h3>{{ $t("general.localOnly") }}</h3>
|
|
<p>{{ $t("general.localHint") }}</p>
|
|
</div>
|
|
<span class="status-dot live" />
|
|
</div>
|
|
</section>
|
|
<p class="settings-footnote">{{ $t("general.savedLocally") }}</p>
|
|
</div>
|
|
</template>
|