118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
import { getBookDetail } from "@/lib/api";
|
|
import { DetailedBook } from "@/lib/book";
|
|
import { Button, Table } from "flowbite-react";
|
|
import { useState, useEffect } from "react";
|
|
import type { Dispatch, ReactNode, SetStateAction } from "react";
|
|
|
|
let setId: Dispatch<SetStateAction<number | null>>;
|
|
const idRegex = new RegExp(/\|([0-9]+)\|/);
|
|
|
|
export function handleOverlay(id: string) {
|
|
if (id.length <= 3) {
|
|
return;
|
|
}
|
|
const regexRes = idRegex.exec(id)?.[1];
|
|
if (!regexRes) {
|
|
return;
|
|
}
|
|
const idInt = parseInt(regexRes);
|
|
if (isNaN(idInt)) {
|
|
return;
|
|
} else if (!isFinite(idInt)) {
|
|
return;
|
|
}
|
|
setId(idInt);
|
|
}
|
|
|
|
export function BookDetailOverlay() {
|
|
const [id, setIdI] = useState(null as number | null);
|
|
setId = setIdI;
|
|
|
|
const [book, setBook] = useState(null as DetailedBook | null);
|
|
|
|
useEffect(() => {
|
|
if (!id) return setBook(null);
|
|
getBookDetail(id.toString()).then((data) => {
|
|
if (!data) {
|
|
console.error("Failed to fetch book details");
|
|
setBook(null);
|
|
alert("Failed to fetch book details. View console for more info.");
|
|
return;
|
|
}
|
|
setBook(data);
|
|
});
|
|
}, [id]);
|
|
|
|
if (!book) {
|
|
return "";
|
|
}
|
|
const rows2 = getRows(book);
|
|
const rows1 = rows2.splice(0, 7);
|
|
|
|
return (
|
|
<div className="fixed left-0 top-0 z-50 flex h-full w-full items-center justify-center bg-zinc-400 bg-opacity-75">
|
|
<div className="rounded-md bg-white p-8">
|
|
<Button
|
|
color="failure"
|
|
className="relative right-0 top-0 float-right m-0 p-0"
|
|
onClick={() => setId(null)}
|
|
>
|
|
X
|
|
</Button>
|
|
<h2 className="text-3xl font-bold">{book.title}</h2>
|
|
<p className="text-lg">{`(${book.subtitle})`}</p>
|
|
<p className="pb-10 text-lg">{book.authors}</p>
|
|
<div className="justify-between overflow-x-auto pb-8">
|
|
<table className="m-auto w-10/12">
|
|
<tr className="m-5 p-10">
|
|
<td>
|
|
<Table className="max-w-xl">
|
|
<Table.Head>
|
|
<Table.HeadCell colSpan={5}></Table.HeadCell>
|
|
</Table.Head>
|
|
<Table.Body className="divide-y">{rows1}</Table.Body>
|
|
</Table>
|
|
</td>
|
|
<td>
|
|
<Table className="max-w-xl">
|
|
<Table.Head>
|
|
<Table.HeadCell colSpan={5}></Table.HeadCell>
|
|
</Table.Head>
|
|
<Table.Body className="divide-y">{rows2}</Table.Body>
|
|
</Table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<Button gradientDuoTone="purpleToBlue" className="float-right">
|
|
Checkout
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function getRows(book: DetailedBook) {
|
|
const rows: ReactNode[] = [];
|
|
Object.entries(book).forEach(([key, value]) => {
|
|
if (key === "id") return;
|
|
if (key == "last_updated") return;
|
|
rows.push(
|
|
<Table.Row key={key}>
|
|
<Table.Cell>{key}</Table.Cell>
|
|
<Table.Cell>{value || "Undefined"}</Table.Cell>
|
|
<Table.Cell>
|
|
<a
|
|
href="#"
|
|
className="font-medium text-cyan-600 hover:underline dark:text-cyan-500"
|
|
>
|
|
Edit
|
|
</a>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
);
|
|
});
|
|
console.log(rows);
|
|
return rows;
|
|
}
|