Готовая Лабораторная работа 3 с отчётом

This commit is contained in:
Никита Белянин 2023-11-13 17:20:17 +04:00
parent 02f65d8865
commit 7caf2181ea
42 changed files with 10578 additions and 0 deletions

20
Lab3/Lab3/.eslintrc.json Normal file
View File

@ -0,0 +1,20 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": "airbnb-base",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"quotes": "off",
"indent": "off",
"no-console": "off",
"no-use-before-define": "off",
"no-alert": "off",
"no-restricted-globals": "off",
"quote-props": "off"
}
}

45
Lab3/Lab3/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
# Ignore dist
dist/

101
Lab3/Lab3/Admin.html Normal file
View File

@ -0,0 +1,101 @@
<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>
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<a class="Name" href="./index.html">UlRent</a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" href="./index.html">Главная</a>
<a class="nav-link" href="./page-help.html">Помощь</a>
</div>
</div>
</div>
</nav>
</header>
<main class="container-fluid wrapper">
<article>
<form id="items-form" class="needs-validation" novalidate>
<table class="w-100 mx-auto">
<thead>
<th scope="col">
<div class="col-md-4 mx-auto">
<img id="image-preview" src="images/assets/Image8.png" class="rounded rounded-circle"
alt="placeholder" accept="image/*" >
</div>
<div class="form-item pt-4">
<label class="form-label" for="image">Изображение</label>
<input id="image" type="file" name="image" class="form-control" accept="image/*">
</div>
<div class="form-item">
<label for="firstname"> Название объявления </label>
<input id="firstname" name="firstname" class="form-control" type="text" required="">
</div>
</th>
<th scope="col">
<div class="form-item">
<label> Описание </label>
<div class="ms-3" style="margin-right: 30px;">
<textarea class="form-control" name="overview" type="text" id="overview" rows="3" style="width: 100%; height: 300px;"></textarea>
</div>
</div>
<div class="form-item">
<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="p-4" style="margin-bottom: 50px;">
<button type="submit" class="btn btn-primary btnsend" style="margin-left: 40px;">Добавить объявление</button>
</div>
</th>
</thead>
<tbody></tbody>
</table>
</form>
</article>
</main>
<footer class="footer mx-auto">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</footer>
<script type="module">
import validation from "./js/validation";
import { linesPageForm } from "./js/lines"
document.addEventListener('DOMContentLoaded', () => {
validation();
linesPageForm();
});
</script>
</body>
</html>

86
Lab3/Lab3/LogIn.html Normal file
View File

@ -0,0 +1,86 @@
<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>
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<a class="Name" href="./index.html">UlRent</a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" href="./index.html">Главная</a>
<a class="nav-link" href="./page-help.html">Помощь</a>
</div>
</div>
</div>
</nav>
</header>
<main class="container-fluid wrapper mx-auto">
<div class="" style="text-align: center; color: white; font-size: 42px;">
<p>Войти в профиль</p>
</div>
<div class="row justify-content-center">
<form class="col-md-6 m-0">
<form id="items-form1" class="needs-validation" novalidate>
<div class="mb-2 ps-4 pe-4">
<label class="form-label" for="email">Ваш логин</label>
<input data-required="true" id="login" name="login" class="form-control" type="login" placeholder="Логин" required>
<div id="emailErrors"> </div>
</div>
<div class="mb-2 ps-4 pe-4">
<label class="form-label" for="pass">Пароль</label>
<input data-required="true" id="password" data-max-length="18" data-min-length="2" name="password" class="form-control" type="password" placeholder="от 6 до 16 символов" required>
</div>
<div class="d-grid gap-2 col-8 pt-5 mx-auto w-100" style="padding-top: 35px;">
<button type="submit" class="btn btn-light mx-auto" style="width: 10rem; color: red;" >
<a class="flex w-100" href="bulletinBoard.html" style="color:red">Войти</a>
</button>
</div>
</form>
</form>
</div>
<div class="row justify-content-center pt-5 w-25 mx-auto">
<img src="./images/assets/Image12.png" alt="im1" class="imgg1">
</div>
</main>
<footer class="footer mx-auto">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</footer>
<script type="module">
import { validationlog } from "./js/lines";
document.addEventListener('DOMContentLoaded', () => {
validationlog();
});
</script>
</body>
</html>

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Главная</title>
<script type="module" src="./node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link href="./node_modules/@fortawesome/fontawesome-free/css/all.min.css" rel="stylesheet" />
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<nav class="navbar navbar-explad-lg" style="background-color: #85DADA;">
<div class="d-flex flex-column mb-3">
<div class="p-2"><a href="index.html"><img src="./images/assets/Image1.png" width="100px" height="80px" alt="logo"></a></div>
</div>
<div class="d-flex justify-content-around">
<div class="p-2"><a id="sslk" href="index.html" style="font-size: 32px; color: white;">UlRent</a></div>
<div class="p-2"><a id="sslk" href="MyBulletinBoard.html" style="font-size: 28px; color: white; padding: 25px;">Мои объявления</a></div>
</div>
<div class="d-flex justify-content-end pe-5">
<button type="button" class="btn btn-primary"> Выход </button>
</div>
</nav>
</header>
<article style="background-color: #85DADA; padding-top: 50px;">
<div class="" style="text-align: center; color: white; font-size: 42px;">
<p>Мои объявления</p>
</div>
<div class="container mb-5">
<div class="row">
<div class="col pb-4 ms-2 me-2">
<div class="card mx-auto" style="width: 18rem;">
<a href="page7.html"><img src="./images/assets/Image9.jpg" class="card-img-top" width="450px" height="200px" alt="dom"></a>
<div class="card-body">
<h5 class="card-title"> <a href="page7.html" style="color: black; text-decoration: none;"> Студия </a></h5>
<p class="card-text">Центр города ул. Зелёная, д43, кв.77 Красивый вид на площадь города, рядом расположены ТЦ и парк атракционов</p>
<a href="page7.html" class="btn btn-primary">4 249₽</a>
</div>
</div>
</div>
<div class="col pb-4 ms-2 me-2">
<div class="card mx-auto" style="width: 18rem;">
<a href="#"><img src="./images/assets/Image10.jpg" class="card-img-top" width="450px" height="200px" alt="dom"></a>
<div class="card-body">
<h5 class="card-title">Апартаменты</h5>
<p class="card-text">Север города ул. Победы, д. 87 кв.182 Удобная развязка, рядом находится деловой центр и аквапарк
</p>
<a href="#" class="btn btn-primary">2 799 ₽</a>
</div>
</div>
</div>
<div class="col pb-4 ms-2 me-2">
<div class="card mx-auto" style="width: 18rem;">
<a href="#"><img src="./images/assets/Image13.jpg" class="card-img-top" width="450px" height="200px" alt="dom"></a>
<div class="card-body">
<h5 class="card-title">Таунхауз</h5>
<p class="card-text">Южная часть города ул. Южная д.87 Возможно проживание двумя семьями, на территории располагается парковка</p>
<a href="#" class="btn btn-primary">3 069₽</a>
</div>
</div>
</div>
<div class="col pb-4 ms-2 me-2">
<div class="card mx-auto" style="width: 18rem;">
<a href="#"><img src="./images/assets/Image8.png" class="card-img-top" width="450px" height="200px" alt="dom"></a>
<div class="card-body">
<h5 class="card-title">Пентхауз</h5>
<p class="card-text">Центр города ул. Ёжиков д.23, кв.100 Современная, удобная квартира на крыше дома, с двумя этажами</p>
<a href="#" class="btn btn-primary">5 199 ₽</a>
</div>
</div>
</div>
</div>
</div>
<div class="d-grid gap-2 col-4 mx-auto">
<button type="button" class="btn btn-light w-100" style="width: 30rem; color: red;" >
<a class="" href="page4.html" style="color:red">Добавить объявление</a>
</button>
</div>
</article>
<div class="push"> </div>
<footer class="footer mt-auto">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
</body>
</html>

