feat: implement edit userinfo

This commit is contained in:
Steven
2023-06-23 20:52:00 +08:00
parent 9ad2eaebc5
commit 9b303da4eb
11 changed files with 173 additions and 189 deletions

View File

@@ -1,18 +1,10 @@
import { Button, Input, Modal, ModalDialog } from "@mui/joy";
import { useState } from "react";
import { toast } from "react-hot-toast";
import { validate, ValidatorConfig } from "../helpers/validator";
import useLoading from "../hooks/useLoading";
import { userService } from "../services";
import Icon from "./Icon";
const validateConfig: ValidatorConfig = {
minLength: 3,
maxLength: 24,
noSpace: true,
noChinese: true,
};
interface Props {
onClose: () => void;
}
@@ -49,12 +41,6 @@ const ChangePasswordDialog: React.FC<Props> = (props: Props) => {
return;
}
const passwordValidResult = validate(newPassword, validateConfig);
if (!passwordValidResult.result) {
toast.error("New password is invalid");
return;
}
requestState.setLoading();
try {
const user = userService.getState().user as User;

View File

@@ -0,0 +1,89 @@
import { Button, Input, Modal, ModalDialog } from "@mui/joy";
import { useState } from "react";
import { toast } from "react-hot-toast";
import useLoading from "../hooks/useLoading";
import { userService } from "../services";
import Icon from "./Icon";
import { useAppSelector } from "../stores";
interface Props {
onClose: () => void;
}
const EditUserinfoDialog: React.FC<Props> = (props: Props) => {
const { onClose } = props;
const user = useAppSelector((state) => state.user.user as User);
const [email, setEmail] = useState(user.email);
const [nickname, setNickname] = useState(user.nickname);
const requestState = useLoading(false);
const handleCloseBtnClick = () => {
onClose();
};
const handleEmailChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setEmail(text);
};
const handleNicknameChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setNickname(text);
};
const handleSaveBtnClick = async () => {
if (email === "" || nickname === "") {
toast.error("Please fill all fields");
return;
}
requestState.setLoading();
try {
const user = userService.getState().user as User;
await userService.patchUser({
id: user.id,
email,
nickname,
});
onClose();
toast("Password changed");
} catch (error: any) {
console.error(error);
toast.error(JSON.stringify(error.response.data));
}
requestState.setFinish();
};
return (
<Modal open={true}>
<ModalDialog>
<div className="flex flex-row justify-between items-center w-80 mb-4">
<span className="text-lg font-medium">Edit Userinfo</span>
<Button variant="plain" onClick={handleCloseBtnClick}>
<Icon.X className="w-5 h-auto text-gray-600" />
</Button>
</div>
<div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Email</span>
<Input className="w-full" type="text" value={email} onChange={handleEmailChanged} />
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Nickname</span>
<Input className="w-full" type="text" value={nickname} onChange={handleNicknameChanged} />
</div>
<div className="w-full flex flex-row justify-end items-center space-x-2">
<Button variant="plain" disabled={requestState.isLoading} onClick={handleCloseBtnClick}>
Cancel
</Button>
<Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleSaveBtnClick}>
Save
</Button>
</div>
</div>
</ModalDialog>
</Modal>
);
};
export default EditUserinfoDialog;

View File

@@ -1,16 +1,14 @@
import { Link, useNavigate } from "react-router-dom";
import { useAppSelector } from "../stores";
import { userService } from "../services";
import Icon from "./Icon";
import Dropdown from "./common/Dropdown";
const Header: React.FC = () => {
const navigate = useNavigate();
const { user } = useAppSelector((state) => state.user);
const user = useAppSelector((state) => state.user).user as User;
const handleSignOutButtonClick = async () => {
await userService.doSignOut();
navigate("/user/auth");
navigate("/auth");
};
return (
@@ -24,37 +22,31 @@ const Header: React.FC = () => {
</Link>
</div>
<div className="relative flex-shrink-0">
{user ? (
<Dropdown
trigger={
<button className="flex flex-row justify-end items-center cursor-pointer">
<span>{user.nickname}</span>
<Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" />
<Dropdown
trigger={
<button className="flex flex-row justify-end items-center cursor-pointer">
<span>{user.nickname}</span>
<Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" />
</button>
}
actions={
<>
<Link
to="/account"
className="w-full flex flex-row justify-start items-center px-3 leading-10 text-left cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
>
<Icon.User className="w-4 h-auto mr-2" /> My Account
</Link>
<button
className="w-full flex flex-row justify-start items-center px-3 leading-10 text-left cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
onClick={() => handleSignOutButtonClick()}
>
<Icon.LogOut className="w-4 h-auto mr-2" /> Sign out
</button>
}
actions={
<>
<Link
to="/account"
className="w-full flex flex-row justify-start items-center px-3 leading-10 text-left cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
>
<Icon.User className="w-4 h-auto mr-2" /> My Account
</Link>
<button
className="w-full flex flex-row justify-start items-center px-3 leading-10 text-left cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
onClick={() => handleSignOutButtonClick()}
>
<Icon.LogOut className="w-4 h-auto mr-2" /> Sign out
</button>
</>
}
actionsClassName="!w-40"
></Dropdown>
) : (
<span className="cursor-pointer" onClick={() => navigate("/user/auth")}>
Sign in
</span>
)}
</>
}
actionsClassName="!w-40"
></Dropdown>
</div>
</div>
</div>