You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.9 KiB

import { menuEnum } from "../constants/index.js";
import { fetchData, downloadBook, searchByAuthor } from "../requests/index.js";
export default class BookSection {
subElements = [];
element;
constructor({ url = "", label = "" } = {}) {
this.url = url;
this.label = label;
this.render();
}
get template() {
return `
<div class='main-book__wrapper'>
<div data-element="body"></div>
<div class='flowers mh-auto'></div>
</div>
`;
}
initialize() {
this.initEventListeners();
}
initEventListeners() {
const booksListener = document.querySelector(".main-book__wrapper");
booksListener.addEventListener("click", (event) => {
let id, title;
const isLike = event.target.closest("[data-like]");
const isMenu = event.target.closest("[data-menu]");
const isAction = event.target.closest("[data-action]");
const isLink = event.target.closest("[data-link]");
const isAuthor = event.target.closest("[data-author]");
switch (true) {
case !!isAction:
id = isAction.dataset.action;
const { authorid, bookid } =
isAction.parentNode.parentNode.dataset || {};
this.makeAction({ id, authorid, bookid });
break;
case !!isLike:
this.makeLike(isLike);
break;
case !!isMenu:
this.openMenu(isMenu);
break;
case !!isLink:
id = isLink.dataset.bookid;
title = isLink.dataset.title;
let format = isLink.dataset.format.toLowerCase();
downloadBook({ id, title, format });
break;
case !!isAuthor:
id = isAuthor.dataset.author;
this.update({ isByAuthor: true, id });
default:
this.closeMenu();
break;
}
});
}
destroyEventListeners() {}
getBookBody(data) {
return (data || [])
.map(
({
id,
authors,
description,
format,
genres,
imageUrl,
title,
series,
subseries,
year,
tags,
isFavorite,
}) => {
const { name, id: authorid } = authors[0] || "Неизвестно";
return `
<article data-element="card" class="main-book__card d-fl mb-m mh-auto">
<div class="main-book__menu_wrapper d-fl">
<div class="main-book__menu_like ${
isFavorite ? "liked" : "not-liked"
}" data-like data-bookid=${id}></div>
<nav class="main-book__menu main-book__menu_closed"
data-authorid=${authorid}
data-bookid=${id}
data-menu></nav>
</div>
<div class="main-book__image mr-m">
<div class='d-fl'>
<div class="main-book__format pr-s">
<a class="main-book__link"
data-link
data-bookid=${id}
data-title=${(title || "Unknown")
.split(" ")
.join("_")}
data-format=${format}
>${format}</a>
</div>
<div>
<img class="d-bl" src=${
imageUrl ? imageUrl : "../web/assets/cover.jpg"
} alt="cover" style="width:80px;height:128px;">
<a class="main-card__author main-book__link second-text mt-s" data-author=${authorid}>
${name || ""}</a>
<div class="second-text mt-s">
${year || "Год неизвестен"}</div>
</div>
</div>
</div>
<div class="main-book__description ">
<div class="main-book__header">
<span class="second-text mt-s no-wrap "><strong>
${title || "Название неизвестно"}</strong></span>
<span class="second-text pl-xs no-wrap">
${series || ""}</span>
<span class="second-text pl-xs no-wrap ">
${subseries || ""}</span>
</div>
<div class="main-book__body mt-s">
<div>
<span class="second-text">
${description || "Нет описания"}</span>
</div>
</div>
<div class="main-book__footer d-fl mt-m">${this.getTags(
tags
)}</div>
</div>
</article>`;
}
)
.join("");
}
getEmptyBody() {
return `
<article class="no-book__card d-fl mb-m mh-auto">
<div class="mh-auto">Ничего не найдено</div>
</article>`;
}
getMenuBody() {
return menuEnum
.map(({ label, id }) => {
return `
<li class="main-book__action second-text" id="main-book__action" data-action=${id}>
${label}
</li>`;
})
.join("");
}
getTags(tags) {
return (tags || [])
.map(({ id, name }) => {
return `<a class="main-book__tag main-book__link" data-id=${id}>#${name}</a>`;
})
.join("");
}
openMenu(element) {
this.closeMenu();
element.classList.remove("main-book__menu_closed");
const divElement = document.createElement("ul");
divElement.innerHTML = this.getMenuBody();
element.append(divElement);
element.classList.add("main-book__menu_opened");
}
closeMenu() {
const elements = document.querySelectorAll(".main-book__menu_opened");
if (elements && elements.length) {
for (const subElement of elements) {
subElement.firstElementChild.remove();
subElement.classList.remove("main-book__menu_opened");
subElement.classList.add("main-book__menu_closed");
}
}
}
async makeAction({ id, authorid, bookid }) {
this.element.classList.add("blur", "spinner");
if (menuEnum[id].action) {
const data = await menuEnum[id].action({ id, authorid, bookid });
} else {
alert("Напиши меня");
}
this.element.classList.remove("spinner");
this.closeMenu()
}
makeLike(element) {
const { bookid: likedBookId } = element.dataset || {};
this.makeAction({ id: 0, authorid: "", bookid: likedBookId });
element.classList.add("liked");
}
async update(params) {
this.element.classList.add("blur", "spinner");
let data = [];
if (params?.isByAuthor) {
data = await searchByAuthor({ id: params.id });
} else {
const query = params;
data = await fetchData({ query, url: this.url });
}
console.log("data", data);
if (data && Object.values(data).length) {
this.subElements.body.innerHTML = this.getBookBody(data);
this.initialize();
} else {
this.subElements.body.innerHTML = this.getEmptyBody();
}
this.element.classList.remove("spinner");
}
getSubElements(element) {
const result = {};
const elements = element.querySelectorAll("[data-element]");
for (const subElement of elements) {
const name = subElement.dataset.element;
result[name] = subElement;
}
return result;
}
render() {
const divElement = document.createElement("div");
divElement.innerHTML = this.template;
this.element = divElement.firstElementChild;
this.subElements = this.getSubElements(this.element);
}
remove() {
if (this.element) {
this.element.remove();
destroyEventListeners();
}
}
destroy() {
this.remove();
this.element = null;
}
}

Powered by TurnKey Linux.