101
Lab3/Lab3/SignIn.html Normal file
View File

@ -0,0 +1,101 @@
<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>
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<a class="Name" href="index.html">UlRent</a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" href="./index.html">Главная</a>
<a class="nav-link" href="./page-help.html">Помощь</a>
</div>
</div>
</div>
</nav>
</header>
<main class="container-fluid wrapper">
<div class="row">
<div class="col-7">
<div class="row justify-content-end">
<form class="col-md-6 m-0" style="width: 600px;" action="./SignIn.html" method="get">
<form id="items-form1" class="needs-validation" novalidate>
<div class="mb-2 ps-4">
<label class="form-label" for="lastname">Как пользователям к вам обращаться</label>
<input id="lastname" name="lastname" class="form-control" type="text" placeholder="Ваше Имя" required>
</div>
<div class="mb-2 ps-4">
<label class="form-label" for="firstname">Ваш логин</label>
<input id="firstname" name="firstname" class="form-control" type="text" placeholder="Логин" required>
</div>
<div class="mb-2 ps-4">
<label class="form-label" for="email">Электронная почта</label>
<input id="email" name="email" class="form-control" type="email" placeholder="Электронная почта" required>
</div>
<div class="mb-2 ps-4">
<label class="form-label" for="password">Пароль</label>
<input id="password" name="password" class="form-control" type="password" placeholder="от 6 до 16 символов" required>
</div>
<div class="bt2">
<div class="d-grid col-8 w-100 mx-auto" style="padding-top: 15px;">
<button type="submit" class="btn btn-light mx-auto" style="width: 12rem; color: red;" >
<a class="" href="bulletinBoard.html" style="color:red">Зарегестрироваться</a>
</button>
</div>
</div>
</form>
</form>
</div>
</div>
<div class="col">
<div class="coll1">
<div class="col-md-8 offset-md-3">
<img src="./images/assets/Image5.png" alt="im1" class="img">
</div>
</div>
</div>
</div>
</main>
<footer class="footer mt-auto">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</footer>
<script type="module">
import { validationreg } from "./js/lines";
import { validationEmail } from "./js/lines";
document.addEventListener('DOMContentLoaded', () => {
validationreg();
validationEmail();
});
</script>
</body>
</html>

88
Lab3/Lab3/aboutus.html Normal file
View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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"/>
<script
src="https://kit.fontawesome.com/49529c639a.js"
crossorigin="anonymous"
></script>
<link rel="stylesheet" href="css/style.css" />
<title>Мой сайт</title>
</head>
<body class="h-100">
<header class>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<div class="mx-auto">
<a class="Name" href="index.html"> UlRent </a>
</div>
</a>
<div class=" mx-auto">
<a class="goback" href="index.html"> Вернуться назад </a>
</div>
</div>
</nav>
</header>
<main class="container-fluid p-4 wrapper flex-shrink-0 pb-3">
<div class="container">
<div class="textus" style="color: white; font-size: 40px">
<p> <u> О портале</u></p>
</div>
<div class="div d-flex justify-content-center">
<iframe src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&amp;source=constructor" class="w-75" style="height: 400px;"></iframe>
</div>
<div class="textus" style="color: white; font-size: 32px">
<p>Позвольте нам сэкономить ваше время и деньги</p>
</div>
<div class="textus" style="color: white; font-size: 28px">
<p>Нужна квартира в Ульяновске? Не хотите перепачивать? Именно на нашем сайте UlRent мы
поможем вам найти необходимое жильё. На нашем портале аренды недвижимости. Место, в котором
можно снять квартиру посуточно или на долгий срок с максимальной экономией. Почему портал
назван "независимым"? Потому что мы не связаны ни с одним агенством недвижимости Ульяновска,
И предлагаем только честные цены на квартиры от реальных собственников. Почему портав назван
"выгодным и экономным"? Статистика показывает, что клиенты, работащие с посредниками переплатили
бы на 20%-30%
</p>
</div>
<div class="textus" style="color: white; font-size: 32px">
<p>Для собственников</p>
</div>
<div class="textus" style="color: white; font-size: 28px">
<p>Если вы являетесь собственником уютной, удобной и комфортной квартиры, то вы можете разместить
своё личное объявление об аренде вашего жилья. Посуточно или на определённый продолжительный срок -
выбор за вами. Для вас в качестве арендодателя представляется возможность определять цену и размещать
свои контактные данные
</p>
</div>
</div>
</main>
<div class="push"></div>
<footer class="footer mx-auto fixed bottom-0 w-100">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
</div>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Главная</title>
<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">
<header>
<nav class="navbar navbar-explad-lg" style="background-color: #85DADA;">
<div class="d-flex flex-column mb-3">
<div class="p-2">
<a href="index.html"><img class="logo5" src="./images/assets/Image1.png" width="100px" height="80px" alt="logo">
</a></div>
</div>
<div class="d-flex justify-content-around">
<div class="p-2">
<a class="header-text1" href="index.html" style="color: white;">UlRent</a>
</div>
<div class="p-2">
<a class="header-text2" href="MyBulletinBoard.html" style="color: white; padding: 25px;">Мои объявления</a>
</div>
</div>
<div class="d-flex justify-content-end pe-5">
<div class="flex-column">
<button type="button" class="btn btn-primary"> Выход </button>
</div>
</div>
</nav>
</header>
<main class="container-fluid mb-5">
<div class="btn-group mt-5 ms-5 mb-5" role="group">
<button id="items-add" class="btn btn-info">Добавить товар (диалог)</button>
</div>
<div>
<table id="items-table" class="">
<thead></thead>
<tbody class="row mb-5">
</tbody>
</table>
</div>
</main>
<div class="push"></div>
<footer class="footer mt-auto fixed bottom-0 w-100">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
<div id="items-update" class="modal fade" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog">
<form id="items-form" class="needs-validation" novalidate>
<div class="modal-content">
<div class="modal-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" alt="placeholder">
<!-- class="rounded rounded-circle" -->
</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="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="description" name="description" class="form-control" type="description" value="0" min="1" step="1"
required>
</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">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<button type="submit" class="btn btn-primary">Сохранить</button>
</div>
</div>
</form>
</div>
</div>
<script type="module">
import validation from "./js/validation";
import { linesForm } from "./js/lines";
document.addEventListener('DOMContentLoaded', () => {
validation();
linesForm();
});
</script>
</body>
</html>

