mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
refactor(web): login page
This commit is contained in:
@@ -6,7 +6,7 @@ import { computed } from 'vue'
|
||||
export type Locale = 'en' | 'zh'
|
||||
|
||||
const i18n = createI18n<typeof en | typeof zh, Locale>({
|
||||
locale: 'zh',
|
||||
locale: 'en',
|
||||
legacy: false,
|
||||
fallbackLocale: 'en',
|
||||
messages: {
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
<template>
|
||||
<section class="w-screen h-screen flex *:m-auto bg-linear-to-t from-[#BFA4A0] to-[#7784AC] ">
|
||||
<section class="w-screen h-screen flex *:m-auto bg-background relative">
|
||||
<div class="absolute top-6 right-6 flex items-center gap-2">
|
||||
<Select
|
||||
:model-value="language"
|
||||
@update:model-value="(v) => v && setLanguage(v as Locale)"
|
||||
>
|
||||
<SelectTrigger class="w-28 h-9">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="en">English</SelectItem>
|
||||
<SelectItem value="zh">中文</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
@click="toggleTheme"
|
||||
>
|
||||
<Sun v-if="theme === 'dark'" class="size-5" />
|
||||
<Moon v-else class="size-5" />
|
||||
</Button>
|
||||
</div>
|
||||
<section class="w-full max-w-sm flex flex-col gap-10 ">
|
||||
<section>
|
||||
<h3
|
||||
class="scroll-m-20 text-3xl tracking-wide font-semibold text-white text-center"
|
||||
style="font-family: 'Source Han Serif CN', 'Noto Serif SC', 'STSong', 'SimSun', serif;"
|
||||
class="scroll-m-20 text-3xl tracking-wide font-semibold text-foreground text-center"
|
||||
>
|
||||
{{ $t('auth.welcome') }}
|
||||
</h3>
|
||||
@@ -96,19 +119,36 @@ import {
|
||||
FormItem,
|
||||
Label,
|
||||
Spinner,
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@memoh/ui'
|
||||
import { Sun, Moon } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { useForm } from 'vee-validate'
|
||||
import * as z from 'zod'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { useSettingsStore } from '@/store/settings'
|
||||
import { ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { postAuthLogin } from '@memoh/sdk'
|
||||
import type { Locale } from '@/i18n'
|
||||
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
const settingsStore = useSettingsStore()
|
||||
const { theme, language } = storeToRefs(settingsStore)
|
||||
const { setLanguage, setTheme } = settingsStore
|
||||
|
||||
const toggleTheme = () => {
|
||||
setTheme(theme.value === 'light' ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
username: z.string().min(1),
|
||||
|
||||
@@ -23,6 +23,78 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Display Settings -->
|
||||
<section>
|
||||
<h6 class="mb-2 flex items-center">
|
||||
<FontAwesomeIcon
|
||||
:icon="['fas', 'gear']"
|
||||
class="mr-2"
|
||||
/>
|
||||
{{ $t('settings.display') }}
|
||||
</h6>
|
||||
<Separator />
|
||||
<div class="mt-4 space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<Label>{{ $t('settings.language') }}</Label>
|
||||
<Select
|
||||
:model-value="language"
|
||||
@update:model-value="(v) => v && setLanguage(v as Locale)"
|
||||
>
|
||||
<SelectTrigger class="w-40">
|
||||
<SelectValue :placeholder="$t('settings.languagePlaceholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="zh">
|
||||
{{ $t('settings.langZh') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="en">
|
||||
{{ $t('settings.langEn') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<Separator />
|
||||
<div class="flex items-center justify-between">
|
||||
<Label>{{ $t('settings.theme') }}</Label>
|
||||
<Select
|
||||
:model-value="theme"
|
||||
@update:model-value="(v) => v && setTheme(v as 'light' | 'dark')"
|
||||
>
|
||||
<SelectTrigger class="w-40">
|
||||
<SelectValue :placeholder="$t('settings.themePlaceholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="light">
|
||||
{{ $t('settings.themeLight') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="dark">
|
||||
{{ $t('settings.themeDark') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Logout -->
|
||||
<section>
|
||||
<Separator class="mb-4" />
|
||||
<ConfirmPopover
|
||||
:message="$t('auth.logoutConfirm')"
|
||||
@confirm="onLogout"
|
||||
>
|
||||
<template #trigger>
|
||||
<Button>
|
||||
{{ $t('auth.logout') }}
|
||||
</Button>
|
||||
</template>
|
||||
</ConfirmPopover>
|
||||
</section>
|
||||
|
||||
<!-- User Profile -->
|
||||
<section>
|
||||
<h6 class="mb-2 flex items-center">
|
||||
@@ -240,78 +312,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Display Settings -->
|
||||
<section>
|
||||
<h6 class="mb-2 flex items-center">
|
||||
<FontAwesomeIcon
|
||||
:icon="['fas', 'gear']"
|
||||
class="mr-2"
|
||||
/>
|
||||
{{ $t('settings.display') }}
|
||||
</h6>
|
||||
<Separator />
|
||||
<div class="mt-4 space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<Label>{{ $t('settings.language') }}</Label>
|
||||
<Select
|
||||
:model-value="language"
|
||||
@update:model-value="(v) => v && setLanguage(v as Locale)"
|
||||
>
|
||||
<SelectTrigger class="w-40">
|
||||
<SelectValue :placeholder="$t('settings.languagePlaceholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="zh">
|
||||
{{ $t('settings.langZh') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="en">
|
||||
{{ $t('settings.langEn') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<Separator />
|
||||
<div class="flex items-center justify-between">
|
||||
<Label>{{ $t('settings.theme') }}</Label>
|
||||
<Select
|
||||
:model-value="theme"
|
||||
@update:model-value="(v) => v && setTheme(v as 'light' | 'dark')"
|
||||
>
|
||||
<SelectTrigger class="w-40">
|
||||
<SelectValue :placeholder="$t('settings.themePlaceholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="light">
|
||||
{{ $t('settings.themeLight') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="dark">
|
||||
{{ $t('settings.themeDark') }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Logout -->
|
||||
<section>
|
||||
<Separator class="mb-4" />
|
||||
<ConfirmPopover
|
||||
:message="$t('auth.logoutConfirm')"
|
||||
@confirm="onLogout"
|
||||
>
|
||||
<template #trigger>
|
||||
<Button variant="outline">
|
||||
{{ $t('auth.logout') }}
|
||||
</Button>
|
||||
</template>
|
||||
</ConfirmPopover>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface Settings {
|
||||
export const useSettingsStore = defineStore('settings', () => {
|
||||
const colorMode = useColorMode()
|
||||
const i18n = useI18n()
|
||||
const language = useStorage<Locale>('language', 'zh')
|
||||
const language = useStorage<Locale>('language', 'en')
|
||||
const theme = useStorage<'light' | 'dark'>('theme', 'light')
|
||||
|
||||
colorMode.value = theme.value
|
||||
|
||||
Reference in New Issue
Block a user