132 lines
4.2 KiB
TypeScript
132 lines
4.2 KiB
TypeScript
import React from "react";
|
|
import Modal from "components/containers/modal/Modal";
|
|
import Button from "components/controls/Button";
|
|
import InputField from "components/controls/InputField";
|
|
import { useUserStore } from "../data/userSlice";
|
|
|
|
import { ReactComponent as SVGCircleProgressIcon } from "assets/svg/circle-progress.svg";
|
|
import classNames from "classnames";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Formik } from "formik";
|
|
|
|
import * as Yup from "yup";
|
|
import { useUserViewModel } from "user/controller/userViewModel";
|
|
import { User } from "user/domain/userEntity";
|
|
|
|
type Props = {
|
|
isShown: boolean;
|
|
onClose: VoidFunction;
|
|
};
|
|
|
|
type FormValues = Pick<User, "username" | "firstname" | "lastname">;
|
|
|
|
type FormValuesValidation = {
|
|
[Prop in keyof FormValues]: any;
|
|
};
|
|
|
|
export default function PersonalInfomrationEditor({
|
|
isShown,
|
|
onClose: extOnClose,
|
|
}: Props) {
|
|
const { t } = useTranslation();
|
|
const store = useUserStore();
|
|
const { user, updatePersonalInfo } = useUserViewModel(store);
|
|
|
|
const onClose = React.useCallback(() => {
|
|
extOnClose();
|
|
}, [extOnClose]);
|
|
|
|
return (
|
|
<Modal isOpen={isShown} onClose={onClose} className="max-w-lg">
|
|
<Modal.CloseButton onClose={onClose} />
|
|
<Modal.Header>{t("account.info")}</Modal.Header>
|
|
<Formik
|
|
initialValues={{
|
|
username: user?.username || "",
|
|
firstname: user?.firstname || "",
|
|
lastname: user?.lastname || "",
|
|
}}
|
|
validationSchema={Yup.object().shape<FormValuesValidation>({
|
|
username: Yup.string()
|
|
.min(2, "min 2 characters")
|
|
.max(50, "50 characters max")
|
|
.notRequired(),
|
|
firstname: Yup.string()
|
|
.min(2, "min 2 characters")
|
|
.max(50, "50 characters max")
|
|
.required("required field"),
|
|
lastname: Yup.string()
|
|
.min(2, "min 2 characters")
|
|
.max(50, "50 characters max")
|
|
.required("required field"),
|
|
})}
|
|
onSubmit={(values, actions) => {
|
|
updatePersonalInfo(values)?.then(() => {
|
|
onClose();
|
|
});
|
|
}}
|
|
>
|
|
{(formik) => (
|
|
<form onSubmit={formik.handleSubmit}>
|
|
<InputField
|
|
name="username"
|
|
placeholder="Nickname"
|
|
value={formik.values.username}
|
|
onChange={formik.handleChange}
|
|
onBlur={formik.handleBlur}
|
|
autoComplete="off"
|
|
error={formik.errors.username}
|
|
touched={formik.touched.username}
|
|
/>
|
|
<InputField
|
|
name="firstname"
|
|
placeholder="Firstname"
|
|
value={formik.values.firstname}
|
|
onChange={formik.handleChange}
|
|
onBlur={formik.handleBlur}
|
|
error={formik.errors.firstname}
|
|
touched={formik.touched.firstname}
|
|
/>
|
|
<InputField
|
|
name="lastname"
|
|
placeholder="Lastname"
|
|
value={formik.values.lastname}
|
|
onChange={formik.handleChange}
|
|
onBlur={formik.handleBlur}
|
|
error={formik.errors.lastname}
|
|
touched={formik.touched.lastname}
|
|
/>
|
|
<Modal.Footer className="flex justify-between">
|
|
<Button type="text" variant="red" onClick={onClose}>
|
|
{t("cancel")}
|
|
</Button>
|
|
<Button
|
|
disabled={
|
|
!formik.isValid || formik.isSubmitting || !formik.touched
|
|
}
|
|
htmlType="submit"
|
|
type="fill"
|
|
variant="blue"
|
|
glowing={true}
|
|
className="relative"
|
|
>
|
|
<span
|
|
className={classNames({ "opacity-0": formik.isSubmitting })}
|
|
>
|
|
{t("save")}
|
|
</span>
|
|
<SVGCircleProgressIcon
|
|
className={classNames(
|
|
"absolute top-1/2 left-1/2 trasnform -translate-x-1/2 -translate-y-1/2 w-8 h-8 stroke-current",
|
|
{ "opacity-0": !formik.isSubmitting }
|
|
)}
|
|
/>
|
|
</Button>
|
|
</Modal.Footer>
|
|
</form>
|
|
)}
|
|
</Formik>
|
|
</Modal>
|
|
);
|
|
}
|