From d513de97b93077409aa59c278673de2489fdb627 Mon Sep 17 00:00:00 2001 From: zum Date: Fri, 11 Apr 2025 22:34:12 +0400 Subject: [PATCH 1/7] done create and delete. Update left --- html/components/bookComponent/api/client.js | 38 ++ html/components/bookComponent/controller.js | 32 + html/components/bookComponent/model.js | 33 ++ html/components/bookComponent/view.js | 56 ++ html/database/data.json | 64 ++ html/mainStyle.css | 6 +- html/profile.html | 36 +- package-lock.json | 626 ++++++++++++++++++++ package.json | 9 +- 9 files changed, 875 insertions(+), 25 deletions(-) create mode 100644 html/components/bookComponent/api/client.js create mode 100644 html/components/bookComponent/controller.js create mode 100644 html/components/bookComponent/model.js create mode 100644 html/components/bookComponent/view.js create mode 100644 html/database/data.json diff --git a/html/components/bookComponent/api/client.js b/html/components/bookComponent/api/client.js new file mode 100644 index 0000000..e38a7f8 --- /dev/null +++ b/html/components/bookComponent/api/client.js @@ -0,0 +1,38 @@ +const URL = "http://localhost:5174/"; + +const makeRequest = async (path, params, vars, method = "GET", data = null) => { + try { + const requestParams = params ? `?${params}` : ""; + const pathVariables = vars ? `/${vars}` : ""; + const options = { method }; + const hasBody = (method === "POST" || method === "PUT") && data; + if (hasBody) { + options.headers = { "Content-Type": "application/json;charset=utf-8" }; + options.body = JSON.stringify(data); + } + const response = await fetch(`${URL}${path}${pathVariables}${requestParams}`, options); + if (!response.ok) { + throw new Error(`Response status: ${response?.status}`); + } + + const json = await response.json(); + console.debug(path, json); + return json; + } catch (error) { + if (error instanceof SyntaxError) { + throw new Error("There was a SyntaxError", error); + } else { + throw new Error("There was an error", error); + } + } +}; + +export const getAllItems = (path, params) => makeRequest(path, params); + +export const getItem = (path, id) => makeRequest(path, null, id); + +export const createItem = (path, data) => makeRequest(path, null, null, "POST", data); + +export const updateItem = (path, id, data) => makeRequest(path, null, id, "PUT", data); + +export const deleteItem = (path, id) => makeRequest(path, null, id, "DELETE"); diff --git a/html/components/bookComponent/controller.js b/html/components/bookComponent/controller.js new file mode 100644 index 0000000..364797d --- /dev/null +++ b/html/components/bookComponent/controller.js @@ -0,0 +1,32 @@ +import model from "./model.js"; +import view from "./view.js"; + +const controller = { + async init() { + const books = await model.getBooks(); + const container = document.getElementById("bookListContent"); + view.renderBooks(books, container); + + view.bindAddForm(async (book) => { + await model.addBook(book); + const books = await model.getBooks(); + view.renderBooks(books, container); + }); + + view.bindDeleteButton(async (id) => { + await model.deleteBook(id); + const books = await model.getBooks(); + view.renderBooks(books, container); + }); + view.bindUpdateButton(async (id) => { + console.log(id); + await model.updateBook(id); + const books = await model.getBooks(); + view.renderBooks(books, container); + }); + }, +}; + +export default controller; + +controller.init(); diff --git a/html/components/bookComponent/model.js b/html/components/bookComponent/model.js new file mode 100644 index 0000000..105da99 --- /dev/null +++ b/html/components/bookComponent/model.js @@ -0,0 +1,33 @@ +import { createItem, deleteItem, getAllItems, updateItem } from "./api/client"; +const BOOKS_URL = "books"; +const AUTHORS_URL = "authors"; +const GENRES_URL = "genres"; + +export default { + async getBooks() { + const books = await getAllItems(BOOKS_URL); + const authors = await getAllItems(AUTHORS_URL); + const genres = await getAllItems(GENRES_URL); + const booksWithDetails = books.map((book) => { + const author = authors.find((author) => author.id === book.author_id); + const genre = genres.find((genre) => genre.id === book.genre_id); + return { + ...book, + author: author ? author.name : "Неизвестный автор", + genre: genre ? genre.name : "Неизвестный жанр", + }; + }); + return booksWithDetails; + }, + async addBook(book) { + const res = await createItem(BOOKS_URL, book); + return res; + }, + async deleteBook(id) { + return await deleteItem(BOOKS_URL, id); + }, + async updateBook(id) { + console.log(id); + return updateItem(BOOKS_URL, id); + }, +}; diff --git a/html/components/bookComponent/view.js b/html/components/bookComponent/view.js new file mode 100644 index 0000000..a4eecbc --- /dev/null +++ b/html/components/bookComponent/view.js @@ -0,0 +1,56 @@ +export default { + renderBooks(books, container) { + container.innerHTML = ""; + books.forEach((book) => { + const div = document.createElement("div"); + div.className = "col border border-dark bg-light border-3 h-100 col-5 col-md-7 col-lg-5 p-1 m-2"; + div.innerHTML = ` + Обложка книги книги +

${book.name}

+

${book.author}

+

${book.genre}

+
+
+ + +
`; + + container.appendChild(div); + }); + }, + + bindAddForm(callback) { + document.getElementById("formAddBook").addEventListener("submit", (e) => { + e.preventDefault(); + const name = document.getElementById("bookTitle").value; + const author_id = document.getElementById("authorName").value; + const genre_id = document.getElementById("genre-select").value; + callback({ name, author_id, genre_id }); + e.target.reset(); + }); + }, + + bindDeleteButton(callback) { + document.getElementById("bookListContent").addEventListener("click", (e) => { + if (e.target.classList.contains("delete")) { + const id = e.target.getAttribute("data-id"); + callback(id); + } + }); + }, + bindUpdateButton(callback) { + document.getElementById("bookListContent").addEventListener("click", (e) => { + if (e.target.classList.contains("update")) { + const id = e.target.getAttribute("data-id"); + // Отправляем id книги на callback, который обновит форму + callback(id); + } + }); + }, + + fillFormForEditing(book) { + document.getElementById("bookTitle").value = book.name; + document.getElementById("authorName").value = book.author_id; + document.getElementById("genre-select").value = book.genreId; + }, +}; diff --git a/html/database/data.json b/html/database/data.json new file mode 100644 index 0000000..c92609b --- /dev/null +++ b/html/database/data.json @@ -0,0 +1,64 @@ +{ + "books": [ + { + "id": "1", + "deadline_date": "2027-10-15", + "genre_id": "2", + "name": "Там, где спит рассвет", + "author_id": "2" + }, + { + "id": "2", + "deadline_date": "2027-10-15", + "genre_id": "2", + "name": "Формула одиночества", + "author_id": "2" + }, + { + "id": "3", + "deadline_date": "2026-10-15", + "genre_id": "3", + "author_id": "1", + "name": "Прах будущего" + }, + { + "id": "4", + "deadline_date": "2027-10-15", + "genre_id": "3", + "author_id": "2", + "name": "Город, который придумал себя" + }, + { + "id": "b019", + "name": "Имя книги", + "author_id": "2", + "genre_id": "2" + } + ], + "authors": [ + { + "id": "1", + "name": "Алекс Фличер", + "biography": "Какая-то краткая и неподробная биография" + }, + { + "id": "2", + "name": "Яков Блэк", + "biography": "Другая, отличающаяся биография другого автора" + } + ], + "genres": [ + { + "id": "1", + "name": "Художественная литература" + }, + { + "id": "2", + "name": "Нон-фикшн" + }, + { + "id": "3", + "name": "Научная фантастика" + } + ] +} diff --git a/html/mainStyle.css b/html/mainStyle.css index 6f53545..d4cc3ff 100644 --- a/html/mainStyle.css +++ b/html/mainStyle.css @@ -10,10 +10,14 @@ main { /* Общие стили */ p { - color: #37745b; + color: #3e8165; margin: 5px; } +footer p { + color: #1e3a3a; + margin: 5px; +} i { margin: 3px; } diff --git a/html/profile.html b/html/profile.html index 5137c13..e9cf042 100644 --- a/html/profile.html +++ b/html/profile.html @@ -95,12 +95,11 @@ > Список книг к прочтению -
+
-
+ >
- + diff --git a/package-lock.json b/package-lock.json index 723277f..8ab07af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "5.2.3", "http-server": "14.1.1", + "json-server": "1.0.0-beta.3", "npm-run-all": "4.1.5", "vite": "6.2.0", "vite-plugin-static-copy": "latest" @@ -601,6 +602,13 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -885,6 +893,327 @@ "dev": true, "license": "MIT" }, + "node_modules/@tinyhttp/accepts": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/accepts/-/accepts-2.2.3.tgz", + "integrity": "sha512-9pQN6pJAJOU3McmdJWTcyq7LLFW8Lj5q+DadyKcvp+sxMkEpktKX5sbfJgJuOvjk6+1xWl7pe0YL1US1vaO/1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime": "4.0.4", + "negotiator": "^0.6.3" + }, + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/accepts/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/app": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.5.2.tgz", + "integrity": "sha512-DcB3Y8GQppLQlO2VxRYF7LzTEAoZb+VRQXuIsErcu2fNaM1xdx6NQZDso5rlZUiaeg6KYYRfU34N4XkZbv6jSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/proxy-addr": "2.2.1", + "@tinyhttp/req": "2.2.5", + "@tinyhttp/res": "2.2.5", + "@tinyhttp/router": "2.2.3", + "header-range-parser": "1.1.3", + "regexparam": "^2.0.2" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-disposition": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.2.tgz", + "integrity": "sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-type": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-type/-/content-type-0.1.4.tgz", + "integrity": "sha512-dl6f3SHIJPYbhsW1oXdrqOmLSQF/Ctlv3JnNfXAE22kIP7FosqJHxkz/qj2gv465prG8ODKH5KEyhBkvwrueKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4" + } + }, + "node_modules/@tinyhttp/cookie": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie/-/cookie-2.1.1.tgz", + "integrity": "sha512-h/kL9jY0e0Dvad+/QU3efKZww0aTvZJslaHj3JTPmIPC9Oan9+kYqmh3M6L5JUQRuTJYFK2nzgL2iJtH2S+6dA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/cookie-signature": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie-signature/-/cookie-signature-2.1.1.tgz", + "integrity": "sha512-VDsSMY5OJfQJIAtUgeQYhqMPSZptehFSfvEEtxr+4nldPA8IImlp3QVcOVuK985g4AFR4Hl1sCbWCXoqBnVWnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/cors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cors/-/cors-2.0.1.tgz", + "integrity": "sha512-qrmo6WJuaiCzKWagv2yA/kw6hIISfF/hOqPWwmI6w0o8apeTMmRN3DoCFvQ/wNVuWVdU5J4KU7OX8aaSOEq51A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/vary": "^0.1.3" + }, + "engines": { + "node": ">=12.20 || 14.x || >=16" + } + }, + "node_modules/@tinyhttp/encode-url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/encode-url/-/encode-url-2.1.1.tgz", + "integrity": "sha512-AhY+JqdZ56qV77tzrBm0qThXORbsVjs/IOPgGCS7x/wWnsa/Bx30zDUU/jPAUcSzNOzt860x9fhdGpzdqbUeUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/etag": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/etag/-/etag-2.1.2.tgz", + "integrity": "sha512-j80fPKimGqdmMh6962y+BtQsnYPVCzZfJw0HXjyH70VaJBHLKGF+iYhcKqzI3yef6QBNa8DKIPsbEYpuwApXTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/forwarded": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.2.tgz", + "integrity": "sha512-9H/eulJ68ElY/+zYpTpNhZ7vxGV+cnwaR6+oQSm7bVgZMyuQfgROW/qvZuhmgDTIxnGMXst+Ba4ij6w6Krcs3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/logger": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tinyhttp/logger/-/logger-2.1.0.tgz", + "integrity": "sha512-Ma1fJ9CwUbn9r61/4HW6+nflsVoslpOnCrfQ6UeZq7GGIgwLzofms3HoSVG7M+AyRMJpxlfcDdbH5oFVroDMKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.20", + "dayjs": "^1.11.13", + "http-status-emojis": "^2.2.0" + }, + "engines": { + "node": ">=14.18 || >=16.20" + } + }, + "node_modules/@tinyhttp/proxy-addr": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.1.tgz", + "integrity": "sha512-BicqMqVI91hHq2BQmnqJUh0FQUnx7DncwSGgu2ghlh+JZG2rHK2ZN/rXkfhrx1rrUw6hnd0L36O8GPMh01+dDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/forwarded": "2.1.2", + "ipaddr.js": "^2.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/req": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.5.tgz", + "integrity": "sha512-trfsXwtmsNjMcGKcLJ+45h912kLRqBQCQD06ams3Tq0kf4gHLxjHjoYOC1Z9yGjOn81XllRx8wqvnvr+Kbe3gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/accepts": "2.2.3", + "@tinyhttp/type-is": "2.2.4", + "@tinyhttp/url": "2.1.1", + "header-range-parser": "^1.1.3" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/res": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.5.tgz", + "integrity": "sha512-yBsqjWygpuKAVz4moWlP4hqzwiDDqfrn2mA0wviJAcgvGiyOErtlQwXY7aj3aPiCpURvxvEFO//Gdy6yV+xEpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-disposition": "2.2.2", + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/cookie-signature": "2.1.1", + "@tinyhttp/encode-url": "2.1.1", + "@tinyhttp/req": "2.2.5", + "@tinyhttp/send": "2.2.3", + "@tinyhttp/vary": "^0.1.3", + "es-escape-html": "^0.1.1", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/res/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/router": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/router/-/router-2.2.3.tgz", + "integrity": "sha512-O0MQqWV3Vpg/uXsMYg19XsIgOhwjyhTYWh51Qng7bxqXixxx2PEvZWnFjP7c84K7kU/nUX41KpkEBTLnznk9/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/send": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/send/-/send-2.2.3.tgz", + "integrity": "sha512-o4cVHHGQ8WjVBS8UT0EE/2WnjoybrfXikHwsRoNlG1pfrC/Sd01u1N4Te8cOd/9aNGLr4mGxWb5qTm2RRtEi7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "@tinyhttp/etag": "2.1.2", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/send/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/type-is": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/type-is/-/type-is-2.2.4.tgz", + "integrity": "sha512-7F328NheridwjIfefBB2j1PEcKKABpADgv7aCJaE8x8EON77ZFrAkI3Rir7pGjopV7V9MBmW88xUQigBEX2rmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/type-is/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/url/-/url-2.1.1.tgz", + "integrity": "sha512-POJeq2GQ5jI7Zrdmj22JqOijB5/GeX+LEX7DUdml1hUnGbJOTWDx7zf2b5cCERj7RoXL67zTgyzVblBJC+NJWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/vary": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/vary/-/vary-0.1.3.tgz", + "integrity": "sha512-SoL83sQXAGiHN1jm2VwLUWQSQeDAAl1ywOm6T0b0Cg1CZhVsjoiZadmjhxF6FHCCY7OHHVaLnTgSMxTPIDLxMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1373,6 +1702,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1466,6 +1802,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -1599,6 +1942,35 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "4.39.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", + "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1723,6 +2095,16 @@ "node": ">= 0.4" } }, + "node_modules/es-escape-html": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/es-escape-html/-/es-escape-html-0.1.1.tgz", + "integrity": "sha512-yUx1o+8RsG7UlszmYPtks+dm6Lho2m8lgHMOsLJQsFI0R8XwUJwiMhM1M4E/S8QLeGyf6MkDV/pWgjQ0tdTSyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.x" + } + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -2172,6 +2554,19 @@ "node": ">=0.10.0" } }, + "node_modules/eta": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz", + "integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -2683,6 +3078,16 @@ "he": "bin/he" } }, + "node_modules/header-range-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/header-range-parser/-/header-range-parser-1.1.3.tgz", + "integrity": "sha512-B9zCFt3jH8g09LR1vHL4pcAn8yMEtlSlOUdQemzHMRKMImNIhhszdeosYFfNW0WXKQtXIlWB+O4owHJKvEJYaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -2766,6 +3171,13 @@ "node": ">=12" } }, + "node_modules/http-status-emojis": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http-status-emojis/-/http-status-emojis-2.2.0.tgz", + "integrity": "sha512-ompKtgwpx8ff0hsbpIB7oE4ax1LXoHmftsHHStMELX56ivG3GhofTX8ZHWlUaFKfGjcGjw6G3rPk7dJRXMmbbg==", + "dev": true, + "license": "MIT" + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -2816,6 +3228,16 @@ "node": ">=0.8.19" } }, + "node_modules/inflection": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.2.tgz", + "integrity": "sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2850,6 +3272,16 @@ "node": ">= 0.4" } }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -3306,6 +3738,90 @@ "dev": true, "license": "MIT" }, + "node_modules/json-server": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-1.0.0-beta.3.tgz", + "integrity": "sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==", + "dev": true, + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "@tinyhttp/app": "^2.4.0", + "@tinyhttp/cors": "^2.0.1", + "@tinyhttp/logger": "^2.0.0", + "chalk": "^5.3.0", + "chokidar": "^4.0.1", + "dot-prop": "^9.0.0", + "eta": "^3.5.0", + "inflection": "^3.0.0", + "json5": "^2.2.3", + "lowdb": "^7.0.1", + "milliparsec": "^4.0.0", + "sirv": "^2.0.4", + "sort-on": "^6.1.0" + }, + "bin": { + "json-server": "lib/bin.js" + }, + "engines": { + "node": ">=18.3" + } + }, + "node_modules/json-server/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/json-server/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/json-server/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-server/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -3402,6 +3918,22 @@ "dev": true, "license": "MIT" }, + "node_modules/lowdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz", + "integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==", + "dev": true, + "license": "MIT", + "dependencies": { + "steno": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3445,6 +3977,16 @@ "node": ">=8.6" } }, + "node_modules/milliparsec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/milliparsec/-/milliparsec-4.0.0.tgz", + "integrity": "sha512-/wk9d4Z6/9ZvoEH/6BI4TrTCgmkpZPuSRN/6fI9aUHOfXdNTuj/VhLS7d+NqG26bi6L9YmGXutVYvWC8zQ0qtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -3481,6 +4023,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3514,6 +4066,16 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4277,6 +4839,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexparam": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.2.tgz", + "integrity": "sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -4653,6 +5225,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sort-on": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sort-on/-/sort-on-6.1.0.tgz", + "integrity": "sha512-WTECP0nYNWO1n2g5bpsV0yZN9cBmZsF8ThHFbOqVN0HBFRoaQZLLEMvMmJlKHNPYQeVngeI5+jJzIfFqOIo1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-prop": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4699,6 +5302,19 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/steno": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", + "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/string.prototype.padend": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", @@ -4876,6 +5492,16 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", diff --git a/package.json b/package.json index c295358..8fece20 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,12 @@ "version": "1.0.0", "type": "module", "scripts": { - "start": "vite", + "start": "npm-run-all --parallel backend vite", + "vite": "vite", "build": "vite build", "serve": "http-server -p 3000 ./html/", - "prod": "npm-run-all build serve", + "backend": "json-server ./html/database/data.json -p 5174", + "prod": "npm-run-all build serve --parallel backend serve", "lint": "eslint . --ext js --report-unused-disable-directives --max-warnings 0" }, "dependencies": { @@ -23,6 +25,7 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "5.2.3", "eslint-plugin-html": "8.1.2", - "vite-plugin-static-copy": "latest" + "vite-plugin-static-copy": "latest", + "json-server": "1.0.0-beta.3" } } -- 2.25.1 From e9960dc2c9604048dd39f73de83f34ba5c764b8e Mon Sep 17 00:00:00 2001 From: zum Date: Sat, 12 Apr 2025 00:19:22 +0400 Subject: [PATCH 2/7] i think good enough --- html/book-edit.html | 121 ++++++++++++++++++++ html/components/bookComponent/controller.js | 20 +++- html/components/bookComponent/model.js | 11 +- html/components/bookComponent/view.js | 27 +++-- html/database/data.json | 116 +++++++++---------- html/profile.html | 2 +- 6 files changed, 217 insertions(+), 80 deletions(-) create mode 100644 html/book-edit.html diff --git a/html/book-edit.html b/html/book-edit.html new file mode 100644 index 0000000..12cb524 --- /dev/null +++ b/html/book-edit.html @@ -0,0 +1,121 @@ + + + + LibraNet + + + + + + + + + + + + +
+
+ + LibraNet Logo + +
+

