diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index cb17589..20e1772 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -50,7 +50,7 @@ function App() { height: "100vh", width: "100vw", fontFamily: "New Amsterdam", - overflow: "scroll", + overflow: "hidden", }} > diff --git a/frontend/src/index.css b/frontend/src/index.css index 319d517..898d521 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -19,7 +19,7 @@ body { .btn-primary { background-color: #5e6268; color: #f2f3f4; - border: 2px solid #5e6268; + border: 1px solid #5e6268; } form-control { @@ -91,6 +91,16 @@ body { border: 2px solid #f2f2e8; } + .form-select { + background-color: #f2f2e8 !important; + color: #5e6268 !important; + border: 2px solid #f2f2e8; + } + + .primary { + color: #5e6268 !important; + } + .danger { background-color: #f9a9ab !important; } @@ -123,7 +133,7 @@ body { .btn-primary { background-color: #f2f3f4; color: #5e6268; - border: 2px solid #5e6268; + border-left: 1px solid #5e6268; } .form-control { @@ -179,6 +189,16 @@ body { border: 2px solid #5e6268; } + .form-select { + background-color: #f2f2e8 !important; + color: #5e6268 !important; + border: 2px solid #f2f2e8; + } + + .primary { + color: #f2f2e8 !important; + } + .dropdown-item { color: #f2f2e8 !important; svg { diff --git a/frontend/src/pages/Library/Library.tsx b/frontend/src/pages/Library/Library.tsx index 0aaaae8..76f5101 100644 --- a/frontend/src/pages/Library/Library.tsx +++ b/frontend/src/pages/Library/Library.tsx @@ -232,7 +232,7 @@ export const Library = (): React.JSX.Element => {
; @@ -19,6 +20,19 @@ export const BookModal = ({ const isEdit = !!book; const [showScanner, setShowScanner] = useState(false); + const [addNew, setAddNew] = useState(false); + + const { data: shelves, isLoading } = useQuery({ + 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 { control, register, formState, setError, setValue, reset } = useForm({ mode: "onChange", @@ -84,7 +98,7 @@ export const BookModal = ({ } if (error) return; const createdBook = await fetch( - isEdit ? "api/books/edit" : "/api/books/create", + isEdit ? "/api/books/edit" : "/api/books/create", { method: "POST", body: JSON.stringify(data), @@ -213,22 +227,52 @@ export const BookModal = ({ Shelf - - {Object.keys(bookShelfs).map((key) => ( -
+ ) : ( + { + if (ev.target.value === "addNew") { + setAddNew(true); + } + }, + })} + isInvalid={!!formState.errors.shelf} > - {key} - + {shelves?.map((shelf) => ( + + ))} + + ))} - {!values.shelf - ? "Shelf is required" + ? "Target shelf is required" : formState.errors.shelf?.message} diff --git a/frontend/src/shared/components/modals/MoveShelfModal.tsx b/frontend/src/shared/components/modals/MoveShelfModal.tsx index 133c94a..fe58fbe 100644 --- a/frontend/src/shared/components/modals/MoveShelfModal.tsx +++ b/frontend/src/shared/components/modals/MoveShelfModal.tsx @@ -1,10 +1,10 @@ -import { useMutation } from "@tanstack/react-query"; +import { useMutation, useQuery } from "@tanstack/react-query"; import { Button, Col, Form, Modal, Row } from "react-bootstrap"; -import { ImBook } from "react-icons/im"; +import { ImBook, ImCancelCircle } from "react-icons/im"; import { ModalHeader } from "./ModalHeader"; import { MoveShelfAction, MoveShelfModalProps } from "./types"; import { useForm, useWatch } from "react-hook-form"; -import { bookShelfs } from "../../../types/Book"; +import { useState } from "react"; export const MoveShelfModal = ({ books, @@ -20,7 +20,7 @@ export const MoveShelfModal = ({ const { mutate: mv } = useMutation({ mutationFn: async () => { if (!values.target) { - setError("target", { message: "Taget shelf is required" }); + setError("target", { message: "Target shelf is required" }); return; } @@ -35,6 +35,19 @@ export const MoveShelfModal = ({ }, }); + const { data: shelves, isLoading } = useQuery({ + 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(false); + return ( - - Shelf + + Shelf - - {Object.keys(bookShelfs).map((key) => ( - + {shelves?.map((shelf) => ( + + ))} + + ))} - {!values.target ? "Target shelf is required" diff --git a/frontend/src/types/Book.ts b/frontend/src/types/Book.ts index 393a1df..dc0e488 100644 --- a/frontend/src/types/Book.ts +++ b/frontend/src/types/Book.ts @@ -1,12 +1,3 @@ -export const bookShelfs = { - available: "AVAILABLE", - fnord1: "FNORD1", - fnord2: "FNORD2", - sharing: "SHARING", -} as const; - -export type Shelf = (typeof bookShelfs)[keyof typeof bookShelfs]; - export type Book = { id: number; uuid: string; @@ -16,5 +7,5 @@ export type Book = { lastCheckoutDate: number | null; checkoutBy: string | null; contact: string | null; - shelf: Shelf | null; + shelf: string | null; }; diff --git a/middleware/index.ts b/middleware/index.ts index 2b3ab01..e87c4a7 100644 --- a/middleware/index.ts +++ b/middleware/index.ts @@ -12,6 +12,7 @@ import { deleteBook, editBook, returnBook, + listShelves, } from "./queries"; import { v4 as uuidv4 } from "uuid"; import path from "path"; @@ -370,6 +371,24 @@ app.get( } ); +app.get( + "/api/shelves/list", + async ( + req: Request, + res: Response + ) => { + try { + const conn = await pool.getConnection(); + const books = await conn.query(listShelves); + const shelves = books.map((e) => (!e.shelf ? "AVAILABLE" : e.shelf)); + await conn.end(); + res.status(200).send(shelves); + } catch (error) { + res.status(500).send("Internal Server Error: " + error); + } + } +); + app.post( "/api/books/return", async ( diff --git a/middleware/queries/index.ts b/middleware/queries/index.ts index 94863aa..c52e1a2 100644 --- a/middleware/queries/index.ts +++ b/middleware/queries/index.ts @@ -6,3 +6,4 @@ export { findBook } from "./findBook"; export { createBook } from "./createBook"; export { deleteBook } from "./deleteBook"; export { editBook } from "./editBook"; +export { listShelves } from "./listShelves"; diff --git a/middleware/queries/listShelves.ts b/middleware/queries/listShelves.ts new file mode 100644 index 0000000..f4adf50 --- /dev/null +++ b/middleware/queries/listShelves.ts @@ -0,0 +1 @@ +export const listShelves = `SELECT DISTINCT shelf FROM bookData;`;