diff --git a/labs/lab-06/dishes.js b/labs/lab-06/dishes.js new file mode 100644 index 0000000..efa1ffe --- /dev/null +++ b/labs/lab-06/dishes.js @@ -0,0 +1,353 @@ +const dishes = [ + { + keyword: "mushroom-soup", + name: "Грибной крем-суп", + price: 280, + category: "soup", + count: "300 мл", + image: "img/soup/mushroom-soup.jpg", + kind: "veg" + }, + { + keyword: "beet-soup", + name: "Традиционный борщ", + price: 240, + category: "soup", + count: "350 мл", + image: "img/soup/beet-soup.jpg", + kind: "meat" + }, + { + keyword: "chicken-noodle-soup", + name: "Куриный бульон с лапшой", + price: 220, + category: "soup", + count: "350 мл", + image: "img/soup/chicken-noodle-soup.jpg", + kind: "meat" + }, + { + keyword: "minestrone-soup", + name: "Итальянский суп минестроне", + price: 260, + category: "soup", + count: "350 мл", + image: "img/soup/minestrone-soup.jpg", + kind: "veg" + }, + { + keyword: "tomato-soup", + name: "Томатный крем-суп", + price: 250, + category: "soup", + count: "300 мл", + image: "img/soup/tomato-soup.jpg", + kind: "veg" + }, + { + keyword: "pumpkin-soup", + name: "Тыквенный суп с имбирем", + price: 270, + category: "soup", + count: "300 мл", + image: "img/soup/pumpkin-soup.jpg", + kind: "veg" + }, + { + keyword: "fish-soup", + name: "Уха из лосося", + price: 320, + category: "soup", + count: "350 мл", + image: "img/soup/fish-soup.jpg", + kind: "fish" + }, + { + keyword: "seafood-soup", + name: "Суп том-ям с морепродуктами", + price: 340, + category: "soup", + count: "350 мл", + image: "img/soup/seafood-soup.jpg", + kind: "fish" + }, + { + keyword: "french-onion-soup", + name: "Французский луковый суп", + price: 300, + category: "soup", + count: "350 мл", + image: "img/soup/french-onion-soup.jpg", + kind: "veg" + }, + { + keyword: "vegan-bowl-chickpeas", + name: "Веганский боул с нутом", + price: 390, + category: "main-course", + count: "350 г", + image: "img/main-dishes/vegan-bowl-chickpeas.jpg", + kind: "veg" + }, + { + keyword: "grilled-chicken-vegetables", + name: "Куриная грудка с овощами гриль", + price: 450, + category: "main-course", + count: "350 г", + image: "img/main-dishes/grilled-chicken-vegetables.jpg", + kind: "meat" + }, + { + keyword: "salmon-quinoa-avocado", + name: "Лосось с киноа и авокадо", + price: 620, + category: "main-course", + count: "380 г", + image: "img/main-dishes/salmon-quinoa-avocado.jpg", + kind: "fish" + }, + { + keyword: "seafood-pasta", + name: "Паста с морепродуктами", + price: 550, + category: "main-course", + count: "330 г", + image: "img/main-dishes/seafood-pasta.jpg", + kind: "fish" + }, + { + keyword: "teriyaki-chicken-noodles", + name: "Рисовая лапша с курицей терияки", + price: 420, + category: "main-course", + count: "340 г", + image: "img/main-dishes/teriyaki-chicken-noodles.jpg", + kind: "meat" + }, + { + keyword: "beef-salad", + name: "Теплый салат с говядиной", + price: 490, + category: "main-course", + count: "320 г", + image: "img/main-dishes/beef-salad.jpg", + kind: "meat" + }, + { + keyword: "vegetable-stir-fry", + name: "Овощное рагу с тофу", + price: 380, + category: "main-course", + count: "350 г", + image: "img/main-dishes/vegetable-stir-fry.jpg", + kind: "veg" + }, + { + keyword: "duck-orange-sauce", + name: "Утка в апельсиновом соусе", + price: 580, + category: "main-course", + count: "360 г", + image: "img/main-dishes/duck-orange-sauce.jpg", + kind: "meat" + }, + { + keyword: "mushroom-risotto", + name: "Ризотто с белыми грибами", + price: 410, + category: "main-course", + count: "340 г", + image: "img/main-dishes/mushroom-risotto.jpg", + kind: "veg" + }, + { + keyword: "berry-juice", + name: "Ягодный морс", + price: 120, + category: "drink", + count: "300 мл", + image: "img/drinks/berry-juice.jpg", + kind: "cold" + }, + { + keyword: "water", + name: "Минеральная вода", + price: 80, + category: "drink", + count: "500 мл", + image: "img/drinks/water.jpg", + kind: "cold" + }, + { + keyword: "spinach-smoothie", + name: "Зеленый смузи с шпинатом", + price: 180, + category: "drink", + count: "350 мл", + image: "img/drinks/spinach-smoothie.jpg", + kind: "cold" + }, + { + keyword: "ginger-lemonade", + name: "Имбирный лимонад", + price: 140, + category: "drink", + count: "300 мл", + image: "img/drinks/ginger-lemonade.jpg", + kind: "cold" + }, + { + keyword: "mango-smoothie", + name: "Смузи манго-маракуйя", + price: 170, + category: "drink", + count: "350 мл", + image: "img/drinks/mango-smoothie.jpg", + kind: "cold" + }, + { + keyword: "orange-juice", + name: "Свежевыжатый апельсиновый сок", + price: 150, + category: "drink", + count: "300 мл", + image: "img/drinks/orange-juice.jpg", + kind: "cold" + }, + { + keyword: "cappuccino", + name: "Капучино", + price: 150, + category: "drink", + count: "300 мл", + image: "img/drinks/cappuccino.jpg", + kind: "hot" + }, + { + keyword: "green-tea", + name: "Зеленый чай", + price: 100, + category: "drink", + count: "400 мл", + image: "img/drinks/green-tea.jpg", + kind: "hot" + }, + { + keyword: "hot-chocolate", + name: "Горячий шоколад", + price: 160, + category: "drink", + count: "300 мл", + image: "img/drinks/hot-chocolate.jpg", + kind: "hot" + }, + { + keyword: "shrimp-salad", + name: "Салат с креветками и авокадо", + price: 380, + category: "salad", + count: "250 г", + image: "img/salads/shrimp-salad.jpg", + kind: "fish" + }, + { + keyword: "caesar-salad", + name: "Цезарь с курицей", + price: 320, + category: "salad", + count: "280 г", + image: "img/salads/caesar-salad.jpg", + kind: "meat" + }, + { + keyword: "greek-salad", + name: "Греческий салат", + price: 280, + category: "salad", + count: "260 г", + image: "img/salads/greek-salad.jpg", + kind: "veg" + }, + { + keyword: "caprese-salad", + name: "Капрезе с моцареллой", + price: 290, + category: "salad", + count: "240 г", + image: "img/salads/caprese-salad.jpg", + kind: "veg" + }, + { + keyword: "quinoa-salad", + name: "Салат с киноа и овощами", + price: 310, + category: "salad", + count: "270 г", + image: "img/salads/quinoa-salad.jpg", + kind: "veg" + }, + { + keyword: "beetroot-salad", + name: "Салат со свеклой и орехами", + price: 260, + category: "salad", + count: "250 г", + image: "img/salads/beetroot-salad.jpg", + kind: "veg" + }, + { + keyword: "chocolate-mousse", + name: "Шоколадный мусс", + price: 180, + category: "dessert", + count: "100 г", + image: "img/desserts/chocolate-mousse.jpg", + kind: "small" + }, + { + keyword: "panna-cotta", + name: "Панна-котта с ягодным соусом", + price: 200, + category: "dessert", + count: "120 г", + image: "img/desserts/panna-cotta.jpg", + kind: "small" + }, + { + keyword: "lemon-tart", + name: "Лимонный тарт", + price: 190, + category: "dessert", + count: "110 г", + image: "img/desserts/lemon-tart.jpg", + kind: "small" + }, + { + keyword: "cheesecake", + name: "Чизкейк Нью-Йорк", + price: 280, + category: "dessert", + count: "150 г", + image: "img/desserts/cheesecake.jpg", + kind: "medium" + }, + { + keyword: "tiramisu", + name: "Тирамису классический", + price: 290, + category: "dessert", + count: "160 г", + image: "img/desserts/tiramisu.jpg", + kind: "medium" + }, + { + keyword: "chocolate-cake", + name: "Шоколадный торт", + price: 350, + category: "dessert", + count: "200 г", + image: "img/desserts/chocolate-cake.jpg", + kind: "large" + } +]; \ No newline at end of file diff --git a/labs/lab-06/img/desserts/cheesecake.jpg b/labs/lab-06/img/desserts/cheesecake.jpg new file mode 100644 index 0000000..44ad609 Binary files /dev/null and b/labs/lab-06/img/desserts/cheesecake.jpg differ diff --git a/labs/lab-06/img/desserts/chocolate-cake.jpg b/labs/lab-06/img/desserts/chocolate-cake.jpg new file mode 100644 index 0000000..acde5bf Binary files /dev/null and b/labs/lab-06/img/desserts/chocolate-cake.jpg differ diff --git a/labs/lab-06/img/desserts/chocolate-mousse.jpg b/labs/lab-06/img/desserts/chocolate-mousse.jpg new file mode 100644 index 0000000..529bbcc Binary files /dev/null and b/labs/lab-06/img/desserts/chocolate-mousse.jpg differ diff --git a/labs/lab-06/img/desserts/lemon-tart.jpg b/labs/lab-06/img/desserts/lemon-tart.jpg new file mode 100644 index 0000000..04ced89 Binary files /dev/null and b/labs/lab-06/img/desserts/lemon-tart.jpg differ diff --git a/labs/lab-06/img/desserts/panna-cotta.jpg b/labs/lab-06/img/desserts/panna-cotta.jpg new file mode 100644 index 0000000..055f771 Binary files /dev/null and b/labs/lab-06/img/desserts/panna-cotta.jpg differ diff --git a/labs/lab-06/img/desserts/tiramisu.jpg b/labs/lab-06/img/desserts/tiramisu.jpg new file mode 100644 index 0000000..c5880aa Binary files /dev/null and b/labs/lab-06/img/desserts/tiramisu.jpg differ diff --git a/labs/lab-06/img/drinks/berry-juice.jpg b/labs/lab-06/img/drinks/berry-juice.jpg new file mode 100644 index 0000000..fd427c1 Binary files /dev/null and b/labs/lab-06/img/drinks/berry-juice.jpg differ diff --git a/labs/lab-06/img/drinks/cappuccino.jpg b/labs/lab-06/img/drinks/cappuccino.jpg new file mode 100644 index 0000000..af51c9f Binary files /dev/null and b/labs/lab-06/img/drinks/cappuccino.jpg differ diff --git a/labs/lab-06/img/drinks/ginger-lemonade.jpg b/labs/lab-06/img/drinks/ginger-lemonade.jpg new file mode 100644 index 0000000..a829370 Binary files /dev/null and b/labs/lab-06/img/drinks/ginger-lemonade.jpg differ diff --git a/labs/lab-06/img/drinks/green-tea.jpg b/labs/lab-06/img/drinks/green-tea.jpg new file mode 100644 index 0000000..cb9e410 Binary files /dev/null and b/labs/lab-06/img/drinks/green-tea.jpg differ diff --git a/labs/lab-06/img/drinks/hot-chocolate.jpg b/labs/lab-06/img/drinks/hot-chocolate.jpg new file mode 100644 index 0000000..7813ca3 Binary files /dev/null and b/labs/lab-06/img/drinks/hot-chocolate.jpg differ diff --git a/labs/lab-06/img/drinks/mango-smoothie.jpg b/labs/lab-06/img/drinks/mango-smoothie.jpg new file mode 100644 index 0000000..3d88b63 Binary files /dev/null and b/labs/lab-06/img/drinks/mango-smoothie.jpg differ diff --git a/labs/lab-06/img/drinks/orange-juice.jpg b/labs/lab-06/img/drinks/orange-juice.jpg new file mode 100644 index 0000000..c26c39e Binary files /dev/null and b/labs/lab-06/img/drinks/orange-juice.jpg differ diff --git a/labs/lab-06/img/drinks/spinach-smoothie.jpg b/labs/lab-06/img/drinks/spinach-smoothie.jpg new file mode 100644 index 0000000..77daa21 Binary files /dev/null and b/labs/lab-06/img/drinks/spinach-smoothie.jpg differ diff --git a/labs/lab-06/img/drinks/water.jpg b/labs/lab-06/img/drinks/water.jpg new file mode 100644 index 0000000..b8fa32e Binary files /dev/null and b/labs/lab-06/img/drinks/water.jpg differ diff --git a/labs/lab-06/img/main-dishes/beef-salad.jpg b/labs/lab-06/img/main-dishes/beef-salad.jpg new file mode 100644 index 0000000..cb315dd Binary files /dev/null and b/labs/lab-06/img/main-dishes/beef-salad.jpg differ diff --git a/labs/lab-06/img/main-dishes/duck-orange-sauce.jpg b/labs/lab-06/img/main-dishes/duck-orange-sauce.jpg new file mode 100644 index 0000000..df9dfc2 Binary files /dev/null and b/labs/lab-06/img/main-dishes/duck-orange-sauce.jpg differ diff --git a/labs/lab-06/img/main-dishes/grilled-chicken-vegetables.jpg b/labs/lab-06/img/main-dishes/grilled-chicken-vegetables.jpg new file mode 100644 index 0000000..8335a13 Binary files /dev/null and b/labs/lab-06/img/main-dishes/grilled-chicken-vegetables.jpg differ diff --git a/labs/lab-06/img/main-dishes/mushroom-risotto.jpg b/labs/lab-06/img/main-dishes/mushroom-risotto.jpg new file mode 100644 index 0000000..85e1392 Binary files /dev/null and b/labs/lab-06/img/main-dishes/mushroom-risotto.jpg differ diff --git a/labs/lab-06/img/main-dishes/salmon-quinoa-avocado.jpg b/labs/lab-06/img/main-dishes/salmon-quinoa-avocado.jpg new file mode 100644 index 0000000..a912374 Binary files /dev/null and b/labs/lab-06/img/main-dishes/salmon-quinoa-avocado.jpg differ diff --git a/labs/lab-06/img/main-dishes/seafood-pasta.jpg b/labs/lab-06/img/main-dishes/seafood-pasta.jpg new file mode 100644 index 0000000..b127a11 Binary files /dev/null and b/labs/lab-06/img/main-dishes/seafood-pasta.jpg differ diff --git a/labs/lab-06/img/main-dishes/teriyaki-chicken-noodles.jpg b/labs/lab-06/img/main-dishes/teriyaki-chicken-noodles.jpg new file mode 100644 index 0000000..cd6d36c Binary files /dev/null and b/labs/lab-06/img/main-dishes/teriyaki-chicken-noodles.jpg differ diff --git a/labs/lab-06/img/main-dishes/vegan-bowl-chickpeas.jpg b/labs/lab-06/img/main-dishes/vegan-bowl-chickpeas.jpg new file mode 100644 index 0000000..65c00ab Binary files /dev/null and b/labs/lab-06/img/main-dishes/vegan-bowl-chickpeas.jpg differ diff --git a/labs/lab-06/img/main-dishes/vegetable-stir-fry.jpg b/labs/lab-06/img/main-dishes/vegetable-stir-fry.jpg new file mode 100644 index 0000000..0f106fa Binary files /dev/null and b/labs/lab-06/img/main-dishes/vegetable-stir-fry.jpg differ diff --git a/labs/lab-06/img/main.jpg b/labs/lab-06/img/main.jpg new file mode 100644 index 0000000..f9f6558 Binary files /dev/null and b/labs/lab-06/img/main.jpg differ diff --git a/labs/lab-06/img/salads/beetroot-salad.jpg b/labs/lab-06/img/salads/beetroot-salad.jpg new file mode 100644 index 0000000..3c2f862 Binary files /dev/null and b/labs/lab-06/img/salads/beetroot-salad.jpg differ diff --git a/labs/lab-06/img/salads/caesar-salad.jpg b/labs/lab-06/img/salads/caesar-salad.jpg new file mode 100644 index 0000000..b0093df Binary files /dev/null and b/labs/lab-06/img/salads/caesar-salad.jpg differ diff --git a/labs/lab-06/img/salads/caprese-salad.jpg b/labs/lab-06/img/salads/caprese-salad.jpg new file mode 100644 index 0000000..7c09b80 Binary files /dev/null and b/labs/lab-06/img/salads/caprese-salad.jpg differ diff --git a/labs/lab-06/img/salads/greek-salad.jpg b/labs/lab-06/img/salads/greek-salad.jpg new file mode 100644 index 0000000..e1790c5 Binary files /dev/null and b/labs/lab-06/img/salads/greek-salad.jpg differ diff --git a/labs/lab-06/img/salads/quinoa-salad.jpg b/labs/lab-06/img/salads/quinoa-salad.jpg new file mode 100644 index 0000000..8ad87d4 Binary files /dev/null and b/labs/lab-06/img/salads/quinoa-salad.jpg differ diff --git a/labs/lab-06/img/salads/shrimp-salad.jpg b/labs/lab-06/img/salads/shrimp-salad.jpg new file mode 100644 index 0000000..99abf15 Binary files /dev/null and b/labs/lab-06/img/salads/shrimp-salad.jpg differ diff --git a/labs/lab-06/img/soup/beet-soup.jpg b/labs/lab-06/img/soup/beet-soup.jpg new file mode 100644 index 0000000..ea428f4 Binary files /dev/null and b/labs/lab-06/img/soup/beet-soup.jpg differ diff --git a/labs/lab-06/img/soup/chicken-noodle-soup.jpg b/labs/lab-06/img/soup/chicken-noodle-soup.jpg new file mode 100644 index 0000000..aac43a8 Binary files /dev/null and b/labs/lab-06/img/soup/chicken-noodle-soup.jpg differ diff --git a/labs/lab-06/img/soup/fish-soup.jpg b/labs/lab-06/img/soup/fish-soup.jpg new file mode 100644 index 0000000..cc0d2bc Binary files /dev/null and b/labs/lab-06/img/soup/fish-soup.jpg differ diff --git a/labs/lab-06/img/soup/french-onion-soup.jpg b/labs/lab-06/img/soup/french-onion-soup.jpg new file mode 100644 index 0000000..cd26ae7 Binary files /dev/null and b/labs/lab-06/img/soup/french-onion-soup.jpg differ diff --git a/labs/lab-06/img/soup/minestrone-soup.jpg b/labs/lab-06/img/soup/minestrone-soup.jpg new file mode 100644 index 0000000..a5f8be8 Binary files /dev/null and b/labs/lab-06/img/soup/minestrone-soup.jpg differ diff --git a/labs/lab-06/img/soup/mushroom-soup.jpg b/labs/lab-06/img/soup/mushroom-soup.jpg new file mode 100644 index 0000000..44ce3f4 Binary files /dev/null and b/labs/lab-06/img/soup/mushroom-soup.jpg differ diff --git a/labs/lab-06/img/soup/pumpkin-soup.jpg b/labs/lab-06/img/soup/pumpkin-soup.jpg new file mode 100644 index 0000000..c4df13d Binary files /dev/null and b/labs/lab-06/img/soup/pumpkin-soup.jpg differ diff --git a/labs/lab-06/img/soup/seafood-soup.jpg b/labs/lab-06/img/soup/seafood-soup.jpg new file mode 100644 index 0000000..47162ba Binary files /dev/null and b/labs/lab-06/img/soup/seafood-soup.jpg differ diff --git a/labs/lab-06/img/soup/tomato-soup.jpg b/labs/lab-06/img/soup/tomato-soup.jpg new file mode 100644 index 0000000..a50d0d0 Binary files /dev/null and b/labs/lab-06/img/soup/tomato-soup.jpg differ diff --git a/labs/lab-06/index.html b/labs/lab-06/index.html new file mode 100644 index 0000000..a608c75 --- /dev/null +++ b/labs/lab-06/index.html @@ -0,0 +1,101 @@ + + + + + + + ЭкоЛанч - Доставка здоровых бизнес-ланчей в Москве + + + + + + +
+