80
Lab3/Lab3/css/banner.css Normal file
View File

@ -0,0 +1,80 @@
#banner {
margin: 5px;
display: flex;
align-items: center;
flex-direction: column;
}
#banner img {
border: 1px solid #3c3c3f;
border-radius: 5px;
}
#banner img.banner-show {
width: 100%;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
#banner img.banner-hide {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
/* Для второго баннера */
#banner2 {
margin: 5px;
display: flex;
align-items: center;
flex-direction: column;
}
#banner2 img {
border: 1px solid #3c3c3f;
border-radius: 5px;
}
#banner2 img.banner-show {
width: 100%;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
#banner2 img.banner-hide {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
/* Для 3его баннера */
#banner3 {
margin: 5px;
display: flex;
align-items: center;
flex-direction: column;
}
#banner3 img {
border: 1px solid #3c3c3f;
border-radius: 5px;
}
#banner3 img.banner-show {
width: 100%;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
#banner3 img.banner-hide {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}

42
Lab3/Lab3/css/button.css Normal file
View File

@ -0,0 +1,42 @@
.form {
display: block;
width: 500px;
}
.input-field {
display: block;
width: 100%;
border: 1px solid blue;
border-radius: 0;
padding: 20px 28px;
margin-bottom: 5px;
font-size: 20px;
}
.send-btn {
border: none;
padding: 20px 28px;
background-color: blue;
color: white;
font-size: 16px;
cursor: pointer;
transition: background-color .2s;
}
.send-btn:hover {
background-color: rgb(55, 55, 255);
}
.send-btn:active {
background-color: rgb(31, 31, 190);
}
.error .input-field {
border-color: red;
}
.error-label {
display: block;
color: red;
margin-bottom: 10px;
}

259
Lab3/Lab3/css/style.css Normal file
View File

@ -0,0 +1,259 @@
body{
background-color: #85DADA;
}
header nav {
background-color: #85DADA;
}
main{
background-color: #85DADA;
}
header nav a:hover {
text-decoration: underline;
}
footer {
background-color: #636363;
padding-top: 15px;
height: 64px;
color: #ffffff;
}
.wrapper {
min-height: 100%;
/* Равно высоте подвала, */
/* но с учётом margin-bottom у последнего дочернего элемента */
margin-bottom: -64px;
}
.push {
height: 64px;
}
img {
height: auto;
max-width: 100%;
border: none;
}
.logo{
width: 60px;
height: 60px;;
}
.Name{
color: #ffffff;
font-size: 32px;
}
.goback{
color: #ffffff;
font-size: 20px;
}
.nav-link{
font-size: 24px;
}
.header-text1{
font-size: 32px;
}
.header-text2{
font-size: 28px;
}
.form-item{
margin-left: 20px;
}
.img222{
display: none;
}
#image-preview {
width: 200px;
}
.card{
width: 18rem;
text-overflow: clip;
overflow:auto;
}
table {
font-family: "--bs-font-sans-serif";
padding: 0%;
color: #85DADA;
justify-content: center;
text-align: center;
border-collapse: separate;
}
td {
width: 150px;
background-color: white;
border: 32px solid #85DADA;
vertical-align: middle;
display: inline-block;
}
button {
justify-content: flex-start;
background: blue;
}
tr{
width: 300px;
height: 30px;
text-overflow: clip;
}
@media (max-width: 550px) {
.form-item{
margin-right: 20px;
}
form{
display: inline;
}
}
@media (max-width: 360px){
.img22{
display: none;
}
}
@media (max-width: 270px){
.img22{
display: table; /*Отмена display: none*/
}
.copywriter{
font-size: 14px;
}
}
@media (min-width: 768px) {
header nav {
height: 64px;
}
/* .btn{
width: 70%;
max-width: 200px;
} */
}
@media (max-width: 420px) {
.header-text1{
font-size: 16px;
}
.header-text2{
font-size: 14px;
}
.bt2{
padding-left: 15px;
}
.coll1{
display: none;
}
/* .btn{
width: 70%;
max-width: 200px;
} */
.header{
margin-left: auto;
margin-right: auto;
font-size: 18px;
}
.btn1{
margin-left: 15px;
margin-right: auto;
}
.btn btn-light{
width: 2rem;
}
.col-8{
width: 200px;
}
/* .row{
display: inline;
} */
}
@media (max-width: 765px){
.card{
margin-left: auto;
margin-right: auto;
}
.header-text1{
font-size: 24px;
}
.header-text2{
font-size: 20px;
}
}
@media (max-width: 600px) {
.header-text1{
font-size: 18px;
}
.header-text2{
font-size: 16px;
}
.img1{
display: none;
}
.img22{
width: 100px;
height:180px;
}
.logo5{
width: 80px;
height: 60px;
}
.card{
margin-left: auto;
margin-right: auto;
}
.img22{
width: 160px;
height: 210px;
}
.imgg1{
display: none;
}
}

View File

