- Add @logto/react dependencies to package.json and lockfile. - Replace custom App layout with LogtoProvider for authentication handling. - Configure Logto settings (endpoint, appId) in frontend.tsx. - Refactor FindUserPage search logic to trigger request on value change instead of manual search key refresh.
81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
import { EditOutlined, HomeOutlined, KeyOutlined, LockOutlined, LoginOutlined, LogoutOutlined, MailOutlined, MobileOutlined } from "@ant-design/icons";
|
|
import { useLogto, type IdTokenClaims } from "@logto/react";
|
|
import { Avatar, Button, Divider, Flex, Modal, Typography } from "antd";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
import { useNavigate } from "react-router";
|
|
|
|
enum modifyRoutes {
|
|
username = '/account/username',
|
|
email = '/account/email',
|
|
passwd = '/account/password',
|
|
passkey = '/account/passkey/manage',
|
|
auth_app = '/account/authenticator-app',
|
|
}
|
|
|
|
const redirect = encodeURIComponent(`${window.location.origin}/user-center`);
|
|
const logto = 'https://logto.ksr.la';
|
|
|
|
export const UserCenter = () => {
|
|
const { signIn, isAuthenticated, signOut, getIdTokenClaims } = useLogto();
|
|
const [user, setUser] = useState<IdTokenClaims>();
|
|
const navigate = useNavigate();
|
|
useEffect(() => {
|
|
if (!isAuthenticated) return;
|
|
getIdTokenClaims().then(claims => setUser(claims));
|
|
}, [isAuthenticated]);
|
|
const handleModifyInfo = useCallback((url: string) => {
|
|
window.location.href = `${logto}${url}?redirect=${redirect}`;
|
|
}, []);
|
|
if (!isAuthenticated) {
|
|
return (
|
|
<div className="app">
|
|
<Button
|
|
block
|
|
type="primary"
|
|
icon={<LogoutOutlined />}
|
|
size="large"
|
|
onClick={() => signIn(`${window.location.origin}/auth/callback`)}
|
|
>
|
|
登录
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
console.debug(user);
|
|
return (
|
|
<Flex className="app" gap={12} vertical align="center" style={{ maxWidth: 600 }}>
|
|
<Avatar size={128} src={user?.picture ?? user?.name} />
|
|
<Flex>
|
|
<Typography.Text>{user?.username ?? user?.name ?? '未设置'}</Typography.Text>
|
|
</Flex>
|
|
<Divider>修改信息</Divider>
|
|
<Button block icon={<EditOutlined />} onClick={() => handleModifyInfo(modifyRoutes.username)}>修改用户名({user?.username ?? '未设置'})</Button>
|
|
<Button block icon={<MailOutlined />} onClick={() => handleModifyInfo(modifyRoutes.email)}>修改 E-Mail</Button>
|
|
<Button block icon={<LockOutlined />} onClick={() => handleModifyInfo(modifyRoutes.auth_app)}>修改密码</Button>
|
|
<Button block icon={<MobileOutlined />} onClick={() => handleModifyInfo(modifyRoutes.auth_app)}>修改验证器</Button>
|
|
<Button block icon={<KeyOutlined />} onClick={() => handleModifyInfo(modifyRoutes.passkey)}>管理 Passkey</Button>
|
|
<Divider />
|
|
<Button block type="primary" onClick={() => navigate('/')} icon={<HomeOutlined />}>回到首页</Button>
|
|
<Divider />
|
|
<Button
|
|
block
|
|
danger
|
|
icon={<LoginOutlined />}
|
|
onClick={() => Modal.confirm({
|
|
title: '确认登出?',
|
|
cancelText: '回到首页',
|
|
cancelButtonProps: { icon: <HomeOutlined /> },
|
|
onCancel: () => navigate('/'),
|
|
okText: '确认登出',
|
|
okButtonProps: {
|
|
icon: <LogoutOutlined />,
|
|
danger: true,
|
|
},
|
|
onOk: () => signOut(`${window.location.origin}/user-center`),
|
|
})}
|
|
>
|
|
登出
|
|
</Button>
|
|
</Flex>
|
|
);
|
|
} |