n39librarian/frontend/src/shared/components/modals/AuthenticationModal.tsx

184 lines
5.4 KiB
TypeScript

import { useCallback, useContext } from "react";
import { Button, Col, Form, Modal, Row } from "react-bootstrap";
import { useForm, useWatch } from "react-hook-form";
import { TfiKey } from "react-icons/tfi";
import { primaryRGBA, primary, secondary } from "../../../colors";
import { ModalHeader } from "./ModalHeader";
import { AuthContext } from "../../../App";
import { AuthModalProps } from "./types";
export const AuthenticationModal = ({
open,
onClose,
isUpdate,
}: Omit<AuthModalProps, "type">) => {
const { control, register, formState, setError, reset } = useForm<{
password: string;
oldPassword: string;
newPassword: string;
}>({
mode: "onChange",
});
const values = useWatch({ control });
const auth = useContext(AuthContext);
const onSubmit = useCallback(
async (
data: Partial<{
password: string;
oldPassword: string;
newPassword: string;
}>
) => {
if (!data.password && !isUpdate) {
return setError("password", { message: "Password is required." });
}
if (isUpdate && !data.oldPassword) {
return setError("oldPassword", {
message: "Current password is required.",
});
}
if (isUpdate && !data.newPassword) {
return setError("newPassword", {
message: "New password is required.",
});
}
const res = await fetch(
isUpdate ? "/api/updateAdminKey" : "/api/authenticate",
{
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
}
);
if (!res.ok) {
setError(isUpdate ? "newPassword" : "password", {
message: await res.text(),
});
reset();
} else {
auth.setAuthenticated?.(true);
reset();
onClose();
}
},
[isUpdate, setError, reset, auth, onClose]
);
return (
<Modal
show={open}
onHide={onClose}
style={{ backgroundColor: primaryRGBA }}
centered
>
<ModalHeader
onClose={onClose}
title={isUpdate ? "Set new Admin key" : "Admin Login"}
icon={<TfiKey size={50} className='ml-0 mr-auto' />}
/>
<Modal.Body
style={{
border: "2px solid black",
borderTop: "none",
backgroundColor: primary,
}}
>
<Form
className='mb-2'
onSubmit={(ev) => {
ev.preventDefault();
onSubmit(values);
}}
>
{isUpdate && (
<>
<Form.Group as={Row} className='mb-2'>
<Col sm='4'>
<Form.Label>Current Password</Form.Label>
</Col>
<Col>
<Form.Control
{...register("oldPassword", { required: true })}
type='password'
placeholder='Enter current admin password ...'
isInvalid={!!formState.errors.oldPassword}
/>
<Form.Control.Feedback type='invalid'>
{!values.oldPassword
? "Old password is required"
: formState.errors.oldPassword?.message}
</Form.Control.Feedback>
</Col>
</Form.Group>
<Form.Group as={Row} className='mb-2'>
<Col sm='4'>
<Form.Label>New Password</Form.Label>
</Col>
<Col>
<Form.Control
{...register("newPassword", {
required: true,
})}
type='password'
placeholder={`Enter new admin password ...`}
isInvalid={!!formState.errors.newPassword}
/>
<Form.Control.Feedback type='invalid'>
{!values.newPassword
? "New password is required"
: formState.errors.newPassword?.message}
</Form.Control.Feedback>
</Col>
</Form.Group>{" "}
</>
)}
{!isUpdate && (
<Form.Group as={Row} className='mb-2'>
<Col sm='4'>
<Form.Label>Password</Form.Label>
</Col>
<Col>
<Form.Control
{...register("password", {
required: true,
})}
type='password'
placeholder={`Enter admin password ...`}
isInvalid={!!formState.errors.password}
/>
<Form.Control.Feedback type='invalid'>
{!values.password
? "Password is required"
: formState.errors.password?.message}
</Form.Control.Feedback>
</Col>
</Form.Group>
)}
<div className='d-flex mx-auto mb-auto mt-2 w-100'>
<Button
style={{
borderRadius: "5px",
backgroundColor: secondary,
color: "black",
border: "2px solid black",
marginLeft: "auto",
marginRight: "10px",
}}
onClick={() => onSubmit(values)}
>
Send
</Button>
</div>
</Form>
</Modal.Body>
</Modal>
);
};