@ -0,0 +1,311 @@
:root {
--bg_gradient: linear-gradient(to bottom right, #00c6ff, #0072ff);
--bg: #02a4fd;
--primary: #white;
--secondary: #fff9;
--invert_bg: white;
--invert_primary: white;
--invert_secondary: #3335;
--link_hover_color: #2efff8;
--text_color: white;
--radius: 5px;
--button_radius: 2px;
}
* {
margin: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
/* color: var(--primary); */
color: var(--text_color);
}
a:hover {
color: var(--link_hover_color);
}
body {
text-align: center;
font-family: 'Rubik', sans-serif;
padding: 10px;
display: grid;
grid-template-rows: auto 1fr;
min-height: 100vh;
}
.Mainmenu{
font-family: 'Rubik', sans-serif;
color: white;
font-size: 28px;
}
.goback{
font-size: 20px;
}
/* Layout */
.adaptive {
width: 1480px;
height: 100%;
margin: auto;
display: grid;
grid-template-columns: 1fr 350px;
grid-template-rows: 100px 1fr;
grid-auto-rows: 50px;
gap: 10px;
}
.adaptive > * {
padding: 10px;
color: var(--primary);
/* background: var(--bg_gradient); */
background-color: #85DADA;
}
/* Header */
.header {
display: flex;
gap: 15px;
align-items: center;
justify-content: space-between;
font-size: 14px;
grid-column: span 2;
}
.header .logo {
padding: 6px 20px;
text-transform: uppercase;
font-weight: 500;
border-radius: var(--button_radius);
background: var(--primary);
color: var(--bg);
}
.header_logo-pic{
height: 100px;
width: 120px;
/* margin-left: 0px; */
float: left;
padding: 10px 10px 10px 0px;
}
.header .menu {
display: flex;
align-items: center;
gap: 50px;
font-size: 24px;
font-weight: 300;
margin-right: 50px;
}
.header .mobile-menu {
display: none;
font-size: 30px;
}
.im6{
width: 273px;
height: 173px;
}
.im7{
width: 273px;
height: 173px;
}
/* Sidebar */
.sidebal__title {
font-size: 18px;
font-weight: 500;
margin-bottom: 5px;
text-align: left;
}
.subscribe {
display: grid;
grid-template-columns: 1.5fr 1fr;
grid-auto-rows: 40px;
gap: 5px;
}
.subscribe input,
.subscribe button {
padding: 5px;
font-size: 16px;
width: 100%;
border: none;
border-radius: 3px;
}
.subscribe button {
background: var(--primary);
}
/* Post */
.posts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, auto));
gap: 10px;
}
.post {
display: grid;
background: var(--primary);
color: var(--invert_primary);
border-radius: var(--radius);
overflow: hidden;
padding: 5px 5px 15px;
font-size: 32px;
}
.post__img {
height: 240px;
margin-bottom: 10px;
border-radius: var(--radius);
background: var(--invert_primary) var(--img) center / cover;
}
.post__content {
padding: 0 10px;
text-align: left;
}
.post__title {
font-size: 24px;
font-weight: 500;
margin-bottom: 5px;
color: var(--invert_primary);
}
.post__desc {
font-weight: 300;
}
.help-text{
width: 100%;
grid-column: span 1;
box-sizing: border-box;
}
.footer{
grid-column: span 2;
left: 0;
bottom: 0;
margin: auto;
width: 100%;
height: 70px;
background: #636363;
color: white;
}
@media (max-width: 1440px) {
.adaptive {
width: 1000px;
grid-template-columns: 1fr 300px;
}
.post {
grid-template-columns: 1fr 2fr;
padding-bottom: 5px;
min-height: 150px;
}
.post__img {
height: 100%;
}
.post__title {
font-size: 22px;
}
}
@media (max-width: 1000px) {
.adaptive {
width: 768px;
}
.post {
grid-template-columns: 1fr;
padding-bottom: 15px;
min-height: 150px;
}
.post__img {
height: 20vw;
}
.post__title {
font-size: 22px;
}
}
@media (max-width: 768px) {
.title {
font-size: 4.5vw;
}
.adaptive {
width: 480px;
grid-template-columns: 1fr;
grid-template-rows: 70px 1fr auto;
}
.header {
position: sticky;
top: 0;
z-index: 2;
border-bottom: 1px solid white;
grid-column: 1;
}
.header .menu {
display: none;
}
.header .mobile-menu {
display: block;
}
.posts {
grid-template-columns: repeat(2, 1fr);
}
.post__title {
font-size: 18px;
}
.post__desc {
font-size: 15px;
}
.post__img {
height: 25vw;
}
.header_logo-pic{
height: 80px;
width: 100px;
}
.Mainmenu{
margin-left: auto;
margin-right: auto;
}
.posts {
grid-template-columns: repeat(auto-fit, minmax(200px, auto));
}
.footer{
grid-column: span 1;
}
}
@media (max-width: 800px) {
.menu{
font-size: 18px;
}
.mn{
width: 100px;
}
.Mainmenu{
justify-content: flex-start;
}
}
@media (max-width: 480px) {
.adaptive {
width: 100%;
grid-template-rows: 50px 1fr auto;
}
.post__desc {
font-size: 14px;
}
.post__img {
height: 35vw;
}
.logo{
padding: 6px, 10px;
}
.header_logo-pic{
height: 60px;
width: 70px;
}
}

64
Lab3/Lab3/data.json Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

113
Lab3/Lab3/index.html Normal file
View File

@ -0,0 +1,113 @@
<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">
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<a class="Name" href="index.html"> UlRent </a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" href="bulletinBoard.html" style="color: white">Обзор</a>
<a class="nav-link" href="page-help.html" style="color: white">Помощь</a>
<a class="nav-link" href="aboutus.html" style="color: white">О нас</a>
<a class="nav-link" href="page-contact.html" style="color: white">Контакты</a>
</div>
</div>
</div>
</nav>
</header>
<main class="container-fluid p-4 wrapper flex-shrink-0 p-0">
<div class="container">
<div class="row">
<div class="col-8">
<div class="row">
<div class="col">
<div id="banner">
<img class="banner-hide" src="images/assets/Image3.png" alt="banner1">
<img class="banner-hide" src="images/assets/Image6.jpg" alt="banner1">
</div>
</div>
<div class="col">
<div id="banner2">
<img class="banner-hide" src="images/assets/Image4.png" alt="banner1">
<img class="banner-hide" src="images/assets/Image9.jpg" alt="banner1">
</div>
<div class="pt-5">
</div>
</div>
<div class="col">
<div id="banner3">
<img class="banner-hide" src="images/assets/Image5.png" alt="banner1">
<img class="banner-hide" src="images/assets/Image10.jpg" alt="banner1">
</div>
</div>
</div>
<div class="flex-column w-100 mx-auto">
<div class="pb-4 pe-4" style="padding-right: 0px;">
<button onclick="document.location='LogIn.html'" type="button" class="btn btn-default btn-lg active w-100" style="background-color: white; color: red; padding-bottom: 25px;">
<a href="LogIn.html" style="color:red">Войти в профиль </a>
</button>
</div>
<div class="pb-4 pe-4" style="padding-right: 0px;">
<button onclick="document.location='SignIn.html'" type="button" class="btn btn-default btn-lg active w-100" style="background-color: white; color: red; padding-bottom: 25px;">
<a href="SignIn.html" style="color: red"> Регистрация </a>
</button>
</div>
</div>
</div>
<div class="col">
<img src="./images/assets/Image2.png" alt="im1" class="img22" style="border-radius: 0px 120px;">
</div>
</div>
</div>
</main>
<div class="push"></div>
<footer class="footer mt-auto fixed bottom-0 w-100">
<div class="copywriter p-2">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
<script type="module">
import myBanner from "./js/banner";
document.addEventListener('DOMContentLoaded', () => {
myBanner("#banner");
myBanner("#banner2");
myBanner("#banner3");
});
</script>
</body>
</html>

