merge: hub auth-aware ghosting + login dock slot

This commit is contained in:
Padreug 2026-05-02 14:18:06 +02:00
commit 95d8b2e307

View file

@ -1,5 +1,6 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useAuth } from '@/composables/useAuthService'
import { useTheme } from '@/components/theme-provider'
import { useLocale } from '@/composables/useLocale'
@ -7,7 +8,7 @@ import { toast } from 'vue-sonner'
import {
Castle, ListTodo, Newspaper, MessageCircle, Wallet, CalendarDays,
Store, UtensilsCrossed,
User as UserIcon, Sun, Moon, Monitor, Globe, Coins,
User as UserIcon, LogIn, Sun, Moon, Monitor, Globe, Coins,
} from 'lucide-vue-next'
import {
DropdownMenu, DropdownMenuTrigger, DropdownMenuContent,
@ -19,6 +20,7 @@ import {
} from '@/components/ui/sheet'
import ProfileSettings from '@/modules/base/components/ProfileSettings.vue'
const router = useRouter()
const { isAuthenticated } = useAuth()
const { theme, setTheme, currentTheme } = useTheme()
const { currentLocale, locales, setLocale } = useLocale()
@ -31,6 +33,8 @@ interface Module {
glow: string
envKey?: string
status?: string
/** When true, the tile is ghosted out unless the user is logged in. */
authRequired?: boolean
/** Unread count for the corner badge. Wire to real data via #32. */
unread?: number
}
@ -39,12 +43,12 @@ interface Module {
const modules: Module[] = [
{ label: 'Restaurant', chakra: 'Muladhara', icon: UtensilsCrossed, bgClass: '', glow: 'rgba(255,80,80,0.5)', status: 'coming soon' },
{ label: 'Market', chakra: 'Muladhara', icon: Store, bgClass: '', glow: 'rgba(255,80,80,0.5)', envKey: 'VITE_HUB_MARKET_URL', status: 'alpha' },
{ label: 'Wallet', chakra: 'Manipura', icon: Wallet, bgClass: '', glow: 'rgba(255,200,0,0.5)', envKey: 'VITE_HUB_WALLET_URL', status: 'alpha' },
{ label: 'Wallet', chakra: 'Manipura', icon: Wallet, bgClass: '', glow: 'rgba(255,200,0,0.5)', envKey: 'VITE_HUB_WALLET_URL', status: 'alpha', authRequired: true },
{ label: 'Activities', chakra: 'Swadhisthana', icon: CalendarDays, bgClass: '', glow: 'rgba(255,165,0,0.5)', envKey: 'VITE_HUB_ACTIVITIES_URL', status: 'beta' },
{ label: 'Chat', chakra: 'Anahata', icon: MessageCircle, bgClass: '', glow: 'rgba(0,200,80,0.5)', envKey: 'VITE_HUB_CHAT_URL', status: 'alpha' },
{ label: 'Chat', chakra: 'Anahata', icon: MessageCircle, bgClass: '', glow: 'rgba(0,200,80,0.5)', envKey: 'VITE_HUB_CHAT_URL', status: 'alpha', authRequired: true },
{ label: 'Forum', chakra: 'Vishuddha', icon: Newspaper, bgClass: '', glow: 'rgba(60,120,255,0.5)', envKey: 'VITE_HUB_FORUM_URL', status: 'alpha' },
{ label: 'Tasks', chakra: 'Ajna', icon: ListTodo, bgClass: '', glow: 'rgba(99,80,200,0.5)', envKey: 'VITE_HUB_TASKS_URL', status: 'alpha' },
{ label: 'Castle', chakra: 'Sahasrara', icon: Castle, bgClass: '', glow: 'rgba(160,80,220,0.5)', envKey: 'VITE_HUB_CASTLE_URL', status: 'beta' },
{ label: 'Castle', chakra: 'Sahasrara', icon: Castle, bgClass: '', glow: 'rgba(160,80,220,0.5)', envKey: 'VITE_HUB_CASTLE_URL', status: 'beta', authRequired: true },
]
// Crown at top, root at bottom
const orderedModules = computed(() => [...modules].reverse())
@ -53,6 +57,8 @@ const token = computed(() => localStorage.getItem('lnbits_access_token') || '')
function hubLink(m: Module): string | null {
if (!m.envKey) return null
// Auth-only modules (wallet, chat, castle) are ghosted when not logged in.
if (m.authRequired && !isAuthenticated.value) return null
const url = import.meta.env[m.envKey] as string | undefined
if (!url) return null
if (isAuthenticated.value && token.value) {
@ -134,8 +140,8 @@ function notImplemented() {
style="padding-bottom: env(safe-area-inset-bottom)"
>
<div class="flex items-center justify-around h-14 max-w-lg mx-auto">
<!-- Profile -->
<Sheet v-model:open="showProfile">
<!-- Profile (when logged in) / Log in (when not) -->
<Sheet v-if="isAuthenticated" v-model:open="showProfile">
<SheetTrigger as-child>
<button class="flex flex-col items-center justify-center gap-0.5 flex-1 h-full text-muted-foreground hover:text-foreground transition-colors">
<UserIcon class="w-5 h-5" />
@ -152,6 +158,14 @@ function notImplemented() {
</div>
</SheetContent>
</Sheet>
<button
v-else
class="flex flex-col items-center justify-center gap-0.5 flex-1 h-full text-muted-foreground hover:text-foreground transition-colors"
@click="router.push('/login')"
>
<LogIn class="w-5 h-5" />
<span class="text-[10px] font-medium">Log in</span>
</button>
<!-- Theme -->
<DropdownMenu>