Skip to content

Repository files navigation

Проектная работа "Веб-ларек"

Стек: HTML, SCSS, TS, Vite

Структура проекта:

  • src/ — исходные файлы проекта
  • src/components/ — папка с JS компонентами
  • src/components/base/ — папка с базовым кодом

Важные файлы:

  • index.html — HTML-файл главной страницы
  • src/types/index.ts — файл с типами
  • src/main.ts — точка входа приложения
  • src/scss/styles.scss — корневой файл стилей
  • src/utils/constants.ts — файл с константами
  • src/utils/utils.ts — файл с утилитами

Установка и запуск

Для установки и запуска проекта необходимо выполнить команды

npm install
npm run dev

или

yarn
yarn dev

Сборка

npm run build

или

yarn build

Интернет-магазин «Web-Larёk»

«Web-Larёk» — это интернет-магазин с товарами для веб-разработчиков, где пользователи могут просматривать товары, добавлять их в корзину и оформлять заказы. Сайт предоставляет удобный интерфейс с модальными окнами для просмотра деталей товаров, управления корзиной и выбора способа оплаты, обеспечивая полный цикл покупки с отправкой заказов на сервер.

Архитектура приложения

Код приложения разделен на слои согласно парадигме MVP (Model-View-Presenter), которая обеспечивает четкое разделение ответственности между классами слоев Model и View. Каждый слой несет свой смысл и ответственность:

Model - слой данных, отвечает за хранение и изменение данных.
View - слой представления, отвечает за отображение данных на странице.
Presenter - презентер содержит основную логику приложения и отвечает за связь представления и данных.

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

Базовый код

Класс Component

Является базовым классом для всех компонентов интерфейса. Класс является дженериком и принимает в переменной T тип данных, которые могут быть переданы в метод render для отображения.

Конструктор:
constructor(container: HTMLElement) - принимает ссылку на DOM элемент за отображение, которого он отвечает.

Поля класса:
container: HTMLElement - поле для хранения корневого DOM элемента компонента.

Методы класса:
render(data?: Partial<T>): HTMLElement - Главный метод класса. Он принимает данные, которые необходимо отобразить в интерфейсе, записывает эти данные в поля класса и возвращает ссылку на DOM-элемент. Предполагается, что в классах, которые будут наследоваться от Component будут реализованы сеттеры для полей с данными, которые будут вызываться в момент вызова render и записывать данные в необходимые DOM элементы.
setImage(element: HTMLImageElement, src: string, alt?: string): void - утилитарный метод для модификации DOM-элементов <img>

Класс Api

Содержит в себе базовую логику отправки запросов.

Конструктор:
constructor(baseUrl: string, options: RequestInit = {}) - В конструктор передается базовый адрес сервера и опциональный объект с заголовками запросов.

Поля класса:
baseUrl: string - базовый адрес сервера
options: RequestInit - объект с заголовками, которые будут использованы для запросов.

Методы:
get(uri: string): Promise<object> - выполняет GET запрос на переданный в параметрах ендпоинт и возвращает промис с объектом, которым ответил сервер
post(uri: string, data: object, method: ApiPostMethods = 'POST'): Promise<object> - принимает объект с данными, которые будут переданы в JSON в теле запроса, и отправляет эти данные на ендпоинт переданный как параметр при вызове метода. По умолчанию выполняется POST запрос, но метод запроса может быть переопределен заданием третьего параметра при вызове.
handleResponse(response: Response): Promise<object> - защищенный метод проверяющий ответ сервера на корректность и возвращающий объект с данными полученный от сервера или отклоненный промис, в случае некорректных данных.

Класс EventEmitter

Брокер событий реализует паттерн "Наблюдатель", позволяющий отправлять события и подписываться на события, происходящие в системе. Класс используется для связи слоя данных и представления.

Конструктор класса не принимает параметров.

Поля класса:
_events: Map<string | RegExp, Set<Function>>) - хранит коллекцию подписок на события. Ключи коллекции - названия событий или регулярное выражение, значения - коллекция функций обработчиков, которые будут вызваны при срабатывании события.

Методы класса:
on<T extends object>(event: EventName, callback: (data: T) => void): void - подписка на событие, принимает название события и функцию обработчик.
emit<T extends object>(event: string, data?: T): void - инициализация события. При вызове события в метод передается название события и объект с данными, который будет использован как аргумент для вызова обработчика.
trigger<T extends object>(event: string, context?: Partial<T>): (data: T) => void - возвращает функцию, при вызове которой инициализируется требуемое в параметрах событие с передачей в него данных из второго параметра.

Данные

В ходе анализа проекта было установлено: в приложении используются две сущности, которые описывают данные, — товар и покупатель.

Интерфейс IProduct

Описывает данные товара.