ЭкоЛанч

+ +
+ +
+
+

О компании ЭкоЛанч

+ Здоровая еда в контейнерах +

ЭкоЛанч - это современная компания по доставке здоровых бизнес-ланчей в офисы Москвы. Наша миссия - сделать правильное питание доступным для занятых людей, которые ценят свое время и здоровье.

+

Мы используем только свежие продукты от проверенных поставщиков, а наши повара готовят блюда каждое утро. Все ланчи упакованы в экологичную биоразлагаемую упаковку, потому что мы заботимся не только о вашем здоровье, но и о здоровье нашей планеты.

+
+ +
+

Наши преимущества

+ +
+ + +
+ + + + \ No newline at end of file diff --git a/labs/lab-06/menu.html b/labs/lab-06/menu.html new file mode 100644 index 0000000..b4fed11 --- /dev/null +++ b/labs/lab-06/menu.html @@ -0,0 +1,246 @@ + + + + + + + Собрать ланч - ЭкоЛанч + + + + + + +
+

ЭкоЛанч

+ +
+
+
+

Доступные для заказа варианты ланча

+
+
+
+ 🍲 +

Суп

+
+
+ 🍽️ +

Главное блюдо

+
+
+ 🥗 +

Салат

+
+
+ 🥤 +

Напиток

