91 lines
No EOL
12 KiB
Markdown
91 lines
No EOL
12 KiB
Markdown
# Лабораторная работа № 8. Реализация функциональности оформления заказа
|
||
|
||
---
|
||
|
||
Реализуйте сохранение выбранных пользователем блюд, чтобы после обновления страницы выбор пользователя не сбрасывался. Добавьте страницу оформления заказа, где будет отображаться текущий состав заказа и форма ввода данных. Реализуйте возможность оформления заказа – отправку данных на сервер.
|
||
|
||
## Порядок выполнения
|
||
|
||
1. Реализуйте сохранение данных о выбранных пользователем блюдах в localStorage, чтобы в последующем иметь возможность получить эти данные на странице "Оформить заказ". В localStorage должны храниться только идентификаторы выбранных блюд. Формат хранения данных выбирается на усмотрение студента.
|
||
|
||
2. Добавьте страницу "Оформить заказ". Внешний вид страницы представлен на макете ниже. Добавьте ссылку на эту страницу в навигационное меню. На странице "Оформить заказ" должно быть два раздела: "Состав заказа" и "Оформление заказа".
|
||
- В разделе "Состав заказа" должны быть отображены ранее добавленные пользователем в заказ блюда (список выбранных блюд нужно загрузить из localStorage, а данные для отображения – загрузить с сервера).
|
||
- Формат отображения блюд такой же, как на странице "Собрать ланч".
|
||
- Вместо кнопки "Добавить" в карточке блюда должна быть кнопка "Удалить", по нажатию на которую соответствующее блюдо удаляется из заказа (т. е. информация о нём удаляется из localStorage) и карточка удаляется со страницы.
|
||
- Если ни одно блюдо не выбрано, нужно отобразить пользователю текст "Ничего не выбрано. Чтобы добавить блюда в заказ, перейдите на страницу Собрать ланч.", где текст "Собрать ланч" – гиперссылка на соответствующую страницу.
|
||
- В разделе "Оформление заказа" должна отображаться форма оформления заказа, перенесённая со страницы "Собрать ланч".
|
||
- Выбранные пользователем блюда отображаются в левой части формы (см. макет выше), напротив каждого блюда отображается его стоимость.
|
||
- При удалении блюда из заказа в соответствующем ему пункте должен отобразиться текст "Не выбран" (или "Не выбрано" для "Главного блюда") и должна быть пересчитана итоговая стоимость заказа.
|
||
- Перед отправкой данных формы на сервер должна производиться проверка соответствия состава заказа одному из доступных комбо (см. задание к ЛР 6).
|
||
|
||
3. Внесите исправления в страницу "Собрать ланч": вместо формы оформления заказа разместите панель для перехода к оформлению заказа, в которой будет отображаться текущая стоимость добавленных в заказ блюд и ссылка "Перейти к оформлению", ведущая на страницу оформления заказа.
|
||
- Панель для перехода к оформлению заказа должна быть скрыта, если пользователь не добавил в заказ ни одного блюда.
|
||
- Ссылка "Перейти к оформлению" должна быть недоступна до тех пор, пока сосав заказа не удовлетворяет одному из доступных комбо (см. задание к ЛР 6).
|
||
- Для размещения элемента на странице используйте position: sticky.
|
||
- При добавлении очередного блюда в заказ, стоимость должна пересчитываться.
|
||
- При открытии страницы "Собрать ланч" должны учитываться данные текущего заказа, хранящиеся в localStorage (т. е. в меню должны быть выделены выбранные блюда, рассчитана и отображена текущая суммарная стоимость выбранных блюд и т. д.).
|
||
|
||
4. Реализуйте отправку данных заказа на сервер по нажатию на кнопку "Отправить".
|
||
- Запрос должен быть отправлен при помощи fetch.
|
||
- В случае возникновения ошибки при отправке запроса или его обработке на стороне сервера пользователю должно быть отображено уведомление об ошибке (можно использовать функцию alert или написать кастомное модальное окно – на ваше усмотрение).
|
||
- После успешного оформления заказа данные о выбранных блюдах из localStorage должны удаляться. Если не удалось оформить заказ – данные не удаляются.
|
||
|
||
## Инструкция по работе с API
|
||
|
||
Для получения доступа к API необходимо пройти процедуру авторизации. Для авторизации нужно указать в качестве параметра запроса api_key значение уникального ключа, который выдаётся каждому пользователю. Ключ представляет собой идентификатор UUIDv4, который является случайным 16-байтным номером (например, 123e4567-e89b-12d3-a456-426655440000).
|
||
|
||
**Обратите внимание, что параметр api_key всегда передаётся в строке запроса.**
|
||
|
||
Пользователь может просматривать, редактировать и удалять только свои заказы. В один момент времени в базе данных может быть не более 10 заказов, созданных одним и тем же пользователем.
|
||
|
||
Если пользователь попробует совершить действие, не пройдя авторизацию, в качестве ответа на его запрос придёт сообщение:
|
||
|
||
{"error": "Для получения доступа к API необходимо пройти процедуру авторизации. Для этого нужно передать в запросе персональный API Key."}
|
||
|
||
При передаче параметров в POST- и PUT-запросах данные должны передаваться в теле запроса в формате application/json (нужно вручную сериализовать данные и установить значение заголовка Content-Type) или multipart/form-data (достаточно при отправке данных формы воспользоваться объектом FormData).
|
||
|
||
При оформлении заказа в запросе к серверу должны быть указаны значения обязательных полей:
|
||
|
||
|Название|Тип|Обязательное|Только для чтения|Примечание|
|
||
|---|---|---|---|---|
|
||
|id|Integer||Да|Устанавливается сервером.|
|
||
|full_name|String|Да|||
|
||
|email|String|Да||
|
||
|subscribe|Boolean|Нет||Допустимы значения 0 и 1.|
|
||
|phone|String|Да|||
|
||
|delivery_address|String|Да|||
|
||
|delivery_type|String|Да||Допустимы значения "now" и "by_time".|
|
||
|delivery_time|Time|Нет||Значение передаётся в формате HH:MM. <br>Доступное время доставки: с 7:00 до 23:00 с шагом 5 минут. <br>Не должно быть пустым, если delivery_type=by_time. <br>Не должно быть раньше текущего времени.|
|
||
|comment|String|Нет|||
|
||
|soup_id|Integer|Нет||Обязательность поля зависит от состава комбо.|
|
||
|main_course_id|Integer|Нет||Обязательность поля зависит от состава комбо.|
|
||
|salad_id|Integer|Нет||Обязательность поля зависит от состава комбо.|
|
||
|drink_id|Integer|Да|||
|
||
|dessert_id|Integer|Нет|||
|
||
|created_at|DateTime||Да|Устанавливается сервером.|
|
||
|updated_at|DateTime||Да|Устанавливается сервером.|
|
||
|student_id|Integer||Да|Устанавливается сервером.|
|
||
|
||
Доступные пользователю действия представлены в таблице:
|
||
|
||
|Действие|Метод и путь|Формат ответа|Примечание|
|
||
|---|---|---|---|
|
||
|Получить данные всех блюд|GET /labs/api/dishes|JSON [{item1},{item2},...{itemN}]||
|
||
|Получить данные конкретного блюда|GET /labs/api/dishes/{int:dish_id}|JSON {Item}|Вместо {int:dish_id} нужно подставить целое число – идентификатор блюда.|
|
||
|Получить данные всех заказов|GET /labs/api/orders|JSON [{item1},{item2},...{itemN}]||
|
||
|Получить данные конкретного заказа|GET /labs/api/orders/{int:order_id}|JSON {Item}|Вместо {int:order_id} нужно подставить целое число – идентификатор заказа.|
|
||
|Создать новый заказ|POST /labs/api/orders|JSON {newItem}|Нужно передать значения всех обязательных полей.|
|
||
|Изменить заказ|PUT /labs/api/orders/{int:order_id}|JSON {updateItem}|Вместо {int:order_id} нужно подставить целое число – идентификатор заказа. <br>Достаточно передать только значения изменившихся полей.|
|
||
|Удалить заказ|DELETE /labs/api/orders/{int:order_id}|JSON {Item}|Вместо {int:order_id} нужно подставить целое число – идентификатор заказа.|
|
||
|
||
### Материалы для изучения
|
||
[localStorage [Doka]](https://doka.guide/js/local-storage/)
|
||
[Получение данных с сервера [MDN]](https://developer.mozilla.org/ru/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data)
|
||
[Работа с JSON [MDN]](https://developer.mozilla.org/ru/docs/Learn/JavaScript/Objects/JSON)
|
||
[Промисы, async/await [Learn JS]](https://learn.javascript.ru/async)
|
||
[async/await [Doka]](https://doka.guide/js/async-await/)
|
||
[Использование промисов [MDN]](https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Using_promises)
|
||
[Fetch [Learn JS]](https://learn.javascript.ru/fetch)
|
||
[Fetch API [MDN]](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
|
||
[fetch() [Doka]](https://doka.guide/js/fetch/)
|
||
[Cross-Origin Resource Sharing (CORS) [MDN]](https://developer.mozilla.org/ru/docs/Web/HTTP/CORS) |