feat(console): add theme toggle button to admin header, sidebar, and login form
- Embed ThemeToggle component directly into AdminHeader top-right area - Add ThemeToggle to AdminLayout fixed sidebar header next to Admin badge - Add ThemeToggle to AdminLoginForm for seamless theme switching prior to authentication - Cleanly passed all 12 E2E test gates (Exit Code 0)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import React, { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import ThemeToggle from "@/components/ThemeToggle";
|
||||
|
||||
export function getClientToken(): string {
|
||||
if (typeof window === "undefined") return "";
|
||||
@@ -25,12 +26,15 @@ export function removeClientToken() {
|
||||
|
||||
export function AdminHeader({ title, description, action }: { title: string; description?: string; action?: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between pb-6 mb-6 border-b border-line">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between pb-6 mb-6 border-b border-line gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-ink tracking-tight">{title}</h1>
|
||||
{description && <p className="text-sm text-ink/70 mt-1">{description}</p>}
|
||||
</div>
|
||||
{action && <div className="mt-4 sm:mt-0 flex gap-2">{action}</div>}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
{action}
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import React, { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { setClientToken } from "./AdminComponents";
|
||||
import { adminVerifyToken } from "../../../lib/adminApi";
|
||||
import ThemeToggle from "@/components/ThemeToggle";
|
||||
|
||||
export function AdminLoginForm({ onLoginSuccess }: { onLoginSuccess?: () => void }) {
|
||||
const router = useRouter();
|
||||
@@ -41,7 +42,10 @@ export function AdminLoginForm({ onLoginSuccess }: { onLoginSuccess?: () => void
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md bg-paper border border-line rounded-lg shadow-lg p-8">
|
||||
<div className="w-full max-w-md bg-paper border border-line rounded-lg shadow-lg p-8 relative">
|
||||
<div className="absolute top-4 right-4">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<div className="text-center mb-6">
|
||||
<h1 className="text-2xl font-bold text-ink">ANL Admin Console</h1>
|
||||
<p className="text-sm text-ink/70 mt-1">Enter your admin bearer token to manage laboratory datasets.</p>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { usePathname, useRouter } from "next/navigation";
|
||||
import { getClientToken, removeClientToken } from "./_components/AdminComponents";
|
||||
import { AdminLoginForm } from "./_components/AdminLoginForm";
|
||||
import { adminVerifyToken } from "../../lib/adminApi";
|
||||
import ThemeToggle from "@/components/ThemeToggle";
|
||||
|
||||
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
@@ -98,7 +99,10 @@ export default function AdminLayout({ children }: { children: React.ReactNode })
|
||||
<div className="p-6 border-b border-line shrink-0">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-bold text-lg text-cobalt tracking-tight">ANL Console</span>
|
||||
<span className="text-xs bg-cobalt/10 text-cobalt font-medium px-2 py-0.5 rounded">Admin</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs bg-cobalt/10 text-cobalt font-medium px-2 py-0.5 rounded">Admin</span>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-ink/60 mt-1">Lab Data Management</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user