лаба3

This commit is contained in:
a.puchkina 2023-12-08 15:57:31 +04:00
parent 900f12a227
commit 84dcce8921
9 changed files with 366 additions and 217 deletions

View File

@ -32,44 +32,145 @@
</a> </a>
</nav> </nav>
</header> </header>
<script type="module">
import validation from "./js/validation";
import { linesFormOnIndex } from "./js/lines";
import { linesForm } from "./js/lines";
document.addEventListener("DOMContentLoaded", () => {
validation();
linesFormOnIndex();
linesForm();
});
</script>
<catalog> <catalog>
<p class="title">КАТАЛОГ</p> <p class="title">КАТАЛОГ</p>
<div class="text-center"> <div class="container-catalog">
<p class="text-catalog">Столы</p> <div id="my-id-for-text" class="container table"></div>
<a href="products/productTable1.html"
><img src="images/table1.png" class="rounded" alt="..."
/></a>
<a href="products/productTable2.html"
><img src="images/table2.png" class="rounded" alt="..." />
</a>
<a href="products/productTable3.html"
><img src="images/table3.png" class="rounded" alt="..."
/></a>
</div>
<div class="text-center">
<p class="text-catalog">Стулья</p>
<a href="products/productChair1.html"
><img src="images/chair1.png" class="rounded" alt="..."
/></a>
<a href="products/productChair2.html"
><img src="images/chair2.png" class="rounded" alt="..." />
</a>
<a href="products/productChair3.html"
><img src="images/chair3.png" class="rounded" alt="..."
/></a>
</div>
<div class="text-center">
<p class="text-catalog">Диваны</p>
<a href="products/productSofa1.html"
><img src="images/sofa1.png" class="rounded" alt="..."
/></a>
<a href="products/productSofa2.html"
><img src="images/sofa2.png" class="rounded" alt="..." />
</a>
<a href="products/productSofa3.html"
><img src="images/sofa3.png" class="rounded" alt="..."
/></a>
</div> </div>
</catalog> </catalog>
<div
id="items-update"
class="modal fade"
tabindex="-1"
data-bs-backdrop="static"
data-bs-keyboard="false"
>
<div class="modal-dialog modal-dialog-scrollable">
<form id="items-form" class="needs-validation" novalidate>
<div class="modal-content">
<div class="modal-header fixed-header">
<h1 class="modal-title fs-5" id="items-update-title"></h1>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<div class="text-center">
<img
id="image-preview"
src="https://via.placeholder.com/200"
class="rounded rounded-circle"
alt="placeholder"
/>
</div>
<input id="items-line-id" type="number" hidden />
<div class="mb-2">
<label for="item" class="form-label">Категория</label>
<select
id="item"
class="form-select"
name="selected"
required
></select>
</div>
<div class="mb-2">
<label class="form-label" for="description">Название</label>
<input
id="name"
name="name"
class="form-control"
type="text"
maxlength="100"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="price">Цена</label>
<input
id="price"
name="price"
class="form-control"
type="number"
value="0"
min="1000"
step="100"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="count">Количество</label>
<input
id="count"
name="count"
class="form-control"
type="number"
value="0"
min="1"
step="1"
required
/>
<div class="mb-2">
<label class="form-label" for="color">Цвет</label>
<input
id="color"
name="color"
class="form-control"
type="color"
maxlength="100"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="size">Размеры</label>
<input
id="size"
name="size"
class="form-control"
type="text"
maxlength="100"
required
/>
</div>
</div>
<div class="mb-2">
<label class="form-label" for="image">Изображение</label>
<input
id="image"
type="file"
name="image"
class="form-control"
accept="image/*"
/>
</div>
</div>
<div class="modal-footer fixed-footer">
<button
type="submit-grey"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Закрыть
</button>
<button type="submit" class="btn btn-success">Сохранить</button>
</div>
</div>
</form>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -267,10 +267,6 @@ orders .container-products {
right: 0; right: 0;
margin-bottom: 3%; margin-bottom: 3%;
} }
.container-products img {
width: 30%;
padding: 2%;
}
cart .card, cart .card,
orders .card { orders .card {
background-color: rgba(191, 180, 161, 1); background-color: rgba(191, 180, 161, 1);
@ -426,3 +422,15 @@ add .container {
#image-preview { #image-preview {
width: 200px; width: 200px;
} }
.container-catalog {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
flex-direction: column;
}
.container-catalog {
margin-left: 15%;
margin-right: 15%;
}

File diff suppressed because one or more lines are too long

View File

@ -50,7 +50,6 @@ export function showUpdateModal(item) {
} else { } else {
resetValues(); resetValues();
} }
myModal.show(); myModal.show();
} }

