aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/pages')
-rw-r--r--FrontEnd/src/pages/about/index.css1
-rw-r--r--FrontEnd/src/pages/about/index.tsx5
-rw-r--r--FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx6
-rw-r--r--FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx2
-rw-r--r--FrontEnd/src/pages/setting/ChangePasswordDialog.tsx2
-rw-r--r--FrontEnd/src/pages/setting/index.css54
-rw-r--r--FrontEnd/src/pages/setting/index.tsx171
7 files changed, 140 insertions, 101 deletions
diff --git a/FrontEnd/src/pages/about/index.css b/FrontEnd/src/pages/about/index.css
index 487f4a0a..1ce7a7c8 100644
--- a/FrontEnd/src/pages/about/index.css
+++ b/FrontEnd/src/pages/about/index.css
@@ -1,5 +1,4 @@
.about-page {
- padding: 1em 2em;
line-height: 1.5;
}
diff --git a/FrontEnd/src/pages/about/index.tsx b/FrontEnd/src/pages/about/index.tsx
index afd4de34..acec1735 100644
--- a/FrontEnd/src/pages/about/index.tsx
+++ b/FrontEnd/src/pages/about/index.tsx
@@ -1,6 +1,7 @@
import "./index.css";
import { useC } from "@/common";
+import Page from "@/views/common/Page";
interface Credit {
name: string;
@@ -52,7 +53,7 @@ export default function AboutPage() {
const c = useC();
return (
- <div className="about-page">
+ <Page className="about-page">
<h2>{c("about.credits.title")}</h2>
<p>{c("about.credits.content")}</p>
<h3>{c("about.credits.frontend")}</h3>
@@ -81,6 +82,6 @@ export default function AboutPage() {
})}
<li>...</li>
</ul>
- </div>
+ </Page>
);
}
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>
);
}