Поля интерфейса: id: string - идентификатор товара description: string - описание товара image: string - изображения товара title: string - название товара category: string - категория товара price: number | null - цена товара (значение null означает, что товар недоступен для покупки)

Интерфейс IBuyer

Описывает данные покупателя.

Поля интерфейса: payment: TPayment - способ оплаты email: string - адрес электронной почты покупателя phone: string - номер телефона покупателя address: string - адрес доставки

Вспомогательный тип TPayment

Задает способ оплаты заказа: card - онлайн; cash - при получении; '' - способ оплаты не выбран (начальное состояние).

type TPayment = 'card' | 'cash' | '';

Вспомогательный тип TBuyerErrors

Используется для типизации объекта с ошибками валидации данных покупателя.

type TBuyerErrors = Partial<Record<keyof IBuyer, string>>;

Интерфейс IProductsResponse

Описывает ответ сервера при получении списка товаров.

Поля интерфейса: total: number - общее количество товаров items: IProduct[] - массив товаров

Интерфейс IOrderData

Описывает данные заказа, которые отправляются на сервер. Расширяет интерфейс IBuyer (наследует поля payment, email, phone, address) и добавляет свои поля.

Поля интерфейса: total: number - общая сумма заказа items: string[] - массив идентификаторов товаров

Интерфейс IOrderResponse

Описывает ответ сервера при успешном оформлении заказа.

Поля интерфейса: id: string - идентификатор заказа total: number - подтвержденная сумма заказа

Интерфейс IHeader

Описывает данные для отображения шапки сайта.

Поля интерфейса: counter: number - количество товаров в корзине

Интерфейс IModal

Описывает данные для управления модальным окном.

Поля интерфейса: content: HTMLElement - HTML-элемент, отображаемый внутри модального окна

Интерфейс ICatalog

Описывает данные для отображения каталога товаров.

Поля интерфейса: content: HTMLElement[] - массив HTML-элементов карточек товаров

Интерфейс IBasket

Описывает данные для отображения корзины.

Поля интерфейса: content: HTMLElement[] - массив HTML-элементов карточек товаров в корзине total: number - общая стоимость товаров в корзине

Интерфейс IOrderSuccess

Описывает данные для отображения сообщения об успешном оформлении заказа.

Поля интерфейса: total: number - сумма списанных синапсов

Интерфейс IForm

Описывает базовое состояние любой формы.

Поля интерфейса: isValid: boolean - флаг валидности формы (true - все поля заполнены корректно) errors: string - текст ошибки для отображения пользователю

Тип TCard

Базовый тип для карточки товара. Содержит минимальный набор полей, общий для всех карточек.

Поля типа: title: string - название товара price: number | null - цена товара (null - товар недоступен)

Тип TCardCatalog

Тип для карточки товара в каталоге. Расширяет базовый тип TCard.

Поля типа: category: string - категория товара (для стилизации фона) image: string - путь к изображению товара

Тип TCardPreview

Тип для карточки товара в режиме предпросмотра (модальное окно). Расширяет TCardCatalog.

Поля типа: description: string - подробное описание товара isUnavailable: boolean - флаг недоступности товара (блокирует кнопку покупки) isInBasket: boolean - флаг наличия товара в корзине (меняет текст кнопки)

Тип TCardBasket

Тип для карточки товара в корзине. Расширяет базовый тип TCard.

Поля типа: index: number - порядковый номер товара в списке корзины

Тип TFormOrder

Тип для формы оформления заказа (способ оплаты и адрес). Расширяет IForm.

Поля типа: payment: TPayment - выбранный способ оплаты address: string - адрес доставки

Тип TFormContacts

Тип для формы ввода контактных данных. Расширяет IForm.

Поля типа: email: string - адрес электронной почты phone: string - номер телефона

Тип TCardActions

Тип для описания действий, доступных на карточке товара.

Поля типа: onClick: () => void - функция-обработчик клика по карточке товара

Модели данных

Для учёта данных в приложении должны быть три класса, которые будут разделены между собой по смыслу и зонам ответственности.

Класс Catalog

Хранение товаров, которые можно купить в приложении.

Конструктор: constructor(protected events: IEvents) - принимает брокер событий для уведомления об изменениях в каталоге

Поля класса:
products: IProduct[] - массив всех товаров
selectedProduct: IProduct | null - товар, выбранный для подробного отображения events: IEvents - брокер событий

Методы класса:
setProducts(products: IProduct[]): void - сохранение массива товаров полученного в параметрах метода getProducts(): IProduct[] - получение массива товаров из модели getProductById(id: string): IProduct | null - получение одного товара по его id setSelectedProduct(product: IProduct): void - сохранение товара для подробного отображения getSelectedProduct(): IProduct | null - получение товара для подробного отображения

Класс Basket