46
Lab3/Lab3/js/banner.js Normal file
View File

@ -0,0 +1,46 @@
// модуль для смены изображения в баннере по таймеру
import "../css/banner.css";
// указывается блок, в котором будет баннер
// блок должен содержать изображения
function myBanner(root) {
console.info("Loaded");
// получение всех изображений внутри баннера
const banners = document.querySelectorAll(`${root} img`);
// всем изображениям устанавливается класс banner-hide
// если были другие классы, то они будут удалены
for (let i = 0; i < banners.length; i += 1) {
banners[i].setAttribute("class", "banner-hide");
}
let old = banners.length - 1;
let current = 0;
// функция меняет изображения в цикле
// изображение с классом banner-show будет показано
// изображение с классом banner-hide будет скрыто
// функция запускает таймер, который через 5 секунд
// запускает функцию, снова создается таймер и т. д.
function loop() {
banners[current].setAttribute("class", "banner-show");
banners[old].setAttribute("class", "banner-hide");
console.info("Banner changed");
old = current;
current += 1;
if (current === banners.length) {
current = 0;
}
setTimeout(loop, 5000);
}
loop();
}
export default myBanner;

View File

@ -0,0 +1,59 @@
// Модуль для работы с модальным окном
// импорт компонента Modal из bootstrap
import { Modal } from "bootstrap";
import { cntrls, imagePlaceholder } from "./lines-ui";
// поиск модального окна на странице
const modal = document.getElementById("items-update");
// если он найден, то создается экземпляр компонента Modal
// для программного управления модальным окном
const myModal = modal ? new Modal(modal, {}) : null;
// поиск тега с заголовком модального кона для его смены
const modalTitle = document.getElementById("items-update-title");
// обнуление значений модального окна, т. к.
// используется одно окно для всех операций
function resetValues() {
cntrls.lineId.value = "";
cntrls.itemsType.value = "";
cntrls.price.value = parseFloat(0).toFixed(2);
cntrls.description.value = "";
cntrls.image.value = "";
cntrls.imagePreview.src = imagePlaceholder;
}
// функция для показа модального окна
// перед показом происходит заполнение формы для редактирования
// если объект item не пуст
export function showUpdateModal(item) {
modalTitle.innerHTML = item === null ? "Добавить" : "Изменить";
console.info(item);
if (item) {
cntrls.lineId.value = item.id;
cntrls.itemsType.value = item.itemsId;
cntrls.price.value = item.price;
cntrls.description.value = item.description;
// заполнение превью
// Если пользователь выбрал изображение, то оно загружается
// в тэг image с id image - preview
// иначе устанавливается заглушка, адрес которой указан в imagePlaceholder
cntrls.imagePreview.src = item.image ? item.image : imagePlaceholder;
} else {
resetValues();
}
myModal.show();
}
// функция для скрытия модального окна
export function hideUpdateModal() {
resetValues();
// удаление класса was-validated для скрытия результатов валидации
cntrls.form.classList.remove("was-validated");
myModal.hide();
}

View File

@ -0,0 +1,99 @@
// модуль для работы с REST API сервера
// адрес сервера
const serverUrl = "http://localhost:8081";
// функция возвращает объект нужной структуры для отправки на сервер
function createLineObject(item, price, description, image) {
return {
itemsId: item,
price: parseFloat(price).toFixed(2),
description,
image,
};
}
// обращение к серверу для получения всех типов товара (get)
export async function getAllItemTypes() {
const response = await fetch(`${serverUrl}/items`);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}
// обращение к серверу для получения всех записей (get)
export async function getAllLines() {
const response = await fetch(`${serverUrl}/lines?_expand=items`);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}
// обращение к серверу для получения записи по первичному ключу (id) (get)
// id передается в качестве части пути URL get-запроса
export async function getLine(id) {
const response = await fetch(`${serverUrl}/lines/${id}?_expand=items`);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}
// обращение к серверу для создания записи (post)
// объект отправляется в теле запроса (body)
export async function createLine(item, price, description, image) {
const itemObject = createLineObject(item, price, description, image);
const options = {
method: "POST",
body: JSON.stringify(itemObject),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
};
const response = await fetch(`${serverUrl}/lines`, options);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}
// обращение к серверу для обновления записи по id (put)
// объект отправляется в теле запроса (body)
// id передается в качестве части пути URL get-запроса
export async function updateLine(id, item, price, description, image) {
const itemObject = createLineObject(item, price, description, image);
const options = {
method: "PUT",
body: JSON.stringify(itemObject),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
};
const response = await fetch(`${serverUrl}/lines/${id}`, options);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}
// обращение к серверу для удаления записи по id (delete)
// id передается в качестве части пути URL get-запроса
export async function deleteLine(id) {
const options = {
method: "DELETE",
};
const response = await fetch(`${serverUrl}/lines/${id}`, options);
if (!response.ok) {
throw response.statusText;
}
return response.json();
}

124
Lab3/Lab3/js/lines-ui.js Normal file
View File

