diff options
Diffstat (limited to 'FrontEnd/src/pages/setting')
-rw-r--r-- | FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx | 2 | ||||
-rw-r--r-- | FrontEnd/src/pages/setting/ChangePasswordDialog.tsx | 2 | ||||
-rw-r--r-- | FrontEnd/src/pages/setting/index.css | 54 | ||||
-rw-r--r-- | FrontEnd/src/pages/setting/index.tsx | 171 |
5 files changed, 137 insertions, 98 deletions
diff --git a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx index 44bd2c68..b2a4e2a8 100644 --- a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx @@ -9,9 +9,9 @@ import { useUser } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; -import ImageCropper, { Clip, applyClipToImage } from "../common/ImageCropper"; -import Button from "../common/button/Button"; -import Dialog from "../common/dialog/Dialog"; +import ImageCropper, { Clip, applyClipToImage } from "@/views/common/ImageCropper"; +import Button from "@/views/common/button/Button"; +import Dialog from "@/views/common/dialog/Dialog"; export interface ChangeAvatarDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx b/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx index 7ba12de8..11c86222 100644 --- a/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx @@ -2,7 +2,7 @@ import { getHttpUserClient } from "@/http/user"; import { useUser } from "@/services/user"; import * as React from "react"; -import OperationDialog from "../common/dialog/OperationDialog"; +import OperationDialog from "@/views/common/dialog/OperationDialog"; export interface ChangeNicknameDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx index a34ca4a7..a523b454 100644 --- a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx @@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom"; import { userService } from "@/services/user"; -import OperationDialog from "../common/dialog/OperationDialog"; +import OperationDialog from "@/views/common/dialog/OperationDialog"; export interface ChangePasswordDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index ccf7a97a..af5ccf20 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -1,3 +1,5 @@ +/* TODO: Make item prettier. */
+
.change-avatar-cropper-row {
max-height: 400px;
}
@@ -8,20 +10,56 @@ max-height: 400px;
}
-.settings-item {
+.setting-section {
+ padding: 1em 0;
+ margin: 1em 0;
+}
+
+.setting-section-title {
+ padding: 0 1em;
+}
+
+.setting-section-item-area {
+ margin-top: 1em;
+ border-top: 1px solid var(--cru-key-container-color);
+}
+
+.setting-item-container {
padding: 0.5em 1em;
- transition: background 0.3s;
- border-bottom: 1px solid #e9ecef;
+ transition: background-color 0.3s;
+ color: var(--cru-surface-on-color);
+ background-color: var(--cru-surface-color);
+ border-bottom: 1px solid var(--cru-key-container-color);
+ display: flex;
align-items: center;
}
-.settings-item.first {
- border-top: 1px solid #e9ecef;
+
+.setting-item-container:hover {
+ background-color: var(--cru-key-container-1-color);
+ border-bottom-color: var(--cru-key-container-1-color);
+}
+
+.setting-item-label-sub {
+ color: var(--cru-secondary-text-color);
}
-.settings-item.clickable {
+
+.setting-item-container.setting-type-button {
cursor: pointer;
}
-.settings-item:hover {
- background: #dee2e6;
+
+.setting-item-container.setting-type-button.danger {
+ color: var(--cru-danger-color);
+}
+
+
+@media (max-width: 576) {
+ .setting-item-container.setting-type-select {
+ flex-direction: column;
+ }
+
+ .setting-item-container.setting-type-select .setting-item-value-area {
+ margin-top: 1em;
+ }
}
.register-code {
diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 4e28585e..5d6dcbc0 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -11,11 +11,11 @@ import classNames from "classnames"; import { useC, Text } from "@/common"; import { useUser, userService } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; -import { TimelineVisibility } from "@/http/timeline"; import ConfirmDialog from "@/views/common/dialog/ConfirmDialog"; import Card from "@/views/common/Card"; import Spinner from "@/views/common/Spinner"; +import Page from "@/views/common/Page"; import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; @@ -24,9 +24,9 @@ import "./index.css"; import { pushAlert } from "@/services/alert"; interface SettingSectionProps - extends Omit<ComponentPropsWithoutRef<"div">, "title"> { + extends Omit<ComponentPropsWithoutRef<typeof Card>, "title"> { title: Text; - children: ReactNode; + children?: ReactNode; } function SettingSection({ @@ -40,7 +40,7 @@ function SettingSection({ return ( <Card className={classNames(className, "setting-section")} {...otherProps}> <h2 className="setting-section-title">{c(title)}</h2> - {children} + <div className="setting-section-item-area">{children}</div> </Card> ); } @@ -115,6 +115,7 @@ function SelectSettingsItem({ <Spinner /> ) : ( <select + className="select-setting-item-select" value={value} onChange={(e) => { onSelect(e.target.value); @@ -131,16 +132,14 @@ function SelectSettingsItem({ ); } -function RegisterCodeSettingItem({ - openRenewDialog, -}: { - openRenewDialog: () => void; -}) { +function RegisterCodeSettingItem() { const user = useUser(); // undefined: loading const [registerCode, setRegisterCode] = useState<undefined | null | string>(); + const [dialogOpen, setDialogOpen] = useState(false); + useEffect(() => { setRegisterCode(undefined); }, [user]); @@ -159,7 +158,7 @@ function RegisterCodeSettingItem({ <SettingItemContainer title="settings.myRegisterCode" description="settings.myRegisterCodeDesc" - onClick={openRenewDialog} + onClick={() => setDialogOpen(true)} > {registerCode === undefined ? ( <Spinner /> @@ -181,13 +180,59 @@ function RegisterCodeSettingItem({ {registerCode} </code> )} + + <ConfirmDialog + title="settings.renewRegisterCode" + body="settings.renewRegisterCodeDesc" + onClose={() => setDialogOpen(false)} + open={dialogOpen} + onConfirm={() => { + if (user == null) throw new Error(); + void getHttpUserClient() + .renewRegisterCode(user.username) + .then(() => { + setRegisterCode(undefined); + }); + }} + /> </SettingItemContainer> ); } -export default function SettingsPage() { - const c = useC(); +function LanguageChangeSettingItem() { const { i18n } = useTranslation(); + + const language = i18n.language.slice(0, 2); + + return ( + <SelectSettingsItem + title="settings.languagePrimary" + description="settings.languageSecondary" + options={[ + { + value: "zh", + label: { + type: "custom", + value: "中文", + }, + }, + { + value: "en", + label: { + type: "custom", + value: "English", + }, + }, + ]} + value={language} + onSelect={(value) => { + void i18n.changeLanguage(value); + }} + /> + ); +} + +export default function SettingPage() { const user = useUser(); const navigate = useNavigate(); @@ -204,66 +249,36 @@ export default function SettingsPage() { return () => setDialog(name); } - const language = i18n.language.slice(0, 2); - return ( - <> - <div className="container"> - {user ? ( - <SettingSection title="settings.subheader.account"> - <RegisterCodeSettingItem - openRenewDialog={dialogOpener("renew-register-code")} - /> - <ButtonSettingItem - title="settings.changeAvatar" - onClick={dialogOpener("change-avatar")} - /> - <ButtonSettingItem - title="settings.changeNickname" - onClick={dialogOpener("change-nickname")} - /> - <ButtonSettingItem - title="settings.changePassword" - onClick={dialogOpener("change-password")} - danger - /> - <ButtonSettingItem - title="settings.logout" - onClick={dialogOpener("logout")} - danger - /> - </SettingSection> - ) : null} - <SettingSection title="settings.subheaders.customization"> - <SelectSettingsItem - title="settings.languagePrimary" - subtext="settings.languageSecondary" - options={[ - { - value: "zh", - label: { - type: "custom", - value: "中文", - }, - }, - { - value: "en", - label: { - type: "custom", - value: "English", - }, - }, - ]} - value={language} - onSelect={(value) => { - void i18n.changeLanguage(value); - }} - first + <Page noTopPadding> + {user ? ( + <SettingSection title="settings.subheader.account"> + <RegisterCodeSettingItem /> + <ButtonSettingItem + title="settings.changeAvatar" + onClick={dialogOpener("change-avatar")} + /> + <ButtonSettingItem + title="settings.changeNickname" + onClick={dialogOpener("change-nickname")} + /> + <ButtonSettingItem + title="settings.changePassword" + onClick={dialogOpener("change-password")} + danger + /> + <ButtonSettingItem + title="settings.logout" + onClick={dialogOpener("logout")} + danger /> </SettingSection> - </div> + ) : null} + <SettingSection title="settings.subheader.customization"> + <LanguageChangeSettingItem /> + </SettingSection> <ChangePasswordDialog - open={dialog === "changepassword"} + open={dialog === "change-password"} close={() => setDialog(null)} /> <ConfirmDialog @@ -277,28 +292,14 @@ export default function SettingsPage() { }); }} /> - <ConfirmDialog - title="settings.renewRegisterCode" - body="settings.renewRegisterCodeDesc" - onClose={() => setDialog(null)} - open={dialog === "renewregistercode"} - onConfirm={() => { - if (user == null) throw new UiLogicError(); - void getHttpUserClient() - .renewRegisterCode(user.username) - .then(() => { - setRegisterCode(undefined); - }); - }} - /> <ChangeAvatarDialog - open={dialog === "changeavatar"} + open={dialog === "change-avatar"} close={() => setDialog(null)} /> <ChangeNicknameDialog - open={dialog === "changenickname"} + open={dialog === "change-nickname"} close={() => setDialog(null)} /> - </> + </Page> ); } |