aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/views
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-04-26 15:15:18 +0800
committercrupest <crupest@outlook.com>2022-04-26 15:15:18 +0800
commit0196ba764bac9abb958b8ded48d9a97991e2ddbb (patch)
treea7399251461ec2ad8c9fa6886845dd5ccf6b56f2 /FrontEnd/src/views
parente71506ca1da6081a6f618228758a67dee8d185e5 (diff)
downloadtimeline-0196ba764bac9abb958b8ded48d9a97991e2ddbb.tar.gz
timeline-0196ba764bac9abb958b8ded48d9a97991e2ddbb.tar.bz2
timeline-0196ba764bac9abb958b8ded48d9a97991e2ddbb.zip
...
Diffstat (limited to 'FrontEnd/src/views')
-rw-r--r--FrontEnd/src/views/about/index.tsx4
-rw-r--r--FrontEnd/src/views/settings/index.tsx203
2 files changed, 153 insertions, 54 deletions
diff --git a/FrontEnd/src/views/about/index.tsx b/FrontEnd/src/views/about/index.tsx
index 11618086..438c1757 100644
--- a/FrontEnd/src/views/about/index.tsx
+++ b/FrontEnd/src/views/about/index.tsx
@@ -25,10 +25,6 @@ const frontendCredits: {
url: "https://getbootstrap.com",
},
{
- name: "react-bootstrap",
- url: "https://react-bootstrap.github.io",
- },
- {
name: "vite",
url: "https://vitejs.dev",
},
diff --git a/FrontEnd/src/views/settings/index.tsx b/FrontEnd/src/views/settings/index.tsx
index 86a8b263..1f526ee0 100644
--- a/FrontEnd/src/views/settings/index.tsx
+++ b/FrontEnd/src/views/settings/index.tsx
@@ -1,6 +1,7 @@
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
+import classnames from "classnames";
import { useUser, userService } from "@/services/user";
@@ -11,9 +12,116 @@ import ConfirmDialog from "../common/dailog/ConfirmDialog";
import Card from "../common/Card";
import "./index.css";
+import { convertI18nText, I18nText } from "@/common";
+import Spinner from "../common/Spinner";
+
+interface SettingSectionProps {
+ title: I18nText;
+}
+
+const SettingSection: React.FC<SettingSectionProps> = ({ title, children }) => {
+ const { t } = useTranslation();
+
+ return (
+ <Card className="my-3 py-3">
+ <h3 className="px-3 mb-3 cru-color-primary">
+ {convertI18nText(title, t)}
+ </h3>
+ {children}
+ </Card>
+ );
+};
+
+interface ButtonSettingItemProps {
+ title: I18nText;
+ subtext?: I18nText;
+ onClick: () => void;
+ first?: boolean;
+ danger?: boolean;
+}
+
+const ButtonSettingItem: React.FC<ButtonSettingItemProps> = ({
+ title,
+ subtext,
+ onClick,
+ first,
+ danger,
+}) => {
+ const { t } = useTranslation();
+
+ return (
+ <div
+ className={classnames(
+ "settings-item clickable",
+ first && "first",
+ danger && "cru-color-danger"
+ )}
+ onClick={onClick}
+ >
+ {convertI18nText(title, t)}
+ {subtext && (
+ <small className="d-block cru-color-secondary">
+ {convertI18nText(subtext, t)}
+ </small>
+ )}
+ </div>
+ );
+};
+
+interface SelectSettingItemProps {
+ title: I18nText;
+ subtext?: I18nText;
+ options: {
+ value: string;
+ label: I18nText;
+ }[];
+ value?: string;
+ onSelect: (value: string) => void;
+ first?: boolean;
+}
+
+const SelectSettingsItem: React.FC<SelectSettingItemProps> = ({
+ title,
+ subtext,
+ options,
+ value,
+ onSelect,
+ first,
+}) => {
+ const { t } = useTranslation();
+
+ return (
+ <div className={classnames("row settings-item mx-0", first && "first")}>
+ <div className="col col-12 col-sm-auto">
+ <div>{convertI18nText(title, t)}</div>
+ <small className="d-block cru-color-secondary">
+ {convertI18nText(subtext, t)}
+ </small>
+ </div>
+ <div className="col col-12 col-sm-auto">
+ {value == null ? (
+ <Spinner />
+ ) : (
+ <select
+ value={value}
+ onChange={(e) => {
+ onSelect(e.target.value);
+ }}
+ >
+ {options.map(({ value, label }) => (
+ <option key={value} value={value}>
+ {convertI18nText(label, t)}
+ </option>
+ ))}
+ </select>
+ )}
+ </div>
+ </div>
+ );
+};
const SettingsPage: React.FC = (_) => {
- const { i18n, t } = useTranslation();
+ const { i18n } = useTranslation();
const user = useUser();
const navigate = useNavigate();
@@ -27,62 +135,57 @@ const SettingsPage: React.FC = (_) => {
<>
<div className="container">
{user ? (
- <Card className="my-3 py-3">
- <h3 className="px-3 mb-3 cru-color-primary">
- {t("settings.subheaders.account")}
- </h3>
- <div
- className="settings-item clickable first"
+ <SettingSection title="settings.subheaders.account">
+ <ButtonSettingItem
+ title="settings.changeAvatar"
onClick={() => setDialog("changeavatar")}
- >
- {t("settings.changeAvatar")}
- </div>
- <div
- className="settings-item clickable"
+ first
+ />
+ <ButtonSettingItem
+ title="settings.changeNickname"
onClick={() => setDialog("changenickname")}
- >
- {t("settings.changeNickname")}
- </div>
- <div
- className="settings-item clickable cru-color-danger"
+ />
+ <ButtonSettingItem
+ title="settings.changePassword"
onClick={() => setDialog("changepassword")}
- >
- {t("settings.changePassword")}
- </div>
- <div
- className="settings-item clickable cru-color-danger"
+ danger
+ />
+ <ButtonSettingItem
+ title="settings.logout"
onClick={() => {
setDialog("logout");
}}
- >
- {t("settings.logout")}
- </div>
- </Card>
+ danger
+ />
+ </SettingSection>
) : null}
- <Card className="my-3 py-3">
- <h3 className="px-3 mb-3 cru-color-primary">
- {t("settings.subheaders.customization")}
- </h3>
- <div className="row settings-item first mx-0">
- <div className="col col-12 col-sm-auto">
- <div>{t("settings.languagePrimary")}</div>
- <small className="d-block cru-color-secondary">
- {t("settings.languageSecondary")}
- </small>
- </div>
- <div className="col col-12 col-sm-auto">
- <select
- value={language}
- onChange={(e) => {
- void i18n.changeLanguage(e.target.value);
- }}
- >
- <option value="zh">中文</option>
- <option value="en">English</option>
- </select>
- </div>
- </div>
- </Card>
+ <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
+ />
+ </SettingSection>
</div>
<ChangePasswordDialog
open={dialog === "changepassword"}