strat-gameplay-webapp/frontend-sba/layouts/default.vue
Cal Corum e0c12467b0 CLAUDE: Improve UX with single-click OAuth, enhanced games list, and layout fix
Frontend UX improvements:
- Single-click Discord OAuth from home page (no intermediate /auth page)
- Auto-redirect authenticated users from home to /games
- Fixed Nuxt layout system - app.vue now wraps NuxtPage with NuxtLayout
- Games page now has proper card container with shadow/border styling
- Layout header includes working logout with API cookie clearing

Games list enhancements:
- Display team names (lname) instead of just team IDs
- Show current score for each team
- Show inning indicator (Top/Bot X) for active games
- Responsive header with wrapped buttons on mobile

Backend improvements:
- Added team caching to SbaApiClient (1-hour TTL)
- Enhanced GameListItem with team names, scores, inning data
- Games endpoint now enriches response with SBA API team data

Docker optimizations:
- Optimized Dockerfile using --chown flag on COPY (faster than chown -R)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:14:00 -06:00

100 lines
2.9 KiB
Vue

<template>
<div class="min-h-screen flex flex-col bg-gray-50">
<!-- Header -->
<header class="bg-primary text-white shadow-lg">
<div class="container mx-auto px-4 py-4">
<div class="flex items-center justify-between">
<!-- Logo and Title -->
<NuxtLink to="/" class="flex items-center space-x-3 hover:opacity-90 transition">
<div class="text-2xl font-bold">SBA</div>
<div class="hidden sm:block text-sm font-light">
Stratomatic Baseball Association
</div>
</NuxtLink>
<!-- Navigation -->
<nav class="flex items-center space-x-6">
<template v-if="authStore.isAuthenticated">
<!-- Authenticated Navigation -->
<NuxtLink
to="/games"
class="hover:text-gray-200 transition text-sm font-medium"
>
Games
</NuxtLink>
<!-- User Menu -->
<div class="flex items-center space-x-3">
<div class="hidden md:block text-sm">
{{ authStore.currentUser?.username }}
</div>
<button
class="px-4 py-2 bg-white/10 hover:bg-white/20 rounded-lg transition text-sm font-medium"
@click="handleLogout"
>
Logout
</button>
</div>
</template>
<template v-else>
<!-- Guest Navigation -->
<NuxtLink
to="/auth/login"
class="px-4 py-2 bg-white text-primary hover:bg-gray-100 rounded-lg transition text-sm font-medium"
>
Login
</NuxtLink>
</template>
</nav>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 container mx-auto px-4 py-8">
<slot />
</main>
<!-- Footer -->
<footer class="bg-gray-800 text-gray-300 py-6 mt-auto">
<div class="container mx-auto px-4">
<div class="text-center text-sm">
<p>&copy; {{ currentYear }} Stratomatic Baseball Association</p>
<p class="mt-2 text-gray-400">
Real-time multiplayer baseball simulation
</p>
</div>
</div>
</footer>
</div>
</template>
<script setup lang="ts">
import { useAuthStore } from '~/store/auth'
const authStore = useAuthStore()
const config = useRuntimeConfig()
const currentYear = new Date().getFullYear()
const handleLogout = async () => {
try {
await $fetch(`${config.public.apiUrl}/api/auth/logout`, {
method: 'POST',
credentials: 'include',
})
} catch (err) {
console.error('[Layout] Logout API call failed:', err)
}
// Always clear local state and redirect
authStore.logout()
navigateTo('/')
}
// Auth is initialized by the auth plugin automatically
</script>
<style scoped>
/* Additional component styles if needed */
</style>