@ -0,0 +1,124 @@
// модуль для работы с элементами управления
// объект для удобного получения элементов
// при обращении к атрибуту объекта вызывается
// нужная функция для поиска элемента
export const cntrls = {
button: document.getElementById("items-add"),
table: document.querySelector("#items-table tbody"),
form: document.getElementById("items-form"),
lineId: document.getElementById("items-line-id"),
itemsType: document.getElementById("item"),
price: document.getElementById("price"),
count: document.getElementById("count"),
description: document.getElementById("description"),
image: document.getElementById("image"),
imagePreview: document.getElementById("image-preview"),
};
// Дефолтное превью
export const imagePlaceholder = "https://via.placeholder.com/200";
// функция создает тег option для select
// <option value="" selected>name</option>
export function createItemsOption(name, value = "", isSelected = false) {
const option = document.createElement("option");
option.value = value || "";
option.selected = isSelected;
option.text = name;
return option;
}
// функция создает ссылку (a) для таблицы
// содержимое тега a заполняется необходимой иконкой (icon)
// при нажатии вызывается callback
// ссылка "оборачивается" тегом td
// <td><a href="#" onclick="callback()"><i class="fa-solid icon"></i></a></td>
function createTableAnchor(icon, callback) {
const i = document.createElement("i");
i.classList.add("fa-solid", icon);
const a = document.createElement("a");
a.classList.add("me-3", "ms-5");
a.href = "#";
a.appendChild(i);
a.onclick = (event) => {
// чтобы в URL не добавлялась решетка
event.preventDefault();
event.stopPropagation();
callback();
};
return a;
}
// функция создает колонку таблицы с текстом value
// <td>value</td>
function createTableRow(value) {
const td = document.createElement("tr");
td.textContent = value;
return td;
}
function createTableImage(image) {
const td = document.createElement("img");
td.src = image;
return td;
}
function createTablePrice(value) {
const td = document.createElement("div");
td.textContent = value;
return td;
}
// функция создает строку таблицы
// <tr>
// <th scope="row">index + 1</th>
// <td>item.items.name</td>
// <td>parseFloat(item.price).toFixed(2))</td>
// <td>item.count</td>
// <td>parseFloat(item.sum).toFixed(2))</td>
// <td><a href="#" onclick="editCallback()"><i class="fa-solid fa-pencil"></i></a></td>
// <td><a href="#" onclick="editPageCallback()"><i class="fa-solid fa-pen-to-square"></i></a></td>
// <td><a href="#" onclick="deleteCallback()"><i class="fa-solid fa-trash"></i></a></td>
// </tr>
export function createTableCol(item, index, editCallback, deleteCallback) {
const container = document.createElement("div");
container.classList.add("col", "pb-4");
container.id = `line-${item.id}`;
const card = document.createElement("div");
card.classList.add("card", "mx-auto");
card.appendChild(createTableImage(item.image));
const cardbody = document.createElement("div");
cardbody.classList.add("card-body");
const cardtitle = document.createElement("h5");
cardtitle.classList.add("card-title");
cardtitle.appendChild(createTableRow(item.items.name));
const cardtext = document.createElement("p");
cardtext.classList.add("card-text");
cardtext.appendChild(createTableRow(item.description));
const row = document.createElement("row");
const a = document.createElement("a");
a.href = "#";
a.classList.add("btn", "btn-primary");
a.appendChild(createTablePrice(parseFloat(item.price).toFixed(2)));
row.appendChild(a);
// редактировать в модальном окне
row.appendChild(createTableAnchor("fa-pencil", editCallback));
// удаление
row.appendChild(createTableAnchor("fa-trash", deleteCallback));
cardbody.appendChild(cardtitle);
cardbody.appendChild(cardtext);
cardbody.appendChild(row);
card.appendChild(cardbody);
container.appendChild(card);
return container;
}

260
Lab3/Lab3/js/lines.js Normal file
View File

@ -0,0 +1,260 @@
// модуль с логикой
import { hideUpdateModal, showUpdateModal } from "./lines-modal";
import {
createLine, deleteLine, getAllItemTypes, getAllLines, updateLine,
} from "./lines-rest-api";
import {
cntrls, createItemsOption, createTableCol, imagePlaceholder,
} from "./lines-ui";
async function drawItemsSelect() {
// вызов метода REST API для получения списка типов товаров
const data = await getAllItemTypes();
// очистка содержимого 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));
});
}
async function drawLinesTable() {
console.info("Try to load data");
if (!cntrls.table) {
return;
}
// вызов метода REST API для получения всех записей
const data = await getAllLines();
// очистка содержимого table
// удаляется все, что находится между тегами <table></table>
// но не атрибуты
cntrls.table.innerHTML = "";
// цикл по результату ответа от сервера
// используется лямбда-выражение
// (item, index) => {} аналогично function(item, index) {}
data.forEach((item, index) => {
cntrls.table.appendChild(
createTableCol(
item,
index,
// функции передаются в качестве параметра
// это очень удобно, так как аргументы функций доступны только
// в данном месте кода и не передаются в сервисные модули
() => showUpdateModal(item),
// () => location.assign(`page-edit.html?id=${item.id}`),
() => removeLine(item.id),
),
);
});
}
async function addLine(item, price, description, image) {
console.info("Try to add item");
// вызов метода REST API для добавления записи
const data = await createLine(item, price, description, image);
console.info("Added");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
async function editLine(id, item, price, description, image) {
console.info("Try to update item");
// вызов метода REST API для обновления записи
const data = await updateLine(id, item, price, description, image);
console.info("Updated");
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
async function removeLine(id) {
if (!confirm("Do you really want to remove this item?")) {
console.info("Canceled");
return;
}
console.info("Try to remove item");
// вызов метода REST API для удаления записи
const data = await deleteLine(id);
console.info(data);
// загрузка и заполнение table
drawLinesTable();
}
// функция для получения содержимого файла в виде base64 строки
// https://ru.wikipedia.org/wiki/Base64
async function readFile(file) {
const reader = new FileReader();
// создание Promise-объекта для использования функции
// с помощью await (асинхронно) без коллбэков (callback)
// https://learn.javascript.ru/promise
return new Promise((resolve, reject) => {
// 2. "Возвращаем" содержимое когда файл прочитан
// через вызов resolve
// Если не использовать Promise, то всю работу по взаимодействию
// с REST API пришлось бы делать в обработчике (callback) функции
// onloadend
reader.onloadend = () => {
const fileContent = reader.result;
// Здесь могла бы быть работа с REST API
// Чтение заканчивает выполняться здесь
resolve(fileContent);
};
// 3. Возвращаем ошибку
reader.onerror = () => {
// Или здесь в случае ошибки
reject(new Error("oops, something went wrong with the file reader."));
};
// Шаг 1. Сначала читаем файл
// Чтение начинает выполняться здесь
reader.readAsDataURL(file);
});
}
// функция для обновления блока с превью выбранного изображения
async function updateImagePreview() {
// получение выбранного файла
// возможен выбор нескольких файлов, поэтому необходимо получить только первый
const file = cntrls.image.files[0];
// чтение содержимого файла в виде base64 строки
const fileContent = await readFile(file);
console.info("base64 ", fileContent);
// обновление атрибута src для тега img с id image-preview
cntrls.imagePreview.src = fileContent;
}
// Функция для обработки создания и редактирования элементов таблицы через модальное окно
// Если хотите делать через страницу, то удалите эту функцию
export function linesForm() {
console.info("linesForm");
// загрузка и заполнение select со списком товаров
drawItemsSelect();
// загрузка и заполнение table
drawLinesTable();
// Вызов функции обновления превью изображения при возникновении
// события oncahnge в тэге input с id image
cntrls.image.addEventListener("change", () => updateImagePreview());
// обработчик события нажатия на кнопку для показа модального окна
cntrls.button.addEventListener("click", () => showUpdateModal(null));
// обработчик события отправки формы
// возникает при нажатии на кнопку (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.price.value,
cntrls.description.value,
// cntrls.image.value,
// cntrls.imagePreview.src = item.image ? item.image : imagePlaceholder,
imageBase64,
);
} else {
await editLine(
currentId,
cntrls.itemsType.value,
cntrls.price.value,
cntrls.description.value,
imageBase64,
);
}
// после выполнения добавления/обновления модальное окно скрывается
hideUpdateModal();
});
}
export async function validationlog() {
const goForward = () => location.assign("MyBulletinBoard.html");
// обработчик события отправки формы
// возникает при нажатии на кнопку (button) с типом submit
// кнопка должна находится внутри тега form
addEventListener("submit", async (event) => {
console.info("Form onSubmit");
// отключение стандартного поведения формы при отправке
// при отправке страница обновляется и JS перестает работать
event.preventDefault();
event.stopPropagation();
goForward();
});
}
export async function validationreg() {
const goForward = () => location.assign("bulletinBoard.html");
// обработчик события отправки формы
// возникает при нажатии на кнопку (button) с типом submit
// кнопка должна находится внутри тега form
addEventListener("submit", async (event) => {
console.info("Form onSubmit");
// отключение стандартного поведения формы при отправке
// при отправке страница обновляется и JS перестает работать
event.preventDefault();
event.stopPropagation();
goForward();
});
}
export async function validationEmail() {
const emailField = document.getElementById("email");
const emailErrors = document.getElementById("emailErrors");
emailField.addEventListener("submitcheck", validateEmail);
function validateEmail() {
if (!emailField.validity.valid) {
emailErrors.textContent = emailField.validationMessage;
emailErrors.style.display = "block";
} else {
emailErrors.textContent = "";
emailErrors.style.display = "none";
}
}
}

