140 lines
6.7 KiB
TypeScript
140 lines
6.7 KiB
TypeScript
import React, { useEffect } from "react";
|
||
import { useLocation, useNavigate } from "react-router-dom";
|
||
import { useAuth } from "@web/src/providers/auth-provider";
|
||
import { RegisterForm } from "./register";
|
||
import { LoginForm } from "./login";
|
||
import { Card, Typography, Button, Spin, Divider } from "antd";
|
||
import { AnimatePresence, motion } from "framer-motion";
|
||
import { useAuthForm } from "./useAuthForm";
|
||
|
||
const { Title, Text, Paragraph } = Typography;
|
||
|
||
const AuthPage: React.FC = () => {
|
||
const {
|
||
showLogin,
|
||
isLoading,
|
||
toggleForm,
|
||
handleLogin,
|
||
handleRegister
|
||
} = useAuthForm();
|
||
const { isAuthenticated } = useAuth();
|
||
const location = useLocation();
|
||
const navigate = useNavigate();
|
||
|
||
useEffect(() => {
|
||
if (isAuthenticated) {
|
||
const params = new URLSearchParams(location.search);
|
||
const redirectUrl = params.get("redirect_url") || "/";
|
||
navigate(redirectUrl, { replace: true });
|
||
}
|
||
}, [isAuthenticated, location]);
|
||
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center p-4">
|
||
<motion.div
|
||
initial={{ opacity: 0, y: 20 }}
|
||
animate={{ opacity: 1, y: 0 }}
|
||
transition={{ duration: 0.5 }}
|
||
>
|
||
<div
|
||
className="w-full max-w-5xl shadow-elegant border-2 border-white rounded-xl overflow-hidden transition-all duration-300 relative"
|
||
>
|
||
<div className="flex flex-col md:flex-row min-h-[650px]">
|
||
{/* Left Panel - Welcome Section */}
|
||
<div className="w-full md:w-1/2 p-12 bg-gradient-to-br from-primary to-primary-600 text-white flex flex-col justify-center relative overflow-hidden">
|
||
<motion.div
|
||
initial={{ opacity: 0, y: 20 }}
|
||
animate={{ opacity: 1, y: 0 }}
|
||
transition={{ delay: 0.2, duration: 0.5 }}
|
||
>
|
||
<div className="text-4xl text-white mb-4 font-serif">
|
||
首长机关信箱
|
||
</div>
|
||
<Paragraph className="text-lg mb-8 text-blue-100 leading-relaxed text-justify">
|
||
聆音于微,润心以答,纾难化雨,解忧惟勤
|
||
</Paragraph>
|
||
{showLogin && (
|
||
<Button
|
||
type="default"
|
||
ghost
|
||
size="large"
|
||
onClick={toggleForm}
|
||
className="w-fit hover:bg-white hover:text-blue-700 transition-all"
|
||
>
|
||
注册账号
|
||
</Button>
|
||
)}
|
||
</motion.div>
|
||
</div>
|
||
|
||
{/* Right Panel - Form Section */}
|
||
<div className="w-full md:w-1/2 p-10 lg:p-16 bg-white relative rounded-xl">
|
||
|
||
<AnimatePresence mode="wait">
|
||
{showLogin ? (
|
||
<motion.div
|
||
key="login"
|
||
initial={{ opacity: 0, x: 50 }}
|
||
animate={{ opacity: 1, x: 0 }}
|
||
exit={{ opacity: 0, x: -50 }}
|
||
transition={{ duration: 0.3 }}
|
||
>
|
||
<motion.div className="mb-8">
|
||
<Title level={3} className="mb-2">登录</Title>
|
||
<Text type="secondary">
|
||
首次使用?{' '}
|
||
<Button
|
||
type="link"
|
||
onClick={toggleForm}
|
||
className="p-0 font-medium"
|
||
>
|
||
注册账号
|
||
</Button>
|
||
</Text>
|
||
</motion.div>
|
||
<LoginForm
|
||
onSubmit={handleLogin}
|
||
isLoading={isLoading}
|
||
/>
|
||
|
||
</motion.div>
|
||
) : (
|
||
<motion.div
|
||
key="register"
|
||
initial={{ opacity: 0, x: 50 }}
|
||
animate={{ opacity: 1, x: 0 }}
|
||
exit={{ opacity: 0, x: -50 }}
|
||
transition={{ duration: 0.3 }}
|
||
>
|
||
<motion.div className="mb-8">
|
||
<Title level={3} className="mb-2">注册账号</Title>
|
||
<Text type="secondary">
|
||
已有账号?{' '}
|
||
<Button
|
||
type="link"
|
||
onClick={toggleForm}
|
||
className="p-0 font-medium"
|
||
>
|
||
登录平台
|
||
</Button>
|
||
</Text>
|
||
</motion.div>
|
||
<RegisterForm
|
||
onSubmit={handleRegister}
|
||
isLoading={isLoading}
|
||
/>
|
||
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</motion.div>
|
||
</div>
|
||
|
||
);
|
||
};
|
||
|
||
export default AuthPage;
|