View File

@ -110,7 +110,8 @@ export async function updateLine(
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
} }
return response.json(); await response.json();
location.reload();
} }
// обращение к серверу для удаления записи по id (delete) // обращение к серверу для удаления записи по id (delete)
@ -124,5 +125,6 @@ export async function deleteLine(id) {
if (!response.ok) { if (!response.ok) {
throw response.statusText; throw response.statusText;
} }
return response.json(); await response.json();
location.reload();
} }

View File

@ -4,6 +4,7 @@
// при обращении к атрибуту объекта вызывается // при обращении к атрибуту объекта вызывается
// нужная функция для поиска элемента // нужная функция для поиска элемента
export const cntrls = { export const cntrls = {
container: document.getElementById("my-id-for-text"),
button: document.getElementById("items-add"), button: document.getElementById("items-add"),
table: document.querySelector("#items-table tbody"), table: document.querySelector("#items-table tbody"),
form: document.getElementById("items-form"), form: document.getElementById("items-form"),
@ -98,9 +99,78 @@ export function createTableRow(
row.appendChild(createTableColumn(parseFloat(item.sum).toFixed(2))); row.appendChild(createTableColumn(parseFloat(item.sum).toFixed(2)));
// редактировать в модальном окне // редактировать в модальном окне
row.appendChild(createTableAnchor("fa-pencil", editCallback)); row.appendChild(createTableAnchor("fa-pencil", editCallback));
// редактировать на странице page-edit
row.appendChild(createTableAnchor("fa-pen-to-square", editPageCallback));
// удаление // удаление
row.appendChild(createTableAnchor("fa-trash", deleteCallback)); row.appendChild(createTableAnchor("fa-trash", deleteCallback));
return row; return row;
} }
export function createTableRowOnIndex(
item,
index,
editCallback,
editPageCallback,
deleteCallback
) {
console.log(item);
const img = document.createElement("img");
img.classList.add("objects");
img.src = item.image;
img.alt = "object";
img.style.height = "300px";
img.style.display = "block";
img.style.marginLeft = "auto";
img.style.marginRight = "auto";
const name = document.createElement("div");
name.classList.add("caption");
name.innerText = item.name;
name.style.padding = "0px";
name.style.fontSize = "22px";
name.style.color = "#533908";
name.style.fontFamily = "Montserrat Alternates";
name.style.fontWeight = 500;
const price = document.createElement("div");
price.classList.add("caption_2");
price.innerText = parseInt(item.price) + "₽";
price.style.padding = "0";
price.style.marginBottom = "40px";
price.style.fontSize = "28px";
price.style.color = "#533908";
price.style.fontFamily = "Montserrat Alternates";
price.style.fontWeight = 400;
const a = document.createElement("a");
a.href = "products/productTable1.html";
a.style.textDecoration = "none";
a.appendChild(img);
a.appendChild(name);
a.appendChild(price);
const buttonsContainer = document.createElement("div");
buttonsContainer.style.display = "flex";
buttonsContainer.style.justifyContent = "center";
const editButton = createTableAnchor("fa-pencil", editCallback);
const deleteButton = createTableAnchor("fa-trash", deleteCallback);
deleteButton.style.marginLeft = "1.2vw";
buttonsContainer.appendChild(editButton);
buttonsContainer.appendChild(deleteButton);
buttonsContainer.style.marginTop = "-40px";
buttonsContainer.style.marginBottom = "40px";
a.appendChild(buttonsContainer);
const div = document.createElement("div");
div.classList.add("col");
div.classList.add("clear-float");
div.appendChild(a);
const uniqueId = `div-${index + 1}`;
div.id = uniqueId;
div.style.float = "left";
div.style.boxSizing = "border-box";
return div;
}

View File

@ -13,6 +13,7 @@ import {
cntrls, cntrls,
createItemsOption, createItemsOption,
createTableRow, createTableRow,
createTableRowOnIndex,
imagePlaceholder, imagePlaceholder,
} from "./lines-ui"; } from "./lines-ui";
@ -22,17 +23,18 @@ async function drawItemsSelect() {
// очистка содержимого select // очистка содержимого select
// удаляется все, что находится между тегами <select></select> // удаляется все, что находится между тегами <select></select>
// но не атрибуты // но не атрибуты
cntrls.itemsType.innerHTML = ""; if (cntrls.itemsType) {
// пустое значение cntrls.itemsType.innerHTML = "";
cntrls.itemsType.appendChild( cntrls.itemsType.appendChild(
createItemsOption("Выберите значение", "", true) createItemsOption("Выберите значение", "", true)
); );
// цикл по результату ответа от сервера // цикл по результату ответа от сервера
// используется лямбда-выражение // используется лямбда-выражение
// (item) => {} аналогично function(item) {} // (item) => {} аналогично function(item) {}
data.forEach((item) => { data.forEach((item) => {
cntrls.itemsType.appendChild(createItemsOption(item.name, item.id)); cntrls.itemsType.appendChild(createItemsOption(item.name, item.id));
}); });
}
} }
async function drawLinesTable() { async function drawLinesTable() {
@ -64,7 +66,35 @@ async function drawLinesTable() {
); );
}); });
} }
async function drawLinesTableOnIndex() {
console.info("Try to load data On Index");
if (!cntrls.container) {
return;
}
// вызов метода REST API для получения всех записей
const data = await getAllLines();
// очистка содержимого table
// удаляется все, что находится между тегами <table></table>
// но не атрибуты
cntrls.container.innerHTML = "";
// цикл по результату ответа от сервера
// используется лямбда-выражение
// (item, index) => {} аналогично function(item, index) {}
data.forEach((item, index) => {
cntrls.container.appendChild(
createTableRowOnIndex(
item,
index,
// функции передаются в качестве параметра
// это очень удобно, так как аргументы функций доступны только
// в данном месте кода и не передаются в сервисные модули
() => showUpdateModal(item),
() => location.assign(`catalog.html?id=${item.id}`),
() => removeLine(item.id)
)
);
});
}
async function addLine(item, name, price, count, color, size, image) { async function addLine(item, name, price, count, color, size, image) {
console.info("Try to add item"); console.info("Try to add item");
// вызов метода REST API для добавления записи // вызов метода REST API для добавления записи
@ -231,7 +261,76 @@ export function linesForm() {
hideUpdateModal(); hideUpdateModal();
}); });
} }
export async function linesFormOnIndex() {
console.info("linesFormOnIndex");
await drawItemsSelect();
await drawLinesTableOnIndex();
// обработчик события отправки формы
// возникает при нажатии на кнопку (button) с типом submit
// кнопка должна находится внутри тега form
cntrls.form.addEventListener("submit", async (event) => {
console.info("Form onSubmit");
// отключение стандартного поведения формы при отправке
// при отправке страница обновляется и JS перестает работать
event.preventDefault();
event.stopPropagation();
// если форма не прошла валидацию, то ничего делать не нужно
if (!cntrls.form.checkValidity()) {
return;
}
let imageBase64 = "";
// Получение выбранного пользователем изображения в виде base64 строки
// Если пользователь ничего не выбрал, то не нужно сохранять в БД
// дефолтное изображение
if (cntrls.imagePreview.src !== imagePlaceholder) {
// Загрузка содержимого атрибута src тэга img с id image-preview
// Здесь выполняется HTTP запрос с типом GET
const result = await fetch(cntrls.imagePreview.src);
// Получение из HTTP-ответа бинарного содержимого
const blob = await result.blob();
// Получение base64 строки для файла
// Здесь выполняется Promise из функции readFile
// Promise позволяет писать линейный код для работы с асинхронными методами
// без использования обработчиков (callback) с помощью await
imageBase64 = await readFile(blob);
}
// получение id строки для редактирования
// это значение содержится в скрытом input
const currentId = cntrls.lineId.value;
// если значение id не задано,
// то необходимо выполнить добавление записи
// иначе обновление записи
if (!currentId) {
await addLine(
cntrls.itemsType.value,
cntrls.name.value,
cntrls.price.value,
cntrls.count.value,
cntrls.color.value,
cntrls.size.value,
imageBase64
);
} else {
await editLine(
currentId,
cntrls.itemsType.value,
cntrls.name.value,
cntrls.price.value,
cntrls.count.value,
cntrls.color.value,
cntrls.size.value,
imageBase64
);
}
// после выполнения добавления/обновления модальное окно скрывается
hideUpdateModal();
});
}
// Функция для обработки создания и редактирования элементов таблицы через страницу page-edit.html // Функция для обработки создания и редактирования элементов таблицы через страницу page-edit.html
// Если хотите делать через модальное окно, то удалите эту функцию // Если хотите делать через модальное окно, то удалите эту функцию
export async function linesPageForm() { export async function linesPageForm() {

View File

@ -1,138 +0,0 @@
<html lang="ru">
<head>
<meta charset="utf-8" />
<title>Добавить товар</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script
type="module"
src="./node_modules/bootstrap/dist/js/bootstrap.min.js"
></script>
<link
href="./node_modules/bootstrap/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link
href="./node_modules/@fortawesome/fontawesome-free/css/all.min.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="./css/style.css" />
</head>
<body class="h-100 d-flex flex-column">
<header>
<a class="navbar-brand p-0" href="catalog.html">
<img src="images/iconCatalog.png" alt="Каталог" width="45" />
</a>
<a class="nav-link active" aria-current="page" href="index.html">ANNA</a>
<nav>
<a class="navbar-brand p-0" href="cart.html">
<img src="images/iconsCor.png" alt="Корзина" width="37" />
</a>
<a class="navbar-brand p-0" href="account.html">
<img src="images/iconsAcc.png" alt="Аккаунт" width="38" />
</a>
</nav>
</header>
<main class="container-fluid p-2">
<div class="text-center">
<img
id="image-preview"
src="https://via.placeholder.com/200"
class="rounded rounded-circle"
alt="placeholder"
/>
</div>
<form id="items-form" class="needs-validation" novalidate>
<div class="mb-2">
<label for="item" class="form-label">Категория</label>
<select
id="item"
class="form-select"
name="selected"
required
></select>
</div>
<div class="mb-2">
<label class="form-label" for="description">Название</label>
<input
id="name"
name="name"
class="form-control"
type="text"
maxlength="100"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="price">Цена</label>
<input
id="price"
name="price"
class="form-control"
type="number"
value="0.00"
min="1000.00"
step="0.50"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="count">Количество</label>
<input
id="count"
name="count"
class="form-control"
type="number"
value="0"
min="1"
step="1"
required
/>
<div class="mb-2">
<label class="form-label" for="color">Цвет</label>
<input
id="color"
name="color"
class="form-control"
type="text"
maxlength="100"
required
/>
</div>
<div class="mb-2">
<label class="form-label" for="size">Размеры</label>
<input
id="size"
name="size"
class="form-control"
type="text"
maxlength="100"
required
/>
</div>
</div>
<div class="mb-2">
<label class="form-label" for="image">Изображение</label>
<input
id="image"
type="file"
name="image"
class="form-control"
accept="image/*"
/>
</div>
<a href="/page4.html" class="btn btn-secondary">Назад</a>
<button type="submit" class="btn btn-primary">Сохранить</button>
</form>
</main>
<script type="module">
import validation from "./js/validation";
import { linesPageForm } from "./js/lines";
document.addEventListener("DOMContentLoaded", () => {
validation();
linesPageForm();
});
</script>
</body>
</html>

View File

@ -37,9 +37,7 @@
<button id="items-add" type="submit" class="btn btn-success"> <button id="items-add" type="submit" class="btn btn-success">
Добавить товар (диалог) Добавить товар (диалог)
</button> </button>
<a class="btn btn-secondary" href="/page-edit.html"
>Добавить товар (страница)</a
>
<div> <div>
<table id="items-table" class="table table-light table-striped"> <table id="items-table" class="table table-light table-striped">
<thead> <thead>
@ -53,7 +51,6 @@
<th scope="col"></th> <th scope="col"></th>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"></th>
</thead> </thead>
<tbody></tbody> <tbody></tbody>
</table> </table>
@ -66,10 +63,10 @@
data-bs-backdrop="static" data-bs-backdrop="static"
data-bs-keyboard="false" data-bs-keyboard="false"
> >
<div class="modal-dialog"> <div class="modal-dialog modal-dialog-scrollable">
<form id="items-form" class="needs-validation" novalidate> <form id="items-form" class="needs-validation" novalidate>
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header fixed-header">
<h1 class="modal-title fs-5" id="items-update-title"></h1> <h1 class="modal-title fs-5" id="items-update-title"></h1>
<button <button
type="button" type="button"
@ -115,9 +112,9 @@
name="price" name="price"
class="form-control" class="form-control"
type="number" type="number"
value="0.00" value="0"
min="1000.00" min="1000"
step="0.50" step="100"
required required
/> />
</div> </div>
@ -139,7 +136,7 @@
id="color" id="color"
name="color" name="color"
class="form-control" class="form-control"
type="text" type="color"
maxlength="100" maxlength="100"
required required
/> />
@ -167,7 +164,7 @@
/> />
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer fixed-footer">
<button <button
type="submit-grey" type="submit-grey"
class="btn btn-secondary" class="btn btn-secondary"