Add initial project structure with backend and frontend setup
- Created backend structure with Go, including main application logic and API endpoints. - Added Docker support for both development and production environments. - Introduced frontend using Nuxt 3 with Tailwind CSS for styling. - Included configuration files for Docker and environment variables. - Established basic documentation for contributing, development, and deployment processes. - Set up .gitignore and .dockerignore files to manage ignored files in the repository.
This commit is contained in:
103
frontend-nuxt/layouts/default.vue
Normal file
103
frontend-nuxt/layouts/default.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="h-screen flex flex-col bg-base-100 overflow-hidden">
|
||||
<header class="navbar bg-base-200/80 backdrop-blur px-4 gap-2 shrink-0">
|
||||
<NuxtLink to="/" class="text-lg font-semibold hover:opacity-80">{{ title }}</NuxtLink>
|
||||
<div class="flex-1" />
|
||||
<NuxtLink v-if="!isLogin" to="/" class="btn btn-ghost btn-sm">Map</NuxtLink>
|
||||
<NuxtLink v-if="!isLogin" to="/profile" class="btn btn-ghost btn-sm">Profile</NuxtLink>
|
||||
<NuxtLink v-if="!isLogin && isAdmin" to="/admin" class="btn btn-ghost btn-sm">Admin</NuxtLink>
|
||||
<button
|
||||
v-if="!isLogin && me"
|
||||
type="button"
|
||||
class="btn btn-ghost btn-sm btn-outline"
|
||||
@click="doLogout"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
<label class="swap swap-rotate btn btn-ghost btn-sm">
|
||||
<input type="checkbox" v-model="dark" @change="toggleTheme" />
|
||||
<span class="swap-off">☀️</span>
|
||||
<span class="swap-on">🌙</span>
|
||||
</label>
|
||||
<span v-if="live" class="badge badge-success badge-sm">Live</span>
|
||||
</header>
|
||||
<main class="flex-1 min-h-0 relative">
|
||||
<slot />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const THEME_KEY = 'hnh-map-theme'
|
||||
|
||||
function getInitialDark(): boolean {
|
||||
if (import.meta.client) {
|
||||
const stored = localStorage.getItem(THEME_KEY)
|
||||
if (stored === 'dark') return true
|
||||
if (stored === 'light') return false
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const title = ref('HnH Map')
|
||||
const dark = ref(false)
|
||||
const live = ref(false)
|
||||
const me = ref<{ username?: string; auths?: string[] } | null>(null)
|
||||
|
||||
const { isLoginPath } = useAppPaths()
|
||||
const isLogin = computed(() => isLoginPath(route.path))
|
||||
const isAdmin = computed(() => !!me.value?.auths?.includes('admin'))
|
||||
|
||||
async function loadMe() {
|
||||
if (isLogin.value) return
|
||||
try {
|
||||
me.value = await useMapApi().me()
|
||||
} catch {
|
||||
me.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadConfig() {
|
||||
if (isLogin.value) return
|
||||
try {
|
||||
const config = await useMapApi().getConfig()
|
||||
if (config?.title) title.value = config.title
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
dark.value = getInitialDark()
|
||||
const html = document.documentElement
|
||||
html.setAttribute('data-theme', dark.value ? 'dark' : 'light')
|
||||
})
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
(path) => {
|
||||
if (!isLoginPath(path)) loadMe().then(loadConfig)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function toggleTheme() {
|
||||
const html = document.documentElement
|
||||
if (dark.value) {
|
||||
html.setAttribute('data-theme', 'dark')
|
||||
localStorage.setItem(THEME_KEY, 'dark')
|
||||
} else {
|
||||
html.setAttribute('data-theme', 'light')
|
||||
localStorage.setItem(THEME_KEY, 'light')
|
||||
}
|
||||
}
|
||||
|
||||
async function doLogout() {
|
||||
await useMapApi().logout()
|
||||
await router.push('/login')
|
||||
me.value = null
|
||||
}
|
||||
|
||||
defineExpose({ setLive: (v: boolean) => { live.value = v } })
|
||||
</script>
|
||||
Reference in New Issue
Block a user