Хранение товаров, которые пользователь выбрал для покупки.

Конструктор: constructor(protected events: IEvents) - принимает брокер событий для уведомления об изменениях в корзине

Поля класса:
selectedProducts: IProduct[] - массив товаров, выбранных покупателем для покупки events: IEvents - брокер событий

Методы класса:
getSelectedProducts(): IProduct[] - получение массива товаров, которые находятся в корзине addProduct(product: IProduct): void - добавление товара, который был получен в параметре, в массив корзины deleteProduct(product: IProduct): void - удаление товара, полученного в параметре из массива корзины clearBasket(): void - очистка корзины getTotalPrice(): number - получение стоимости всех товаров в корзине getProductsCount(): number - получение количества товаров в корзине hasProductInBasket(id: string): boolean - проверка наличия товара в корзине по его id, полученного в параметр метода

Класс Buyer

Данные покупателя, которые тот должен указать при оформлении заказа.

Конструктор: constructor(protected events: IEvents) - принимает брокер событий для уведомления об изменениях данных покупателя

Поля класса:
payment: TPayment - способ оплаты email: string - адрес электронной почты покупателя phone: string - номер телефона покупателя address: string - адрес доставки events: IEvents - брокер событий

Методы класса:
setPayment(payment: TPayment): void - сохранение способа оплаты setEmail(email: string): void - сохранение адреса электронной почты покупателя setPhone(phone: string): void - сохранение номера телефона покупателя setAddress(address: string): void - сохранение адреса доставки getBuyerData(): IBuyer - получение всех данных покупателя clearBuyerData(): void - очистка данных покупателя validateBuyerData(): TBuyerErrors - валидация данных покупателя. Возвращает объект, где ключи названия полей с ошибками, а значения текст ошибки. Если поле валидно, оно отсутствует в возвращаемом объекте.

Слой коммуникации

Класс AppApi

Отвечает за получение данных с сервера и отправку данных на сервер.

Конструктор:
constructor(api: IApi) - принимает объект, реализующий интерфейс IApi, который будет использоваться для выполнения запросов к серверу.

Поля класса:
api: IApi - поле для хранения экземпляра класса, реализующего интерфейс IApi, через который выполняются HTTP-запросы

Методы класса:
getProducts(): Promise<IProductsResponse> - выполняет GET запрос на эндпоинт /product/ и возвращает промис с объектом, полученным от сервера, в котором находится массив товаров. postOrder(order: IOrderData): Promise<IOrderResponse> - выполняет POST запрос на эндпоинт /order/, передаёт в него данные, полученные в параметрах метода, и возвращает промис с объектом, подтверждающим покупку на определенную сумму.

Слой представления

HeaderComponent

Шапка сайта с корзиной.

Конструктор: constructor(container: HTMLElement, events: IEvents) - принимает контейнер шапки и брокер событий

Поля: counterElement: HTMLElement - элемент для отображения количества товаров в корзине basketButton: HTMLButtonElement - кнопка-иконка корзины

Методы: set counter(value: number) - устанавливает значение счетчика товаров в корзине

CatalogComponent

Каталог товаров.

Конструктор: constructor(container: HTMLElement) - принимает DOM-элемент-контейнер для каталога

Поля: galleryElement: HTMLElement - элемент галереи для размещения карточек товаров

Методы: set content(value: HTMLElement[]) - заполняет каталог массивом DOM-элементов карточек товаров, заменяя текущее содержимое

ModalComponent

Модальное окно.

Конструктор: constructor(container: HTMLElement, events: IEvents) - принимает контейнер модального окна и брокер событий

Поля: contentElement: HTMLElement - элемент для размещения основного контента модального окна closeButton: HTMLButtonElement - кнопка закрытия (крестик)

Методы: set content(value: HTMLElement) - устанавливает содержимое модального окна open(): void - открывает модальное окно (добавляет класс modal_active) и генерирует событие modal:open close(): void - закрывает модальное окно, очищает содержимое и генерирует событие modal:close

CardComponent

Базовый абстрактный класс для всех карточек товара.

Конструктор: constructor(container: HTMLElement) - принимает контейнер карточки

Поля: cardTitleElement: HTMLElement - элемент для отображения названия товара cardPriceElement: HTMLElement - элемент для отображения цены товара

Методы: set title(value: string) - устанавливает название товара set price(value: number | null) - устанавливает цену (при null отображает "Бесценно")

CardCatalogComponent

Карточка товара в каталоге.

Конструктор: constructor(container: HTMLElement, actions: TCardActions) - принимает контейнер и объект с обработчиком события

Поля: cardCategoryElement: HTMLElement - элемент для отображения категории товара cardImageElement: HTMLImageElement - элемент для отображения изображения товара

Методы: set category(value: string) - устанавливает категорию с соответствующим CSS-классом set image(value: string) - устанавливает изображение (добавляет базовый URL CDN)

