2025-06-21 12:42:09 +03:00

175 lines
4.2 KiB
JavaScript

import "./bookCard.css";
import axios from "axios";
import Skeleton from "react-loading-skeleton";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import IconButton from "../../md-components/IconButton";
import Icon from "../../md-components/Icon";
function personToString(person) {
let tmpString;
if (person.lastName) {
tmpString = person.lastName;
} else {
tmpString = person.firstName;
}
if (person.middleName) {
tmpString += " " + person.middleName[0] + ".";
}
if (person.lastName && person.firstName) {
tmpString += " " + person.firstName[0] + ".";
}
return tmpString;
}
function authorsString(authors) {
let authorsStr = authors
.slice(0, 2)
.map((author) => personToString(author))
.join(", ");
if (authors.length > 2) {
authorsStr += " и др.";
}
return authorsStr;
}
const BookCard = ({
id,
title,
authors,
reader,
offline,
fromSearch,
collectionDelId,
fixed,
filetype,
}) => {
const [loaded, setLoaded] = useState(false);
const [bookImgSrc, setBookImgSrc] = useState("");
async function loadImgFromCache() {
if (window.caches === undefined) {
setBookImgSrc(axios.defaults.baseURL + "/book/" + id + "/cover");
return;
}
let cache = await window.caches.open("bookCovers");
let img = await cache.match(`/api/book/${id}/cover`);
if (img === undefined) {
if (window.onLine) {
setBookImgSrc(axios.defaults.baseURL + "/book/" + id + "/cover");
return;
} else {
setBookImgSrc("/favicon.png");
return;
}
}
let blob = await img.blob();
setBookImgSrc(URL.createObjectURL(blob));
}
useEffect(() => {
loadImgFromCache();
}, []);
return (
<Link
className={"book_card" + (fixed ? " fixed" : "")}
to={
!offline && !window.onLine
? false
: reader === undefined
? `/book/${id}${fromSearch ? "?from_search=" + fromSearch : ""}`
: `/reader/${id}`
}
style={{
color: "black",
textDecoration: "none",
}}
>
{!offline && !window.onLine ? (
<div className="book_card_deactivate"></div>
) : (
<md-ripple></md-ripple>
)}
<div
style={{
width: "100%",
overflow: "hidden",
backgroundImage: "url(" + bookImgSrc + ")",
backgroundSize: "100%",
}}
className="book_card_image"
>
<div
style={{
position: "absolute",
left: 5,
top: 5,
zIndex: 1,
background: "var(--md-sys-color-inverse-primary)",
padding: 5,
borderRadius: 10,
}}
>
<b>{filetype}</b>
</div>
{/* {
collectionDelId ?
<div className="book_actions">
<IconButton onClick={() => {
axios.post("/collection/"+collectionDelId, {book_id: String(id)})
}}>
<Icon>delete</Icon>
</IconButton>
</div> : <></>
} */}
<div
style={{
display: "flex",
alignItems: "center",
height: "100%",
backdropFilter: "blur(5px)",
}}
>
{loaded ? (
<></>
) : (
<Skeleton
style={{
width: 240,
height: 380,
lineHeight: "revert",
}}
/>
)}
<img
onLoad={() => setLoaded(true)}
style={{
pointerEvents: "none",
boxShadow: "0px 0px 20px gray",
width: "100%",
}}
src={bookImgSrc}
/>
</div>
</div>
<div
style={{
padding: "10px 0px",
}}
>
<span className="h-fit line-clamp-2 break-words">
<b>{title}</b>
</span>
<span
style={{
color: "gray",
}}
>
{authorsString(authors)}
</span>
</div>
</Link>
);
};
export default BookCard;