View File

@ -0,0 +1,25 @@
// модуль используется для валидации форма на странице
function validation() {
// поиск всех форма с классом .needs-validation
const forms = document.querySelectorAll("form.needs-validation");
for (let i = 0; i < forms.length; i += 1) {
const form = forms[i];
// для каждой формы добавляется обработчик события отправки
form.addEventListener("submit", (event) => {
// если форма не прошла валидацию
// то выключить стандартное действие
if (!form.checkValidity()) {
event.preventDefault();
// предотвращает распространение preventDefault
// на другие объекты
event.stopPropagation();
}
// добавляет к форме класс was-validated
form.classList.add("was-validated");
});
}
}
export default validation;

14
Lab3/Lab3/jsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2020",
"jsx": "preserve",
"strictNullChecks": true,
"strictFunctionTypes": true
},
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

7950
Lab3/Lab3/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

26
Lab3/Lab3/package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "int-prog",
"version": "1.0.0",
"type": "module",
"scripts": {
"vite": "vite",
"serve": "http-server -p 3000 ./dist/",
"build": "vite build",
"rest": "json-server --watch data.json -p 8081",
"dev": "npm-run-all --parallel rest vite",
"prod": "npm-run-all build --parallel serve rest"
},
"dependencies": {
"bootstrap": "5.3.2",
"@fortawesome/fontawesome-free": "6.4.2"
},
"devDependencies": {
"vite": "4.4.9",
"eslint": "8.50.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-plugin-import": "2.28.1",
"http-server": "14.1.1",
"json-server": "0.17.4",
"npm-run-all": "4.1.5"
}
}

View File

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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"/>
<script
src="https://kit.fontawesome.com/49529c639a.js"
crossorigin="anonymous"
></script>
<link rel="stylesheet" href="./css/style.css" />
<title>Мой сайт</title>
</head>
<body class="h-100">
<header class="stiky-top">
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<div class="mx-auto">
<a class="Name" href="index.html"> UlRent </a>
</div>
</a>
<div class=" mx-auto">
<a class="goback" href="index.html"> Вернуться назад </a>
</div>
</div>
</nav>
</header>
<main class="container-fluid p-4 wrapper h-100">
<div class="container h-100">
<div>
<a href="bulletinBoard.html"><img src="./images/assets/Image9.jpg" class="card-img-top" width="450px" height="200px" alt="im"></a>
</div>
<div class="textus" style="color: white; font-size: 36px">
<p> <i> Контактные данные </i></p>
</div>
<div class="textus" style="color: white; font-size: 32px">
<p> +7(909)-985-87-54</p>
<p> +7(909)-657-82-94</p>
<p> +7(909)-247-47-11</p>
</div>
<div class="textus" style="color: white; font-size: 36px">
<p> <i> E-mail </i> </p>
</div>
<div class="textus" style="color: white; font-size: 32px">
<p> Ulrent@mail.ru</p>
<p> Ulrent73@yandex.</p>
<p> RussianRent@mail.ru</p>
</div>
</div>
</main>
<div class="push"></div>
<footer class="footer mx-auto fixed bottom-0 w-100">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
</div>
</body>
</html>

101
Lab3/Lab3/page-help.html Normal file
View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <script type="module" src="./node_modules/bootstrap/dist/js/bootstrap.min.js"></script> -->
<script src="https://kit.fontawesome.com/49529c639a.js" crossorigin="anonymous"></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"/>
<script
src="https://kit.fontawesome.com/49529c639a.js"
crossorigin="anonymous"
></script>
<link rel="stylesheet" href="css/style_help.css" />
<title>Мой сайт</title>
</head>
<body>
<div class="adaptive">
<header class="header">
<div class="logo">
<a href="/" class="header_logolink">
<img src="./images/assets/Image1.png" alt="UlRent" class="header_logo-pic">
</a>
</div>
<div class="mn">
<div class="Mainmenu">
<a href= index.html > UlRent </a>
</div>
</div>
<div class=" mx-auto">
<a class="goback" href="index.html" style="margin-right: 45px;"> Вернуться назад </a>
</div>
</header>
<main class="container-fluid wrapper">
<div class="posts">
<div class="" style="color: white">
<p>Добро пожаловать на наш сайт аренды жилья. На данном сайте вы можете размещать
свои объявления, а также оставлять заявки на бронирование </p>
<div class="row" style="padding-top: 20px;">
<div class="col pb-4">
<img src="./images/assets/Image5.png" alt="im2">
</div>
<div class="col pb-4">
<img class="im6" src="./images/assets/Image6.jpg" alt="im2">
</div>
<div class="col pb-4">
<img class="im7" src="./images/assets/Image7.jpg" alt="im3">
</div>
</div>
<div class="row" style="padding-top: 50px;">
<div class="col pb-4">
<img src="./images/assets/Image8.png" alt="im2">
</div>
<div class="col pb-4">
<img class="im6" src="./images/assets/Image9.jpg" alt="im2">
</div>
<div class="col pb-4">
<img class="im7" src="./images/assets/Image11.jpg" alt="im3">
</div>
</div>
</div>
</div>
</main>
<div class="sidebar">
<div class="sidebal__title">
<p>Хотите узнать больше? Или остались вопросы?</p>
<p>Ответим прямо на вашу почту</p>
</div>
<div class="subscribe">
<input type="text" placeholder="Email" />
<button type="button" style="background-color: aqua;">Отправить</button>
<div class="input-group">
<span class="input-group-text"></span>
<textarea class="form-control" style="height: 40px;" aria-label="With textarea"></textarea>
</div>
</div>
</div>
<footer class="footer">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
</div>
</body>
</html>