+
+
+ +
+
+ 🍲 +

Суп

+
+
+ 🍽️ +

Главное блюдо

+
+
+ 🥤 +

Напиток

+
+
+ +
+
+ 🍲 +

Суп

+
+
+ 🥗 +

Салат

+
+
+ 🥤 +

Напиток

+
+
+ +
+
+ 🍽️ +

Главное блюдо

+
+
+ 🥗 +

Салат

+
+
+ 🥤 +

Напиток

+
+
+ +
+
+ 🍽️ +

Главное блюдо

+
+
+ 🥤 +

Напиток

+
+
+ +
+
+ 🍰 +

Десерт

+
+

(Можно добавить к любому заказу)

+
+
+

Десерты можно добавить к любому варианту ланча

+
+ +
+
+

Супы

+
+ + + +
+
+
+
+ +
+
+

Главные блюда

+
+ + + +
+
+
+
+ +
+
+

Салаты и стартеры

+
+ + + +
+
+
+
+ +
+
+

Напитки

+
+ + +
+
+
+
+ +
+
+

Десерты

+
+ + + +
+
+
+
+
+ +
+

Оформить заказ

+
+
+ +
+

Ваш заказ

+
+

Ничего не выбрано

+
+
+ +
+

Данные для доставки

+ + + + + + + +
+ + +
+ + + + + + + Доставка осуществляется только по Москве + +
+ +
+ + +
+
+ + +
+
+ + + + Доступное время доставки с 7:00 до 23:00 + + + + +
+ + +
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/labs/lab-06/menu.js b/labs/lab-06/menu.js new file mode 100644 index 0000000..7d39c9e --- /dev/null +++ b/labs/lab-06/menu.js @@ -0,0 +1,406 @@ +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 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'); + + soupSection.innerHTML = ''; + mainCourseSection.innerHTML = ''; + saladSection.innerHTML = ''; + drinkSection.innerHTML = ''; + dessertSection.innerHTML = ''; + + 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 ` +
+ ${dish.name} +

