|
| 1 | +import { Layout, Menu } from "antd"; |
| 2 | +import { Route, Switch, useLocation, useHistory } from "react-router-dom"; |
| 3 | +import { |
| 4 | + CheckOutlined, |
| 5 | + LockOutlined, |
| 6 | + MailOutlined, |
| 7 | + SafetyOutlined, |
| 8 | + SettingOutlined, |
| 9 | +} from "@ant-design/icons"; |
| 10 | +import ChangePasswordView from "./change_password_view"; |
| 11 | +import AuthTokenView from "./auth_token_view"; |
| 12 | +import { useWkSelector } from "libs/react_hooks"; |
| 13 | +import type { APIUserTheme } from "types/api_types"; |
| 14 | +import { getSystemColorTheme } from "theme"; |
| 15 | +import { updateSelectedThemeOfUser } from "admin/rest_api"; |
| 16 | +import Store from "viewer/store"; |
| 17 | +import { setActiveUserAction } from "viewer/model/actions/user_actions"; |
| 18 | +import { setThemeAction } from "viewer/model/actions/ui_actions"; |
| 19 | + |
| 20 | +const { Sider, Content } = Layout; |
| 21 | + |
| 22 | +function EmailSettings() { |
| 23 | + return ( |
| 24 | + <div> |
| 25 | + <h2>Email Settings</h2> |
| 26 | + <p>Email settings page content will be added here.</p> |
| 27 | + </div> |
| 28 | + ); |
| 29 | +} |
| 30 | + |
| 31 | +function PasskeysSettings() { |
| 32 | + return ( |
| 33 | + <div> |
| 34 | + <h2>Passkeys</h2> |
| 35 | + <p>Passkeys settings page content will be added here.</p> |
| 36 | + </div> |
| 37 | + ); |
| 38 | +} |
| 39 | + |
| 40 | +function AppearanceSettings() { |
| 41 | + const activeUser = useWkSelector((state) => state.activeUser); |
| 42 | + const { selectedTheme } = activeUser || { selectedTheme: "auto" }; |
| 43 | + |
| 44 | + const setSelectedTheme = async (newTheme: APIUserTheme) => { |
| 45 | + if (!activeUser) return; |
| 46 | + |
| 47 | + if (newTheme === "auto") newTheme = getSystemColorTheme(); |
| 48 | + |
| 49 | + if (selectedTheme !== newTheme) { |
| 50 | + const newUser = await updateSelectedThemeOfUser(activeUser.id, newTheme); |
| 51 | + Store.dispatch(setThemeAction(newTheme)); |
| 52 | + Store.dispatch(setActiveUserAction(newUser)); |
| 53 | + } |
| 54 | + }; |
| 55 | + |
| 56 | + return ( |
| 57 | + <div> |
| 58 | + <h2>Appearance</h2> |
| 59 | + <div style={{ marginTop: 16 }}> |
| 60 | + <h3>Theme</h3> |
| 61 | + <Menu |
| 62 | + mode="inline" |
| 63 | + selectedKeys={[selectedTheme]} |
| 64 | + items={[ |
| 65 | + { |
| 66 | + key: "auto", |
| 67 | + label: "System Default", |
| 68 | + icon: selectedTheme === "auto" ? <CheckOutlined /> : null, |
| 69 | + onClick: () => setSelectedTheme("auto"), |
| 70 | + }, |
| 71 | + { |
| 72 | + key: "light", |
| 73 | + label: "Light", |
| 74 | + icon: selectedTheme === "light" ? <CheckOutlined /> : null, |
| 75 | + onClick: () => setSelectedTheme("light"), |
| 76 | + }, |
| 77 | + { |
| 78 | + key: "dark", |
| 79 | + label: "Dark", |
| 80 | + icon: selectedTheme === "dark" ? <CheckOutlined /> : null, |
| 81 | + onClick: () => setSelectedTheme("dark"), |
| 82 | + }, |
| 83 | + ]} |
| 84 | + /> |
| 85 | + </div> |
| 86 | + </div> |
| 87 | + ); |
| 88 | +} |
| 89 | + |
| 90 | +function AccountSettingsView() { |
| 91 | + const location = useLocation(); |
| 92 | + const history = useHistory(); |
| 93 | + const selectedKey = location.pathname.split("/").pop() || "email"; |
| 94 | + |
| 95 | + const menuItems = [ |
| 96 | + { |
| 97 | + key: "email", |
| 98 | + icon: <MailOutlined />, |
| 99 | + label: "Email", |
| 100 | + }, |
| 101 | + { |
| 102 | + key: "password", |
| 103 | + icon: <LockOutlined />, |
| 104 | + label: "Password", |
| 105 | + }, |
| 106 | + { |
| 107 | + key: "passkeys", |
| 108 | + icon: <SafetyOutlined />, |
| 109 | + label: "Passkeys", |
| 110 | + }, |
| 111 | + { |
| 112 | + key: "token", |
| 113 | + icon: <SettingOutlined />, |
| 114 | + label: "Auth Token", |
| 115 | + }, |
| 116 | + { |
| 117 | + key: "appearance", |
| 118 | + icon: <SettingOutlined />, |
| 119 | + label: "Appearance", |
| 120 | + }, |
| 121 | + ]; |
| 122 | + |
| 123 | + return ( |
| 124 | + <Layout style={{ minHeight: "calc(100vh - 64px)" }}> |
| 125 | + <Sider width={200} theme="light"> |
| 126 | + <Menu |
| 127 | + mode="inline" |
| 128 | + selectedKeys={[selectedKey]} |
| 129 | + style={{ height: "100%" }} |
| 130 | + items={menuItems} |
| 131 | + onClick={({ key }) => history.push(`/account/${key}`)} |
| 132 | + /> |
| 133 | + </Sider> |
| 134 | + <Content style={{ padding: "24px", minHeight: 280 }}> |
| 135 | + <Switch> |
| 136 | + <Route path="/account/email" component={EmailSettings} /> |
| 137 | + <Route path="/account/password" component={ChangePasswordView} /> |
| 138 | + <Route path="/account/passkeys" component={PasskeysSettings} /> |
| 139 | + <Route path="/account/token" component={AuthTokenView} /> |
| 140 | + <Route path="/account/appearance" component={AppearanceSettings} /> |
| 141 | + <Route path="/account" component={EmailSettings} /> |
| 142 | + </Switch> |
| 143 | + </Content> |
| 144 | + </Layout> |
| 145 | + ); |
| 146 | +} |
| 147 | + |
| 148 | +export default AccountSettingsView; |
0 commit comments