feat: Improve user authorization UI and session management

- Enhance UserAuthorize component with Card-based loading and error states
- Add animated loading spinner and error icon for better user feedback
- Implement router refresh after successful authentication
- Update NavBar to automatically update session on component mount
- Streamline sign-out process with router refresh
This commit is contained in:
wood chen 2025-02-21 13:42:38 +08:00
parent f9521d9afb
commit 8a7997f5b9
2 changed files with 47 additions and 13 deletions

View File

@ -5,6 +5,8 @@ import { useRouter } from "next/navigation";
import { signIn } from "@/actions/user-authorize"; import { signIn } from "@/actions/user-authorize";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
interface UserAuthorizeProps extends React.HTMLAttributes<HTMLDivElement> { interface UserAuthorizeProps extends React.HTMLAttributes<HTMLDivElement> {
data: Record<string, any>; data: Record<string, any>;
} }
@ -17,6 +19,7 @@ export function UserAuthorize({
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<Error | unknown>(null); const [error, setError] = useState<Error | unknown>(null);
const { update } = useSession(); const { update } = useSession();
const router = useRouter();
const signInCallback = useCallback(async () => { const signInCallback = useCallback(async () => {
if (isLoading) { if (isLoading) {
@ -27,27 +30,53 @@ export function UserAuthorize({
await signIn({ ...data, redirectTo: "/dashboard" }); await signIn({ ...data, redirectTo: "/dashboard" });
// 更新 session // 更新 session
await update(); await update();
// 强制刷新页面状态
router.refresh();
setIsLoading(false); setIsLoading(false);
} catch (error) { } catch (error) {
setError(error); setError(error);
setIsLoading(false); setIsLoading(false);
} }
}, [data, isLoading, update]); }, [data, isLoading, update, router]);
useEffect(() => { useEffect(() => {
const timer = setTimeout(signInCallback, 5); // 直接执行登录回调
return () => { signInCallback();
clearTimeout(timer);
};
}, [signInCallback]); }, [signInCallback]);
if (error) {
return (
<Card className="w-full">
<CardHeader className="space-y-4 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
<div className="h-8 w-8 text-red-600"></div>
</div>
<CardTitle className="text-2xl font-semibold text-red-600">
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-center text-gray-500">
</p>
</CardContent>
</Card>
);
}
return ( return (
<> <Card className="w-full">
{error ? ( <CardHeader className="space-y-4 text-center">
<p className="text-center"></p> <div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-blue-100">
) : ( <div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div>
<p className="text-center">...</p> </div>
)} <CardTitle className="text-2xl font-semibold"></CardTitle>
</> </CardHeader>
<CardContent>
<p className="text-center text-gray-500">
{isLoading ? "请稍候,我们正在处理您的授权请求" : "正在跳转..."}
</p>
</CardContent>
</Card>
); );
} }

View File

@ -21,13 +21,18 @@ import { ThemeToggle } from "../theme-toggle";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
export function NavBar() { export function NavBar() {
const { data: session, status } = useSession(); const { data: session, status, update } = useSession();
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const user = session?.user; const user = session?.user;
useEffect(() => {
update();
}, [update]);
const handleSignOut = async () => { const handleSignOut = async () => {
await signOut({ redirect: false }); await signOut({ redirect: false });
router.refresh();
router.push("/"); router.push("/");
}; };