${dish.price} руб.

+

${dish.name}

+

${dish.count}

+ +
+ `; +} + +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'); + } + + updateOrderSummary(); +} + +function updateOrderSummary() { + const orderSummary = document.getElementById('order-summary'); + const hasSelection = selectedDishes.soup || + selectedDishes['main-course'] || + selectedDishes.salad || + selectedDishes.drink || + selectedDishes.dessert; + + if (!hasSelection) { + orderSummary.innerHTML = '

Ничего не выбрано

'; + return; + } + + let summaryHTML = ''; + let totalPrice = 0; + + if (selectedDishes.soup) { + summaryHTML += ` +
+

Суп

+
+ ${selectedDishes.soup.name} + ${selectedDishes.soup.price} руб. +
+
+ `; + totalPrice += selectedDishes.soup.price; + } else { + summaryHTML += ` +
+

Суп

+

Блюдо не выбрано

+
+ `; + } + + if (selectedDishes['main-course']) { + summaryHTML += ` +
+

Главное блюдо

+
+ ${selectedDishes['main-course'].name} + ${selectedDishes['main-course'].price} руб. +
+
+ `; + totalPrice += selectedDishes['main-course'].price; + } else { + summaryHTML += ` +
+

Главное блюдо

+

Блюдо не выбрано

