admin: completeness + UI consistency pass
Arcadia wiring: - home: real Overview dashboard (tenants/users/audit/health probe) replacing the inherited Vibespace welcome tiles; skeleton loaders, refresh button, registers admin context - profile: split into Account (synced via getUser/updateUser of session user) and local Preferences; updateSessionUser keeps the appbar in sync after edits - session: drop unused signIn mock, add updateSessionUser, refresh tests - profile schema: drop redundant Profile.name/email (session is the source of truth) - routes: delete orphaned resources route + lib Auth flows that previously 404'd: - /signup, /login/forgot, /login/reset, /login/2fa wired via @crema/arcadia-auth-ui - shared AuthShell + AuthBrand wrapper Assistant tools (admin-tools.ts): - +10 tools: deactivate_tenant, set_user_status, delete_user, list_memberships, list_roles, revoke_api_key, create_user, update_user, assign_role, remove_role - list_memberships gains user_id filter for "tenants this user belongs to" queries - search_kb / read_chunk: new token resolution (window override → VITE_ARCADIA_SEARCH_TOKEN service token → operator session JWT → "dev"); on 401/403 emit a tailored hint based on which token was used UI consistency: - new PageHeader component - AppShell.title was unrendered — dropped; first-child padding on #main-content keeps the floating actions pill from colliding with header content - removed dead "Sign in required" fallback cards from 14 routes (AppShell already redirects) - stripped p-6 from outer wrappers across 14 routes (was double-padding under AppShell's own p-6) - migrated home + tenants to PageHeader arcadia-search ergonomics: - scripts/mint-search-token.mjs + `npm run mint:search-token` mints HS512 JWT with required tenant_id claim, upserts VITE_ARCADIA_SEARCH_TOKEN into .env.local - README/.env document the new VITE_ARCADIA_SEARCH_URL / VITE_ARCADIA_SEARCH_TOKEN knobs - .env.local now gitignored Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { LoginForm } from "@crema/arcadia-auth-ui"
|
||||
import { useBrand } from "~/lib/identity"
|
||||
import { pageTitle } from "~/lib/page-meta"
|
||||
import { useSession, persistFromArcadiaLogin } from "~/lib/session"
|
||||
import { AuthBrand, AuthShell } from "~/components/auth/auth-shell"
|
||||
|
||||
export const meta = () => pageTitle("Sign in")
|
||||
|
||||
@@ -13,40 +14,24 @@ export default function LoginRoute() {
|
||||
const [params] = useSearchParams()
|
||||
const session = useSession()
|
||||
const brand = useBrand()
|
||||
const BrandIcon = brand.icon
|
||||
|
||||
const next = params.get("next") || "/"
|
||||
|
||||
// Already signed in? Bounce.
|
||||
useEffect(() => {
|
||||
if (session) navigate(next, { replace: true })
|
||||
}, [session, next, navigate])
|
||||
|
||||
return (
|
||||
<div
|
||||
// Force dark mode on the login page regardless of the operator's
|
||||
// saved theme preference. Scoped to this wrapper (not documentElement)
|
||||
// so navigating away after sign-in restores their preferred mode.
|
||||
className="dark relative isolate flex min-h-svh items-center justify-center p-4"
|
||||
style={{ background: "var(--background)" }}
|
||||
>
|
||||
<AuthShell>
|
||||
<LoginForm
|
||||
brand={
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className="flex size-8 items-center justify-center rounded-lg"
|
||||
style={{ background: "var(--primary)", color: "var(--primary-foreground)" }}
|
||||
>
|
||||
<BrandIcon className="size-4" />
|
||||
</span>
|
||||
<span className="text-sm font-semibold">{brand.name}</span>
|
||||
</div>
|
||||
}
|
||||
brand={<AuthBrand />}
|
||||
heading={`Sign in to ${brand.name}`}
|
||||
subhead="Use your arcadia credentials. In dev seeds: admin@example.com / AdminP@ssw0rd."
|
||||
onSuccess={async ({ tokens, user, twoFactorRequired, twoFactorChallenge }) => {
|
||||
if (twoFactorRequired && twoFactorChallenge) {
|
||||
navigate(`/login/2fa?challenge=${encodeURIComponent(twoFactorChallenge)}&next=${encodeURIComponent(next)}`)
|
||||
navigate(
|
||||
`/login/2fa?challenge=${encodeURIComponent(twoFactorChallenge)}&next=${encodeURIComponent(next)}`,
|
||||
)
|
||||
return
|
||||
}
|
||||
persistFromArcadiaLogin(tokens, user)
|
||||
@@ -55,6 +40,6 @@ export default function LoginRoute() {
|
||||
onForgotPassword={() => navigate("/login/forgot")}
|
||||
onSignup={() => navigate("/signup")}
|
||||
/>
|
||||
</div>
|
||||
</AuthShell>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user