セッションを確認しています...
` : null } @@ -64,34 +64,8 @@ export class AppAdminShell extends LitElement implements RouteShellElement { routeShellStyles, css` :host { - /* デザイントークンを admin 用に上書き */ - --font-en: system-ui, -apple-system, sans-serif; - --font-jp: system-ui, -apple-system, sans-serif; - --color-bg-top: #f5f5f5; - --color-bg-bottom: #ffffff; - --color-text-primary: #1a1a1a; - --color-text-secondary: #6b6b6b; - --color-text-tertiary: #9a9a9a; - --color-border: #d9d9d9; - --color-border-light: #e8e8e8; - --color-surface: #f0f0f0; - --tracking-wide: 0.02em; - --tracking-wider: 0.04em; - /* admin 専用トークン */ - --admin-accent: #0057b8; - --admin-accent-hover: #004494; - --admin-sidebar-width: 220px; - /* セマンティックカラートークン */ - --color-danger: #c0392b; - --color-danger-bg: rgba(192, 57, 43, 0.06); - --color-success: #3d7a56; - --color-success-bg: rgba(61, 122, 86, 0.06); - --color-notice: #5a6b85; - --color-notice-bg: rgba(90, 107, 133, 0.08); - display: block; - background: var(--color-bg-top); - font-family: var(--font-jp); + min-height: 100dvh; } .layout { @@ -119,14 +93,14 @@ export class AppAdminShell extends LitElement implements RouteShellElement { font-family: var(--font-jp); font-size: 14px; font-weight: 400; - letter-spacing: var(--tracking-wide); + letter-spacing: var(--tracking-tight); color: var(--color-text-secondary); border-radius: 4px; transition: background 0.15s ease, color 0.15s ease; } .sidebar a:hover { - background: var(--color-surface); + background: var(--color-bg-surface); color: var(--color-text-primary); } @@ -165,7 +139,7 @@ export class AppAdminShell extends LitElement implements RouteShellElement { #outlet { padding: 28px 24px 48px; - background: var(--color-bg-top); + background: var(--color-bg-deep); } } `, diff --git a/frontend/src/components/app-root.ts b/frontend/src/components/app-root.ts index a5ccd11..474d2f3 100644 --- a/frontend/src/components/app-root.ts +++ b/frontend/src/components/app-root.ts @@ -1,26 +1,20 @@ +import { provide } from '@lit/context' import { Router, Routes } from '@lit-labs/router' import type { PropertyValues } from 'lit' -import { css, html, LitElement, nothing } from 'lit' +import { css, html, LitElement } from 'lit' import { customElement, state } from 'lit/decorators.js' -import { - changeEmail, - login, - logout, - refreshSession, - revokeAllSessions, -} from '../admin/auth-api.js' -import { getMe, updateMe } from '../admin/me-api.js' -import { - type AdminLoginInput, - ApiError, - type ChangeEmailInput, - createEmptyMeProfile, - describeApiError, - type MeProfile, -} from '../admin/types.js' -import type { RouteShellElement } from './route-shell.js' +import { articleContext } from '../contexts/article-context.js' +import { authContext } from '../contexts/auth-context.js' +import { profileContext } from '../contexts/profile-context.js' +import { RepositoryObserver } from '../controllers/RepositoryObserver.js' +import { ArticleRepository } from '../domain/ArticleRepository.js' +import { AuthRepository } from '../domain/AuthRepository.js' +import { ProfileRepository } from '../domain/ProfileRepository.js' +import { setupCursor } from '../utils/cursor.js' +import { setupBackgroundShift } from '../utils/scroll.js' import './app-admin-shell.js' import './app-public-shell.js' +import '../components/admin/ui/me-auth-guard.js' import '../pages/page-admin-account.js' import '../pages/page-admin-articles.js' import '../pages/page-admin-dashboard.js' @@ -30,154 +24,94 @@ import '../pages/page-about.js' import '../pages/page-articles.js' import '../pages/page-not-found.js' import '../pages/page-top.js' -import { setupCursor } from '../utils/cursor.js' -import { setupBackgroundShift } from '../utils/scroll.js' +import type { RouteShellElement } from './route-shell.js' @customElement('app-root') export class AppRoot extends LitElement { - @state() - private currentPath = window.location.pathname - - @state() - private adminSessionStatus: - | 'unknown' - | 'checking' - | 'authenticated' - | 'guest' = 'unknown' - - @state() - private adminLoginPending = false - - @state() - private adminLoginError = '' - - @state() - private adminLoginNotice = '' - - @state() - private publicProfile: MeProfile | null = null - - @state() - private publicProfileLoading = false - - @state() - private adminProfile = createEmptyMeProfile() - - @state() - private adminProfileLoading = false - - @state() - private adminProfileSaving = false - - @state() - private adminProfileLoaded = false - - @state() - private adminProfileError = '' - - @state() - private adminProfileSuccess = '' + @provide({ context: authContext }) + auth = new AuthRepository() - @state() - private adminProfileDirty = false + @provide({ context: profileContext }) + profile = new ProfileRepository() - @state() - private adminArticlesDirty = false + @provide({ context: articleContext }) + article = new ArticleRepository() @state() - private adminAccountBusyAction = '' - - @state() - private adminAccountError = '' - - @state() - private adminAccountSuccess = '' + private currentPath = window.location.pathname private cleanups: Array<() => void> = [] private router = new Router(this, []) private adminReturnPath = '/admin' - private adminSessionBootstrap?: Promise${message}
-