лаба3
This commit is contained in:
parent
900f12a227
commit
84dcce8921
@ -32,44 +32,145 @@
|
||||
</a>
|
||||
</nav>
|
||||
</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>
|
||||
<p class="title">КАТАЛОГ</p>
|
||||
<div class="text-center">
|
||||
<p class="text-catalog">Столы</p>
|
||||
<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 class="container-catalog">
|
||||
<div id="my-id-for-text" class="container table"></div>
|
||||
</div>
|
||||
</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>
|
||||
</html>
|
||||
|
@ -267,10 +267,6 @@ orders .container-products {
|
||||
right: 0;
|
||||
margin-bottom: 3%;
|
||||
}
|
||||
.container-products img {
|
||||
width: 30%;
|
||||
padding: 2%;
|
||||
}
|
||||
cart .card,
|
||||
orders .card {
|
||||
background-color: rgba(191, 180, 161, 1);
|
||||
@ -426,3 +422,15 @@ add .container {
|
||||
#image-preview {
|
||||
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
@ -50,7 +50,6 @@ export function showUpdateModal(item) {
|
||||
} else {
|
||||
resetValues();
|
||||
}
|
||||
|
||||
myModal.show();
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,8 @@ export async function updateLine(
|
||||
if (!response.ok) {
|
||||
throw response.statusText;
|
||||
}
|
||||
return response.json();
|
||||
await response.json();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
// обращение к серверу для удаления записи по id (delete)
|
||||
@ -124,5 +125,6 @@ export async function deleteLine(id) {
|
||||
if (!response.ok) {
|
||||
throw response.statusText;
|
||||
}
|
||||
return response.json();
|
||||
await response.json();
|
||||
location.reload();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
// при обращении к атрибуту объекта вызывается
|
||||
// нужная функция для поиска элемента
|
||||
export const cntrls = {
|
||||
container: document.getElementById("my-id-for-text"),
|
||||
button: document.getElementById("items-add"),
|
||||
table: document.querySelector("#items-table tbody"),
|
||||
form: document.getElementById("items-form"),
|
||||
@ -98,9 +99,78 @@ export function createTableRow(
|
||||
row.appendChild(createTableColumn(parseFloat(item.sum).toFixed(2)));
|
||||
// редактировать в модальном окне
|
||||
row.appendChild(createTableAnchor("fa-pencil", editCallback));
|
||||
// редактировать на странице page-edit
|
||||
row.appendChild(createTableAnchor("fa-pen-to-square", editPageCallback));
|
||||
// удаление
|
||||
row.appendChild(createTableAnchor("fa-trash", deleteCallback));
|
||||
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;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
cntrls,
|
||||
createItemsOption,
|
||||
createTableRow,
|
||||
createTableRowOnIndex,
|
||||
imagePlaceholder,
|
||||
} from "./lines-ui";
|
||||
|
||||
@ -22,17 +23,18 @@ async function drawItemsSelect() {
|
||||
// очистка содержимого select
|
||||
// удаляется все, что находится между тегами <select></select>
|
||||
// но не атрибуты
|
||||
cntrls.itemsType.innerHTML = "";
|
||||
// пустое значение
|
||||
cntrls.itemsType.appendChild(
|
||||
createItemsOption("Выберите значение", "", true)
|
||||
);
|
||||
// цикл по результату ответа от сервера
|
||||
// используется лямбда-выражение
|
||||
// (item) => {} аналогично function(item) {}
|
||||
data.forEach((item) => {
|
||||
cntrls.itemsType.appendChild(createItemsOption(item.name, item.id));
|
||||
});
|
||||
if (cntrls.itemsType) {
|
||||
cntrls.itemsType.innerHTML = "";
|
||||
cntrls.itemsType.appendChild(
|
||||
createItemsOption("Выберите значение", "", true)
|
||||
);
|
||||
// цикл по результату ответа от сервера
|
||||
// используется лямбда-выражение
|
||||
// (item) => {} аналогично function(item) {}
|
||||
data.forEach((item) => {
|
||||
cntrls.itemsType.appendChild(createItemsOption(item.name, item.id));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
console.info("Try to add item");
|
||||
// вызов метода REST API для добавления записи
|
||||
@ -231,7 +261,76 @@ export function linesForm() {
|
||||
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
|
||||
// Если хотите делать через модальное окно, то удалите эту функцию
|
||||
export async function linesPageForm() {
|
||||
|
@ -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>
|
@ -37,9 +37,7 @@
|
||||
<button id="items-add" type="submit" class="btn btn-success">
|
||||
Добавить товар (диалог)
|
||||
</button>
|
||||
<a class="btn btn-secondary" href="/page-edit.html"
|
||||
>Добавить товар (страница)</a
|
||||
>
|
||||
|
||||
<div>
|
||||
<table id="items-table" class="table table-light table-striped">
|
||||
<thead>
|
||||
@ -53,7 +51,6 @@
|
||||
<th scope="col"></th>
|
||||
<th scope="col"></th>
|
||||
<th scope="col"></th>
|
||||
<th scope="col"></th>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
@ -66,10 +63,10 @@
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
<form id="items-form" class="needs-validation" novalidate>
|
||||
<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>
|
||||
<button
|
||||
type="button"
|
||||
@ -115,9 +112,9 @@
|
||||
name="price"
|
||||
class="form-control"
|
||||
type="number"
|
||||
value="0.00"
|
||||
min="1000.00"
|
||||
step="0.50"
|
||||
value="0"
|
||||
min="1000"
|
||||
step="100"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
@ -139,7 +136,7 @@
|
||||
id="color"
|
||||
name="color"
|
||||
class="form-control"
|
||||
type="text"
|
||||
type="color"
|
||||
maxlength="100"
|
||||
required
|
||||
/>
|
||||
@ -167,7 +164,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer fixed-footer">
|
||||
<button
|
||||
type="submit-grey"
|
||||
class="btn btn-secondary"
|
||||
|
Loading…
Reference in New Issue
Block a user