140 lines
4.2 KiB
TypeScript
140 lines
4.2 KiB
TypeScript
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
import { Button, Col, Form, Modal, Row } from "react-bootstrap";
|
|
import { ImBook, ImCancelCircle } from "react-icons/im";
|
|
import { ModalHeader } from "./ModalHeader";
|
|
import { MoveShelfAction, MoveShelfModalProps } from "./types";
|
|
import { useForm, useWatch } from "react-hook-form";
|
|
import { useState } from "react";
|
|
|
|
export const MoveShelfModal = ({
|
|
books,
|
|
open,
|
|
onClose,
|
|
}: Omit<MoveShelfModalProps, "type">): React.JSX.Element => {
|
|
const { control, register, formState, setError } = useForm<MoveShelfAction>({
|
|
mode: "onChange",
|
|
});
|
|
|
|
const values = useWatch({ control });
|
|
|
|
const { mutate: mv } = useMutation({
|
|
mutationFn: async () => {
|
|
if (!values.target) {
|
|
setError("target", { message: "Target shelf is required" });
|
|
return;
|
|
}
|
|
|
|
await fetch(`/api/shelf/move`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ ...values, books }),
|
|
});
|
|
onClose();
|
|
},
|
|
});
|
|
|
|
const { data: shelves, isLoading } = useQuery<string[]>({
|
|
queryFn: async () => {
|
|
const response = await fetch(`/api/shelves/list`);
|
|
const data = await response.text();
|
|
return data
|
|
.split(",")
|
|
.map((s) => s.replaceAll('"', "").replace("[", "").replace("]", ""));
|
|
},
|
|
queryKey: ["shleves"],
|
|
});
|
|
|
|
const [addNew, setAddNew] = useState<boolean>(false);
|
|
|
|
return (
|
|
<Modal show={open} onHide={onClose} centered>
|
|
<ModalHeader
|
|
onClose={onClose}
|
|
title={"Move to Shelf"}
|
|
icon={<ImBook size={50} className='ml-0 mr-auto' />}
|
|
/>
|
|
<Modal.Body
|
|
style={{
|
|
borderTop: "none",
|
|
}}
|
|
>
|
|
<Form.Group as={Row} className='mb-2'>
|
|
<Col className='d-flex' sm='2'>
|
|
<Form.Label className='m-auto'>Shelf</Form.Label>
|
|
</Col>
|
|
<Col>
|
|
{!isLoading &&
|
|
(addNew ? (
|
|
<div className='d-flex'>
|
|
<Form.Control
|
|
id='move-shelf-text-input'
|
|
{...register("target", { required: true })}
|
|
/>
|
|
<Button
|
|
style={{
|
|
background: "transparent",
|
|
marginLeft: "0px",
|
|
marginRight: "10px",
|
|
}}
|
|
className='d-flex m-auto'
|
|
onClick={() => setAddNew(false)}
|
|
>
|
|
<ImCancelCircle className='m-auto primary' size={20} />
|
|
</Button>
|
|
</div>
|
|
) : (
|
|
<Form.Select
|
|
id='move-shelf-select'
|
|
{...register("target", {
|
|
required: true,
|
|
onChange: (ev) => {
|
|
if (ev.target.value === "addNew") {
|
|
setAddNew(true);
|
|
}
|
|
},
|
|
})}
|
|
isInvalid={!!formState.errors.target}
|
|
>
|
|
{shelves?.map((shelf) => (
|
|
<option key='key' value={shelf}>
|
|
{shelf}
|
|
</option>
|
|
))}
|
|
<option value='addNew'>Add new</option>
|
|
</Form.Select>
|
|
))}
|
|
<Form.Control.Feedback type='invalid'>
|
|
{!values.target
|
|
? "Target shelf is required"
|
|
: formState.errors.target?.message}
|
|
</Form.Control.Feedback>
|
|
</Col>
|
|
</Form.Group>
|
|
<div className='d-flex mx-auto mb-auto mt-2 w-100'>
|
|
<Button
|
|
style={{
|
|
borderRadius: "5px",
|
|
marginLeft: "auto",
|
|
marginRight: "10px",
|
|
}}
|
|
onClick={() => onClose()}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
style={{
|
|
borderRadius: "5px",
|
|
marginLeft: "0px",
|
|
marginRight: "10px",
|
|
}}
|
|
onClick={() => mv()}
|
|
>
|
|
Move
|
|
</Button>
|
|
</div>
|
|
</Modal.Body>
|
|
</Modal>
|
|
);
|
|
};
|