75 lines
2.8 KiB
Vue
75 lines
2.8 KiB
Vue
<template>
|
|
<div class="min-h-[calc(100vh-4rem)] flex flex-col items-center justify-center p-4 md:p-8">
|
|
<div v-if="!isAuthenticated" class="text-center max-w-md px-4">
|
|
<h1 class="text-5xl md:text-6xl font-black text-blue-500 mb-6 tracking-tight">XFlow</h1>
|
|
<p class="text-slate-400 text-lg mb-10 leading-relaxed">Визуальное управление задачами в формате Obsidian Canvas.</p>
|
|
<NuxtLink
|
|
to="/login"
|
|
class="w-full md:w-auto inline-block px-10 py-4 bg-blue-600 hover:bg-blue-500 text-white rounded-2xl font-bold text-lg shadow-xl shadow-blue-900/40 transition-all transform active:scale-95"
|
|
>
|
|
Начать работу
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div v-else class="w-full max-w-6xl">
|
|
<div class="flex items-center justify-between mb-8 px-2">
|
|
<h1 class="text-3xl md:text-4xl font-bold text-white">Дашборд</h1>
|
|
<div class="md:hidden w-10 h-10 bg-slate-800 rounded-full flex items-center justify-center text-xl">✨</div>
|
|
</div>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<NuxtLink
|
|
to="/canvases"
|
|
class="p-6 bg-slate-800 border border-slate-700 rounded-lg hover:border-blue-500 transition group"
|
|
>
|
|
<div class="text-3xl mb-2">🗺️</div>
|
|
<h3 class="font-semibold group-hover:text-blue-400 transition">Проекты</h3>
|
|
<p class="text-sm text-slate-400">{{ homeStats.canvases }} канвасов доступно</p>
|
|
</NuxtLink>
|
|
|
|
<div class="p-6 bg-slate-800 border border-slate-700 rounded-lg">
|
|
<div class="text-3xl mb-2">✅</div>
|
|
<h3 class="font-semibold">Задачи</h3>
|
|
<p class="text-sm text-slate-400">{{ homeStats.tasks.completed }} / {{ homeStats.tasks.total }} выполнено</p>
|
|
</div>
|
|
|
|
<div class="p-6 bg-slate-800 border border-slate-700 rounded-lg">
|
|
<div class="text-3xl mb-2">🏆</div>
|
|
<h3 class="font-semibold">Ачивки</h3>
|
|
<p class="text-sm text-slate-400">{{ homeStats.achievements }} разблокировано</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ClientOnly>
|
|
<InstallPWA />
|
|
</ClientOnly>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
const { isAuthenticated, token } = useAuth()
|
|
const homeStats = ref({
|
|
canvases: 0,
|
|
tasks: { total: 0, completed: 0 },
|
|
achievements: 0
|
|
})
|
|
const loadingStats = ref(true)
|
|
|
|
const fetchHomeStats = async () => {
|
|
if (!isAuthenticated.value) return
|
|
try {
|
|
const data = await $fetch('/api/user/stats', {
|
|
headers: { Authorization: `Bearer ${token.value}` }
|
|
})
|
|
homeStats.value = data.stats
|
|
} catch (e) {
|
|
console.error('Failed to load home stats', e)
|
|
} finally {
|
|
loadingStats.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
fetchHomeStats()
|
|
})
|
|
</script>
|