LAB-10
BIN
labs/lab-10/img/main.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
207
labs/lab-10/index.html
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>ЭкоЛанч - Доставка здоровых бизнес-ланчей в Москве</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="templates/menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="templates/order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="templates/orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="templates/delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="templates/about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="hero-section">
|
||||
<div class="container">
|
||||
<div class="row align-items-center min-vh-100">
|
||||
<div class="col-lg-6 mb-5 mb-lg-0">
|
||||
<h1 class="display-4 fw-bold mb-4">Здоровое питание для вашего офиса</h1>
|
||||
<p class="lead mb-4">ЭкоЛанч доставляет свежие и полезные бизнес-ланчи прямо в ваш офис. Сбалансированное меню, быстрая доставка и забота о вашем здоровье.</p>
|
||||
<div class="d-flex flex-column flex-sm-row gap-3">
|
||||
<a href="templates/menu.html" class="btn btn-primary btn-lg">Собрать ланч</a>
|
||||
<a href="#advantages" class="btn btn-outline-primary btn-lg">Узнать больше</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<img src="img/main.jpg" alt="Здоровая еда" class="img-fluid rounded-4 shadow-lg">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="advantages" class="advantages-section py-5">
|
||||
<div class="container">
|
||||
<div class="row mb-5">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<h2 class="display-5 fw-bold mb-3">Почему выбирают нас</h2>
|
||||
<p class="lead text-muted">Мы предлагаем лучшие условия для здорового питания вашей команды</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">⚡</div>
|
||||
<h4 class="fw-bold mb-3">Быстрая доставка</h4>
|
||||
<p class="text-muted">Доставляем в течение 60 минут по всей Москве в пределах МКАД</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">🥗</div>
|
||||
<h4 class="fw-bold mb-3">Свежие продукты</h4>
|
||||
<p class="text-muted">Готовим каждое утро из качественных продуктов от проверенных поставщиков</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">💚</div>
|
||||
<h4 class="fw-bold mb-3">Сбалансированное меню</h4>
|
||||
<p class="text-muted">Меню разработано профессиональными диетологами</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">♻️</div>
|
||||
<h4 class="fw-bold mb-3">Эко-упаковка</h4>
|
||||
<p class="text-muted">Используем биоразлагаемую упаковку, заботимся о планете</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">💰</div>
|
||||
<h4 class="fw-bold mb-3">Гибкие цены</h4>
|
||||
<p class="text-muted">Система скидок для корпоративных клиентов и постоянных заказчиков</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="advantage-card text-center p-4 h-100">
|
||||
<div class="advantage-icon mb-3">👨🍳</div>
|
||||
<h4 class="fw-bold mb-3">Опытные повара</h4>
|
||||
<p class="text-muted">Профессиональные повара с многолетним опытом</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-section py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8 text-center">
|
||||
<h2 class="display-5 fw-bold mb-4">Готовы попробовать здоровое питание?</h2>
|
||||
<p class="lead mb-4">Соберите свой идеальный ланч прямо сейчас. Выберите блюда из нашего меню и оформите заказ всего за несколько минут.</p>
|
||||
<a href="templates/menu.html" class="btn btn-light btn-lg px-5">Собрать ланч сейчас</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="contacts" class="contacts-section py-5">
|
||||
<div class="container">
|
||||
<div class="row mb-5">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<h2 class="display-5 fw-bold mb-3">Свяжитесь с нами</h2>
|
||||
<p class="lead text-muted">Есть вопросы? Напишите нам, и мы обязательно ответим</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-6">
|
||||
<h4 class="fw-bold mb-4">Контактная информация</h4>
|
||||
<div class="contact-info">
|
||||
<div class="contact-item mb-3">
|
||||
<strong>Телефон:</strong>
|
||||
<a href="tel:+79993737737">+7 (999) 373-77-37</a>
|
||||
</div>
|
||||
<div class="contact-item mb-3">
|
||||
<strong>Email:</strong>
|
||||
<a href="mailto:egor@deev.space">egor@deev.space</a>
|
||||
</div>
|
||||
<div class="contact-item mb-3">
|
||||
<strong>Адрес:</strong>
|
||||
<span>г. Москва, ул. Михалковская, д. 7, к. 1</span>
|
||||
</div>
|
||||
<div class="contact-item mb-3">
|
||||
<strong>Режим работы:</strong>
|
||||
<span>Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<h4 class="fw-bold mb-4">Форма обратной связи</h4>
|
||||
<form id="contact-form">
|
||||
<div class="mb-3">
|
||||
<label for="contact-name" class="form-label">Имя</label>
|
||||
<input type="text" class="form-control" id="contact-name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="contact-email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="contact-email" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="contact-phone" class="form-label">Телефон</label>
|
||||
<input type="tel" class="form-control" id="contact-phone">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="contact-message" class="form-label">Сообщение</label>
|
||||
<textarea class="form-control" id="contact-message" rows="4" required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Отправить сообщение</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-info">
|
||||
<div class="footer-row footer-title">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
314
labs/lab-10/js/menu.js
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
let dishes = [];
|
||||
|
||||
const selectedDishes = {
|
||||
soup: null,
|
||||
'main-course': null,
|
||||
salad: null,
|
||||
drink: null,
|
||||
dessert: null
|
||||
};
|
||||
|
||||
let activeFilters = {
|
||||
soup: null,
|
||||
'main-course': null,
|
||||
salad: null,
|
||||
drink: null,
|
||||
dessert: null
|
||||
};
|
||||
|
||||
function loadDishes() {
|
||||
const apiUrl = 'https://edu.std-900.ist.mospolytech.ru/labs/api/dishes';
|
||||
|
||||
console.log('Загрузка блюд из API...');
|
||||
|
||||
fetch(apiUrl)
|
||||
.then(function(response) {
|
||||
console.log('Ответ получен:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка загрузки данных: ' + response.status);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Данные загружены:', data.length, 'блюд');
|
||||
dishes = data;
|
||||
sortDishes();
|
||||
loadOrderFromLocalStorage();
|
||||
displayDishes();
|
||||
updateOrderPanel();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при загрузке блюд:', error);
|
||||
alert('Не удалось загрузить меню. Проверьте подключение к интернету.');
|
||||
});
|
||||
}
|
||||
|
||||
function sortDishes() {
|
||||
dishes.sort(function(a, b) {
|
||||
return a.name.localeCompare(b.name, 'ru');
|
||||
});
|
||||
}
|
||||
|
||||
function displayDishes() {
|
||||
const soupSection = document.getElementById('soup-section');
|
||||
const mainCourseSection = document.getElementById('main-course-section');
|
||||
const saladSection = document.getElementById('salad-section');
|
||||
const drinkSection = document.getElementById('drink-section');
|
||||
const dessertSection = document.getElementById('dessert-section');
|
||||
|
||||
if (!soupSection || !mainCourseSection || !saladSection ||
|
||||
!drinkSection || !dessertSection) {
|
||||
console.error('Не найдены секции для отображения блюд');
|
||||
return;
|
||||
}
|
||||
|
||||
soupSection.innerHTML = '';
|
||||
mainCourseSection.innerHTML = '';
|
||||
saladSection.innerHTML = '';
|
||||
drinkSection.innerHTML = '';
|
||||
dessertSection.innerHTML = '';
|
||||
|
||||
console.log('Отображение блюд. Всего:', dishes.length);
|
||||
|
||||
dishes.forEach(function(dish) {
|
||||
const dishCard = createDishCard(dish);
|
||||
|
||||
if (dish.category === 'soup') {
|
||||
if (!activeFilters.soup || dish.kind === activeFilters.soup) {
|
||||
soupSection.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
} else if (dish.category === 'main-course') {
|
||||
if (!activeFilters['main-course'] ||
|
||||
dish.kind === activeFilters['main-course']) {
|
||||
mainCourseSection.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
} else if (dish.category === 'salad') {
|
||||
if (!activeFilters.salad || dish.kind === activeFilters.salad) {
|
||||
saladSection.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
} else if (dish.category === 'drink') {
|
||||
if (!activeFilters.drink || dish.kind === activeFilters.drink) {
|
||||
drinkSection.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
} else if (dish.category === 'dessert') {
|
||||
if (!activeFilters.dessert ||
|
||||
dish.kind === activeFilters.dessert) {
|
||||
dessertSection.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addDishClickHandlers();
|
||||
restoreSelection();
|
||||
}
|
||||
|
||||
function createDishCard(dish) {
|
||||
return `
|
||||
<div class="dish-card" data-dish="${dish.keyword}">
|
||||
<img src="${dish.image}" alt="${dish.name}">
|
||||
<p class="dish-price">${dish.price} руб.</p>
|
||||
<p class="dish-name">${dish.name}</p>
|
||||
<p class="dish-weight">${dish.count}</p>
|
||||
<button>Добавить</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function addDishClickHandlers() {
|
||||
const dishCards = document.querySelectorAll('.dish-card');
|
||||
|
||||
dishCards.forEach(function(card) {
|
||||
card.addEventListener('click', function() {
|
||||
const keyword = this.dataset.dish;
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.keyword === keyword;
|
||||
});
|
||||
|
||||
if (dish) {
|
||||
selectDish(dish);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function selectDish(dish) {
|
||||
const previousDish = selectedDishes[dish.category];
|
||||
|
||||
if (previousDish) {
|
||||
const previousCard = document.querySelector(
|
||||
`.dish-card[data-dish="${previousDish.keyword}"]`
|
||||
);
|
||||
if (previousCard) {
|
||||
previousCard.classList.remove('selected');
|
||||
}
|
||||
}
|
||||
|
||||
selectedDishes[dish.category] = dish;
|
||||
|
||||
const currentCard = document.querySelector(
|
||||
`.dish-card[data-dish="${dish.keyword}"]`
|
||||
);
|
||||
if (currentCard) {
|
||||
currentCard.classList.add('selected');
|
||||
}
|
||||
|
||||
saveOrderToLocalStorage();
|
||||
updateOrderPanel();
|
||||
}
|
||||
|
||||
function saveOrderToLocalStorage() {
|
||||
const order = {};
|
||||
|
||||
Object.keys(selectedDishes).forEach(function(category) {
|
||||
if (selectedDishes[category]) {
|
||||
order[category] = selectedDishes[category].id;
|
||||
}
|
||||
});
|
||||
|
||||
localStorage.setItem('selectedDishes', JSON.stringify(order));
|
||||
console.log('Заказ сохранен в localStorage:', order);
|
||||
}
|
||||
|
||||
function loadOrderFromLocalStorage() {
|
||||
const savedOrder = localStorage.getItem('selectedDishes');
|
||||
|
||||
if (!savedOrder) {
|
||||
console.log('Сохраненный заказ не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const order = JSON.parse(savedOrder);
|
||||
console.log('Загружен заказ из localStorage:', order);
|
||||
|
||||
Object.keys(order).forEach(function(category) {
|
||||
const dishId = order[category];
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === dishId;
|
||||
});
|
||||
|
||||
if (dish) {
|
||||
selectedDishes[category] = dish;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Ошибка при загрузке заказа:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function updateOrderPanel() {
|
||||
const orderPanel = document.getElementById('order-panel');
|
||||
const orderPanelPrice = document.getElementById('order-panel-price');
|
||||
const orderPanelLink = document.getElementById('order-panel-link');
|
||||
|
||||
if (!orderPanel || !orderPanelPrice || !orderPanelLink) {
|
||||
console.error('Не найдены элементы панели заказа');
|
||||
return;
|
||||
}
|
||||
|
||||
const hasSelection = selectedDishes.soup ||
|
||||
selectedDishes['main-course'] ||
|
||||
selectedDishes.salad ||
|
||||
selectedDishes.drink ||
|
||||
selectedDishes.dessert;
|
||||
|
||||
if (!hasSelection) {
|
||||
orderPanel.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
orderPanel.classList.remove('hidden');
|
||||
|
||||
let totalPrice = 0;
|
||||
|
||||
Object.keys(selectedDishes).forEach(function(category) {
|
||||
if (selectedDishes[category]) {
|
||||
totalPrice += selectedDishes[category].price;
|
||||
}
|
||||
});
|
||||
|
||||
orderPanelPrice.textContent = totalPrice + ' руб.';
|
||||
|
||||
if (isValidCombo()) {
|
||||
orderPanelLink.classList.remove('disabled');
|
||||
} else {
|
||||
orderPanelLink.classList.add('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
function setupFilters() {
|
||||
const filterButtons = document.querySelectorAll('.filter-btn');
|
||||
|
||||
filterButtons.forEach(function(button) {
|
||||
button.addEventListener('click', function() {
|
||||
const kind = this.dataset.kind;
|
||||
const section = this.closest('section');
|
||||
const category = section.querySelector('.dishes-grid').id
|
||||
.replace('-section', '');
|
||||
|
||||
if (this.classList.contains('active')) {
|
||||
this.classList.remove('active');
|
||||
activeFilters[category] = null;
|
||||
} else {
|
||||
const sectionButtons = section
|
||||
.querySelectorAll('.filter-btn');
|
||||
sectionButtons.forEach(function(btn) {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
this.classList.add('active');
|
||||
activeFilters[category] = kind;
|
||||
}
|
||||
|
||||
displayDishes();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function isValidCombo() {
|
||||
const hasSoup = selectedDishes.soup !== null;
|
||||
const hasMainCourse = selectedDishes['main-course'] !== null;
|
||||
const hasSalad = selectedDishes.salad !== null;
|
||||
const hasDrink = selectedDishes.drink !== null;
|
||||
|
||||
if (hasSoup && hasMainCourse && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasSoup && hasMainCourse && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasSoup && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasMainCourse && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasMainCourse && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function restoreSelection() {
|
||||
Object.keys(selectedDishes).forEach(function(category) {
|
||||
const dish = selectedDishes[category];
|
||||
if (dish) {
|
||||
const card = document.querySelector(
|
||||
`.dish-card[data-dish="${dish.keyword}"]`
|
||||
);
|
||||
if (card) {
|
||||
card.classList.add('selected');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM загружен, начинаем инициализацию');
|
||||
loadDishes();
|
||||
setupFilters();
|
||||
});
|
||||
448
labs/lab-10/js/order.js
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
const API_URL = 'https://edu.std-900.ist.mospolytech.ru/labs/api';
|
||||
const API_KEY = '358a63a5-52ae-4ab0-800b-90f75ce5a5c2';
|
||||
|
||||
let dishes = [];
|
||||
let orderDishes = {
|
||||
soup: null,
|
||||
'main-course': null,
|
||||
salad: null,
|
||||
drink: null,
|
||||
dessert: null
|
||||
};
|
||||
|
||||
function loadDishes() {
|
||||
console.log('Загрузка блюд для страницы заказа...');
|
||||
|
||||
fetch(API_URL + '/dishes')
|
||||
.then(function(response) {
|
||||
console.log('Ответ получен:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка загрузки данных: ' + response.status);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Данные загружены:', data.length, 'блюд');
|
||||
dishes = data;
|
||||
loadOrderFromLocalStorage();
|
||||
displayOrderDishes();
|
||||
updateOrderSummary();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при загрузке блюд:', error);
|
||||
alert('Не удалось загрузить данные о блюдах. Проверьте подключение.');
|
||||
});
|
||||
}
|
||||
|
||||
function loadOrderFromLocalStorage() {
|
||||
const savedOrder = localStorage.getItem('selectedDishes');
|
||||
|
||||
if (!savedOrder) {
|
||||
console.log('Сохраненный заказ не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const order = JSON.parse(savedOrder);
|
||||
console.log('Загружен заказ из localStorage:', order);
|
||||
|
||||
Object.keys(order).forEach(function(category) {
|
||||
const dishId = order[category];
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === dishId;
|
||||
});
|
||||
|
||||
if (dish) {
|
||||
orderDishes[category] = dish;
|
||||
console.log('Найдено блюдо:', dish.name, 'для категории:', category);
|
||||
} else {
|
||||
console.warn('Блюдо с ID', dishId, 'не найдено для категории:', category);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Ошибка при загрузке заказа:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function displayOrderDishes() {
|
||||
const orderDishesContainer = document.getElementById('order-dishes');
|
||||
const emptyOrderMessage = document.getElementById('empty-order');
|
||||
|
||||
if (!orderDishesContainer || !emptyOrderMessage) {
|
||||
console.error('Не найдены контейнеры для отображения заказа');
|
||||
return;
|
||||
}
|
||||
|
||||
const hasAnyDish = Object.values(orderDishes).some(function(dish) {
|
||||
return dish !== null;
|
||||
});
|
||||
|
||||
console.log('Есть блюда для отображения:', hasAnyDish);
|
||||
|
||||
if (!hasAnyDish) {
|
||||
orderDishesContainer.innerHTML = '';
|
||||
emptyOrderMessage.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
emptyOrderMessage.classList.add('hidden');
|
||||
orderDishesContainer.innerHTML = '';
|
||||
|
||||
Object.keys(orderDishes).forEach(function(category) {
|
||||
const dish = orderDishes[category];
|
||||
if (dish) {
|
||||
const dishCard = createOrderDishCard(dish);
|
||||
orderDishesContainer.insertAdjacentHTML('beforeend', dishCard);
|
||||
}
|
||||
});
|
||||
|
||||
addRemoveHandlers();
|
||||
}
|
||||
|
||||
function createOrderDishCard(dish) {
|
||||
return `
|
||||
<div class="dish-card" data-dish-id="${dish.id}">
|
||||
<img src="${dish.image}" alt="${dish.name}">
|
||||
<p class="dish-price">${dish.price} руб.</p>
|
||||
<p class="dish-name">${dish.name}</p>
|
||||
<p class="dish-weight">${dish.count}</p>
|
||||
<button class="remove-dish-btn">Удалить</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function addRemoveHandlers() {
|
||||
const removeButtons = document.querySelectorAll('.remove-dish-btn');
|
||||
|
||||
removeButtons.forEach(function(button) {
|
||||
button.addEventListener('click', function(event) {
|
||||
event.stopPropagation();
|
||||
const card = this.closest('.dish-card');
|
||||
const dishId = parseInt(card.dataset.dishId);
|
||||
removeDishFromOrder(dishId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeDishFromOrder(dishId) {
|
||||
console.log('Удаление блюда с ID:', dishId);
|
||||
|
||||
Object.keys(orderDishes).forEach(function(category) {
|
||||
if (orderDishes[category] && orderDishes[category].id === dishId) {
|
||||
orderDishes[category] = null;
|
||||
}
|
||||
});
|
||||
|
||||
saveOrderToLocalStorage();
|
||||
displayOrderDishes();
|
||||
updateOrderSummary();
|
||||
}
|
||||
|
||||
function saveOrderToLocalStorage() {
|
||||
const order = {};
|
||||
|
||||
Object.keys(orderDishes).forEach(function(category) {
|
||||
if (orderDishes[category]) {
|
||||
order[category] = orderDishes[category].id;
|
||||
}
|
||||
});
|
||||
|
||||
localStorage.setItem('selectedDishes', JSON.stringify(order));
|
||||
console.log('Заказ сохранен в localStorage:', order);
|
||||
}
|
||||
|
||||
function updateOrderSummary() {
|
||||
const orderSummary = document.getElementById('order-summary');
|
||||
|
||||
if (!orderSummary) {
|
||||
console.error('Не найден контейнер для сводки заказа');
|
||||
return;
|
||||
}
|
||||
|
||||
const hasSelection = Object.values(orderDishes).some(function(dish) {
|
||||
return dish !== null;
|
||||
});
|
||||
|
||||
if (!hasSelection) {
|
||||
orderSummary.innerHTML =
|
||||
'<p class="empty-order">Ничего не выбрано</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
let summaryHTML = '';
|
||||
let totalPrice = 0;
|
||||
|
||||
if (orderDishes.soup) {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Суп</h3>
|
||||
<div class="order-item">
|
||||
<span>${orderDishes.soup.name}</span>
|
||||
<span>${orderDishes.soup.price} руб.</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
totalPrice += orderDishes.soup.price;
|
||||
} else {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Суп</h3>
|
||||
<p class="not-selected">Блюдо не выбрано</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if (orderDishes['main-course']) {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Главное блюдо</h3>
|
||||
<div class="order-item">
|
||||
<span>${orderDishes['main-course'].name}</span>
|
||||
<span>${orderDishes['main-course'].price} руб.</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
totalPrice += orderDishes['main-course'].price;
|
||||
} else {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Главное блюдо</h3>
|
||||
<p class="not-selected">Блюдо не выбрано</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if (orderDishes.salad) {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Салат</h3>
|
||||
<div class="order-item">
|
||||
<span>${orderDishes.salad.name}</span>
|
||||
<span>${orderDishes.salad.price} руб.</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
totalPrice += orderDishes.salad.price;
|
||||
} else {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Салат</h3>
|
||||
<p class="not-selected">Блюдо не выбрано</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if (orderDishes.drink) {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Напиток</h3>
|
||||
<div class="order-item">
|
||||
<span>${orderDishes.drink.name}</span>
|
||||
<span>${orderDishes.drink.price} руб.</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
totalPrice += orderDishes.drink.price;
|
||||
} else {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Напиток</h3>
|
||||
<p class="not-selected">Напиток не выбран</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if (orderDishes.dessert) {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Десерт</h3>
|
||||
<div class="order-item">
|
||||
<span>${orderDishes.dessert.name}</span>
|
||||
<span>${orderDishes.dessert.price} руб.</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
totalPrice += orderDishes.dessert.price;
|
||||
} else {
|
||||
summaryHTML += `
|
||||
<div class="order-category">
|
||||
<h3>Десерт</h3>
|
||||
<p class="not-selected">Десерт не выбран</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
summaryHTML += `
|
||||
<div class="order-total">
|
||||
<h3>Стоимость заказа</h3>
|
||||
<p class="total-price">${totalPrice} руб.</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
orderSummary.innerHTML = summaryHTML;
|
||||
}
|
||||
|
||||
function isValidCombo() {
|
||||
const hasSoup = orderDishes.soup !== null;
|
||||
const hasMainCourse = orderDishes['main-course'] !== null;
|
||||
const hasSalad = orderDishes.salad !== null;
|
||||
const hasDrink = orderDishes.drink !== null;
|
||||
|
||||
if (hasSoup && hasMainCourse && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasSoup && hasMainCourse && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasSoup && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasMainCourse && hasSalad && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasMainCourse && hasDrink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getValidationMessage() {
|
||||
const hasSoup = orderDishes.soup !== null;
|
||||
const hasMainCourse = orderDishes['main-course'] !== null;
|
||||
const hasSalad = orderDishes.salad !== null;
|
||||
const hasDrink = orderDishes.drink !== null;
|
||||
|
||||
if (!hasSoup && !hasMainCourse && !hasSalad && !hasDrink) {
|
||||
return 'Ничего не выбрано. Выберите блюда для заказа';
|
||||
}
|
||||
|
||||
if (!hasDrink) {
|
||||
return 'Выберите напиток';
|
||||
}
|
||||
|
||||
if (hasSoup && !hasMainCourse && !hasSalad) {
|
||||
return 'Выберите главное блюдо/салат/стартер';
|
||||
}
|
||||
|
||||
if (hasSalad && !hasSoup && !hasMainCourse) {
|
||||
return 'Выберите суп или главное блюдо';
|
||||
}
|
||||
|
||||
if (!hasMainCourse && !hasSoup && (hasDrink || orderDishes.dessert)) {
|
||||
return 'Выберите главное блюдо';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function setupFormSubmission() {
|
||||
const form = document.getElementById('order-form');
|
||||
|
||||
if (!form) {
|
||||
console.error('Форма заказа не найдена');
|
||||
return;
|
||||
}
|
||||
|
||||
form.addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
console.log('Отправка формы заказа');
|
||||
|
||||
if (!isValidCombo()) {
|
||||
const message = getValidationMessage();
|
||||
alert(message);
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData(form);
|
||||
const orderData = {
|
||||
full_name: formData.get('full_name'),
|
||||
email: formData.get('email'),
|
||||
subscribe: formData.get('subscribe') === '1' ? 1 : 0,
|
||||
phone: formData.get('phone'),
|
||||
delivery_address: formData.get('delivery_address'),
|
||||
delivery_type: formData.get('delivery_type'),
|
||||
delivery_time: formData.get('delivery_time') || '',
|
||||
comment: formData.get('comment') || ''
|
||||
};
|
||||
|
||||
if (orderDishes.soup) {
|
||||
orderData.soup_id = orderDishes.soup.id;
|
||||
}
|
||||
if (orderDishes['main-course']) {
|
||||
orderData.main_course_id = orderDishes['main-course'].id;
|
||||
}
|
||||
if (orderDishes.salad) {
|
||||
orderData.salad_id = orderDishes.salad.id;
|
||||
}
|
||||
if (orderDishes.drink) {
|
||||
orderData.drink_id = orderDishes.drink.id;
|
||||
}
|
||||
if (orderDishes.dessert) {
|
||||
orderData.dessert_id = orderDishes.dessert.id;
|
||||
}
|
||||
|
||||
console.log('Данные заказа:', orderData);
|
||||
sendOrder(orderData);
|
||||
});
|
||||
}
|
||||
|
||||
function sendOrder(orderData) {
|
||||
const url = API_URL + '/orders?api_key=' + API_KEY;
|
||||
|
||||
console.log('Отправка заказа на сервер:', url);
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(orderData)
|
||||
})
|
||||
.then(function(response) {
|
||||
console.log('Ответ от сервера:', response.status);
|
||||
if (!response.ok) {
|
||||
return response.json().then(function(errorData) {
|
||||
throw new Error(errorData.error ||
|
||||
'Ошибка при оформлении заказа');
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Заказ успешно создан:', data);
|
||||
alert('Заказ успешно оформлен! Номер заказа: ' + data.id);
|
||||
localStorage.removeItem('selectedDishes');
|
||||
window.location.href = '../templates/orders.html';
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при отправке заказа:', error);
|
||||
alert('Не удалось оформить заказ: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function setupResetButton() {
|
||||
const resetButton = document.getElementById('reset-button');
|
||||
|
||||
if (!resetButton) {
|
||||
console.error('Кнопка сброса не найдена');
|
||||
return;
|
||||
}
|
||||
|
||||
resetButton.addEventListener('click', function() {
|
||||
const form = document.getElementById('order-form');
|
||||
form.reset();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM загружен для страницы заказа');
|
||||
loadDishes();
|
||||
setupFormSubmission();
|
||||
setupResetButton();
|
||||
});
|
||||
584
labs/lab-10/js/orders.js
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
const API_URL = 'https://edu.std-900.ist.mospolytech.ru/labs/api';
|
||||
const API_KEY = '358a63a5-52ae-4ab0-800b-90f75ce5a5c2';
|
||||
|
||||
let orders = [];
|
||||
let dishes = [];
|
||||
let currentOrderId = null;
|
||||
|
||||
function loadOrders() {
|
||||
console.log('Загрузка заказов...');
|
||||
|
||||
const url = API_URL + '/orders?api_key=' + API_KEY;
|
||||
|
||||
fetch(url)
|
||||
.then(function(response) {
|
||||
console.log('Ответ получен:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка загрузки заказов: ' + response.status);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Заказы загружены:', data.length);
|
||||
orders = data;
|
||||
sortOrders();
|
||||
return loadDishes();
|
||||
})
|
||||
.then(function() {
|
||||
displayOrders();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при загрузке заказов:', error);
|
||||
showNotification('Не удалось загрузить заказы: ' + error.message,
|
||||
'error');
|
||||
});
|
||||
}
|
||||
|
||||
function loadDishes() {
|
||||
console.log('Загрузка блюд...');
|
||||
|
||||
return fetch(API_URL + '/dishes')
|
||||
.then(function(response) {
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка загрузки блюд');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Блюда загружены:', data.length);
|
||||
dishes = data;
|
||||
});
|
||||
}
|
||||
|
||||
function sortOrders() {
|
||||
orders.sort(function(a, b) {
|
||||
const dateA = new Date(a.created_at);
|
||||
const dateB = new Date(b.created_at);
|
||||
return dateB - dateA;
|
||||
});
|
||||
}
|
||||
|
||||
function displayOrders() {
|
||||
const ordersList = document.getElementById('orders-list');
|
||||
const emptyOrders = document.getElementById('empty-orders');
|
||||
|
||||
if (!ordersList || !emptyOrders) {
|
||||
console.error('Не найдены контейнеры для отображения заказов');
|
||||
return;
|
||||
}
|
||||
|
||||
if (orders.length === 0) {
|
||||
ordersList.innerHTML = '';
|
||||
emptyOrders.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
emptyOrders.classList.add('hidden');
|
||||
ordersList.innerHTML = '';
|
||||
|
||||
orders.forEach(function(order, index) {
|
||||
const orderCard = createOrderCard(order, index + 1);
|
||||
ordersList.insertAdjacentHTML('beforeend', orderCard);
|
||||
});
|
||||
|
||||
addOrderActionHandlers();
|
||||
}
|
||||
|
||||
function createOrderCard(order, number) {
|
||||
const date = formatDate(order.created_at);
|
||||
const composition = getOrderComposition(order);
|
||||
const price = calculateOrderPrice(order);
|
||||
const deliveryTime = getDeliveryTime(order);
|
||||
|
||||
return `
|
||||
<div class="order-card" data-order-id="${order.id}">
|
||||
<div class="order-card-header">
|
||||
<span class="order-number">Заказ №${number}</span>
|
||||
<span class="order-date">${date}</span>
|
||||
</div>
|
||||
<div class="order-card-body">
|
||||
<div class="order-info">
|
||||
<p><strong>Состав:</strong> ${composition}</p>
|
||||
<p><strong>Стоимость:</strong> ${price} руб.</p>
|
||||
<p><strong>Доставка:</strong> ${deliveryTime}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-card-footer">
|
||||
<button class="order-btn order-btn-view" data-action="view">Подробнее</button>
|
||||
<button class="order-btn order-btn-edit" data-action="edit">Редактировать</button>
|
||||
<button class="order-btn order-btn-delete" data-action="delete">Удалить</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const year = date.getFullYear();
|
||||
return day + '.' + month + '.' + year;
|
||||
}
|
||||
|
||||
function formatDateTime(dateString) {
|
||||
const date = new Date(dateString);
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const year = date.getFullYear();
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return day + '.' + month + '.' + year + ' ' + hours + ':' + minutes;
|
||||
}
|
||||
|
||||
function getOrderComposition(order) {
|
||||
const dishNames = [];
|
||||
|
||||
if (order.soup_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.soup_id;
|
||||
});
|
||||
if (dish) {
|
||||
dishNames.push(dish.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.main_course_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.main_course_id;
|
||||
});
|
||||
if (dish) {
|
||||
dishNames.push(dish.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.salad_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.salad_id;
|
||||
});
|
||||
if (dish) {
|
||||
dishNames.push(dish.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.drink_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.drink_id;
|
||||
});
|
||||
if (dish) {
|
||||
dishNames.push(dish.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (order.dessert_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.dessert_id;
|
||||
});
|
||||
if (dish) {
|
||||
dishNames.push(dish.name);
|
||||
}
|
||||
}
|
||||
|
||||
return dishNames.join(', ');
|
||||
}
|
||||
|
||||
function calculateOrderPrice(order) {
|
||||
let total = 0;
|
||||
|
||||
if (order.soup_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.soup_id;
|
||||
});
|
||||
if (dish) {
|
||||
total += dish.price;
|
||||
}
|
||||
}
|
||||
|
||||
if (order.main_course_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.main_course_id;
|
||||
});
|
||||
if (dish) {
|
||||
total += dish.price;
|
||||
}
|
||||
}
|
||||
|
||||
if (order.salad_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.salad_id;
|
||||
});
|
||||
if (dish) {
|
||||
total += dish.price;
|
||||
}
|
||||
}
|
||||
|
||||
if (order.drink_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.drink_id;
|
||||
});
|
||||
if (dish) {
|
||||
total += dish.price;
|
||||
}
|
||||
}
|
||||
|
||||
if (order.dessert_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.dessert_id;
|
||||
});
|
||||
if (dish) {
|
||||
total += dish.price;
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
function getDeliveryTime(order) {
|
||||
if (order.delivery_type === 'by_time') {
|
||||
return order.delivery_time;
|
||||
}
|
||||
return 'Как можно скорее (с 7:00 до 23:00)';
|
||||
}
|
||||
|
||||
function addOrderActionHandlers() {
|
||||
const buttons = document.querySelectorAll('.order-btn');
|
||||
|
||||
buttons.forEach(function(button) {
|
||||
button.addEventListener('click', function() {
|
||||
const action = this.dataset.action;
|
||||
const card = this.closest('.order-card');
|
||||
const orderId = parseInt(card.dataset.orderId);
|
||||
|
||||
const order = orders.find(function(o) {
|
||||
return o.id === orderId;
|
||||
});
|
||||
|
||||
if (!order) {
|
||||
console.error('Заказ не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === 'view') {
|
||||
showViewModal(order);
|
||||
} else if (action === 'edit') {
|
||||
showEditModal(order);
|
||||
} else if (action === 'delete') {
|
||||
showDeleteModal(order);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showViewModal(order) {
|
||||
const modal = document.getElementById('view-modal');
|
||||
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateTime = formatDateTime(order.created_at);
|
||||
const deliveryTime = getDeliveryTime(order);
|
||||
|
||||
document.getElementById('view-date').textContent = dateTime;
|
||||
document.getElementById('view-name').textContent = order.full_name;
|
||||
document.getElementById('view-address').textContent =
|
||||
order.delivery_address;
|
||||
document.getElementById('view-time').textContent = deliveryTime;
|
||||
document.getElementById('view-phone').textContent = order.phone;
|
||||
document.getElementById('view-email').textContent = order.email;
|
||||
|
||||
const commentSection = document.getElementById('view-comment-section');
|
||||
const commentElement = document.getElementById('view-comment');
|
||||
if (order.comment && order.comment.trim() !== '') {
|
||||
commentSection.style.display = 'block';
|
||||
commentElement.textContent = order.comment;
|
||||
} else {
|
||||
commentSection.style.display = 'none';
|
||||
}
|
||||
|
||||
const itemsContainer = document.getElementById('view-items');
|
||||
itemsContainer.innerHTML = '';
|
||||
|
||||
const orderItems = getOrderItems(order);
|
||||
orderItems.forEach(function(item) {
|
||||
const itemHTML = `
|
||||
<div class="modal-order-item">
|
||||
<span>${item.label}</span>
|
||||
<span>${item.name} (${item.price}Р)</span>
|
||||
</div>
|
||||
`;
|
||||
itemsContainer.insertAdjacentHTML('beforeend', itemHTML);
|
||||
});
|
||||
|
||||
const total = calculateOrderPrice(order);
|
||||
document.getElementById('view-total').textContent = total + 'Р';
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function showEditModal(order) {
|
||||
const modal = document.getElementById('edit-modal');
|
||||
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentOrderId = order.id;
|
||||
|
||||
const dateTime = formatDateTime(order.created_at);
|
||||
document.getElementById('edit-created-date').textContent = dateTime;
|
||||
|
||||
document.getElementById('edit-name').value = order.full_name;
|
||||
document.getElementById('edit-email').value = order.email;
|
||||
document.getElementById('edit-phone').value = order.phone;
|
||||
document.getElementById('edit-address').value = order.delivery_address;
|
||||
document.getElementById('edit-time').value = order.delivery_time || '';
|
||||
document.getElementById('edit-comment').value = order.comment || '';
|
||||
|
||||
const itemsContainer = document.getElementById('edit-items');
|
||||
itemsContainer.innerHTML = '';
|
||||
|
||||
const orderItems = getOrderItems(order);
|
||||
orderItems.forEach(function(item) {
|
||||
const itemHTML = `
|
||||
<div class="modal-order-item">
|
||||
<span>${item.label}</span>
|
||||
<span>${item.name} (${item.price}Р)</span>
|
||||
</div>
|
||||
`;
|
||||
itemsContainer.insertAdjacentHTML('beforeend', itemHTML);
|
||||
});
|
||||
|
||||
const total = calculateOrderPrice(order);
|
||||
document.getElementById('edit-total').textContent = total + 'Р';
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function showDeleteModal(order) {
|
||||
const modal = document.getElementById('delete-modal');
|
||||
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentOrderId = order.id;
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function getOrderItems(order) {
|
||||
const items = [];
|
||||
|
||||
if (order.main_course_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.main_course_id;
|
||||
});
|
||||
if (dish) {
|
||||
items.push({
|
||||
label: 'Основное блюдо',
|
||||
name: dish.name,
|
||||
price: dish.price
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (order.drink_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.drink_id;
|
||||
});
|
||||
if (dish) {
|
||||
items.push({
|
||||
label: 'Напиток',
|
||||
name: dish.name,
|
||||
price: dish.price
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (order.dessert_id) {
|
||||
const dish = dishes.find(function(d) {
|
||||
return d.id === order.dessert_id;
|
||||
});
|
||||
if (dish) {
|
||||
items.push({
|
||||
label: 'Десерт',
|
||||
name: dish.name,
|
||||
price: dish.price
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
currentOrderId = null;
|
||||
}
|
||||
|
||||
function setupModalHandlers() {
|
||||
const closeButtons = document.querySelectorAll('.modal-close');
|
||||
closeButtons.forEach(function(button) {
|
||||
button.addEventListener('click', function() {
|
||||
const modal = this.closest('.modal');
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
currentOrderId = null;
|
||||
});
|
||||
});
|
||||
|
||||
const viewOkButton = document.getElementById('view-modal-ok');
|
||||
if (viewOkButton) {
|
||||
viewOkButton.addEventListener('click', function() {
|
||||
closeModal('view-modal');
|
||||
});
|
||||
}
|
||||
|
||||
const editCancelButton = document.getElementById('edit-modal-cancel');
|
||||
if (editCancelButton) {
|
||||
editCancelButton.addEventListener('click', function() {
|
||||
closeModal('edit-modal');
|
||||
});
|
||||
}
|
||||
|
||||
const editSaveButton = document.getElementById('edit-modal-save');
|
||||
if (editSaveButton) {
|
||||
editSaveButton.addEventListener('click', function() {
|
||||
saveOrderEdit();
|
||||
});
|
||||
}
|
||||
|
||||
const deleteCancelButton = document.getElementById('delete-modal-cancel');
|
||||
if (deleteCancelButton) {
|
||||
deleteCancelButton.addEventListener('click', function() {
|
||||
closeModal('delete-modal');
|
||||
});
|
||||
}
|
||||
|
||||
const deleteConfirmButton =
|
||||
document.getElementById('delete-modal-confirm');
|
||||
if (deleteConfirmButton) {
|
||||
deleteConfirmButton.addEventListener('click', function() {
|
||||
deleteOrder();
|
||||
});
|
||||
}
|
||||
|
||||
const modals = document.querySelectorAll('.modal');
|
||||
modals.forEach(function(modal) {
|
||||
modal.addEventListener('click', function(event) {
|
||||
if (event.target === modal) {
|
||||
modal.classList.add('hidden');
|
||||
currentOrderId = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveOrderEdit() {
|
||||
const form = document.getElementById('edit-form');
|
||||
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData(form);
|
||||
const updateData = {
|
||||
full_name: formData.get('full_name'),
|
||||
email: formData.get('email'),
|
||||
phone: formData.get('phone'),
|
||||
delivery_address: formData.get('delivery_address'),
|
||||
delivery_type: formData.get('delivery_time') ? 'by_time' : 'now',
|
||||
delivery_time: formData.get('delivery_time') || '',
|
||||
comment: formData.get('comment') || ''
|
||||
};
|
||||
|
||||
const url = API_URL + '/orders/' + currentOrderId + '?api_key=' + API_KEY;
|
||||
|
||||
console.log('Отправка изменений заказа:', updateData);
|
||||
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(updateData)
|
||||
})
|
||||
.then(function(response) {
|
||||
console.log('Ответ от сервера:', response.status);
|
||||
if (!response.ok) {
|
||||
return response.json().then(function(errorData) {
|
||||
throw new Error(errorData.error ||
|
||||
'Ошибка при редактировании заказа');
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Заказ успешно изменен:', data);
|
||||
closeModal('edit-modal');
|
||||
showNotification('Заказ успешно изменён', 'success');
|
||||
loadOrders();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при редактировании заказа:', error);
|
||||
showNotification('Не удалось изменить заказ: ' + error.message,
|
||||
'error');
|
||||
});
|
||||
}
|
||||
|
||||
function deleteOrder() {
|
||||
const url = API_URL + '/orders/' + currentOrderId + '?api_key=' + API_KEY;
|
||||
|
||||
console.log('Удаление заказа:', currentOrderId);
|
||||
|
||||
fetch(url, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(function(response) {
|
||||
console.log('Ответ от сервера:', response.status);
|
||||
if (!response.ok) {
|
||||
return response.json().then(function(errorData) {
|
||||
throw new Error(errorData.error ||
|
||||
'Ошибка при удалении заказа');
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
console.log('Заказ успешно удален:', data);
|
||||
closeModal('delete-modal');
|
||||
showNotification('Заказ успешно удалён', 'success');
|
||||
loadOrders();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Ошибка при удалении заказа:', error);
|
||||
showNotification('Не удалось удалить заказ: ' + error.message,
|
||||
'error');
|
||||
});
|
||||
}
|
||||
|
||||
function showNotification(message, type) {
|
||||
const notification = document.getElementById('notification');
|
||||
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
notification.textContent = message;
|
||||
notification.className = 'notification notification-' + type;
|
||||
notification.classList.remove('hidden');
|
||||
|
||||
setTimeout(function() {
|
||||
notification.classList.add('hidden');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM загружен для страницы заказов');
|
||||
setupModalHandlers();
|
||||
loadOrders();
|
||||
});
|
||||
236
labs/lab-10/other/course-landing/index.html
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="robots" content="noindex">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
|
||||
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
<link rel="stylesheet" href="static/css/styles.css">
|
||||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@1,400;1,700&display=swap" rel="stylesheet">
|
||||
|
||||
<title>Основы веб-технологий</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg fixed-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">
|
||||
<img class="img-fluid" src="static/img/logo_187_50.png">
|
||||
</a>
|
||||
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon">
|
||||
<i class="fa fa-bars"></i>
|
||||
</span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="collapsibleNavId">
|
||||
<ul class="navbar-nav mt-2 mt-lg-0">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">О курсе <span class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Программа</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Технологии</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid banner">
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 py-5 my-auto">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 offset-lg-1">
|
||||
<h1 class="pb-3">Основы веб-технологий</h1>
|
||||
<p class="pb-3">
|
||||
Курс знакомит слушателей с основами технологий HTML, CSS и JavaScript.
|
||||
</p>
|
||||
<div class="btn btn-lg btn-outline-secondary mb-3">Подробнее</div>
|
||||
<div class="btn btn-lg btn-secondary mb-3">Написать нам</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 p-5 d-flex justify-content-center align-items-center">
|
||||
<img class="img-fluid" src="static/img/web-dev.svg">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="call-to-action py-5">
|
||||
<div class="container text-center w-50">
|
||||
<h2 class="pb-3">Заложите прочный фундамент будущей карьеры!</h2>
|
||||
<div class="heading-line mx-auto"></div>
|
||||
<p class="py-3">
|
||||
Только знакомитесь с веб-технологиями? Интернет на сегодняшний день развивается феноменально быстро. Поэтому выбрав
|
||||
веб-технологии в качестве своей специализации, можете быть уверены — достойное будущее Вам гарантировано.
|
||||
</p>
|
||||
<button class="btn btn-lg btn-primary">Записаться на курс</button>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="program">
|
||||
<div class="text-center py-5">
|
||||
<h2 class="pb-3">Программа курса</h2>
|
||||
<div class="heading-line mx-auto"></div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-code"></i>
|
||||
<h4 class="py-3">Development tools</h4>
|
||||
<p class="pb-3">Visual Studio Code, Emmet, Postman.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-html5"></i>
|
||||
<h4 class="py-3">HTML</h4>
|
||||
<p class="pb-3">Основы языка разметки HTML5.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-css3"></i>
|
||||
<h4 class="py-3">CSS</h4>
|
||||
<p class="pb-3">Основы каскадных таблиц стилей.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-code"></i>
|
||||
<h4 class="py-3">HTTP</h4>
|
||||
<p class="pb-3">Структура протокола HTTP.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-code"></i>
|
||||
<h4 class="py-3">JavaScript</h4>
|
||||
<p class="pb-3">Язык программирования JavaScript, формат JSON.</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<i class="fa fa-code"></i>
|
||||
<h4 class="py-3">Twitter Bootstrap</h4>
|
||||
<p class="pb-3">Фреймворк для вёрстки Twitter Bootstrap.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="techologies container-fluid bg-light">
|
||||
<div class="text-center py-5">
|
||||
<h2 class="pb-3">Технологии</h2>
|
||||
<div class="heading-line mx-auto"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 p-0">
|
||||
<img class="img-fluid" src="static/img/html.jpg">
|
||||
</div>
|
||||
<div class="col-md-3 p-0 d-flex align-items-center justify-content-center dark">
|
||||
<div class="text-center">
|
||||
<h4 class="py-3">HTML & CSS</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 p-0">
|
||||
<img class="img-fluid" src="static/img/js.jpg">
|
||||
</div>
|
||||
<div class="col-md-3 p-0 d-flex align-items-center justify-content-center dark">
|
||||
<h4 class="py-3">JavaScript</h4>
|
||||
</div>
|
||||
<div class="col-md-3 p-0 d-flex align-items-center justify-content-center dark">
|
||||
<h4 class="py-3">Twitter Bootstrap</h4>
|
||||
</div>
|
||||
<div class="col-md-3 p-0">
|
||||
<img class="img-fluid" src="static/img/bootstrap.jpg">
|
||||
</div>
|
||||
<div class="col-md-3 p-0 d-flex align-items-center justify-content-center dark">
|
||||
<h4 class="py-3">HTTP</h4>
|
||||
</div>
|
||||
<div class="col-md-3 p-0">
|
||||
<img class="img-fluid" src="static/img/http.jpg">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="contacts">
|
||||
<div class="container">
|
||||
<div class="text-center py-5">
|
||||
<h2 class="pb-3">Контакты</h2>
|
||||
<div class="heading-line mx-auto"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-5">
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2243.6754304915576!2d37.70853691593169!3d55.781508730561015!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x46b54ad610abc8a5%3A0xc42703145fe53a8d!2sMoskovskiy%20Politekhnicheskiy%20Universitet!5e0!3m2!1sen!2sru!4v1589880984408!5m2!1sen!2sru"
|
||||
width="100%" height="450" frameborder="0" style="border:0;" allowfullscreen="" aria-hidden="false"
|
||||
tabindex="0"></iframe>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-5">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="email">Электронная почта</label>
|
||||
<input class="form-control" type="email" id="email" placeholder="Введите адрес электронной почты">
|
||||
<small id="emailHelp" class="form-text text-muted">Мы не передём введённые данные третьим лицам.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Имя</label>
|
||||
<input class="form-control" type="text" id="name" placeholder="Введите имя">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message">Сообщение</label>
|
||||
<textarea class="form-control" name="message" id="message" cols="30" rows="10" placeholder="Введите сообщение"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-outline-secondary">Отправить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="text-center py-5">
|
||||
<a href="#">
|
||||
<img src="static/img/logo_187_50_white.png">
|
||||
</a>
|
||||
</div>
|
||||
<div class="container mb-3">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 offset-lg-2 text-center">
|
||||
<p>
|
||||
Московский политехнический университет является крупнейшей образовательной организацией, готовящей квалифицированных
|
||||
специалистов для производства.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="copyright text-center py-3 border-top text-muted">
|
||||
<p>Московский политех © 2020</p>
|
||||
<p>Vector disign by <a href="https://www.vecteezy.com/">Vecteezy</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
|
||||
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
|
||||
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
|
||||
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
95
labs/lab-10/other/course-landing/static/css/styles.css
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
body {
|
||||
font-family: "Montserrat", sans-serif;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
h4, h5, h6 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #011627;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: #011627;
|
||||
}
|
||||
|
||||
.banner {
|
||||
background-color: #eaecf0;
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
background-color: transparent !important;
|
||||
border-color: #011627;
|
||||
color: #011627;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.btn-outline-secondary:hover {
|
||||
color: #011627 !important;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
border-radius: 0;
|
||||
background-color: #011627;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
color: #83F3ED;
|
||||
background-color: #011627;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
border-radius: 0;
|
||||
background-color: #83F3ED;
|
||||
color: #011627;
|
||||
border-color: #83F3ED !important;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #011627;
|
||||
color: #83F3ED;
|
||||
}
|
||||
|
||||
.call-to-action {
|
||||
background-color: #011627;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.heading-line {
|
||||
height: 3px;
|
||||
width: 200px;
|
||||
background-color: #83F3ED;
|
||||
}
|
||||
|
||||
.program i {
|
||||
font-size: 2rem;
|
||||
color: #83F3ED;
|
||||
}
|
||||
|
||||
.techologies .img-fluid {
|
||||
height: 300px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.dark {
|
||||
background-color: #011627;
|
||||
color: #83F3ED;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: #011627;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.call-to-action .container {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
BIN
labs/lab-10/other/course-landing/static/img/bootstrap.jpg
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
labs/lab-10/other/course-landing/static/img/css.jpg
Normal file
|
After Width: | Height: | Size: 509 KiB |
BIN
labs/lab-10/other/course-landing/static/img/html.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
labs/lab-10/other/course-landing/static/img/http.jpg
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
labs/lab-10/other/course-landing/static/img/js.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
labs/lab-10/other/course-landing/static/img/logo_187_50.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
258
labs/lab-10/other/course-landing/static/img/web-dev.svg
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="335.986px" height="235.19px" viewBox="0 0 335.986 235.19" enable-background="new 0 0 335.986 235.19"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect fill="#EAECF0" width="335.986" height="235.19"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M263.858,182.53V59.717
|
||||
c0-1.817-1.592-3.302-3.539-3.302H78.123c-1.946,0-3.539,1.484-3.539,3.302V182.53H263.858z"/>
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="80.825" cy="61.891" r="1.975"/>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="94.095" cy="61.891" r="1.977"/>
|
||||
</g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="87.46" cy="61.891" r="1.978"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M242.043,66.6H103.695
|
||||
c-0.778,0-1.411-0.636-1.411-1.412v-1.694c0-0.776,0.633-1.412,1.411-1.412h138.348c0.776,0,1.413,0.636,1.413,1.412v1.694
|
||||
C243.456,65.964,242.819,66.6,242.043,66.6z"/>
|
||||
<rect x="78.729" y="72.01" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="180.983" height="106.975"/>
|
||||
<rect x="175.95" y="96.681" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.813" height="31.102"/>
|
||||
<rect x="132.328" y="96.677" fill="#84DBFF" width="34.374" height="31.102"/>
|
||||
<g>
|
||||
|
||||
<rect x="132.328" y="137.48" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="34.374" height="31.104"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="86.601" y="96.677" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
|
||||
<rect x="86.601" y="102.178" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
|
||||
<rect x="86.601" y="107.678" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
|
||||
<rect x="86.601" y="113.178" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.428"/>
|
||||
|
||||
<rect x="86.601" y="124.181" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
|
||||
<rect x="86.601" y="129.682" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
|
||||
<rect x="86.601" y="135.182" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.428"/>
|
||||
|
||||
<rect x="86.601" y="146.184" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="37.378" height="1.427"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="175.95" y="135.337" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.397" height="1.428"/>
|
||||
|
||||
<rect x="175.95" y="140.839" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.397" height="1.427"/>
|
||||
|
||||
<rect x="175.95" y="151.84" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.397" height="1.427"/>
|
||||
|
||||
<rect x="175.95" y="157.34" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.397" height="1.428"/>
|
||||
|
||||
<rect x="175.95" y="168.342" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="76.397" height="1.427"/>
|
||||
</g>
|
||||
<rect x="213.496" y="78.265" fill="#EDEEF1" width="37.579" height="9.376"/>
|
||||
<rect x="85.678" y="80.131" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="120.849" height="5.645"/>
|
||||
<rect x="242.611" y="78.265" fill="#84DBFF" width="9.846" height="9.376"/>
|
||||
<path fill="#FFFFFF" d="M249.938,83.256c0.745-0.748,0.745-1.958,0-2.705c-0.749-0.748-1.959-0.748-2.709,0
|
||||
c-0.644,0.645-0.731,1.636-0.261,2.377l-1.834,1.836c-0.162,0.16-0.162,0.428,0,0.59l0,0c0.162,0.163,0.428,0.163,0.593,0
|
||||
l1.83-1.834C248.3,83.989,249.29,83.902,249.938,83.256z M247.687,82.8c-0.494-0.495-0.494-1.298,0-1.792
|
||||
c0.494-0.495,1.295-0.495,1.792,0c0.496,0.494,0.496,1.297,0,1.792C248.981,83.296,248.181,83.296,247.687,82.8z"/>
|
||||
<rect x="185.989" y="204.798" fill="#34525C" width="15.758" height="2.061"/>
|
||||
<rect x="158.999" y="209.427" fill="#34525C" width="50.626" height="2.061"/>
|
||||
<g>
|
||||
|
||||
<rect x="135.566" y="194.098" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="9.713" height="9.711"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="276.949" y="123.143" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="9.713" height="9.711"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="190.935" y="33.9" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="9.713" height="9.711"/>
|
||||
</g>
|
||||
<path fill="#84DBFF" d="M155.145,151.843l-9.795-5.655c-0.199-0.116-0.428-0.176-0.655-0.176c-0.725,0-1.314,0.59-1.314,1.313v11.31
|
||||
c0,0.726,0.59,1.313,1.314,1.313c0.228,0,0.456-0.06,0.655-0.177l9.795-5.654c0.409-0.238,0.655-0.664,0.656-1.137
|
||||
C155.801,152.506,155.554,152.08,155.145,151.843z"/>
|
||||
<g>
|
||||
<rect x="25.071" y="108.357" fill="#34525C" width="1.291" height="3.869"/>
|
||||
<rect x="27.019" y="113.299" fill="#34525C" width="3.869" height="1.29"/>
|
||||
<rect x="25.071" y="115.66" fill="#34525C" width="1.291" height="3.869"/>
|
||||
<rect x="20.546" y="113.299" fill="#34525C" width="3.87" height="1.29"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="213.712" y="191.465" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="215.658" y="196.406" fill="#34525C" width="3.869" height="1.29"/>
|
||||
<rect x="213.712" y="198.768" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="209.186" y="196.406" fill="#34525C" width="3.87" height="1.29"/>
|
||||
</g>
|
||||
<rect x="29.301" y="81.933" fill="#34525C" width="28.443" height="2.061"/>
|
||||
<rect x="29.301" y="91.288" fill="#34525C" width="20.718" height="2.061"/>
|
||||
<rect x="20.078" y="86.562" fill="#34525C" width="44.994" height="2.061"/>
|
||||
<rect x="22.48" y="205.786" fill="#34525C" width="28.444" height="2.061"/>
|
||||
<rect x="22.48" y="215.142" fill="#34525C" width="20.719" height="2.061"/>
|
||||
<rect x="13.257" y="210.415" fill="#34525C" width="44.995" height="2.061"/>
|
||||
<g>
|
||||
<rect x="311.243" y="122.834" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="313.189" y="127.774" fill="#34525C" width="3.869" height="1.29"/>
|
||||
<rect x="311.243" y="130.137" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="306.717" y="127.774" fill="#34525C" width="3.87" height="1.29"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="177.72" y="18.91" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="179.666" y="23.851" fill="#34525C" width="3.869" height="1.29"/>
|
||||
<rect x="177.72" y="26.213" fill="#34525C" width="1.29" height="3.869"/>
|
||||
<rect x="173.193" y="23.851" fill="#34525C" width="3.869" height="1.29"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M67.533,42.965
|
||||
c0,13.767-11.189,24.956-24.955,24.956c-13.769,0-24.96-11.189-24.96-24.956c0-13.768,11.191-24.956,24.96-24.956
|
||||
c4.496,0,8.743,1.219,12.413,3.317c-4.894,8.656-12.413,21.639-12.413,21.639l24.52-4.545
|
||||
C67.403,39.902,67.533,41.437,67.533,42.965z"/>
|
||||
<path fill="#84DBFF" d="M74.043,33.808l-24.521,4.545c0,0,7.521-13.025,12.414-21.635C68.183,20.259,72.73,26.465,74.043,33.808z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M318.2,220.982v-69.191
|
||||
c0-1.817-1.591-3.302-3.538-3.302H231.65c-1.946,0-3.539,1.484-3.539,3.302v69.191H318.2z"/>
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="234.352" cy="153.965" r="1.975"/>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="247.622" cy="153.965" r="1.977"/>
|
||||
</g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="240.987" cy="153.965" r="1.978"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M306.386,158.674h-49.163
|
||||
c-0.777,0-1.412-0.636-1.412-1.412v-1.694c0-0.776,0.635-1.412,1.412-1.412h49.163c0.777,0,1.414,0.636,1.414,1.412v1.694
|
||||
C307.8,158.038,307.163,158.674,306.386,158.674z"/>
|
||||
<rect x="232.257" y="164.084" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="81.799" height="53.353"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M125.845,195.015v-69.191
|
||||
c0-1.817-1.592-3.302-3.539-3.302H39.293c-1.945,0-3.538,1.484-3.538,3.302v69.191H125.845z"/>
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="41.996" cy="127.997" r="1.974"/>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="55.266" cy="127.997" r="1.977"/>
|
||||
</g>
|
||||
<circle fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" cx="48.631" cy="127.997" r="1.978"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M114.03,132.706H64.867
|
||||
c-0.778,0-1.412-0.636-1.412-1.412V129.6c0-0.776,0.634-1.412,1.412-1.412h49.163c0.776,0,1.413,0.636,1.413,1.412v1.694
|
||||
C115.443,132.07,114.807,132.706,114.03,132.706z"/>
|
||||
<rect x="39.9" y="138.116" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="81.799" height="53.353"/>
|
||||
<g>
|
||||
<path fill="#84DBFF" d="M297.452,207.153h-8.418c-0.206,0-0.358-0.153-0.358-0.358v-30.511c0-0.205,0.152-0.359,0.358-0.359h8.418
|
||||
c0.204,0,0.357,0.154,0.357,0.359v30.511C297.81,206.982,297.656,207.153,297.452,207.153z"/>
|
||||
<path fill="#84DBFF" d="M284.067,207.153h-8.419c-0.205,0-0.358-0.153-0.358-0.358v-21.548c0-0.204,0.153-0.357,0.358-0.357h8.419
|
||||
c0.205,0,0.357,0.153,0.357,0.357v21.548C284.407,206.982,284.253,207.153,284.067,207.153z"/>
|
||||
<path fill="#84DBFF" d="M270.664,207.153h-8.42c-0.204,0-0.356-0.153-0.356-0.358v-32.458c0-0.205,0.152-0.358,0.356-0.358h8.42
|
||||
c0.204,0,0.357,0.153,0.357,0.358v32.458C271.021,206.982,270.868,207.153,270.664,207.153z"/>
|
||||
<path fill="#84DBFF" d="M257.276,207.153h-8.416c-0.205,0-0.359-0.153-0.359-0.358v-15.999c0-0.205,0.154-0.357,0.359-0.357h8.416
|
||||
c0.205,0,0.357,0.152,0.357,0.357v15.999C257.634,206.982,257.465,207.153,257.276,207.153z"/>
|
||||
</g>
|
||||
<rect x="242.559" y="207.526" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="61.194" height="3.968"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M60.032,155.895c0,0.168-0.014,0.336-0.028,0.503
|
||||
c-1.301,0.504-2.839,0.798-4.477,0.798c-1.635,0-3.174-0.294-4.475-0.798c-0.014-0.167-0.029-0.335-0.029-0.503
|
||||
c0-2.616,2.016-4.728,4.504-4.728C58.018,151.167,60.032,153.278,60.032,155.895z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M57.375,147.88c0,1.272-0.826,2.825-1.848,2.825
|
||||
c-1.02,0-1.846-1.553-1.846-2.825c0-1.273,0.826-1.776,1.846-1.776C56.549,146.104,57.375,146.606,57.375,147.88z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M60.032,169.672c0,0.168-0.014,0.335-0.028,0.503
|
||||
c-1.301,0.504-2.839,0.798-4.477,0.798c-1.635,0-3.174-0.294-4.475-0.798c-0.014-0.168-0.029-0.335-0.029-0.503
|
||||
c0-2.616,2.016-4.728,4.504-4.728C58.018,164.944,60.032,167.056,60.032,169.672z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M57.375,161.657c0,1.272-0.826,2.825-1.848,2.825
|
||||
c-1.02,0-1.846-1.553-1.846-2.825c0-1.273,0.826-1.776,1.846-1.776C56.549,159.881,57.375,160.384,57.375,161.657z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M60.032,183.449c0,0.167-0.014,0.335-0.028,0.503
|
||||
c-1.301,0.504-2.839,0.798-4.477,0.798c-1.635,0-3.174-0.294-4.475-0.798c-0.014-0.168-0.029-0.336-0.029-0.503
|
||||
c0-2.616,2.016-4.729,4.504-4.729C58.018,178.721,60.032,180.833,60.032,183.449z"/>
|
||||
<path fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" d="M57.375,175.435c0,1.272-0.826,2.825-1.848,2.825
|
||||
c-1.02,0-1.846-1.553-1.846-2.825c0-1.273,0.826-1.776,1.846-1.776C56.549,173.658,57.375,174.161,57.375,175.435z"/>
|
||||
<rect x="63.473" y="147.152" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="29.947" height="8.979"/>
|
||||
<rect x="64.97" y="148.649" fill="#84DBFF" width="21.456" height="5.972"/>
|
||||
<rect x="63.473" y="160.93" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="29.947" height="8.979"/>
|
||||
<rect x="64.97" y="162.426" fill="#84DBFF" width="13.204" height="5.973"/>
|
||||
<rect x="63.473" y="174.707" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="29.947" height="8.979"/>
|
||||
<rect x="64.97" y="176.203" fill="#84DBFF" width="17.009" height="5.973"/>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" points="280.581,23.927 290.509,24.71
|
||||
295.438,18.087 302.198,20.458 301.539,29.101 307.919,35.934 317.438,34.079 319.842,41.836 311.042,47.13 311.872,56.425
|
||||
318.749,62.126 315.956,68.486 309.43,66.071 300.237,72.755 301.65,82.764 294.271,85.321 289.666,77.497 280.159,77.789
|
||||
275.234,85.448 267.93,82.239 269.295,73.022 262.492,65.118 254.202,67.728 251.253,60.186 258.759,56.323 259.251,46.045
|
||||
252.081,39.997 255.04,33.255 264.145,35.921 270.925,28.614 268.91,19.471 276.021,17.007 "/>
|
||||
<path fill="#84DBFF" d="M272.043,45.773c-3.309,7.352-0.029,16.019,7.33,19.332c7.367,3.316,16.029,0.026,19.34-7.322
|
||||
c3.316-7.366,0.036-16.031-7.33-19.349C284.022,35.121,275.36,38.409,272.043,45.773z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" points="223.943,19.476 228.381,17.479
|
||||
228.935,13.483 232.389,12.913 234.137,16.771 238.474,18.197 242.115,15.169 244.967,17.927 242.441,22.26 244.979,26.047
|
||||
249.265,26.873 249.561,30.255 246.198,30.752 243.83,35.774 246.784,39.729 244.226,42.557 240.416,40.288 236.412,42.646
|
||||
236.102,47.081 232.218,47.423 230.639,43.154 225.87,41.366 222.932,44.431 219.898,41.894 222.206,38.477 220.003,33.959
|
||||
215.512,33.051 215.195,29.469 219.721,28.474 220.909,23.75 217.899,20.307 220.367,17.582 "/>
|
||||
<path fill="#84DBFF" d="M225.419,30.839c0.31,3.925,3.749,6.867,7.679,6.559c3.934-0.311,6.872-3.754,6.564-7.679
|
||||
c-0.31-3.934-3.75-6.875-7.684-6.565C228.049,23.462,225.109,26.904,225.419,30.839z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
|
||||
<rect x="92.973" y="16.838" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="65.744" height="8.657"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="108.618" y="18.787" fill="#84DBFF" width="47.907" height="4.762"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
|
||||
<rect x="92.973" y="32.815" fill="#FFFFFF" stroke="#34525C" stroke-width="2" stroke-miterlimit="10" width="65.744" height="8.657"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="125.844" y="34.764" fill="#84DBFF" width="30.681" height="4.762"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#84DBFF" d="M83.343,215.663c0,2.938,2.678,5.319,5.98,5.319h29.559c2.317,0,4.197-1.675,4.197-3.736
|
||||
c0-1.945-1.668-3.523-3.799-3.699c0.01-0.148,0.023-0.283,0.023-0.433c0-4.347-3.961-7.862-8.846-7.862
|
||||
c-0.445,0-0.883,0.038-1.312,0.098c-2-2.311-5.127-3.795-8.647-3.795c-2.845,0-5.426,0.967-7.366,2.55
|
||||
c-1.947,1.582-3.239,3.78-3.501,6.253C86.328,210.357,83.343,212.726,83.343,215.663z"/>
|
||||
<path fill="#84DBFF" d="M319.875,108.323c0,2.938-2.678,5.319-5.98,5.319h-29.559c-2.317,0-4.197-1.675-4.197-3.736
|
||||
c0-1.945,1.668-3.523,3.799-3.699c-0.01-0.148-0.023-0.283-0.023-0.433c0-4.347,3.961-7.862,8.846-7.862
|
||||
c0.444,0,0.883,0.038,1.312,0.098c2-2.311,5.127-3.795,8.647-3.795c2.845,0,5.425,0.967,7.365,2.55
|
||||
c1.947,1.582,3.24,3.78,3.502,6.253C316.89,103.018,319.875,105.386,319.875,108.323z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
15
labs/lab-10/other/Вопросы для подготовки к защите ЛР №10.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Bootstrap
|
||||
1. Что такое Bootstrap? Для каких целей он используется?
|
||||
2. Какие основные компоненты входят в состав фреймворка Bootstrap?
|
||||
3. В чем заключается принцип адаптивного дизайна в Bootstrap? Как реализуется мобильная версия сайта?
|
||||
4. Опишите структуру HTML-документа, использующего Bootstrap. Какие обязательные элементы должны присутствовать?
|
||||
5. Что такое сетка Bootstrap? Сколько колонок она содержит и какие классы используются для их создания?
|
||||
6. Какие возможности предоставляет Bootstrap для стилизации текста? Приведите примеры классов.
|
||||
7. Расскажите о компонентах навигации в Bootstrap. Как создать простую панель навигации?
|
||||
8. Как реализовать модальные окна в Bootstrap? Какие параметры необходимо указать для настройки модального окна?
|
||||
9. Как добавить формы в проект с использованием Bootstrap? Какие классы применяются для оформления полей ввода?
|
||||
10. Какие компоненты Bootstrap вы использовали в своей работе? Почему именно они были выбраны?
|
||||
11. Каким образом можно изменить стандартные стили компонентов Bootstrap? Можно ли использовать свои собственные CSS-правила поверх Bootstrap?
|
||||
12. Как реализуются всплывающие подсказки (tooltips) и выпадающие списки (dropdowns) в Bootstrap?
|
||||
13. Как работает система медиа-запросов в Bootstrap? Приведите пример использования различных размеров экрана.
|
||||
|
||||
27
labs/lab-10/other/Задание - Лабораторная работа 10.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Лабораторная работа № 10. Вёрстка адаптивного лендинга для компании доставки еды
|
||||
---
|
||||
|
||||
При помощи фреймворка Bootstrap 5 создайте адаптивный лендинг (landing page) для компании, доставляющей бизнес-ланчи.
|
||||
|
||||
## Порядок выполнения
|
||||
|
||||
Добавьте к вашему проекту страницу лендинга. На этой странице должны присутствовать следующие элементы:
|
||||
|
||||
- Блок с названием компании, её кратким описанием и картинкой для привлечения внимания (hero section).
|
||||
- Блок с перечислением основных особенностей/преимуществ компании.
|
||||
- Блок с призывом к действию (CTA, call to action) и ссылкой для перехода на страницу "Собрать ланч".
|
||||
- Блок с формой для обратной связи и контактами.
|
||||
|
||||
Дизайн страницы формируется на усмотрение студента с учётом обязательных блоков, перечисленных выше. Идеи для оформления лендинга можно посмотреть [здесь](https://www.landingfolio.com/).
|
||||
|
||||
- Вёрстка лендинга должна быть выполнена с использованием фреймворка Bootstrap 5.
|
||||
- Допускается определение кастомных стилей в случае, если требуемого результата нельзя добиться средствами Bootstrap.
|
||||
- Обязательно использование системы сеток Bootstrap (Bootstrap Grid System).
|
||||
- Страница должна корректно отображаться на мобильных устройствах (смартфонах, планшетах).
|
||||
- Вёрстка должна быть выполнена студентом самостоятельно (использование готовых шаблонов лендингов не допускается).
|
||||
|
||||
### Материалы для изучения
|
||||
[Документация Bootstrap](https://getbootstrap.com/)
|
||||
[Bootstrap Grid System](https://www.tutorialrepublic.com/twitter-bootstrap-tutorial/bootstrap-grid-system.php)
|
||||
[Отзывчивый дизайн [MDN]](https://developer.mozilla.org/ru/docs/Learn/CSS/CSS_layout/Responsive_Design)
|
||||
[Что такое лендинг и чем он отличается от сайта?](https://www.insales.ru/page/landing)
|
||||
298
labs/lab-10/styles/menu.css
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
.combo-section {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.combo-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.combo-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.combo-dessert {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.combo-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.combo-icon {
|
||||
font-size: 50px;
|
||||
display: block;
|
||||
margin: 0 0 8px 0;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.combo-item:hover .combo-icon {
|
||||
transform: translateY(-5px) scale(1.1);
|
||||
}
|
||||
|
||||
.combo-item p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.combo-note-inline {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.combo-note {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.filter-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
background-color: white;
|
||||
border: 2px solid #2d5016;
|
||||
color: #2d5016;
|
||||
padding: 10px 20px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.filter-btn:hover {
|
||||
background-color: #f1eee9;
|
||||
}
|
||||
|
||||
.filter-btn.active {
|
||||
background-color: #2d5016;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dishes-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dish-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 30px 40px;
|
||||
border-radius: 35px;
|
||||
cursor: pointer;
|
||||
filter: drop-shadow(17px 19px 24px rgba(0, 0, 0, 0.13));
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.dish-card.selected {
|
||||
border: 3px solid #2d5016;
|
||||
background-color: #f0f7ec;
|
||||
}
|
||||
|
||||
.dish-card.selected button {
|
||||
background-color: #2d5016;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dish-card:hover {
|
||||
border: 2px solid tomato;
|
||||
}
|
||||
|
||||
.dish-card:hover button {
|
||||
background-color: tomato;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dish-card img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 12 / 9;
|
||||
object-fit: cover;
|
||||
border-radius: 35px;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.dish-price {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.dish-name {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.dish-weight {
|
||||
color: #888;
|
||||
margin: 0 0 10px 0;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.dish-card button {
|
||||
background-color: #f1eee9;
|
||||
border: none;
|
||||
padding: 10px 30px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.remove-dish-btn {
|
||||
background-color: tomato;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.remove-dish-btn:hover {
|
||||
background-color: #ff4500;
|
||||
}
|
||||
|
||||
.order-panel {
|
||||
position: sticky;
|
||||
bottom: 20px;
|
||||
background-color: white;
|
||||
padding: 20px 40px;
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.order-panel.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.order-panel-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.order-panel-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.order-panel-label {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.order-panel-price {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #2d5016;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.order-panel-button {
|
||||
background-color: #2d5016;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
padding: 15px 40px;
|
||||
border-radius: 10px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.order-panel-button:hover {
|
||||
background-color: #3d6020;
|
||||
}
|
||||
|
||||
.order-panel-button.disabled {
|
||||
background-color: #ccc;
|
||||
color: #888;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.combo-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.dishes-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
nav {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.about-company img {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.order-panel-content {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.combo-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.dishes-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.order-panel {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.order-panel-content {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.order-panel-button {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
266
labs/lab-10/styles/order.css
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
.empty-order-message {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.empty-order-message.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.empty-order-message p {
|
||||
font-size: 18px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.empty-order-message a {
|
||||
color: #2d5016;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.order-form {
|
||||
margin: 0 auto;
|
||||
padding: 40px 60px;
|
||||
max-width: 1200px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.order-form h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#order-summary {
|
||||
background-color: #f9f9f9;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.empty-order {
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.order-category {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.order-category h3 {
|
||||
font-size: 20px;
|
||||
color: #2d5016;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.order-item span:first-child {
|
||||
font-weight: 600;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
max-width: 70%;
|
||||
}
|
||||
|
||||
.order-item span:last-child {
|
||||
color: #2d5016;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.not-selected {
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.order-total {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 2px solid #2d5016;
|
||||
}
|
||||
|
||||
.order-total h3 {
|
||||
font-size: 22px;
|
||||
color: #2d5016;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #2d5016;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.order-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.order-section h3 {
|
||||
font-size: 22px;
|
||||
color: #2d5016;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.customer-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.customer-section h3 {
|
||||
font-size: 22px;
|
||||
color: #2d5016;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.order-form label {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
margin: 0 0 8px 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.order-form select,
|
||||
.order-form input[type="text"],
|
||||
.order-form input[type="email"],
|
||||
.order-form input[type="tel"],
|
||||
.order-form input[type="time"],
|
||||
.order-form textarea {
|
||||
width: 100%;
|
||||
padding: 12px 15px;
|
||||
margin: 0 0 20px 0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.order-form select {
|
||||
cursor: pointer;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.order-form textarea {
|
||||
height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.checkbox-group input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 0 10px 0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox-group label {
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.radio-group > label {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.radio-group > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.radio-group input[type="radio"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 0 10px 0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.radio-group input[type="radio"] + label {
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.form-buttons button {
|
||||
flex: 1;
|
||||
padding: 15px 30px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.form-buttons button[type="button"] {
|
||||
background-color: #f1eee9;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-buttons button[type="button"]:hover {
|
||||
background-color: #e0ddd8;
|
||||
}
|
||||
|
||||
.form-buttons button[type="submit"] {
|
||||
background-color: #2d5016;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.form-buttons button[type="submit"]:hover {
|
||||
background-color: #3d6020;
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin: -15px 0 20px 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.form-container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.form-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
414
labs/lab-10/styles/orders.css
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
.orders-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.empty-orders-message {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.empty-orders-message.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.empty-orders-message p {
|
||||
font-size: 18px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.empty-orders-message a {
|
||||
color: #2d5016;
|
||||
text-decoration: underline;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: white;
|
||||
border-radius: 15px;
|
||||
padding: 25px 30px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.order-card:hover {
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.order-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 2px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-number {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #2d5016;
|
||||
}
|
||||
|
||||
.order-date {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.order-card-body {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.order-info p {
|
||||
margin: 10px 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.order-info strong {
|
||||
color: #2d5016;
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.order-btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.order-btn-view {
|
||||
background-color: #2d5016;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.order-btn-view:hover {
|
||||
background-color: #3d6020;
|
||||
}
|
||||
|
||||
.order-btn-edit {
|
||||
background-color: #f1eee9;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-btn-edit:hover {
|
||||
background-color: #e0ddd8;
|
||||
}
|
||||
|
||||
.order-btn-delete {
|
||||
background-color: tomato;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.order-btn-delete:hover {
|
||||
background-color: #ff4500;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: white;
|
||||
border-radius: 15px;
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.modal-content-small {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px 30px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.modal-section {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.modal-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modal-section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.modal-label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.modal-value {
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.modal-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.modal-info-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.modal-order-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.modal-order-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.modal-order-item span:first-child {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.modal-total {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.modal-delete-text {
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-body form label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
margin: 0 0 8px 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.modal-body form input[type="text"],
|
||||
.modal-body form input[type="email"],
|
||||
.modal-body form input[type="tel"],
|
||||
.modal-body form input[type="time"],
|
||||
.modal-body form textarea {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
margin: 0 0 15px 0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.modal-body form textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding: 20px 30px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
padding: 10px 30px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.modal-btn-ok {
|
||||
background-color: #e8e8e8;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.modal-btn-ok:hover {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.modal-btn-cancel {
|
||||
background-color: #e8e8e8;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.modal-btn-cancel:hover {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.modal-btn-save {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-btn-save:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
.modal-btn-delete {
|
||||
background-color: #c62828;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-btn-delete:hover {
|
||||
background-color: #b71c1c;
|
||||
}
|
||||
|
||||
.notification {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
padding: 15px 25px;
|
||||
border-radius: 10px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
||||
z-index: 2000;
|
||||
animation: slideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.notification.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.notification-success {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.notification-error {
|
||||
background-color: #c62828;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(400px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.modal-content {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.order-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.modal-header {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 15px 20px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.notification {
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
1403
labs/lab-10/styles/styles.css
Normal file
89
labs/lab-10/templates/about.html
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>О нас - ЭкоЛанч</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main style="padding-top: 80px;">
|
||||
<div class="container py-5">
|
||||
<section class="bg-light p-5 rounded">
|
||||
<h2 class="text-center mb-4">О нашей компании</h2>
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<p>ЭкоЛанч - это команда профессионалов, которые заботятся о вашем здоровье и комфорте. Мы готовим вкусные и полезные блюда из свежих продуктов и доставляем их прямо в ваш офис.</p>
|
||||
<p>Наша миссия - сделать здоровое питание доступным и удобным для каждого занятого человека в Москве.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-title">Контактная информация</div>
|
||||
<div class="footer-info">
|
||||
<div class="footer-row">
|
||||
<span>Телефон: <a href="tel:+79993737737">+7 (999) 373-77-37</a></span>
|
||||
<span>Email: <a href="mailto:egor@deev.space">egor@deev.space</a></span>
|
||||
</div>
|
||||
<div class="footer-row">
|
||||
<span>Адрес: г. Москва, ул. Михалковская, д. 7</span>
|
||||
<span>Режим работы: Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
<div class="footer-row footer-copyright">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
89
labs/lab-10/templates/delivery.html
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>Доставка - ЭкоЛанч</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main style="padding-top: 80px;">
|
||||
<div class="container py-5">
|
||||
<section class="bg-light p-5 rounded">
|
||||
<h2 class="text-center mb-4">Условия доставки</h2>
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<p>Мы осуществляем доставку здоровых бизнес-ланчей по всей Москве. Доставка производится с понедельника по пятницу с 7:00 до 23:00.</p>
|
||||
<p>Доставка по всей Москве в пределах МКАД осуществляется бесплатно!</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-title">Контактная информация</div>
|
||||
<div class="footer-info">
|
||||
<div class="footer-row">
|
||||
<span>Телефон: <a href="tel:+79993737737">+7 (999) 373-77-37</a></span>
|
||||
<span>Email: <a href="mailto:egor@deev.space">egor@deev.space</a></span>
|
||||
</div>
|
||||
<div class="footer-row">
|
||||
<span>Адрес: г. Москва, ул. Михалковская, д. 7</span>
|
||||
<span>Режим работы: Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
<div class="footer-row footer-copyright">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
240
labs/lab-10/templates/menu.html
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>Собрать ланч - ЭкоЛанч</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main style="padding-top: 80px;">
|
||||
<div class="container py-5">
|
||||
<section class="combo-section">
|
||||
<h2 class="text-center mb-4">Доступные для заказа варианты ланча</h2>
|
||||
<div class="combo-grid">
|
||||
<div class="combo-card">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍲</span>
|
||||
<p>Суп</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍽️</span>
|
||||
<p>Главное блюдо</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥗</span>
|
||||
<p>Салат</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥤</span>
|
||||
<p>Напиток</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="combo-card">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍲</span>
|
||||
<p>Суп</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍽️</span>
|
||||
<p>Главное блюдо</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥤</span>
|
||||
<p>Напиток</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="combo-card">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍲</span>
|
||||
<p>Суп</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥗</span>
|
||||
<p>Салат</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥤</span>
|
||||
<p>Напиток</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="combo-card">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍽️</span>
|
||||
<p>Главное блюдо</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥗</span>
|
||||
<p>Салат</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥤</span>
|
||||
<p>Напиток</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="combo-card">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍽️</span>
|
||||
<p>Главное блюдо</p>
|
||||
</div>
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🥤</span>
|
||||
<p>Напиток</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="combo-card combo-dessert">
|
||||
<div class="combo-item">
|
||||
<span class="combo-icon">🍰</span>
|
||||
<p>Десерт</p>
|
||||
</div>
|
||||
<p class="combo-note-inline">(Можно добавить к любому заказу)</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="combo-note">Десерты можно добавить к любому варианту ланча</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-5">
|
||||
<div class="section-header">
|
||||
<h2>Супы</h2>
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-btn" data-kind="fish">Рыбный</button>
|
||||
<button class="filter-btn" data-kind="meat">Мясной</button>
|
||||
<button class="filter-btn" data-kind="veg">Вегетарианский</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dishes-grid" id="soup-section"></div>
|
||||
</section>
|
||||
|
||||
<section class="mb-5">
|
||||
<div class="section-header">
|
||||
<h2>Главные блюда</h2>
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-btn" data-kind="fish">Рыбное</button>
|
||||
<button class="filter-btn" data-kind="meat">Мясное</button>
|
||||
<button class="filter-btn" data-kind="veg">Вегетарианское</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dishes-grid" id="main-course-section"></div>
|
||||
</section>
|
||||
|
||||
<section class="mb-5">
|
||||
<div class="section-header">
|
||||
<h2>Салаты и стартеры</h2>
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-btn" data-kind="fish">Рыбный</button>
|
||||
<button class="filter-btn" data-kind="meat">Мясной</button>
|
||||
<button class="filter-btn" data-kind="veg">Вегетарианский</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dishes-grid" id="salad-section"></div>
|
||||
</section>
|
||||
|
||||
<section class="mb-5">
|
||||
<div class="section-header">
|
||||
<h2>Напитки</h2>
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-btn" data-kind="cold">Холодный</button>
|
||||
<button class="filter-btn" data-kind="hot">Горячий</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dishes-grid" id="drink-section"></div>
|
||||
</section>
|
||||
|
||||
<section class="mb-5">
|
||||
<div class="section-header">
|
||||
<h2>Десерты</h2>
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-btn" data-kind="small">Маленькая порция</button>
|
||||
<button class="filter-btn" data-kind="medium">Средняя порция</button>
|
||||
<button class="filter-btn" data-kind="large">Большая порция</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dishes-grid" id="dessert-section"></div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="order-panel" class="order-panel hidden">
|
||||
<div class="order-panel-content">
|
||||
<div class="order-panel-info">
|
||||
<p class="order-panel-label">Ваш заказ:</p>
|
||||
<p class="order-panel-price" id="order-panel-price">0 руб.</p>
|
||||
</div>
|
||||
<a href="order.html" id="order-panel-link" class="order-panel-button disabled">
|
||||
Перейти к оформлению
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-title">Контактная информация</div>
|
||||
<div class="footer-info">
|
||||
<div class="footer-row">
|
||||
<span>Телефон: <a href="tel:+79993737737">+7 (999) 373-77-37</a></span>
|
||||
<span>Email: <a href="mailto:egor@deev.space">egor@deev.space</a></span>
|
||||
</div>
|
||||
<div class="footer-row">
|
||||
<span>Адрес: г. Москва, ул. Михалковская, д. 7</span>
|
||||
<span>Режим работы: Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
<div class="footer-row footer-copyright">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="../js/menu.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
148
labs/lab-10/templates/order.html
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>Оформить заказ - ЭкоЛанч</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main style="padding-top: 80px;">
|
||||
<div class="container py-5">
|
||||
<section class="mb-5">
|
||||
<h2 class="text-center mb-4">Состав заказа</h2>
|
||||
<div id="order-dishes" class="dishes-grid"></div>
|
||||
<div id="empty-order" class="empty-order-message hidden">
|
||||
<p>Ничего не выбрано. Чтобы добавить блюда в заказ, перейдите на страницу <a href="menu.html">Собрать ланч</a>.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="order-form">
|
||||
<h2>Оформление заказа</h2>
|
||||
<form id="order-form" method="POST">
|
||||
<div class="form-container">
|
||||
<div class="order-section">
|
||||
<h3>Ваш заказ</h3>
|
||||
<div id="order-summary">
|
||||
<p class="empty-order">Ничего не выбрано</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="customer-section">
|
||||
<h3>Данные для доставки</h3>
|
||||
|
||||
<label for="name">Имя</label>
|
||||
<input type="text" name="full_name" id="name" placeholder="Введите ваше имя" required>
|
||||
|
||||
<label for="email">Email</label>
|
||||
<input type="email" name="email" id="email" placeholder="Введите ваш email" required>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" name="subscribe" id="subscribe" value="1" checked>
|
||||
<label for="subscribe">Подписаться на рассылку</label>
|
||||
</div>
|
||||
|
||||
<label for="phone">Телефон</label>
|
||||
<input type="tel" name="phone" id="phone" placeholder="Введите ваш телефон" required>
|
||||
|
||||
<label for="address">Адрес доставки</label>
|
||||
<input type="text" name="delivery_address" id="address" placeholder="Введите адрес доставки" required>
|
||||
<small class="form-hint">Доставка осуществляется только по Москве</small>
|
||||
|
||||
<div class="radio-group">
|
||||
<label>Время доставки</label>
|
||||
<div>
|
||||
<input type="radio" name="delivery_type" id="asap" value="now" required checked>
|
||||
<label for="asap">Как можно скорее</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" name="delivery_type" id="specific-time" value="by_time" required>
|
||||
<label for="specific-time">К определенному времени</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label for="delivery-time">Указать время</label>
|
||||
<input type="time" name="delivery_time" id="delivery-time" min="07:00" max="23:00" step="300">
|
||||
<small class="form-hint">Доступное время доставки с 7:00 до 23:00</small>
|
||||
|
||||
<label for="comment">Комментарий к заказу</label>
|
||||
<textarea name="comment" id="comment" placeholder="Введите комментарий к заказу"></textarea>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="button" id="reset-button">Сбросить</button>
|
||||
<button type="submit">Отправить заказ</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-title">Контактная информация</div>
|
||||
<div class="footer-info">
|
||||
<div class="footer-row">
|
||||
<span>Телефон: <a href="tel:+79993737737">+7 (999) 373-77-37</a></span>
|
||||
<span>Email: <a href="mailto:egor@deev.space">egor@deev.space</a></span>
|
||||
</div>
|
||||
<div class="footer-row">
|
||||
<span>Адрес: г. Москва, ул. Михалковская, д. 7</span>
|
||||
<span>Режим работы: Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
<div class="footer-row footer-copyright">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="../js/order.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
218
labs/lab-10/templates/orders.html
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="https://deev.space/media/favicon.ico" type="image/x-icon">
|
||||
<title>Мои заказы - ЭкоЛанч</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
<span class="brand-icon">🌿</span>
|
||||
<span class="brand-eco">Эко</span><span class="brand-lunch">Ланч</span>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../index.html">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="menu.html">Собрать ланч</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="order.html">Оформить заказ</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="orders.html">Мои заказы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="delivery.html">Доставка</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="about.html">О нас</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main style="padding-top: 80px;">
|
||||
<div class="container py-5">
|
||||
<section>
|
||||
<h2 class="text-center mb-4">Мои заказы</h2>
|
||||
<div id="orders-list" class="orders-list"></div>
|
||||
<div id="empty-orders" class="empty-orders-message hidden">
|
||||
<p>У вас пока нет оформленных заказов. Перейдите на страницу <a href="menu.html">Собрать ланч</a>, чтобы создать первый заказ.</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="view-modal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Просмотр заказа</h3>
|
||||
<span class="modal-close">×</span>
|
||||
</div>
|
||||
<div class="modal-body" id="view-modal-body">
|
||||
<div class="modal-section">
|
||||
<p class="modal-label">Дата оформления</p>
|
||||
<p class="modal-value" id="view-date"></p>
|
||||
</div>
|
||||
|
||||
<div class="modal-section">
|
||||
<h4 class="modal-section-title">Доставка</h4>
|
||||
<div class="modal-info-grid">
|
||||
<div class="modal-info-item">
|
||||
<span class="modal-label">Имя получателя</span>
|
||||
<span class="modal-value" id="view-name"></span>
|
||||
</div>
|
||||
<div class="modal-info-item">
|
||||
<span class="modal-label">Адрес доставки</span>
|
||||
<span class="modal-value" id="view-address"></span>
|
||||
</div>
|
||||
<div class="modal-info-item">
|
||||
<span class="modal-label">Время доставки</span>
|
||||
<span class="modal-value" id="view-time"></span>
|
||||
</div>
|
||||
<div class="modal-info-item">
|
||||
<span class="modal-label">Телефон</span>
|
||||
<span class="modal-value" id="view-phone"></span>
|
||||
</div>
|
||||
<div class="modal-info-item">
|
||||
<span class="modal-label">Email</span>
|
||||
<span class="modal-value" id="view-email"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-section" id="view-comment-section">
|
||||
<h4 class="modal-section-title">Комментарий</h4>
|
||||
<p class="modal-value" id="view-comment"></p>
|
||||
</div>
|
||||
|
||||
<div class="modal-section">
|
||||
<h4 class="modal-section-title">Состав заказа</h4>
|
||||
<div class="modal-order-items" id="view-items"></div>
|
||||
<div class="modal-total">
|
||||
<span>Стоимость:</span>
|
||||
<span id="view-total"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="modal-btn modal-btn-ok" id="view-modal-ok">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-modal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Редактирование заказа</h3>
|
||||
<span class="modal-close">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-section">
|
||||
<p class="modal-label">Дата оформления</p>
|
||||
<p class="modal-value" id="edit-created-date"></p>
|
||||
</div>
|
||||
|
||||
<form id="edit-form">
|
||||
<div class="modal-section">
|
||||
<h4 class="modal-section-title">Доставка</h4>
|
||||
|
||||
<label for="edit-name">Имя получателя</label>
|
||||
<input type="text" id="edit-name" name="full_name" required>
|
||||
|
||||
<label for="edit-address">Адрес доставки</label>
|
||||
<input type="text" id="edit-address" name="delivery_address" required>
|
||||
|
||||
<label for="edit-time">Время доставки</label>
|
||||
<input type="time" id="edit-time" name="delivery_time" min="07:00" max="23:00" step="300">
|
||||
|
||||
<label for="edit-phone">Телефон</label>
|
||||
<input type="tel" id="edit-phone" name="phone" required>
|
||||
|
||||
<label for="edit-email">Email</label>
|
||||
<input type="email" id="edit-email" name="email" required>
|
||||
</div>
|
||||
|
||||
<div class="modal-section">
|
||||
<h4 class="modal-section-title">Комментарий</h4>
|
||||
<textarea id="edit-comment" name="comment" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="modal-section">
|
||||
<h4 class="modal-section-title">Состав заказа</h4>
|
||||
<div class="modal-order-items" id="edit-items"></div>
|
||||
<div class="modal-total">
|
||||
<span>Стоимость:</span>
|
||||
<span id="edit-total"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="modal-btn modal-btn-cancel" id="edit-modal-cancel">Отмена</button>
|
||||
<button class="modal-btn modal-btn-save" id="edit-modal-save">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="delete-modal" class="modal hidden">
|
||||
<div class="modal-content modal-content-small">
|
||||
<div class="modal-header">
|
||||
<h3>Удаление заказа</h3>
|
||||
<span class="modal-close">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="modal-delete-text">Вы уверены, что хотите удалить заказ?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="modal-btn modal-btn-cancel" id="delete-modal-cancel">Отмена</button>
|
||||
<button class="modal-btn modal-btn-delete" id="delete-modal-confirm">Да</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="notification" class="notification hidden"></div>
|
||||
|
||||
<footer id="contacts" class="footer py-4">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-title">Контактная информация</div>
|
||||
<div class="footer-info">
|
||||
<div class="footer-row">
|
||||
<span>Телефон: <a href="tel:+79993737737">+7 (999) 373-77-37</a></span>
|
||||
<span>Email: <a href="mailto:egor@deev.space">egor@deev.space</a></span>
|
||||
</div>
|
||||
<div class="footer-row">
|
||||
<span>Адрес: г. Москва, ул. Михалковская, д. 7</span>
|
||||
<span>Режим работы: Пн-Пт с 7:00 до 23:00</span>
|
||||
</div>
|
||||
<div class="footer-row footer-copyright">
|
||||
© 2024 ЭкоЛанч. Все права защищены.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="../js/orders.js"></script>
|
||||
</body>
|
||||
</html>
|
||||