| <script lang="ts"> |
| import { authStore } from '$lib/stores/auth'; |
| import type { HuggingFaceLibs } from '$lib/types'; |
| |
| interface Props { |
| hfAuth: HuggingFaceLibs | null; |
| currentTab?: string; |
| } |
| |
| let { hfAuth, currentTab = 'Piclets' }: Props = $props(); |
| const auth = $derived(authStore); |
| |
| async function handleSignIn() { |
| if (!hfAuth) return; |
| |
| const url = await hfAuth.oauthLoginUrl({ scopes: ["inference-api"] }); |
| window.location.href = url; |
| } |
| </script> |
|
|
| <header class="app-header"> |
| <h1 class="app-title">{currentTab}</h1> |
| |
| {#if $auth.showSignIn && !$auth.userInfo} |
| <button class="sign-in-btn" onclick={handleSignIn}> |
| Sign In |
| </button> |
| {:else if $auth.userInfo} |
| <div class="user-info"> |
| <span class="username">{$auth.userInfo.preferred_username || 'User'}</span> |
| </div> |
| {/if} |
| </header> |
|
|
| {#if $auth.bannerMessage} |
| <div class="auth-banner"> |
| {$auth.bannerMessage} |
| </div> |
| {/if} |
|
|
| <style> |
| .app-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 1rem; |
| background: white; |
| border-bottom: 1px solid #f0f0f0; |
| } |
| |
| .app-title { |
| margin: 0; |
| font-size: 1.25rem; |
| font-weight: 700; |
| color: #333; |
| } |
| |
| .sign-in-btn { |
| padding: 0.5rem 1rem; |
| background: #007bff; |
| color: white; |
| border: none; |
| border-radius: 20px; |
| font-size: 0.875rem; |
| font-weight: 500; |
| cursor: pointer; |
| transition: background 0.2s; |
| } |
| |
| .sign-in-btn:active { |
| background: #0056b3; |
| } |
| |
| .user-info { |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| } |
| |
| .username { |
| font-size: 0.875rem; |
| color: #666; |
| font-weight: 500; |
| } |
| |
| .auth-banner { |
| padding: 0.75rem 1rem; |
| background: #fff3cd; |
| color: #856404; |
| font-size: 0.875rem; |
| text-align: center; |
| border-bottom: 1px solid #ffeeba; |
| } |
| </style> |