- bookmark management with dnd-kit reordering, bulk edit, search, category filter/rename, and meta auto-fetch - migrate /bookmarks → /dashboard/bookmarks under (main) layout - homepage redesign with category grid, /-key search, dock tooltips - theme toggle + use-theme, sonner toasts, alert-dialog/skeleton, visual refresh of auth pages Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { redirect } from "next/navigation";
|
|
import { Suspense } from "react";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/components/ui/dialog";
|
|
import { LoginForm } from "./login-form";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "登录",
|
|
};
|
|
|
|
const hasKeycloak = !!process.env.AUTH_KEYCLOAK_ISSUER;
|
|
|
|
export default async function LoginPage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
|
|
}) {
|
|
const sp = await searchParams;
|
|
const callbackUrl = typeof sp.callbackUrl === "string" ? sp.callbackUrl : null;
|
|
const error = typeof sp.error === "string" ? sp.error : null;
|
|
|
|
if (!callbackUrl && !error) {
|
|
redirect("/?login=1");
|
|
}
|
|
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-background via-background to-muted/40 p-4">
|
|
<Dialog defaultOpen>
|
|
<DialogContent className="sm:max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle className="text-center">登录</DialogTitle>
|
|
</DialogHeader>
|
|
{error && (
|
|
<p className="rounded-md border border-destructive/30 bg-destructive/10 p-2 text-center text-xs text-destructive">
|
|
登录过程中出现错误,请重试
|
|
</p>
|
|
)}
|
|
<Suspense fallback={<div className="text-sm text-muted-foreground">加载中...</div>}>
|
|
<LoginForm hasKeycloak={hasKeycloak} callbackUrl={callbackUrl ?? undefined} />
|
|
</Suspense>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
}
|