this repo has no description
1<script lang="ts"> 2 import { getAuthState, logout } from '../lib/auth.svelte' 3 import { navigate } from '../lib/router.svelte' 4 5 const auth = getAuthState() 6 7 $effect(() => { 8 if (!auth.loading && !auth.session) { 9 navigate('/login') 10 } 11 }) 12 13 async function handleLogout() { 14 await logout() 15 navigate('/login') 16 } 17</script> 18 19{#if auth.session} 20 <div class="dashboard"> 21 <header> 22 <h1>Dashboard</h1> 23 <button class="logout" onclick={handleLogout}>Sign Out</button> 24 </header> 25 26 <section class="account-overview"> 27 <h2>Account Overview</h2> 28 <dl> 29 <dt>Handle</dt> 30 <dd>@{auth.session.handle}</dd> 31 32 <dt>DID</dt> 33 <dd class="mono">{auth.session.did}</dd> 34 35 {#if auth.session.email} 36 <dt>Email</dt> 37 <dd> 38 {auth.session.email} 39 {#if auth.session.emailConfirmed} 40 <span class="badge success">Verified</span> 41 {:else} 42 <span class="badge warning">Unverified</span> 43 {/if} 44 </dd> 45 {/if} 46 </dl> 47 </section> 48 49 <nav class="nav-grid"> 50 <a href="#/app-passwords" class="nav-card"> 51 <h3>App Passwords</h3> 52 <p>Manage passwords for third-party apps</p> 53 </a> 54 55 <a href="#/invite-codes" class="nav-card"> 56 <h3>Invite Codes</h3> 57 <p>View and create invite codes</p> 58 </a> 59 60 <a href="#/settings" class="nav-card"> 61 <h3>Account Settings</h3> 62 <p>Email, password, handle, and more</p> 63 </a> 64 65 <a href="#/notifications" class="nav-card"> 66 <h3>Notification Preferences</h3> 67 <p>Discord, Telegram, Signal channels</p> 68 </a> 69 70 <a href="#/repo" class="nav-card"> 71 <h3>Repository Explorer</h3> 72 <p>Browse and manage raw AT Protocol records</p> 73 </a> 74 </nav> 75 </div> 76{:else if auth.loading} 77 <div class="loading">Loading...</div> 78{/if} 79 80<style> 81 .dashboard { 82 max-width: 800px; 83 margin: 0 auto; 84 padding: 2rem; 85 } 86 87 header { 88 display: flex; 89 justify-content: space-between; 90 align-items: center; 91 margin-bottom: 2rem; 92 } 93 94 header h1 { 95 margin: 0; 96 } 97 98 .logout { 99 padding: 0.5rem 1rem; 100 background: transparent; 101 border: 1px solid var(--border-color-light); 102 border-radius: 4px; 103 cursor: pointer; 104 color: var(--text-primary); 105 } 106 107 .logout:hover { 108 background: var(--bg-secondary); 109 } 110 111 section { 112 background: var(--bg-secondary); 113 padding: 1.5rem; 114 border-radius: 8px; 115 margin-bottom: 2rem; 116 } 117 118 section h2 { 119 margin: 0 0 1rem 0; 120 font-size: 1.25rem; 121 } 122 123 dl { 124 display: grid; 125 grid-template-columns: auto 1fr; 126 gap: 0.5rem 1rem; 127 margin: 0; 128 } 129 130 dt { 131 font-weight: 500; 132 color: var(--text-secondary); 133 } 134 135 dd { 136 margin: 0; 137 } 138 139 .mono { 140 font-family: monospace; 141 font-size: 0.875rem; 142 word-break: break-all; 143 } 144 145 .badge { 146 display: inline-block; 147 padding: 0.125rem 0.5rem; 148 border-radius: 4px; 149 font-size: 0.75rem; 150 margin-left: 0.5rem; 151 } 152 153 .badge.success { 154 background: var(--success-bg); 155 color: var(--success-text); 156 } 157 158 .badge.warning { 159 background: var(--warning-bg); 160 color: var(--warning-text); 161 } 162 163 .nav-grid { 164 display: grid; 165 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 166 gap: 1rem; 167 } 168 169 .nav-card { 170 display: block; 171 padding: 1.5rem; 172 background: var(--bg-card); 173 border: 1px solid var(--border-color); 174 border-radius: 8px; 175 text-decoration: none; 176 color: inherit; 177 transition: border-color 0.15s, box-shadow 0.15s; 178 } 179 180 .nav-card:hover { 181 border-color: var(--accent); 182 box-shadow: 0 2px 8px rgba(77, 166, 255, 0.15); 183 } 184 185 .nav-card h3 { 186 margin: 0 0 0.5rem 0; 187 color: var(--accent); 188 } 189 190 .nav-card p { 191 margin: 0; 192 color: var(--text-secondary); 193 font-size: 0.875rem; 194 } 195 196 .loading { 197 text-align: center; 198 padding: 4rem; 199 color: var(--text-secondary); 200 } 201</style>