aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/views/settings
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/views/settings')
-rw-r--r--FrontEnd/src/views/settings/ChangeAvatarDialog.tsx196
-rw-r--r--FrontEnd/src/views/settings/ChangeNicknameDialog.tsx4
-rw-r--r--FrontEnd/src/views/settings/ChangePasswordDialog.tsx4
-rw-r--r--FrontEnd/src/views/settings/index.tsx53
4 files changed, 130 insertions, 127 deletions
diff --git a/FrontEnd/src/views/settings/ChangeAvatarDialog.tsx b/FrontEnd/src/views/settings/ChangeAvatarDialog.tsx
index c4f6f492..0bf51c21 100644
--- a/FrontEnd/src/views/settings/ChangeAvatarDialog.tsx
+++ b/FrontEnd/src/views/settings/ChangeAvatarDialog.tsx
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { AxiosError } from "axios";
-import { Modal, Row, Button } from "react-bootstrap";
import { UiLogicError } from "@/common";
@@ -10,6 +9,8 @@ import { useUserLoggedIn } 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/dailog/Dialog";
export interface ChangeAvatarDialogProps {
open: boolean;
@@ -148,36 +149,38 @@ const ChangeAvatarDialog: React.FC<ChangeAvatarDialogProps> = (props) => {
throw new UiLogicError();
}
return (
- <Row className="justify-content-center">
+ <div className="row justify-content-center">
<img
className="change-avatar-img"
src={resultUrl}
alt={t("settings.dialogChangeAvatar.previewImgAlt")}
/>
- </Row>
+ </div>
);
};
return (
- <Modal show={props.open} onHide={close}>
- <Modal.Header>
- <Modal.Title> {t("settings.dialogChangeAvatar.title")}</Modal.Title>
- </Modal.Header>
+ <Dialog open={props.open} onClose={close}>
+ <h3>{t("settings.dialogChangeAvatar.title")}</h3>
{(() => {
if (state === "select") {
return (
<>
- <Modal.Body className="container">
- <Row>{t("settings.dialogChangeAvatar.prompt.select")}</Row>
- <Row>
+ <div className="container">
+ <div className="row">
+ {t("settings.dialogChangeAvatar.prompt.select")}
+ </div>
+ <div className="row">
<input type="file" accept="image/*" onChange={onSelectFile} />
- </Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={close}>
- {t("operationDialog.cancel")}
- </Button>
- </Modal.Footer>
+ </div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.cancel"
+ color="secondary"
+ onClick={close}
+ />
+ </div>
</>
);
} else if (state === "crop") {
@@ -186,119 +189,144 @@ const ChangeAvatarDialog: React.FC<ChangeAvatarDialogProps> = (props) => {
}
return (
<>
- <Modal.Body className="container">
- <Row className="justify-content-center">
+ <div className="container">
+ <div className="row justify-content-center">
<ImageCropper
clip={clip}
onChange={setClip}
imageUrl={fileUrl}
imageElementCallback={setCropImgElement}
/>
- </Row>
- <Row>{t("settings.dialogChangeAvatar.prompt.crop")}</Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={close}>
- {t("operationDialog.cancel")}
- </Button>
- <Button variant="secondary" onClick={onCropPrevious}>
- {t("operationDialog.previousStep")}
- </Button>
+ </div>
+ <div className="row">
+ {t("settings.dialogChangeAvatar.prompt.crop")}
+ </div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.cancel"
+ color="secondary"
+ onClick={close}
+ />
<Button
+ text="operationDialog.previousStep"
+ color="secondary"
+ onClick={onCropPrevious}
+ />
+ <Button
+ text="operationDialog.nextStep"
color="primary"
onClick={onCropNext}
disabled={
cropImgElement == null || clip == null || clip.width === 0
}
- >
- {t("operationDialog.nextStep")}
- </Button>
- </Modal.Footer>
+ />
+ </div>
</>
);
} else if (state === "processcrop") {
return (
<>
- <Modal.Body className="container">
- <Row>
+ <div className="container">
+ <div className="row">
{t("settings.dialogChangeAvatar.prompt.processingCrop")}
- </Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={close}>
- {t("operationDialog.cancel")}
- </Button>
- <Button variant="secondary" onClick={onPreviewPrevious}>
- {t("operationDialog.previousStep")}
- </Button>
- </Modal.Footer>
+ </div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.cancel"
+ color="secondary"
+ onClick={close}
+ />
+ <Button
+ text="operationDialog.previousStep"
+ color="secondary"
+ onClick={onPreviewPrevious}
+ />
+ </div>
</>
);
} else if (state === "preview") {
return (
<>
- <Modal.Body className="container">
+ <div className="container">
{createPreviewRow()}
- <Row>{t("settings.dialogChangeAvatar.prompt.preview")}</Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={close}>
- {t("operationDialog.cancel")}
- </Button>
- <Button variant="secondary" onClick={onPreviewPrevious}>
- {t("operationDialog.previousStep")}
- </Button>
- <Button variant="primary" onClick={upload}>
- {t("settings.dialogChangeAvatar.upload")}
- </Button>
- </Modal.Footer>
+ <div className="row">
+ {t("settings.dialogChangeAvatar.prompt.preview")}
+ </div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.cancel"
+ color="secondary"
+ onClick={close}
+ />
+ <Button
+ text="operationDialog.previousStep"
+ color="secondary"
+ onClick={onPreviewPrevious}
+ />
+ <Button
+ text="settings.dialogChangeAvatar.upload"
+ color="primary"
+ onClick={upload}
+ />
+ </div>
</>
);
} else if (state === "uploading") {
return (
<>
- <Modal.Body className="container">
+ <div className="container">
{createPreviewRow()}
- <Row>{t("settings.dialogChangeAvatar.prompt.uploading")}</Row>
- </Modal.Body>
- <Modal.Footer></Modal.Footer>
+ <div className="row">
+ {t("settings.dialogChangeAvatar.prompt.uploading")}
+ </div>
+ </div>
+ <div></div>
</>
);
} else if (state === "success") {
return (
<>
- <Modal.Body className="container">
- <Row className="p-4 text-success">
+ <div className="container">
+ <div className="row p-4 text-success">
{t("operationDialog.success")}
- </Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="success" onClick={close}>
- {t("operationDialog.ok")}
- </Button>
- </Modal.Footer>
+ </div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.ok"
+ color="success"
+ onClick={close}
+ />
+ </div>
</>
);
} else {
return (
<>
- <Modal.Body className="container">
+ <div className="container">
{createPreviewRow()}
- <Row className="text-danger">{trueMessage}</Row>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={close}>
- {t("operationDialog.cancel")}
- </Button>
- <Button variant="primary" onClick={upload}>
- {t("operationDialog.retry")}
- </Button>
- </Modal.Footer>
+ <div className="row text-danger">{trueMessage}</div>
+ </div>
+ <div>
+ <Button
+ text="operationDialog.cancel"
+ color="secondary"
+ onClick={close}
+ />
+ <Button
+ text="operationDialog.retry"
+ color="primary"
+ onClick={upload}
+ />
+ </div>
</>
);
}
})()}
- </Modal>
+ </Dialog>
);
};
diff --git a/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx b/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx
index 4b44cdd6..605796ca 100644
--- a/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx
+++ b/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx
@@ -2,7 +2,7 @@ import { getHttpUserClient } from "@/http/user";
import { useUserLoggedIn } from "@/services/user";
import React from "react";
-import OperationDialog from "../common/OperationDialog";
+import OperationDialog from "../common/dailog/OperationDialog";
export interface ChangeNicknameDialogProps {
open: boolean;
@@ -24,7 +24,7 @@ const ChangeNicknameDialog: React.FC<ChangeNicknameDialogProps> = (props) => {
nickname: newNickname,
});
}}
- close={props.close}
+ onClose={props.close}
/>
);
};
diff --git a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx b/FrontEnd/src/views/settings/ChangePasswordDialog.tsx
index 21eeeb09..944fdaed 100644
--- a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx
+++ b/FrontEnd/src/views/settings/ChangePasswordDialog.tsx
@@ -3,7 +3,7 @@ import { useHistory } from "react-router";
import { userService } from "@/services/user";
-import OperationDialog from "../common/OperationDialog";
+import OperationDialog from "../common/dailog/OperationDialog";
export interface ChangePasswordDialogProps {
open: boolean;
@@ -55,7 +55,7 @@ const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props) => {
await userService.changePassword(oldPassword, newPassword);
setRedirect(true);
}}
- close={() => {
+ onClose={() => {
props.close();
if (redirect) {
history.push("/login");
diff --git a/FrontEnd/src/views/settings/index.tsx b/FrontEnd/src/views/settings/index.tsx
index 840bb7e8..f25911d7 100644
--- a/FrontEnd/src/views/settings/index.tsx
+++ b/FrontEnd/src/views/settings/index.tsx
@@ -1,43 +1,17 @@
import React, { useState } from "react";
import { useHistory } from "react-router";
import { useTranslation } from "react-i18next";
-import { Container, Form, Row, Col, Button, Modal } from "react-bootstrap";
import { useUser, userService } from "@/services/user";
import ChangePasswordDialog from "./ChangePasswordDialog";
import ChangeAvatarDialog from "./ChangeAvatarDialog";
import ChangeNicknameDialog from "./ChangeNicknameDialog";
+import ConfirmDialog from "../common/dailog/ConfirmDialog";
import Card from "../common/Card";
import "./index.css";
-const ConfirmLogoutDialog: React.FC<{
- onClose: () => void;
- onConfirm: () => void;
-}> = ({ onClose, onConfirm }) => {
- const { t } = useTranslation();
-
- return (
- <Modal show centered onHide={onClose}>
- <Modal.Header>
- <Modal.Title className="text-danger">
- {t("settings.dialogConfirmLogout.title")}
- </Modal.Title>
- </Modal.Header>
- <Modal.Body>{t("settings.dialogConfirmLogout.prompt")}</Modal.Body>
- <Modal.Footer>
- <Button variant="secondary" onClick={onClose}>
- {t("operationDialog.cancel")}
- </Button>
- <Button variant="danger" onClick={onConfirm}>
- {t("operationDialog.confirm")}
- </Button>
- </Modal.Footer>
- </Modal>
- );
-};
-
const SettingsPage: React.FC = (_) => {
const { i18n, t } = useTranslation();
const user = useUser();
@@ -51,7 +25,7 @@ const SettingsPage: React.FC = (_) => {
return (
<>
- <Container>
+ <div className="container">
{user ? (
<Card className="my-3 py-3">
<h3 className="px-3 mb-3 text-primary">
@@ -89,16 +63,15 @@ const SettingsPage: React.FC = (_) => {
<h3 className="px-3 mb-3 text-primary">
{t("settings.subheaders.customization")}
</h3>
- <Row className="settings-item first mx-0">
- <Col xs="12" sm="auto">
+ <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 text-secondary">
{t("settings.languageSecondary")}
</small>
- </Col>
- <Col xs="auto" className="ms-auto">
- <Form.Control
- as="select"
+ </div>
+ <div className="col col-12 col-sm-auto">
+ <select
value={language}
onChange={(e) => {
void i18n.changeLanguage(e.target.value);
@@ -106,18 +79,20 @@ const SettingsPage: React.FC = (_) => {
>
<option value="zh">中文</option>
<option value="en">English</option>
- </Form.Control>
- </Col>
- </Row>
+ </select>
+ </div>
+ </div>
</Card>
- </Container>
+ </div>
{(() => {
switch (dialog) {
case "changepassword":
return <ChangePasswordDialog open close={() => setDialog(null)} />;
case "logout":
return (
- <ConfirmLogoutDialog
+ <ConfirmDialog
+ title="settings.dialogConfirmLogout.title"
+ body="settings.dialogConfirmLogout.prompt"
onClose={() => setDialog(null)}
onConfirm={() => {
void userService.logout().then(() => {