+
+ `; + } + + if (selectedDishes.salad) { + summaryHTML += ` +
+

Салат

+
+ ${selectedDishes.salad.name} + ${selectedDishes.salad.price} руб. +
+
+ `; + totalPrice += selectedDishes.salad.price; + } else { + summaryHTML += ` +
+

Салат

+

Блюдо не выбрано

+
+ `; + } + + if (selectedDishes.drink) { + summaryHTML += ` +
+

Напиток

+
+ ${selectedDishes.drink.name} + ${selectedDishes.drink.price} руб. +
+
+ `; + totalPrice += selectedDishes.drink.price; + } else { + summaryHTML += ` +
+

Напиток

+

Напиток не выбран

+
+ `; + } + + if (selectedDishes.dessert) { + summaryHTML += ` +
+

Десерт

+
+ ${selectedDishes.dessert.name} + ${selectedDishes.dessert.price} руб. +
+
+ `; + totalPrice += selectedDishes.dessert.price; + } else { + summaryHTML += ` +
+

Десерт

+

Десерт не выбран

+
+ `; + } + + summaryHTML += ` +
+

Стоимость заказа

+

${totalPrice} руб.

+
+ `; + + orderSummary.innerHTML = summaryHTML; +} + +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 getValidationMessage() { + 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 'Ничего не выбрано. Выберите блюда для заказа'; + } + + if (!hasDrink) { + return 'Выберите напиток'; + } + + if (hasSoup && !hasMainCourse && !hasSalad) { + return 'Выберите главное блюдо/салат/стартер'; + } + + if (hasSalad && !hasSoup && !hasMainCourse) { + return 'Выберите суп или главное блюдо'; + } + + if (!hasMainCourse && !hasSoup && (hasDrink || selectedDishes.dessert)) { + return 'Выберите главное блюдо'; + } + + return ''; +} + +function showNotification(message) { + const notification = document.createElement('div'); + notification.classList.add('notification'); + + const messageText = document.createElement('p'); + messageText.textContent = message; + + const okButton = document.createElement('button'); + okButton.textContent = 'Окей'; + + okButton.addEventListener('click', function() { + notification.remove(); + }); + + notification.append(messageText); + notification.append(okButton); + + document.body.append(notification); +} + +function setupFormValidation() { + const orderForm = document.getElementById('order-form'); + + orderForm.addEventListener('submit', function(event) { + if (!isValidCombo()) { + event.preventDefault(); + const message = getValidationMessage(); + showNotification(message); + } + }); +} + +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'); + } + } + }); +} + +function resetSelection() { + Object.keys(selectedDishes).forEach(function(category) { + if (selectedDishes[category]) { + const card = document.querySelector( + `.dish-card[data-dish="${selectedDishes[category].keyword}"]` + ); + if (card) { + card.classList.remove('selected'); + } + } + selectedDishes[category] = null; + }); + updateOrderSummary(); +} + +document.addEventListener('DOMContentLoaded', function() { + sortDishes(); + displayDishes(); + setupFilters(); + setupFormValidation(); + + const resetButton = document.querySelector('button[type="reset"]'); + if (resetButton) { + resetButton.addEventListener('click', function() { + resetSelection(); + }); + } +}); \ No newline at end of file diff --git a/labs/lab-06/other/Вопросы для подготовки к защите ЛР №6.txt b/labs/lab-06/other/Вопросы для подготовки к защите ЛР №6.txt new file mode 100644 index 0000000..a31268f --- /dev/null +++ b/labs/lab-06/other/Вопросы для подготовки к защите ЛР №6.txt @@ -0,0 +1,18 @@ +Валидация форм +1. Для чего нужен метод preventDefault()? + +2. Какие события связаны с формами и их элементами? В чём их отличия? + +3. Что такое объект ValidityState и какие свойства он содержит? + +4. Что позволяет задать метод setCustomValidity()? + +5. Почему требуется проверять данные на стороне клиента? + +6. Почему недостаточно проверять данные только на стороне клиента? + +7. Как программно проверить валидность всей формы перед отправкой? + +8. Какие события связаны непосредственно с процессом валидации? + +9. Как программно отправить форму или сбросить её значения? \ No newline at end of file diff --git a/labs/lab-06/other/Задание - Лабораторная работа 6.md b/labs/lab-06/other/Задание - Лабораторная работа 6.md new file mode 100644 index 0000000..acd272f --- /dev/null +++ b/labs/lab-06/other/Задание - Лабораторная работа 6.md @@ -0,0 +1,86 @@ +# Лабораторная работа №6. Проверка данных на стороне клиента. Уведомления + +--- + +Добавьте блок с доступными для заказа вариантами ланча. Создайте скрипт, проверяющий состав ланча при отправке формы. Реализуйте показ уведомлений для пользователей. + +## Порядок выполнения + +Примерные макеты представлены ниже. +* Макет блока с доступными для заказа вариантами +* Макет уведомления + +[Полный макет](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockupfull.png "Полный макет") страницы: + +1. Создайте блок с доступными для заказа вариантами ланча. + +Структура блока: + +- Заголовок +- Блок с вариантами (grid-контейнер, с 3 колонками на каждой строке) + - Блок каждого варианта ланча (flex-контейнер) + - Блок каждого блюда (flex-контейнер, направление главной оси - сверху вниз) + - Изображение блюда + - Подпись + +Изображения с блюдами можно скачать [здесь](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/icons.zip?time=1730060948701 "здесь"). + +Доступные для заказа варианты: + +|1|2|3|4|5| +|---|---|---|---|---| +|Суп
Главное блюдо
Салат
Напиток|Суп
Главное блюдо
Напиток|Суп
Салат
Напиток|Главное блюдо
Салат
Напиток|Главное блюдо
Напиток| + +В отдельном блоке необходимо разместить информацию о десертах. Их можно добавлять в любой вид ланча. Эту информацию нужно также отобразить на странице (поместить ниже подписи; шрифт меньше, чем у подписи на 2 пункта). + +Измените свойства для изображений данного блока при наведении на них курсора. Используйте для этого transform с функциями трансформации translateY и scale. + +На видео продемонстрирована работа transform: + +2. Создайте скрипт, который будет проверять все ли необходимые блюда добавил пользователь. + +Скрипт должен запускаться, когда пользователь отправляет форму. Пользователь может добавлять в заказ произвольные блюда. В итоге у него должен получиться один из вариантов ланчей, описанных выше. Если перечень выбранных блюд не соответствует ни одному из возможных вариантов (комбо), у пользователя не должно быть возможности оформить заказ (форма не должна отправляться), и на странице должно быть выведено уведомление с информацией о недостающих блюдах. + +Существует 5 видов уведомлений: + +|Текст уведомления|Когда выводится|Изображение| +|---|---|---| +|«Ничего не выбрано. Выберите блюда для заказа»|Не добавлено ни одно блюдо|![Ничего не выбрано](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockup3.png)| +|«Выберите напиток»|Выбраны все необходимые блюда, кроме напитка|![Выберите напиток](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockup4.png)| +|«Выберите главное блюдо/салат/стартер»|Выбран суп, но не выбраны главное блюдо/салат/стартер|![Выберите главное блюдо/салат/стартер](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockup5.png)| +|«Выберите суп или главное блюдо»|Выбран салат/стартер, но не выбраны суп/главное блюдо|![Выберите суп или главное блюдо](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockup6.png)| +|«Выберите главное блюдо»|Выбран напиток/десерт|![Выберите главное блюдо](https://lms.mospolytech.ru/pluginfile.php/1314144/mod_assign/intro/mockup7.png)| + +Уведомление должно создаваться динамически каждый раз, когда при попытке отправить форму скрипт обнаруживает, что какое-то блюдо не добавлено. + +Оно должно отображаться поверх остальных элементов на странице и не менять положение при прокрутке. Также, его нужно отцентровать по вертикали и горизонтали. +При наведении на кнопку "Окей", изменяется цвет фона и текста кнопки. +При нажатии на кнопку, уведомление исчезает и удаляется со страницы. +На видео продемонстрирована работа уведомления: + +### Материалы для изучения + +#### CSS +[transform [Doka]](https://doka.guide/css/transform/) +[translateX() [MDN]](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX) +[translateY() [MDN]](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY)  +[scale() [MDN]](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale) +[position [Doka]](https://doka.guide/css/position/) +[top, left, right, bottom [Doka]](https://doka.guide/css/top-left-right-bottom/)[](https://lms.mospolytech.ru/mod/assign/view.php?id=540007&forceview=1) +#### JS +[Отправка формы: событие и метод submit [JS.RU]](https://learn.javascript.ru/forms-submit) +[submit [Doka]](https://doka.guide/js/event-submit/) +[preventDefault() [Doka]](https://doka.guide/js/event-prevent-default/) +[preventDefault() [MDN]](https://developer.mozilla.org/ru/docs/Web/API/Event/preventDefault) +[Изменение документа [JS.RU]](https://learn.javascript.ru/modifying-document) +[document.createElement [MDN]](https://developer.mozilla.org/ru/docs/Web/API/Document/createElement) +[Создание элемента [JS.RU]](https://learn.javascript.ru/modifying-document#sozdanie-elementa +[Element.append() [MDN]](https://developer.mozilla.org/ru/docs/Web/API/Element/append) +[before() [MDN]](https://developer.mozilla.org/en-US/docs/Web/API/Element/before) +[after() [MDN]](https://developer.mozilla.org/en-US/docs/Web/API/Element/after) +[Методы вставки [JS.RU]](https://learn.javascript.ru/modifying-document#metody-vstavki) +[Element.remove() [MDN]](https://developer.mozilla.org/ru/docs/Web/API/Element/remove) +[Удаление узлов [JS.RU]](https://learn.javascript.ru/modifying-document#udalenie-uzlov) +#### Другое +[Юникод, внутреннее устройство строк](https://learn.javascript.ru/unicode) +[Emoji юникод](https://symbl.cc/ru/emoji/) \ No newline at end of file diff --git a/labs/lab-06/other/Результат запроса.png b/labs/lab-06/other/Результат запроса.png new file mode 100644 index 0000000..32a483f Binary files /dev/null and b/labs/lab-06/other/Результат запроса.png differ diff --git a/labs/lab-06/styles.css b/labs/lab-06/styles.css new file mode 100644 index 0000000..10d0bc1 --- /dev/null +++ b/labs/lab-06/styles.css @@ -0,0 +1,666 @@ +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + font-family: 'Montserrat', sans-serif; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +header { + background-color: #2d5016; + color: white; + padding: 20px 40px; + margin: 0; +} + +h1 { + margin: 0 0 15px 0; + font-size: 36px; + color: white; +} + +nav { + margin: 0; + padding: 10px 0; + display: flex; + flex-wrap: wrap; + gap: 15px; +} + +nav a { + text-decoration: none; + color: white; + font-family: 'Montserrat', sans-serif; + font-size: 16px; +} + +nav a:hover { + color: #a8d08d; +} + +nav a#active { + color: tomato; +} + +main { + margin: 0 auto; + padding: 40px 60px; + max-width: 1200px; + flex: 1; +} + +section { + margin: 0 0 50px 0; + padding: 30px; + background-color: #f9f9f9; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + flex-wrap: wrap; + gap: 15px; +} + +.section-header h2 { + margin: 0; +} + +h2 { + font-size: 28px; + color: #2d5016; + margin: 0 0 20px 0; +} + +p { + font-family: 'Montserrat', sans-serif; + font-size: 16px; + color: #333; + line-height: 1.6; + margin: 0 0 15px 0; +} + +img { + width: 100%; + height: 400px; + object-fit: cover; + margin: 0 0 20px 0; +} + +ul { + margin: 20px 0; + padding: 0 0 0 25px; +} + +ul li { + font-family: 'Montserrat', sans-serif; + font-size: 16px; + color: #333; + margin: 0 0 12px 0; + line-height: 1.5; +} + +table { + width: 100%; + border-collapse: collapse; + margin: 20px 0; +} + +table th { + background-color: #2d5016; + color: white; + padding: 15px; + text-align: left; + border: 1px solid #2d5016; + font-size: 16px; +} + +table td { + padding: 12px 15px; + border: 1px solid #ddd; + text-align: left; + font-size: 15px; + color: #333; +} + +table tr:nth-child(even) { + background-color: #f2f2f2; +} + +.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; +} + +.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; +} + +.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="reset"] { + background-color: #f1eee9; + color: #333; +} + +.form-buttons button[type="reset"]: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; +} + +.notification { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: white; + padding: 40px; + border-radius: 15px; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); + z-index: 1000; + text-align: center; + max-width: 500px; +} + +.notification p { + font-size: 18px; + margin: 0 0 25px 0; + color: #333; +} + +.notification button { + background-color: #2d5016; + color: white; + border: none; + padding: 12px 40px; + border-radius: 10px; + font-family: 'Montserrat', sans-serif; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s; +} + +.notification button:hover { + background-color: white; + color: #2d5016; + border: 2px solid #2d5016; +} + +footer { + background-color: black; + color: white; + padding: 30px 60px; + margin: 0; +} + +footer p { + color: white; + margin: 0 0 10px 0; +} + +footer a { + text-decoration: none; + color: white; + font-family: 'Montserrat', sans-serif; + font-size: 16px; +} + +footer a:hover { + color: #a8d08d; +} + +@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; + } + + .form-container { + grid-template-columns: 1fr; + gap: 20px; + } +} + +@media (max-width: 600px) { + h1 { + text-align: center; + } + + nav { + flex-direction: column; + align-items: center; + } + + nav a { + font-size: 20px; + } + + section h2 { + text-align: center; + } + + .combo-grid { + grid-template-columns: 1fr; + } + + .dishes-grid { + grid-template-columns: 1fr; + } + + .about-company img { + width: 100%; + } + + table th, + table td { + font-size: 14px; + } + + .form-container { + grid-template-columns: 1fr; + } + + .form-buttons { + flex-direction: column; + } + + .notification { + max-width: 90%; + padding: 30px 20px; + } +} + +@media (max-width: 400px) { + table th, + table td { + font-size: 12px; + } +} \ No newline at end of file