LibraNet

+

Сборник свободных и бесплатных книг

+
+
+ + +
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+ +
+ + + + diff --git a/html/components/bookComponent/controller.js b/html/components/bookComponent/controller.js index 364797d..5b83710 100644 --- a/html/components/bookComponent/controller.js +++ b/html/components/bookComponent/controller.js @@ -1,6 +1,5 @@ import model from "./model.js"; import view from "./view.js"; - const controller = { async init() { const books = await model.getBooks(); @@ -19,14 +18,25 @@ const controller = { view.renderBooks(books, container); }); view.bindUpdateButton(async (id) => { - console.log(id); - await model.updateBook(id); - const books = await model.getBooks(); - view.renderBooks(books, container); + window.location.href = `./book-edit?id=${id}`; + }); + }, + async initEditPage() { + const params = new URLSearchParams(window.location.search); + const bookId = params.get("id"); + if (!bookId) return; + + const book = await model.getBook(bookId); + await view.fillFormForEditing(book); + view.bindSaveButton(async (updatedBook) => { + await model.updateBook(updatedBook); + window.location.href = `./profile`; }); }, }; export default controller; +controller.initEditPage(); + controller.init(); diff --git a/html/components/bookComponent/model.js b/html/components/bookComponent/model.js index 105da99..62c1840 100644 --- a/html/components/bookComponent/model.js +++ b/html/components/bookComponent/model.js @@ -1,4 +1,4 @@ -import { createItem, deleteItem, getAllItems, updateItem } from "./api/client"; +import { createItem, deleteItem, getAllItems, getItem, updateItem } from "./api/client"; const BOOKS_URL = "books"; const AUTHORS_URL = "authors"; const GENRES_URL = "genres"; @@ -19,6 +19,10 @@ export default { }); return booksWithDetails; }, + async getBook(id) { + const book = await getItem(BOOKS_URL, id); + return book; + }, async addBook(book) { const res = await createItem(BOOKS_URL, book); return res; @@ -26,8 +30,7 @@ export default { async deleteBook(id) { return await deleteItem(BOOKS_URL, id); }, - async updateBook(id) { - console.log(id); - return updateItem(BOOKS_URL, id); + async updateBook(model) { + return updateItem(BOOKS_URL, model.id, model); }, }; diff --git a/html/components/bookComponent/view.js b/html/components/bookComponent/view.js index a4eecbc..798687c 100644 --- a/html/components/bookComponent/view.js +++ b/html/components/bookComponent/view.js @@ -3,7 +3,7 @@ export default { container.innerHTML = ""; books.forEach((book) => { const div = document.createElement("div"); - div.className = "col border border-dark bg-light border-3 h-100 col-5 col-md-7 col-lg-5 p-1 m-2"; + div.className = "col border border-dark bg-light border-3 h-100 col-5 col-md-6 col-lg-5 p-1 m-2"; div.innerHTML = ` Обложка книги книги

${book.name}

@@ -12,7 +12,7 @@ export default {
- +
`; container.appendChild(div); @@ -40,17 +40,30 @@ export default { }, bindUpdateButton(callback) { document.getElementById("bookListContent").addEventListener("click", (e) => { + e.preventDefault(); if (e.target.classList.contains("update")) { const id = e.target.getAttribute("data-id"); - // Отправляем id книги на callback, который обновит форму callback(id); } }); }, - + bindSaveButton(callback) { + const form = document.getElementById("formRedact"); + form.addEventListener("submit", (e) => { + e.preventDefault(); + const params = new URLSearchParams(window.location.search); + const updatedBook = { + id: params.get("id"), + name: document.getElementById("redactTitle").value, + author_id: document.getElementById("redactAuthorName").value, + genre_id: document.getElementById("redact-genre-select").value, + }; + callback(updatedBook); + }); + }, fillFormForEditing(book) { - document.getElementById("bookTitle").value = book.name; - document.getElementById("authorName").value = book.author_id; - document.getElementById("genre-select").value = book.genreId; + document.getElementById("redactTitle").value = book.name; + document.getElementById("redactAuthorName").value = book.author_id; + document.getElementById("redact-genre-select").value = book.genre_id; }, }; diff --git a/html/database/data.json b/html/database/data.json index c92609b..866dc79 100644 --- a/html/database/data.json +++ b/html/database/data.json @@ -1,64 +1,54 @@ { - "books": [ - { - "id": "1", - "deadline_date": "2027-10-15", - "genre_id": "2", - "name": "Там, где спит рассвет", - "author_id": "2" - }, - { - "id": "2", - "deadline_date": "2027-10-15", - "genre_id": "2", - "name": "Формула одиночества", - "author_id": "2" - }, - { - "id": "3", - "deadline_date": "2026-10-15", - "genre_id": "3", - "author_id": "1", - "name": "Прах будущего" - }, - { - "id": "4", - "deadline_date": "2027-10-15", - "genre_id": "3", - "author_id": "2", - "name": "Город, который придумал себя" - }, - { - "id": "b019", - "name": "Имя книги", - "author_id": "2", - "genre_id": "2" - } - ], - "authors": [ - { - "id": "1", - "name": "Алекс Фличер", - "biography": "Какая-то краткая и неподробная биография" - }, - { - "id": "2", - "name": "Яков Блэк", - "biography": "Другая, отличающаяся биография другого автора" - } - ], - "genres": [ - { - "id": "1", - "name": "Художественная литература" - }, - { - "id": "2", - "name": "Нон-фикшн" - }, - { - "id": "3", - "name": "Научная фантастика" - } - ] -} + "books": [ + { + "id": "b019", + "name": "Имя книги", + "author_id": "2", + "genre_id": "2" + }, + { + "id": "262b", + "name": "Скорее всего верстка поехала", + "author_id": "1", + "genre_id": "3" + }, + { + "id": "4425", + "name": "Нормальное название", + "author_id": "1", + "genre_id": "1" + }, + { + "id": "820b", + "name": "Измененное имя книги", + "author_id": "2", + "genre_id": "2" + } + ], + "authors": [ + { + "id": "1", + "name": "Алекс Фличер", + "biography": "Какая-то краткая и неподробная биография" + }, + { + "id": "2", + "name": "Яков Блэк", + "biography": "Другая, отличающаяся биография другого автора" + } + ], + "genres": [ + { + "id": "1", + "name": "Художественная литература" + }, + { + "id": "2", + "name": "Нон-фикшн" + }, + { + "id": "3", + "name": "Научная фантастика" + } + ] +} \ No newline at end of file diff --git a/html/profile.html b/html/profile.html index e9cf042..df6a940 100644 --- a/html/profile.html +++ b/html/profile.html @@ -102,7 +102,7 @@ > - - `; - + div.innerHTML = ` + + Обложка книги +

${book.name}

+

${book.author}

+

${book.genre}

+
+
+ + +
`; container.appendChild(div); }); }, @@ -40,8 +42,8 @@ export default { }, bindUpdateButton(callback) { document.getElementById("bookListContent").addEventListener("click", (e) => { - e.preventDefault(); if (e.target.classList.contains("update")) { + e.preventDefault(); const id = e.target.getAttribute("data-id"); callback(id); } diff --git a/html/database/data.json b/html/database/data.json index 866dc79..7b1a8ad 100644 --- a/html/database/data.json +++ b/html/database/data.json @@ -1,28 +1,22 @@ { "books": [ { - "id": "b019", - "name": "Имя книги", + "id": "d91f", + "name": "Какое-то название другое", "author_id": "2", "genre_id": "2" }, { - "id": "262b", - "name": "Скорее всего верстка поехала", + "id": "d6d0", + "name": "Другое название ", "author_id": "1", + "genre_id": "2" + }, + { + "id": "3b3c", + "name": "ДримТим", + "author_id": "2", "genre_id": "3" - }, - { - "id": "4425", - "name": "Нормальное название", - "author_id": "1", - "genre_id": "1" - }, - { - "id": "820b", - "name": "Измененное имя книги", - "author_id": "2", - "genre_id": "2" } ], "authors": [ diff --git a/html/mainStyle.css b/html/mainStyle.css index d4cc3ff..dbae907 100644 --- a/html/mainStyle.css +++ b/html/mainStyle.css @@ -20,6 +20,7 @@ footer p { } i { margin: 3px; + pointer-events: none } img { margin: 4px; diff --git a/html/profile.html b/html/profile.html index df6a940..4557eaf 100644 --- a/html/profile.html +++ b/html/profile.html @@ -95,12 +95,12 @@ > Список книг к прочтению -
-
-
+ +
+ + + `; + + container.appendChild(div); + }); + }, + + bindAddForm(callback) { + document.getElementById("formAddBook").addEventListener("submit", (e) => { + e.preventDefault(); + const name = document.getElementById("bookTitle").value; + const author_id = document.getElementById("authorName").value; + const genre_id = document.getElementById("genre-select").value; + callback({ name, author_id, genre_id }); + e.target.reset(); + }); + }, + + bindDeleteButton(callback) { + document.getElementById("bookListContent").addEventListener("click", (e) => { + if (e.target.classList.contains("delete")) { + const id = e.target.getAttribute("data-id"); + callback(id); + } + }); + }, + bindUpdateButton(callback) { + document.getElementById("bookListContent").addEventListener("click", (e) => { + if (e.target.classList.contains("update")) { + const id = e.target.getAttribute("data-id"); + // Отправляем id книги на callback, который обновит форму + callback(id); + } + }); + }, + + fillFormForEditing(book) { + document.getElementById("bookTitle").value = book.name; + document.getElementById("authorName").value = book.author_id; + document.getElementById("genre-select").value = book.genreId; + }, +}; diff --git a/html/database/data.json b/html/database/data.json new file mode 100644 index 0000000..c92609b --- /dev/null +++ b/html/database/data.json @@ -0,0 +1,64 @@ +{ + "books": [ + { + "id": "1", + "deadline_date": "2027-10-15", + "genre_id": "2", + "name": "Там, где спит рассвет", + "author_id": "2" + }, + { + "id": "2", + "deadline_date": "2027-10-15", + "genre_id": "2", + "name": "Формула одиночества", + "author_id": "2" + }, + { + "id": "3", + "deadline_date": "2026-10-15", + "genre_id": "3", + "author_id": "1", + "name": "Прах будущего" + }, + { + "id": "4", + "deadline_date": "2027-10-15", + "genre_id": "3", + "author_id": "2", + "name": "Город, который придумал себя" + }, + { + "id": "b019", + "name": "Имя книги", + "author_id": "2", + "genre_id": "2" + } + ], + "authors": [ + { + "id": "1", + "name": "Алекс Фличер", + "biography": "Какая-то краткая и неподробная биография" + }, + { + "id": "2", + "name": "Яков Блэк", + "biography": "Другая, отличающаяся биография другого автора" + } + ], + "genres": [ + { + "id": "1", + "name": "Художественная литература" + }, + { + "id": "2", + "name": "Нон-фикшн" + }, + { + "id": "3", + "name": "Научная фантастика" + } + ] +} diff --git a/html/mainStyle.css b/html/mainStyle.css index 6f53545..d4cc3ff 100644 --- a/html/mainStyle.css +++ b/html/mainStyle.css @@ -10,10 +10,14 @@ main { /* Общие стили */ p { - color: #37745b; + color: #3e8165; margin: 5px; } +footer p { + color: #1e3a3a; + margin: 5px; +} i { margin: 3px; } diff --git a/html/profile.html b/html/profile.html index 5137c13..e9cf042 100644 --- a/html/profile.html +++ b/html/profile.html @@ -95,12 +95,11 @@ > Список книг к прочтению -
+
-
+ >
- + diff --git a/package-lock.json b/package-lock.json index 723277f..8ab07af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "5.2.3", "http-server": "14.1.1", + "json-server": "1.0.0-beta.3", "npm-run-all": "4.1.5", "vite": "6.2.0", "vite-plugin-static-copy": "latest" @@ -601,6 +602,13 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -885,6 +893,327 @@ "dev": true, "license": "MIT" }, + "node_modules/@tinyhttp/accepts": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/accepts/-/accepts-2.2.3.tgz", + "integrity": "sha512-9pQN6pJAJOU3McmdJWTcyq7LLFW8Lj5q+DadyKcvp+sxMkEpktKX5sbfJgJuOvjk6+1xWl7pe0YL1US1vaO/1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime": "4.0.4", + "negotiator": "^0.6.3" + }, + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/accepts/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/app": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.5.2.tgz", + "integrity": "sha512-DcB3Y8GQppLQlO2VxRYF7LzTEAoZb+VRQXuIsErcu2fNaM1xdx6NQZDso5rlZUiaeg6KYYRfU34N4XkZbv6jSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/proxy-addr": "2.2.1", + "@tinyhttp/req": "2.2.5", + "@tinyhttp/res": "2.2.5", + "@tinyhttp/router": "2.2.3", + "header-range-parser": "1.1.3", + "regexparam": "^2.0.2" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-disposition": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.2.tgz", + "integrity": "sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-type": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-type/-/content-type-0.1.4.tgz", + "integrity": "sha512-dl6f3SHIJPYbhsW1oXdrqOmLSQF/Ctlv3JnNfXAE22kIP7FosqJHxkz/qj2gv465prG8ODKH5KEyhBkvwrueKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4" + } + }, + "node_modules/@tinyhttp/cookie": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie/-/cookie-2.1.1.tgz", + "integrity": "sha512-h/kL9jY0e0Dvad+/QU3efKZww0aTvZJslaHj3JTPmIPC9Oan9+kYqmh3M6L5JUQRuTJYFK2nzgL2iJtH2S+6dA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/cookie-signature": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie-signature/-/cookie-signature-2.1.1.tgz", + "integrity": "sha512-VDsSMY5OJfQJIAtUgeQYhqMPSZptehFSfvEEtxr+4nldPA8IImlp3QVcOVuK985g4AFR4Hl1sCbWCXoqBnVWnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/cors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cors/-/cors-2.0.1.tgz", + "integrity": "sha512-qrmo6WJuaiCzKWagv2yA/kw6hIISfF/hOqPWwmI6w0o8apeTMmRN3DoCFvQ/wNVuWVdU5J4KU7OX8aaSOEq51A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/vary": "^0.1.3" + }, + "engines": { + "node": ">=12.20 || 14.x || >=16" + } + }, + "node_modules/@tinyhttp/encode-url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/encode-url/-/encode-url-2.1.1.tgz", + "integrity": "sha512-AhY+JqdZ56qV77tzrBm0qThXORbsVjs/IOPgGCS7x/wWnsa/Bx30zDUU/jPAUcSzNOzt860x9fhdGpzdqbUeUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/etag": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/etag/-/etag-2.1.2.tgz", + "integrity": "sha512-j80fPKimGqdmMh6962y+BtQsnYPVCzZfJw0HXjyH70VaJBHLKGF+iYhcKqzI3yef6QBNa8DKIPsbEYpuwApXTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/forwarded": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.2.tgz", + "integrity": "sha512-9H/eulJ68ElY/+zYpTpNhZ7vxGV+cnwaR6+oQSm7bVgZMyuQfgROW/qvZuhmgDTIxnGMXst+Ba4ij6w6Krcs3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/logger": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tinyhttp/logger/-/logger-2.1.0.tgz", + "integrity": "sha512-Ma1fJ9CwUbn9r61/4HW6+nflsVoslpOnCrfQ6UeZq7GGIgwLzofms3HoSVG7M+AyRMJpxlfcDdbH5oFVroDMKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.20", + "dayjs": "^1.11.13", + "http-status-emojis": "^2.2.0" + }, + "engines": { + "node": ">=14.18 || >=16.20" + } + }, + "node_modules/@tinyhttp/proxy-addr": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.1.tgz", + "integrity": "sha512-BicqMqVI91hHq2BQmnqJUh0FQUnx7DncwSGgu2ghlh+JZG2rHK2ZN/rXkfhrx1rrUw6hnd0L36O8GPMh01+dDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/forwarded": "2.1.2", + "ipaddr.js": "^2.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/req": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.5.tgz", + "integrity": "sha512-trfsXwtmsNjMcGKcLJ+45h912kLRqBQCQD06ams3Tq0kf4gHLxjHjoYOC1Z9yGjOn81XllRx8wqvnvr+Kbe3gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/accepts": "2.2.3", + "@tinyhttp/type-is": "2.2.4", + "@tinyhttp/url": "2.1.1", + "header-range-parser": "^1.1.3" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/res": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.5.tgz", + "integrity": "sha512-yBsqjWygpuKAVz4moWlP4hqzwiDDqfrn2mA0wviJAcgvGiyOErtlQwXY7aj3aPiCpURvxvEFO//Gdy6yV+xEpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-disposition": "2.2.2", + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/cookie-signature": "2.1.1", + "@tinyhttp/encode-url": "2.1.1", + "@tinyhttp/req": "2.2.5", + "@tinyhttp/send": "2.2.3", + "@tinyhttp/vary": "^0.1.3", + "es-escape-html": "^0.1.1", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/res/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/router": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/router/-/router-2.2.3.tgz", + "integrity": "sha512-O0MQqWV3Vpg/uXsMYg19XsIgOhwjyhTYWh51Qng7bxqXixxx2PEvZWnFjP7c84K7kU/nUX41KpkEBTLnznk9/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/send": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/send/-/send-2.2.3.tgz", + "integrity": "sha512-o4cVHHGQ8WjVBS8UT0EE/2WnjoybrfXikHwsRoNlG1pfrC/Sd01u1N4Te8cOd/9aNGLr4mGxWb5qTm2RRtEi7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "@tinyhttp/etag": "2.1.2", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/send/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/type-is": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/type-is/-/type-is-2.2.4.tgz", + "integrity": "sha512-7F328NheridwjIfefBB2j1PEcKKABpADgv7aCJaE8x8EON77ZFrAkI3Rir7pGjopV7V9MBmW88xUQigBEX2rmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/type-is/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@tinyhttp/url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/url/-/url-2.1.1.tgz", + "integrity": "sha512-POJeq2GQ5jI7Zrdmj22JqOijB5/GeX+LEX7DUdml1hUnGbJOTWDx7zf2b5cCERj7RoXL67zTgyzVblBJC+NJWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/vary": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/vary/-/vary-0.1.3.tgz", + "integrity": "sha512-SoL83sQXAGiHN1jm2VwLUWQSQeDAAl1ywOm6T0b0Cg1CZhVsjoiZadmjhxF6FHCCY7OHHVaLnTgSMxTPIDLxMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1373,6 +1702,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1466,6 +1802,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -1599,6 +1942,35 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "4.39.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", + "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1723,6 +2095,16 @@ "node": ">= 0.4" } }, + "node_modules/es-escape-html": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/es-escape-html/-/es-escape-html-0.1.1.tgz", + "integrity": "sha512-yUx1o+8RsG7UlszmYPtks+dm6Lho2m8lgHMOsLJQsFI0R8XwUJwiMhM1M4E/S8QLeGyf6MkDV/pWgjQ0tdTSyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.x" + } + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -2172,6 +2554,19 @@ "node": ">=0.10.0" } }, + "node_modules/eta": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz", + "integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -2683,6 +3078,16 @@ "he": "bin/he" } }, + "node_modules/header-range-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/header-range-parser/-/header-range-parser-1.1.3.tgz", + "integrity": "sha512-B9zCFt3jH8g09LR1vHL4pcAn8yMEtlSlOUdQemzHMRKMImNIhhszdeosYFfNW0WXKQtXIlWB+O4owHJKvEJYaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -2766,6 +3171,13 @@ "node": ">=12" } }, + "node_modules/http-status-emojis": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http-status-emojis/-/http-status-emojis-2.2.0.tgz", + "integrity": "sha512-ompKtgwpx8ff0hsbpIB7oE4ax1LXoHmftsHHStMELX56ivG3GhofTX8ZHWlUaFKfGjcGjw6G3rPk7dJRXMmbbg==", + "dev": true, + "license": "MIT" + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -2816,6 +3228,16 @@ "node": ">=0.8.19" } }, + "node_modules/inflection": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.2.tgz", + "integrity": "sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2850,6 +3272,16 @@ "node": ">= 0.4" } }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -3306,6 +3738,90 @@ "dev": true, "license": "MIT" }, + "node_modules/json-server": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-1.0.0-beta.3.tgz", + "integrity": "sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==", + "dev": true, + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "@tinyhttp/app": "^2.4.0", + "@tinyhttp/cors": "^2.0.1", + "@tinyhttp/logger": "^2.0.0", + "chalk": "^5.3.0", + "chokidar": "^4.0.1", + "dot-prop": "^9.0.0", + "eta": "^3.5.0", + "inflection": "^3.0.0", + "json5": "^2.2.3", + "lowdb": "^7.0.1", + "milliparsec": "^4.0.0", + "sirv": "^2.0.4", + "sort-on": "^6.1.0" + }, + "bin": { + "json-server": "lib/bin.js" + }, + "engines": { + "node": ">=18.3" + } + }, + "node_modules/json-server/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/json-server/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/json-server/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-server/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -3402,6 +3918,22 @@ "dev": true, "license": "MIT" }, + "node_modules/lowdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz", + "integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==", + "dev": true, + "license": "MIT", + "dependencies": { + "steno": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3445,6 +3977,16 @@ "node": ">=8.6" } }, + "node_modules/milliparsec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/milliparsec/-/milliparsec-4.0.0.tgz", + "integrity": "sha512-/wk9d4Z6/9ZvoEH/6BI4TrTCgmkpZPuSRN/6fI9aUHOfXdNTuj/VhLS7d+NqG26bi6L9YmGXutVYvWC8zQ0qtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -3481,6 +4023,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3514,6 +4066,16 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4277,6 +4839,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexparam": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.2.tgz", + "integrity": "sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -4653,6 +5225,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sort-on": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sort-on/-/sort-on-6.1.0.tgz", + "integrity": "sha512-WTECP0nYNWO1n2g5bpsV0yZN9cBmZsF8ThHFbOqVN0HBFRoaQZLLEMvMmJlKHNPYQeVngeI5+jJzIfFqOIo1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-prop": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4699,6 +5302,19 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/steno": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", + "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/string.prototype.padend": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", @@ -4876,6 +5492,16 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", diff --git a/package.json b/package.json index c295358..8fece20 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,12 @@ "version": "1.0.0", "type": "module", "scripts": { - "start": "vite", + "start": "npm-run-all --parallel backend vite", + "vite": "vite", "build": "vite build", "serve": "http-server -p 3000 ./html/", - "prod": "npm-run-all build serve", + "backend": "json-server ./html/database/data.json -p 5174", + "prod": "npm-run-all build serve --parallel backend serve", "lint": "eslint . --ext js --report-unused-disable-directives --max-warnings 0" }, "dependencies": { @@ -23,6 +25,7 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "5.2.3", "eslint-plugin-html": "8.1.2", - "vite-plugin-static-copy": "latest" + "vite-plugin-static-copy": "latest", + "json-server": "1.0.0-beta.3" } } -- 2.25.1 From 741bba02246c5a2bee33f6c84307298698b2faaf Mon Sep 17 00:00:00 2001 From: zum Date: Sat, 12 Apr 2025 00:19:22 +0400 Subject: [PATCH 6/7] i think good enough --- html/book-edit.html | 121 ++++++++++++++++++++ html/components/bookComponent/controller.js | 20 +++- html/components/bookComponent/model.js | 11 +- html/components/bookComponent/view.js | 27 +++-- html/database/data.json | 116 +++++++++---------- html/profile.html | 2 +- 6 files changed, 217 insertions(+), 80 deletions(-) create mode 100644 html/book-edit.html diff --git a/html/book-edit.html b/html/book-edit.html new file mode 100644 index 0000000..12cb524 --- /dev/null +++ b/html/book-edit.html @@ -0,0 +1,121 @@ + + + + LibraNet + + + + + + + + + + + + +
+
+ + LibraNet Logo + +
+

LibraNet

+

Сборник свободных и бесплатных книг

+
+
+ + +
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+ +
+ + + + diff --git a/html/components/bookComponent/controller.js b/html/components/bookComponent/controller.js index 364797d..5b83710 100644 --- a/html/components/bookComponent/controller.js +++ b/html/components/bookComponent/controller.js @@ -1,6 +1,5 @@ import model from "./model.js"; import view from "./view.js"; - const controller = { async init() { const books = await model.getBooks(); @@ -19,14 +18,25 @@ const controller = { view.renderBooks(books, container); }); view.bindUpdateButton(async (id) => { - console.log(id); - await model.updateBook(id); - const books = await model.getBooks(); - view.renderBooks(books, container); + window.location.href = `./book-edit?id=${id}`; + }); + }, + async initEditPage() { + const params = new URLSearchParams(window.location.search); + const bookId = params.get("id"); + if (!bookId) return; + + const book = await model.getBook(bookId); + await view.fillFormForEditing(book); + view.bindSaveButton(async (updatedBook) => { + await model.updateBook(updatedBook); + window.location.href = `./profile`; }); }, }; export default controller; +controller.initEditPage(); + controller.init(); diff --git a/html/components/bookComponent/model.js b/html/components/bookComponent/model.js index 105da99..62c1840 100644 --- a/html/components/bookComponent/model.js +++ b/html/components/bookComponent/model.js @@ -1,4 +1,4 @@ -import { createItem, deleteItem, getAllItems, updateItem } from "./api/client"; +import { createItem, deleteItem, getAllItems, getItem, updateItem } from "./api/client"; const BOOKS_URL = "books"; const AUTHORS_URL = "authors"; const GENRES_URL = "genres"; @@ -19,6 +19,10 @@ export default { }); return booksWithDetails; }, + async getBook(id) { + const book = await getItem(BOOKS_URL, id); + return book; + }, async addBook(book) { const res = await createItem(BOOKS_URL, book); return res; @@ -26,8 +30,7 @@ export default { async deleteBook(id) { return await deleteItem(BOOKS_URL, id); }, - async updateBook(id) { - console.log(id); - return updateItem(BOOKS_URL, id); + async updateBook(model) { + return updateItem(BOOKS_URL, model.id, model); }, }; diff --git a/html/components/bookComponent/view.js b/html/components/bookComponent/view.js index a4eecbc..798687c 100644 --- a/html/components/bookComponent/view.js +++ b/html/components/bookComponent/view.js @@ -3,7 +3,7 @@ export default { container.innerHTML = ""; books.forEach((book) => { const div = document.createElement("div"); - div.className = "col border border-dark bg-light border-3 h-100 col-5 col-md-7 col-lg-5 p-1 m-2"; + div.className = "col border border-dark bg-light border-3 h-100 col-5 col-md-6 col-lg-5 p-1 m-2"; div.innerHTML = ` Обложка книги книги

${book.name}

@@ -12,7 +12,7 @@ export default {
- +
`; container.appendChild(div); @@ -40,17 +40,30 @@ export default { }, bindUpdateButton(callback) { document.getElementById("bookListContent").addEventListener("click", (e) => { + e.preventDefault(); if (e.target.classList.contains("update")) { const id = e.target.getAttribute("data-id"); - // Отправляем id книги на callback, который обновит форму callback(id); } }); }, - + bindSaveButton(callback) { + const form = document.getElementById("formRedact"); + form.addEventListener("submit", (e) => { + e.preventDefault(); + const params = new URLSearchParams(window.location.search); + const updatedBook = { + id: params.get("id"), + name: document.getElementById("redactTitle").value, + author_id: document.getElementById("redactAuthorName").value, + genre_id: document.getElementById("redact-genre-select").value, + }; + callback(updatedBook); + }); + }, fillFormForEditing(book) { - document.getElementById("bookTitle").value = book.name; - document.getElementById("authorName").value = book.author_id; - document.getElementById("genre-select").value = book.genreId; + document.getElementById("redactTitle").value = book.name; + document.getElementById("redactAuthorName").value = book.author_id; + document.getElementById("redact-genre-select").value = book.genre_id; }, }; diff --git a/html/database/data.json b/html/database/data.json index c92609b..866dc79 100644 --- a/html/database/data.json +++ b/html/database/data.json @@ -1,64 +1,54 @@ { - "books": [ - { - "id": "1", - "deadline_date": "2027-10-15", - "genre_id": "2", - "name": "Там, где спит рассвет", - "author_id": "2" - }, - { - "id": "2", - "deadline_date": "2027-10-15", - "genre_id": "2", - "name": "Формула одиночества", - "author_id": "2" - }, - { - "id": "3", - "deadline_date": "2026-10-15", - "genre_id": "3", - "author_id": "1", - "name": "Прах будущего" - }, - { - "id": "4", - "deadline_date": "2027-10-15", - "genre_id": "3", - "author_id": "2", - "name": "Город, который придумал себя" - }, - { - "id": "b019", - "name": "Имя книги", - "author_id": "2", - "genre_id": "2" - } - ], - "authors": [ - { - "id": "1", - "name": "Алекс Фличер", - "biography": "Какая-то краткая и неподробная биография" - }, - { - "id": "2", - "name": "Яков Блэк", - "biography": "Другая, отличающаяся биография другого автора" - } - ], - "genres": [ - { - "id": "1", - "name": "Художественная литература" - }, - { - "id": "2", - "name": "Нон-фикшн" - }, - { - "id": "3", - "name": "Научная фантастика" - } - ] -} + "books": [ + { + "id": "b019", + "name": "Имя книги", + "author_id": "2", + "genre_id": "2" + }, + { + "id": "262b", + "name": "Скорее всего верстка поехала", + "author_id": "1", + "genre_id": "3" + }, + { + "id": "4425", + "name": "Нормальное название", + "author_id": "1", + "genre_id": "1" + }, + { + "id": "820b", + "name": "Измененное имя книги", + "author_id": "2", + "genre_id": "2" + } + ], + "authors": [ + { + "id": "1", + "name": "Алекс Фличер", + "biography": "Какая-то краткая и неподробная биография" + }, + { + "id": "2", + "name": "Яков Блэк", + "biography": "Другая, отличающаяся биография другого автора" + } + ], + "genres": [ + { + "id": "1", + "name": "Художественная литература" + }, + { + "id": "2", + "name": "Нон-фикшн" + }, + { + "id": "3", + "name": "Научная фантастика" + } + ] +} \ No newline at end of file diff --git a/html/profile.html b/html/profile.html index e9cf042..df6a940 100644 --- a/html/profile.html +++ b/html/profile.html @@ -102,7 +102,7 @@ >