134
Lab3/Lab3/page4.html Normal file
View File

@ -0,0 +1,134 @@
<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>
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./images/assets/Image1.png" alt="logo">
<a class="Name" href="./index.html">UlRent</a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" style="color: white;" href="./Admin.html">Администратор</a>
<a class="nav-link" style="color: white;" href="./index.html">Главная</a>
<a class="nav-link" style="color: white;" href="./page-help.html">Помощь</a>
</div>
</div>
</div>
</nav>
</header>
<main class="container-fluid p-1 wrapper">
<article>
<div class="w-100 mx-auto">
<form action="./page4.html" method="get" novalidate style="width: 100%;">
<div class="row">
<div class="col w-100 mx-auto">
<div class="form-item">
<label for="lastname">Как к вам обращаться?</label>
<input id="lastname" name="lastname" class="form-control" type="text" required="">
</div>
<div class="form-item">
<label for="firstname">Название объявления</label>
<input id="firstname" name="firstname" class="form-control" type="text" required="">
</div>
<div class="form-item">
<label for="email">E-mail</label>
<input id="email" name="email" class="form-control" type="email" placeholder="name@example.ru" required="">
</div>
<div class="form-item">
<label for="firstname"> Город </label>
<input id="firstname" name="firstname" class="form-control" type="text" required="">
</div>
<div class="form-item">
<label for="Category"> Район </label>
<select class="form-select" name="selected" required="">
<option value="" selected="">Выберите значение</option>
<option value="1">Ленинский</option>
<option value="2">Железнодорожный</option>
<option value="2">Засвияжьский</option>
<option value="2">Новый город</option>
</select>
</div>
<div class="form-item">
<label for="firstname"> Номер телефона </label>
<input id="firstname" name="firstname" class="form-control" type="text" required="">
</div>
<div class="form-item">
<label for="aboutme">Цена</label>
<input id="aboutme" name="aboutme" class="form-control" placeholder="5000 ₽" type="text" required="">
</div>
<div class="form-item">
<label for="Category"> Категория </label>
<select class="form-select" name="selected" required="">
<option value="" selected="">Выберите значение</option>
<option value="1">Посуточно</option>
<option value="2">На длительный срок</option>
</select>
</div>
</div>
<div class="col w-100 pt-3 ms-3 mx-auto">
<img src="./images/assets/Image8.png" alt="im1" class="img-thumbnail">
<label class="form-label pt-3 ms-3" for="image">Изображение</label>
<input id="image" type="file" name="image" accept="image/*">
<div class="p-2 ms-3">
<button type="submit" class="btn btn-light">Сохранить</button>
</div>
<div style="margin-right: 30px;">
<input id="aboutme" class="form-label" name="aboutme" type="text" required="" style="width: 380px; height: 100px;">
</div>
<div class="p-4" style="margin-bottom: 50px;">
<button type="submit" class="btn btn-primary btnsend" data-bs-toggle="modal" data-bs-target="#exampleModal" style="margin-left: 40px;">Отправить</button>
</div>
</div>
</div>
</form>
</div>
</article>
</main>
<footer class="footer mt-auto">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</footer>
<script type="module">
import validation from "./js/validation";
import { linesPageForm } from "./js/lines"
document.addEventListener('DOMContentLoaded', () => {
validation();
linesPageForm();
});
</script>
</body>
</html>

100
Lab3/Lab3/page7.html Normal file
View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Главная</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img class="logo" src="./assets/Image1.png" alt="logo">
<a class="Name" href="./index.html">UlRent</a>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
<div class="navbar-nav pe-5">
<a class="nav-link" href="./index.html">Главная</a>
<a class="nav-link" href="./page-help.html">Помощь</a>
</div>
</div>
</div>
</nav>
</header>
<article>
<div class="row mx-auto">
<div class="col pt-4 ps-4 pe-4" style="margin-left: 20px;">
<img src="assets/Image7.jpg" alt="...">
<div class="text-us" style="color: white; font-size: 28px">
<p> Адрес: Улица Ёжиков, д.45, кв-7 </p>
<p> Номер телефона: +7(900)-785-84-56 </p>
</div>
</div>
<div class="col ps-4 pe-4">
<div class="textus mx-auto" style="color: white; font-size: 28px">
<p> Цена: 4500 рублей </p>
<p> Описание </p>
<p> Уютная квартира в центре города с красивым видом на Волгу, современный ремонт, удобная парковка.
Квартира оснащена бытовой техникой: стиралка, телевизор, холодильник, плита. Есть WI-FI роутер
4 спальных места (двуспальная кровать и два раскладывающихся дивана. Расчётный час - 12 часов дня.</p>
</div>
</div>
</div>
<div class="row margo mx-auto">
<div id="carouselExample" class="carousel slide">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="assets/Image7.jpg" class="d-block" style="margin-left: auto; margin-right: auto;" alt="...">
</div>
<div class="carousel-item">
<img src="assets/Image11.jpg" class="d-block" style="margin-left: auto; margin-right: auto;" alt="...">
</div>
<div class="carousel-item">
<img src="assets/Image13.jpg" class="d-block" style="margin-left: auto; margin-right: auto;" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExample" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExample" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
</article>
<footer class="footer mx-auto fixed bottom-0 w-100">
<div class="copywriter">
&copy; 2023 UlRent Белянин Никита ПИбд-21 | Все права защищены ;)
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js"
integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>

21
Lab3/Lab3/readme.md Normal file
View File

@ -0,0 +1,21 @@
### Окружение
В VSCode необходимо установить плагин (расширение) ESLint:
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
ESLint уже настроен (см. конфиг .eslintrc.json), но для справки можно почитать материал по ссылке
https://www.digitalocean.com/community/tutorials/linting-and-formatting-with-eslint-in-vs-code
### Установка зависимостей
npm install
### Запуск в режиме разработки
npm run dev
### Запуск продуктовой версии (production)
npm run prod

18
Lab3/Lab3/vite.config.js Normal file
View File

@ -0,0 +1,18 @@
import { resolve } from "path";
// eslint-disable-next-line import/no-extraneous-dependencies
import { defineConfig } from "vite";
export default defineConfig({
build: {
sourcemap: true,
emptyOutDir: true,
rollupOptions: {
input: {
main: resolve(__dirname, "index.html"),
page2: resolve(__dirname, "page2.html"),
page3: resolve(__dirname, "page3.html"),
page4: resolve(__dirname, "page4.html"),
},
},
},
});