CardBasketComponent

Карточка товара в корзине.

Конструктор: constructor(container: HTMLElement, actions: TCardActions) - принимает контейнер и объект с обработчиком события

Поля: cardIndexElement: HTMLElement - элемент для отображения порядкового номера cardDeleteButton: HTMLButtonElement - кнопка удаления товара из корзины

Методы: set index(value: number) - устанавливает порядковый номер товара

CardPreviewComponent

Предпросмотр карточки товара.

Конструктор: constructor(container: HTMLElement, protected events: IEvents) - принимает контейнер и брокер событий

Поля: cardCategoryElement: HTMLElement - элемент для отображения категории cardImageElement: HTMLImageElement - элемент для отображения изображения cardDescriptionElement: HTMLElement - элемент для отображения описания cardButtonElement: HTMLButtonElement - кнопка действия (Купить/Удалить)

Методы: set image(value: string) - устанавливает изображение (добавляет базовый URL CDN) set description(value: string) - устанавливает описание товара set buttonText(value: string) - устанавливает текст кнопки set buttonDisabled(value: boolean) - блокирует/разблокирует кнопку set category(value: string) - устанавливает категорию с соответствующим CSS-классом

FormComponent

Базовый абстрактный класс для всех форм приложения.

Конструктор: constructor(container: HTMLFormElement, events: IEvents) - принимает элемент формы и брокер событий

Поля: formElement: HTMLFormElement - элемент формы errorsElement: HTMLElement - элемент для отображения текста ошибок submitButton: HTMLButtonElement - кнопка отправки формы

Методы: set isValid(value: boolean) - блокирует/разблокирует кнопку отправки в зависимости от валидности формы set errors(value: string) - устанавливает текст ошибки

FormOrderComponent

Форма для выбора способа оплаты и ввода адреса доставки.

Конструктор: constructor(container: HTMLFormElement, events: IEvents) - принимает элемент формы и брокер событий

Поля: cardButton: HTMLButtonElement - кнопка выбора оплаты картой cashButton: HTMLButtonElement - кнопка выбора оплаты наличными addressInput: HTMLInputElement - поле ввода адреса доставки

Методы: set payment(value: string) - устанавливает активный способ оплаты set address(value: string) - устанавливает значение поля адреса

FormContactsComponent

Форма для ввода контактных данных покупателя.

Конструктор: constructor(container: HTMLFormElement, events: IEvents) - принимает элемент формы и брокер событий

Поля: emailInput: HTMLInputElement - поле ввода email phoneInput: HTMLInputElement - поле ввода телефона

Методы: set email(value: string) - устанавливает значение поля email set phone(value: string) - устанавливает значение поля phone

BasketComponent

Компонент корзины.

Конструктор: constructor(container: HTMLElement, events: IEvents) - принимает контейнер и брокер событий

Поля: listElement: HTMLElement - элемент списка товаров priceElements: HTMLElement - элемент отображения суммы orderButton: HTMLButtonElement - кнопка оформления заказа

Методы: set content(value: HTMLElement[]) - заполняет список карточками товаров set total(value: number) - устанавливает текст общей суммы set buttonDisabled(value: boolean) - блокирует/разблокирует кнопку оформления заказа

OrderSuccessComponent

Экран успешного оформления заказа.

Конструктор: constructor(container: HTMLElement, events: IEvents) - принимает контейнер и брокер событий

Поля: descriptionElement: HTMLElement - элемент для отображения сообщения о списании closeButton: HTMLButtonElement - кнопка закрытия

Методы: set total(value: number) - устанавливает текст сообщения с суммой списанных синапсов

Презентер

Презентер реализован в файле main.ts и связывает модели данных с компонентами представления. Выбран подход с использованием единого файла-презентера без выделения отдельного класса, что соответствует рекомендациям для одностраничного приложения.

События моделей данных

catalog:change - изменение каталога товаров product:select - изменение выбранного для просмотра товара basket:change - изменение содержимого корзины buyer:change - изменение данных покупателя

События представления

card:click - выбор карточки для просмотра product:toggle - нажатие кнопки в карточке предпросмотра (добавление/удаление из корзины) basket:open - нажатие кнопки открытия корзины basket:remove - нажатие кнопки удаления товара из корзины (в корзине) basket:order - нажатие кнопки оформления заказа order:submit - нажатие кнопки перехода ко второй форме оформления заказа contacts:submit - нажатие кнопки оплаты/завершения оформления заказа success:close - закрытие окна успешного оформления заказа payment:change - изменение способа оплаты address:change - изменение адреса доставки email:change - изменение email phone:change - изменение телефона

Системные события модального окна

modal:open - открытие модального окна modal:close - закрытие модального окна

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages