diff --git a/web/src/App.tsx b/web/src/App.tsx index 800516f..4ed6451 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -48,7 +48,7 @@ function App() { } /> } /> - } /> + } /> } /> } /> diff --git a/web/src/components/ChangePasswordDialog.tsx b/web/src/components/ChangePasswordDialog.tsx new file mode 100644 index 0000000..4ade93f --- /dev/null +++ b/web/src/components/ChangePasswordDialog.tsx @@ -0,0 +1,123 @@ +import { useState } from "react"; +import { validate, ValidatorConfig } from "../helpers/validator"; +import useLoading from "../hooks/useLoading"; +import { userService } from "../services"; +import Icon from "./Icon"; +import { generateDialog } from "./Dialog"; +import toastHelper from "./Toast"; + +const validateConfig: ValidatorConfig = { + minLength: 3, + maxLength: 24, + noSpace: true, + noChinese: true, +}; + +type Props = DialogProps; + +const ChangePasswordDialog: React.FC = ({ destroy }: Props) => { + const [newPassword, setNewPassword] = useState(""); + const [newPasswordAgain, setNewPasswordAgain] = useState(""); + const requestState = useLoading(false); + + const handleCloseBtnClick = () => { + destroy(); + }; + + const handleNewPasswordChanged = (e: React.ChangeEvent) => { + const text = e.target.value as string; + setNewPassword(text); + }; + + const handleNewPasswordAgainChanged = (e: React.ChangeEvent) => { + const text = e.target.value as string; + setNewPasswordAgain(text); + }; + + const handleSaveBtnClick = async () => { + if (newPassword === "" || newPasswordAgain === "") { + toastHelper.error("Please fill all inputs"); + return; + } + + if (newPassword !== newPasswordAgain) { + toastHelper.error("Not matched"); + setNewPasswordAgain(""); + return; + } + + const passwordValidResult = validate(newPassword, validateConfig); + if (!passwordValidResult.result) { + toastHelper.error("New password is invalid"); + return; + } + + requestState.setLoading(); + try { + const user = userService.getState().user as User; + await userService.patchUser({ + id: user.id, + password: newPassword, + }); + toastHelper.info("Password changed"); + handleCloseBtnClick(); + } catch (error: any) { + console.error(error); + toastHelper.error(error.response.data.message); + } + requestState.setFinish(); + }; + + return ( + <> +
+

Change Password

+ +
+
+
+ New Password + +
+
+ New Password Again + +
+
+ + +
+
+ + ); +}; + +function showChangePasswordDialog() { + generateDialog({}, ChangePasswordDialog); +} + +export default showChangePasswordDialog; diff --git a/web/src/components/CreateWorkspaceDialog.tsx b/web/src/components/CreateWorkspaceDialog.tsx index 5aba668..8edaa8d 100644 --- a/web/src/components/CreateWorkspaceDialog.tsx +++ b/web/src/components/CreateWorkspaceDialog.tsx @@ -63,6 +63,7 @@ const CreateWorkspaceDialog: React.FC = (props: Props) => { return; } + requestState.setLoading(); try { if (workspaceId) { await workspaceService.patchWorkspace({ @@ -79,6 +80,7 @@ const CreateWorkspaceDialog: React.FC = (props: Props) => { console.error(error); toastHelper.error(error.response.data.error || error.response.data.message); } + requestState.setFinish(); }; return ( @@ -110,6 +112,7 @@ const CreateWorkspaceDialog: React.FC = (props: Props) => {
+

+

+ OpenID: + + + +

); diff --git a/web/src/pages/WorkspaceDetail.tsx b/web/src/pages/WorkspaceDetail.tsx index 392ee44..e6fb615 100644 --- a/web/src/pages/WorkspaceDetail.tsx +++ b/web/src/pages/WorkspaceDetail.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { Link, useParams } from "react-router-dom"; +import { useParams } from "react-router-dom"; import { shortcutService, workspaceService } from "../services"; import { useAppSelector } from "../store"; import useLoading from "../hooks/useLoading";