Вы находитесь на странице: 1из 163

Введение, теория, план на урок

Stack технологии – BACKEND

1. NODE JS – это платформа на которой можно делать backend на языке Javascript


2. Express – это Framework для написания backend-да то есть серверной части
3. PostgreSQL – Система управления базами данных
4. Sequelize – ORM для реляционных баз данных на node js (ORM это некая технология которая
позволяет связывать программный код с базами данных, грубо говоря мы не пишем
напрямую SQL запросы а вызываем какую-то функцию например << create >> и обьект
добавляется в базу данных.)

Что будем делать ?

1. Посмотрим диаграмму базы данных, состояшую их 8 таблиц (В ходе разработки серверной


части мы построим диаграмму базы данных оно будет состоять из 8 таблиц)
2. Реализуем авторизацию пользователя по JWT токену
3. Полноценное Rest API интернет магазина электроники (REST API с помощью которого мы
сможем получать какие-то данные, добавлять какие-то данные в базу данных или их удалять,
также на простом примере поработаем с ролями пользователя, у нас будет админ панель с
помощью которой администратор магазина сможет добавлять какие-то товары на продажу,
обычный же пользователь такой возможностью обладать не будет)

При разработке клиентской части которая будет отображаться уже в браузере будет следующий Stack
технологий – FRONTEND:

1. REACT JS
2. React bootstrap – графика (для того чтобы не тратить время на верстку)
3. Axios – запросы к серверу
4. React-router-dom – навигация (для навигации по страницам будем использовать)
5. MobX- стейт (state) менеджмент
Что представляеть из себя Rest API и что такое в целом full stack разработка:

После того как пользователь открыл приложение в браузере или нажал на какую-то кнопку, должно
произойти какое-то действие и мы должны получить данные сервера. Сервер расположен по какому-
то адресу, например << http://server.com >>, мы отправляем по этому адресу запрос, сервер как-то
взаимодействует с базой данных, как-то данные обрабатывает, происходят какие-то манипуляции,
после чего сервер эти данные возвращают на клиент и пользователь уже получает их виде какой-то
информации, например карточки какого-то товара, список пользователей, список друзей в
социальной сети и так далее.

SERVER

На сервере определен список endpoint-ов с помощью которых мы с этим сервером можем


взаймодействовать. Чаще всего взаимодействия происходит по протоколу http.
http протокол имеет четыре основных метода.

GET – для получения данных

POST – для создания данных

PUT – для обнавления данных

DELETE – для удаления данных

Users

GET – http://......./api/users - получить пользователей


POST – http://......./api/users - добавить пользователей
DELETE - http://......./api/users - удалить пользователей
Devices

GET – http://......./api/devices - получить устройства


POST - http://......./api/devices - добавить устройства
…….

Создания endpoint-а на сервере выглядит примерно таким образом

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

CLIENT

Клиентская часть приложение представляет из себя страницу открытую в браузере.

А запрос на сервере выглядит примерно таким образом:

<< const users = fetch(‘http://…./api/users’) >>


[BACKEND] - Начало

ПРАКТИКА

Я создал абсолютно пустой проект и в нем создадим две папки:

Одну назывем << client >>, там будет наша клиентская часть приложения и << server >>
соответственно для BACKEND.

Начнём мы с разработки сервера, создаем в корне файл << index.js >> (он будет самым корневым для
нашего приложения, с него будет начинаться запуск)
В терминале откроем папку сервером и проинициализируем проект командой << npm init -y >> после
этого в папки << server >> должен был появиться файлик << package.json >> где будет описания
проектов, зависимости который в нем исполбзуются и как раз мы начнём мы разработку с того что
установим эти самые зависимости.

<< package.json >>


Мы будем использовать framework Express в качестве системы управления базами данных PostgreSQL
устанавливаем два модуля и это << pg >> и << pg-hstore >> и также нам понадобится << sequelize >> и
так же для того чтобы могли обращаться с браузера к нашему серверу нам понадобится << cors >> и
чтобы задавать переменное окружение установим также модуль << dotenv >>

<< npm install express pg pg-hstore sequelize cors dotenv >>

После установки все модули можно увидеть в поле << dependencies >> в файле << package.json >>

<< package.json >>

Так же как << -D >> зависимость, то есть зависимость для разработки установим << nodemon >>

<< npm -D nodemon >>

он нужен для того чтобы при каждом изменений в коде не перезапускать сервер и он как раз будет
перезапускать его автоматически.
Дописываем:
<< npm install -D nodemon >>

Следующим этапом напишем скрипт который будет запускать приложения в режиме разработки для
этого в поле << "scripts" >> пишем « "dev": "nodemon index.js" >>

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

<< "nodemon index.js" >>

Теперь перейдем к созданию структуры приложения в файле << index.js >>

<< const express = require('express') >>

с помощью << require >> можем импортировать какие-то модули в файл, в данном случае
импортируем << 'express' >>.

Следующим этапом создадим объект вызвав функцию << express >>

<< const app = express() >>

с него и будет начинается запуск нашего приложения.

Следующим этапом укажем порт на котором наше приложение будет работать

<< const PORT = 5000 >>

и затем у << app >> вызываем функцию << listen >> в которой указываем какой порт должен
прослушивать наш сервер

<< app.listen(PORT, () => console.log(`Server started on port ${5000}`)) >>


а вторым параметром передаем << !callback! () => >> который отработает при успешном запуске
сервера и еще здесь напишем что сервер стартовал на таком порту << 5000 >>.

Теперь в терминале пишем тот самый скрипт который мы сделали в << package.json >> с помощью
командой << npm run dev >> запускаем. Если в терминале вы увидели вот это сообщение

значит сервер запустился успешно, но вот так вот порт объявлять статично не очень хорошая практика

<< const PORT = 5000 >>

поэтому всю конфигурацию мы будем выносить в переменное окружение, для этого создадим файл
<< .env >> и здесь просто указываем название переменной равно его значение сделаем порт
например 7000

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

<< const PORT = process.env.PORT || 5000 >> вместо << const PORT = 5000 >> в файле << index.js >>

<< process.env.PORT >> то есть название в самой переменной, если же эта переменная не задано
тогда по умолчанию будем ставить 5000 но для того чтобы наш сервер мог считывать этот файл,
необходимо также сюда импортировать конфиг из модуля << .env >> который мы установили самом
начале, единственный момент что вот здесь конечно мы передаем саму переменную

<< app.listen(PORT, () => console.log(`Server started on port ${PORT}`)) >>

но не 5000 порту и как видите переменная считалось файлов и сервер стартовал на 7000-нам порту но
вернем как было на 5000-нам порту в файле << .env >>.
[BACKEND] - Подключение к базе данных

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

Создаем файл < db.js > и здесь мы опять же импортируем << Sequelize >> и сразу же делаем
деструктуризацию так как модуль большой и нам нужен конкретно вот этот вот класс.

<< const {Sequelize} = require('sequelize') >>

Затем на выходе мы экспортируем объект который мы создаем из этого класса

<< module.exports = new Sequelize() >>

в конструкторе как раз и будем указывать конфигурацию.

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

В данном курсе в качестве системы как я уже говорил будем использовать PostgreSQL поэтому он
должен быть установлен вас на компьютере. Вместе с СУБД у вас установится программа которая
называется << pgAdmin >> с помощью нее можно удобно управлять базой данных
Сейчас на примере все рассмотрим.

Первое с чего начнем это создадим новую базу данных

напишем online_magaz и сохраняем. База данных появляется в списке теперь приступим к


конфигурации.

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

<< DB_NAME=online_magaz >>

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

<< DB_USER=postgres >>

здесь укажем главного пользователя который создается при установке сервера СУБД и его пароль вы
также указываете при установке СУБД

<< DB_PASSWORD=123 >>

Так как мы в режиме разработки хост указываем << localhost >

<< DB_HOST=localhost >>

и по умолчанию порт 5432

DB_PORT=5432

И теперь все эти переменные передаем в конструктор

первым параметром передаем название базы данных


вторым передаем имя пользователя под которым мы подключаемся

третьем передаем пароль

и затем передаем объект у которого будут следующие поля необходимо указать << dialect >> это либо
<< postgres >> либо << mysql >> либо какая-то другая СУБД

затем указываем хост и соответственно порт

Возвращаемся в index.js и теперь сюда импортируем объект который мы сделали файле << db.js >> и
которые оттуда же экспортировали

импортируем его сюда и теперь необходимо только вызвать функцию для подключения к базе
данных для этого мы создадим функцию << start >> сделаем ее асинхронной << async >> поскольку
все операции с базой данных являются асинхронной
const start = async () => {}
все это обернем в блок << try >> << catch >> чтобы отлавливать потенциально возможные ошибки,
чтобы наше приложения не падала и вызов функции << listen >> перенесем как раз в этот блок << try
>> и не забываем эту функцию вызвать чтобы сервер нас принципе запустился, теперь здесь
вызываем у объекта который мы сюда импортировали функцию << authenticate >> с помощью нее
будет устанавливаться подключение к базе данных, среда разработки нам подсказывает что эта
функция асинхронная << async >> поэтому вызываем << await >>, следующим этапом у этого же
объекта вызываем функцию << sync >> эта функция будет сверять состоянии базы данных со схемой
данных которые мы опишем чуть позже.

Как видите влогах уже появились какие-то запросы ошибку мы не получили значит к бд мы
подключились успешно.

11:30 - [BACKEND] - Строим диаграмму базы данных

Cледующим этапом построим диаграмму схемы базы данных это также очень важный процесс для
этого откроем сайт draw.io.

Cпускаемся чуть ниже находим вкладку entity relation и здесь есть вот такой элемент с таблицей
пишем название таблицы мы начнем с описание сущности пользовател “ user ”, у каждой сущности
обязательно должен быть уникальный идентификатор который однозначно определяет сущность это
“ id “ , также у пользователя будет “ e-mail “ “ password ” и также у пользователя будет роль “role
STRING “, по-хорошему у каждого пользователя должен быть массив ролей то есть он может быть
одновременно и пользователем и модераторам и администратором но в нашем случае у
пользователя будет всего одна роль, он либо просто пользователь либо администратор.
И так создаем следующую сущность, эта сущность корзины пользователя “ basket “, здесь будет всего
два поля, это уникальный идентификатор “ id “ и ссылка то есть внешний ключ на пользователя “
user_id” чтобы понимать кому эта корзина принадлежит.

Связь между этими таблицами (“ user “ и “ basket “) будет один к одному, то есть одному
пользователю может принадлежать только одна корзина в то время как одна корзина может
принадлежать только одному пользователю

Следующая сущность эта сущность устройство конкретного девайса “ device “ , у него будут
следующие поля, само собой разумеется айди “ id “, название устройства “ name “, его цена “ price “ и
рейтинг конкретного устройства от 0 до 5 “ rating ”, также будет изображение устройство “ img “, и в
этой сущности еще будет 2 ссылки: два внешних ключа один на тип устройства “typeId” и другой на
бренд “brandId”, под типом я подразумеваю тип электроники ( холодильник, телевизор или например
смартфон), смартфон под брендом я подразумеваю samsung , lenovo или например смартфон apple, и
вот все эти типы и бренды будут храниться также в отдельных двух таблицах, одну называем
соответственно тип “type” вторую называем соответственно бренд “brand”, здесь связь между
таблицами будет следующая: одному типу “type” может принадлежать несколько устройств “device” в
то время как одному бренду “brand” также могут принадлежать несколько устройств “device”
соответственно связи между этими таблицами один-ко-многим. У сущности типа “type” будет всего
два поля это “id” и название “name” и у бренда будет то же самое это “id” и название “name”. Эти две
таблицы будут также между собой связаны поскольку не каждому типу принадлежит бренд например
apple или стиральные машины не производит, связь между этими сущностями будет много ко многим
поскольку один бренд может принадлежать нескольким типам и в то же время один тип может
принадлежать нескольким брендом также у каждого устройства будет какая-то индивидуальная
информация, например у телефона можно описать оперативную память а у стиральной машины нет,
для этого создадим отдельную таблицу которая будет хранить информацию о конкретном девайсе
“device_info”, у нее будет “id”, ссылка на устройство “device_id”, связи между этими таблицами один-
ко-многим (“device” “device_info”), один девайс может иметь много характеристик и также в каких-то
полях эти характеристики необходимо хранить поэтому создаем поле “title” там будет название
характеристики например оперативная память и “description” там будет уже само описание например
там 8 гигабайт. У каждого пользователя в корзине “basket” могут находиться какие-то товары для
этого также создадим еще одну табличку назовем ее “basket_device” это таблица будет неким
связующим звеном между корзиной “basket” и устройством “device”, она будет содержать ссылки как
раз на корзину “basket_id” и на соответственно устройство “device_id”, вот здесь связь (“basket” и
“basket_device”) будет один ко многим поскольку одна корзина может содержать большое
количество устройств и в то же время как устройство которое находится в корзине однозначно
ссылается на реальное устройство которое есть у нас в магазине поэтому тут связь будет один к
одному (“basket_device” и “device”).
16:50 - [BACKEND] - Модели данных и связи между ними

Теперь эту диаграмму мы перенесем в наш проект и реализуем схему того как эти данные будут уже
реально хранится в базе данных, создаем папочку “modules” и в ней файлик “modules.js” здесь мы
модели данных как раз и будем описывать, сюда мы импортируем объект “sequelize” который мы
создавали в файле “db.js”. Из самого пакета “sequelize” нам понадобится импортировать класс
“DataTypes” с помощью которого описываются типы того или иного поля (string, интеджер, массив и
так далее) и начнем описывать первую модель, начнем с модели пользователя, у “sequelize”
вызываем функцию “define” передаем туда объект а первым параметром указываем название этой
модели в данном случае пишем “user” и внутри объектов описываем уже поля которые будут у этой
модели, первое поле “id”, тип у этого поля будет интеджер “INTEGER” то есть числовой, это будет
первичный ключ и он будет авто инкрементироваться то есть при создании каждого нового объекта
“id” будет 1,2 и так далее, следующее поле это “e-mail” тип у него уже будет строковый то есть
“STRING” он должен быть уникальным поскольку двух пользователь с одинаковыми “e-mail” в
системе быть не может, третье поле это соответственно пароль, “password” уже уникальным быть не
должен, пароль может повторяться у разных пользователей и последнее поле это роль “role”, как я
уже сказал роль будет тоже просто “STRING” и по умолчанию будем делать пользователя просто
юзерам, роль будем указывать большой буквой соответственно админ либо же просто пользователь.

Cоздаем следующую модель это будет модель корзины “Basket” здесь параметрам также указываем
“basket” здесь у нас будет “id” и “user_id”.

Создаем модель для “basket_device” здесь тоже будет просто “id” и приступаем теперь к самой
большой сущности, сущности устройство “Device” здесь все будет по аналогии.

Модель типа “Type” и бренда “Brand” у нас одинаковые два поля, это “id” и “name” также должно
быть уникальным и не может быть пустым, тоже самое делаем и для бренда, остается у нас девайс
info

В “DeviceInfo” у нас будет два поля это название, характеристики и описание характеристики, это
строковое значение “STRING” и они также не могут быть пустыми.

И теперь настал момент описать того как эти модели связаны друг с другом, обращаемся к моделей
вызываем соответствующую функцию либо hasMany либо hasOne, таким образом мы сообщаем что
одна запись девайса “Device” в базе данных содержит много записей с характеристиками, а для
“DeviceInfo” мы указываем что эта сущность принадлежит девайсу и вот такая вот двухсторонняя
связь получается.

Остается экспортировать отсюда все эти модели чтобы мы в дальнейшем в других каких-то файлах
могли их использовать.

В файле “index.js” настроим “cors” для того чтобы мы могли отправлять запросы с браузера для этого
импортируем сюда функцию “cors” из пакета “cors” который мы установили в начале.

Функцию “use” который мы вызываем у “app” также функцию “use” мы передадим “express.json” для
того чтобы наше приложение могло парсить “json” формат. могло парсить “json” формат.
25:30 - [BACKEND] - Роутинг и эндпоинты

Теперь зададим каркас нашего приложения, начнем из маршрутов по которым будут отрабатывать те
или иные методы. Cоздаем папочку “routes” для типов брендов, корзины, устройств пользователей. У
нас будет отдельный файлик с маршрутами. А файл “index.js” будет все эти маршруты объединять,
грубо говоря связующее звено, основной роутер нашего приложения. Здесь мы получаем “Router” из
“express”. Cоздаем объект этого “router” и по итогу этот “router” из этого файла мы экспортируем так
как файлы “typeRouter.js”, “brandRouter.js”, “deviceRouter.js” и “userRouter.js” будут являться под
роутерами грубо говоря какой-то его частью мы должны вот в этом основном роутере
“routes\index.js” это указать. Вызываем функцию “use” первым параметром указываем URL по
которому тот роутер будет отрабатывать, а вторым необходимо будет чуть позже передать сам
роутер. В файле “brandRouter.js”какие методы у нас будут по работе с брендами, это соответственно
метод “post” для того чтобы бренд создавать и также будет еще один метод соответственно “get” для
того чтобы все бренды получать. Для типов и брендов (“typeRouter.js” и “brandRouter.js”) маршруты
будут абсолютно одинаковые, для пользователя (“userRouter.js”) уже будет немного отличаться, здесь
будет 2 "post” метода, соответственно регистрация и авторизация и также будет один метод “get” с
помощью которого мы будем проверять авторизован пользователь или нет, это будет делаться по
“jwt token“. Для “deviceRouter.js” будут те же методы на создание и получения но добавляется еще
один, для того чтобы получить отдельно конкретно взятый девайс после того как мы перешли на
страницу подробной информации. Теперь возвращаемся в “routes\index.js” и все эти роутеры
которые мы только что сделали импортируем в этот файл и следующим этапом сопоставляем
маршруты которые мы указали соответствующим роутером. Над данном этапе мы объединили все
четыре роутеров в один, но наш сервер об этом ничего не знает поэтому ему об этом необходимо
сообщить, возвращаемся в корневой “server\index.js” и сюда импортируем как раз основной роутер
который связывает все остальные, затем по аналогии вызываем функцию “use” первым параметром
указан URL по которому роутер должен обрабатываться, в нашем случае это “/api”, на вторым
параметром передаем сам роутер “router”.

Чтобы роутер “router” не становился слишком толстым отделяем логику. Для этого создадим папочку
“controllers” и в ней создадим для каждого роутеров соответствующий контроллер, начнем с
“userController.js” здесь создаем одноименный класс “UserController” можно обойтись и без класса,
просто создавать функции, но классы грубо говоря группируют и здесь создадим соответствующие
функции, это регистрация “registration”, логин “login” и функция которая будет проверять авторизован
пользователь или нет “check”. Теперь проделаем ту же самую процедуру для остальных
контроллеров “brandController.js”, “typeController” и “deviceController.js”
54:20 - [BACKEND] - Регистрация, авторизация, jwt токен, bcrypt

Осталось разобраться с регистрации и авторизации но перед этим небольшое теоретическое


вступлением.

Авторизация будет происходить под “JWT token”. “JWT token” или же “token” доступа это простая
строка разделенная точками на три части, по большей части нас интересует центральная часть это
“PAYLOAD”, туда мы будем прятать данные о пользователе, это его email, id и его роль. После того как
пользователь зарегистрировался, вел e-mail и пароль, для него генерируется подобный токен, все его
данные вшиваются в середину и что тут важно понимать эти данные никак не шифруются они в
принципе никакой секретной информации не несут и мы на клиенте можем спокойно
расшифровывать, но проверить на то, валиден “token” или нет, можно только с помощью секретного
ключа который объявлен на сервере и его по идее уже никто знать не должен, в общем пользователь
вводит e-mail пароль, первую очередь мы проверяем существует ли пользователь с таким e-mail в
нашей системе, если да то сравниваем пароль который находится в базе данных с паролем который
написал пользователь, если эти пароли совпадают мы генерируем “JWT token” и отправляем его на
клиент, после чего на клиенте этот “token” где-то сохраняется, либо в куках “cookie-uri“либо в local
storage, безопасней конечно в куках “cookie-uri“,
затем этот “token” прикрепляется к запросам где необходима авторизация, допустим в корзину мы не
можем зайти если мы не авторизованы. Мы авторизуемся, сервер генерирует “token”, возвращает его
обратно на клиент, затем мы нажимаем на кнопку войти в корзину, и у нас отправляется запрос на
получение товаров, к этому запросу в “headers”, в “http” заголовки мы добавляем “authorization” и
туда помещаем тот самый “token” который мы достаем опять же из “cookie” или же из local storage,
server валидирует этот “token” по секретному ключу, если он валидный то пользователь попадает на
страницу корзины и получать все товары которые у него там находятся. В общем с помощью “JWT
token” обеспечивается доступ к той или иной функции.

В терминале “npm i jsonwebtoken bcrypt”

Первое что мы сделаем, это установим несколько модулей, один это “JSON web token” для генерации
“JWT token”, а второй “bcrypt” для того чтобы хэшировать пароли и не храните в базе данных в
открытом виде.

Прям в контроллер “userController.js” импортируем “bcrypt”, также нам понадобятся модели


пользователя и корзины. Начнем с регистрации “registration”, здесь в первую очередь получаем из
тела запроса email и соответственно пароль, и как я уже говорил роль у нас носит такой
второстепенный характер, она нигде не задается, поэтому её будем принимать тоже в запросе просто
чтобы мы могли отдельно создавать пользователей и отдельно создавать администраторов, затем
сделаем небольшую проверку если в теле запроса email или пароль пустые то будем возвращать
ошибку на клиент, напишем что некорректный email или пароль. Следующий этап это проверить
существует ли пользователь с таким емейлом в системе, возможно уже кто-то под этот e-mail
пользователя пытался зарегистрировать, поэтому указываем условия, в него передаем e-mail.
Следующим этапом, задаем условия если нам вернулся пользователь и он не пустой то тогда опять
возвращаем ошибку в которой указываем что пользователь с таким емейлом уже существует, если
это условие не выполнилось, пользователя мы не нашли, тогда мы можем зафиксировать пароль и
создать уже нового пользователя, функция хеширования пароля в “bcrypt” асинхронная, вызываемы
её, первым параметром мы передаем непосредственно сам пароль пользователя который мы
получали в теле запроса, а вторым параметром передаем сколько раз мы его будем хэшировать,
слишком большое число не указываем, напишем допустим 5. Следующим этапом с помощью
функций “create” пользователя создаем передаем туда e-mail, роль и пароль. Cразу же для
пользователя создаем корзину, вызываем функцию “create” у модели basket и все что туда
необходимо передать это id пользователя “userId” которое мы можем получить уже из созданного
объекта самого пользователя, затем нам надо сгенерировать тот самый “JSON web token”,
импортируем сюда файл контроллера модуль “jsonwebtoken” который мы уже установили, вызываем
функцию “generateJWT”, туда передаем id пользователя “user.id”, его e-mail “user.email” и
соответственно роль “user.role” мы уже получаем из самого пользователя, вот на данном моменте
роль у нас нигде не затеряется потому что по дефолту присваивается “user” после того как
пользователь был создан, из этой функции мы возвращаем результат выполнения функций “sign” ну и
по итогу нам вернется как раз “token”.

Реализовываем функцию логина “login”, здесь также из тела запроса получаем email и пароль, сразу
делаем деструктуризацию, затем нам необходимо убедиться что пользователь с такими емейлом в
базе данных у нас существует поэтому опять же по условию ищем этого пользователя, но здесь в
отличие от регистрации проверяем уже что если пользователь не найден то тогда возвращаем
соответственно ошибку, добавляем “next” третьим параметрам и для разнообразия давайте
передадим например “internal” и напишем что пользователь с таким именем не найден, если это
условие мы проскочили нам необходимо убедиться в том что пароль который написал пользователь
совпадает с тем которая лежит в базе данных, но в базе данных у нас лежит зафиксированный пароль
поэтому с помощью “bcrypt” функции “compareSync” она является синхронной, сравниваем эти
пароли, первым параметром передаем пароль который написал пользователь, а второй получаем из
базы данных, затем если пароли не совпадают так же возвращаем ошибку, затем опять же
генерируем “token” с помощью функций “generateJwt” и передаем туда все необходимые параметры
и на клиент возвращаем по аналогии с регистрации сам “token”.

01:04:10 - [BACKEND] - Middleware, проверяющий авторизован ли пользователь

Cоздаем папочку “middleware” и в этой папки создадим “authMiddleware.js” именно в нем мы будем
декорировать “token” и проверять его на валидность, если “token” невалидный будем возвращать
сразу ошибку о том что пользователь не авторизован, отсюда сразу экспортируем функцию
“middleware” здесь сразу сделаем проверку если “method” у нас равен “OPTIONS” то пропускаем, нас
интересуют только “post”, “get”, “put”, “delete”. Если где то все таки ошибка у нас возникло
возвращаем “status code 401”, в сообщений напишем что пользователь не авторизован, теперь
приступаем к логике, первое что нам необходимо сделать это из “headers” выцепить сам “token” но в
“header” обычно помещают сначала тип “token” а потом сам “token”, поэтому нам по пробелу два
этих слово друг от друга надо отлепить и по первому индексу получить непосредственно сам “token”
если этого “token” нет, если он не существует, опять же возвращаем ошибку. На надо его
раскодировать, импортируем сюда модуль “jsonwebtoken” и вызываем функцию “verify” который
будет проверять “token” на валидность, сюда необходимо первым параметром передать сам “token”
а вторым секретный ключ “SECRET_KEY” который мы помещали в переменное окружение.
Следующим этапом к “req” например “user”добавим данные которые мы вытащили из этого “token” и
во всех функциях этот “user” будет доступен, затем вызываем функцию “next” и этим мы вызываем
следующий в цепочке “middleware”. Переходим в “userRouter.js” сюда этот “middleware”
импортируем и передаем его вторым параметром “get” запрос который будет проверять
пользователя на авторизованность.

01:07:50 - [BACKEND] - Middleware, проверяющий роль пользователя

Добавлять типы, бренды, получать их и добавлять устройство не должен уметь делать абсолютно
любой пользователь, нам необходимо убедиться в том что добавить новые устройства в магазин
пытается именно администратор, поэтому создаем новый “middleware” и копируем туда код из
“authMiddleware.js” потому что логика будет очень похожа, но отсюда мы будем экспортировать
функцию которая не принимает request response как
предыдущими dvr а принимать параметрам

роль и уже из-за этой функции мы будем

возвращать сам тот самый медальер своего

рода замыкание то есть мы вызываем

функцию передаем туда роль и эта функция

нам возвращает уже медальер и здесь

единственное отличие это нам необходимо

будет после того как токен мы

декодировали выцепить оттуда роль

пользователя и сравнить ее с ролью

которую мы передали в мидл и если они не

совпадают возвращаем status code 403 то

есть у вас нет доступа и пишем это

сообщение на этом в принципе медальер

закончен до есть проблема в том что код


дублируются на тратить время на

разделении логике мы сейчас не будем

переходим в type роутер сюда этот middle

ear мы импортируем

и вторым параметром мы этот middle в

р-не просто передаем а вызываем нам

необходимо чтобы после вызова этой

функции как раз туда попал видел веер

параметрам передаем роль администратора

теперь давайте попробуем какой-нибудь

тип создать здесь напишем допустим

lenovo

отправляем запрос и получаем ошибку в

данном случае мы talkin' не указали

вообще поэтому получаем что пользователь


не авторизован пробуем добавить хэдер

авторизуемся скопируем talkin'

им его здесь в хедер и отправим запрос

еще раз теперь мы получаем сообщение о

том что у нас нет доступа но попробуем

создать еще одного пользователя

равенна registration сделаем например

юзер 1 и здесь мы добавим еще одно поле

в которой укажем роль роль указываем как

администратора

большими буквами

управляем

прос получаем токен теперь копируем этот

токен

и добавляем его в авторизация старый


talkin' удаляем и отправляем запрос и

видим что товар был создан таким образом

товары в нашем магазине теперь могут

добавлять только администраторы

этот мидлер необходимо передать еще на

создание девайсов брендов но это вы

можете сделать уже и сами таким образом

друзья у нас получилось можно сказать

полноценное rest api по хорошему

добавить еще удаления товаров наш сервер

может раздавать статику мы можем

регистрироваться авторизовываться и на

этом в принципе можно завершать основная

составляющая интернет-магазина готова и

мы можем переходить наконец-то фронту


клиентской части нашего приложения

терминале переходим в папку клиент и с

помощью утилиты cray 3 акт об

разворачиваем ряд приложения

те поудалял лишние файлы оставил только

индекс ртс чтобы лишние файлы не

мозолили глаза теперь установим

необходимые зависимости нам понадобится

аксиос для того чтобы отправлять запросы

на сервер react раутер дом для

постраничной навигации моб x это стоит

менеджер и mop x5 light для того чтобы

связать модекс

с функциональными компонентами react а

также мы будем использовать bootstrap


для того чтобы не тратить время на

верстку но думаю с bootstrap а многие

знакомы тут особо поясните ничего

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

установим его также нам понадобится

стиле пролистаем здесь чуть ниже здесь

можно вот так импорта медь и стиле

подгружать но мы скопируем линк и

добавим его в корневой index.htm и

добавим link самый самый низ вот эти

всякие лишние комментарии мета тэги

поудаляем не люблю когда что-то мешает

перейдем в ps это будет основным

компонентом нашего приложения здесь

напишем что все работает и команды npm


старт запустим ряд приложения откроем

браузер видим надпись workin' значит

приложение работает теперь зададим

структуру нашего приложения создадим все

папки которые на в дальнейшем

понадобятся

первая папка star там мы будем

взаимодействовать смог x и хранить

какие-то данные вторая папка пейдж там

будут корневые компоненты которые будут

являться страницами и соответственно

папка с компонентами там будут всякие

навбар и и все в таком духе и сразу же

создадим странице 1 будет страница с

авторизацией если вы используете веб


шторм пишем rsc

нажимаем тab и компонент развернется

здесь напишем что это components

авторизацией сразу же создаем компонент

shop

это будет в принципе основная страница

там будут как раз карточки с

устройствами постраничный вывод список

брендов и так далее следующая страница

эта страница уже когда мы откроем

конкретное устройство там будут написаны

характеристики возможность добавить в

корзину

назовем ее девайс пейдж еще одна

страница
это админ-панель там администратор будет

добавлять типы бренды и устройство в наш

магазин и заключительная страница эта

страница с корзиной ем реализовывать не

будем это ваше домашнее задание теперь

известно какие страницы будут в нашем

приложении и мы можем реализовать

навигацию по ним для этого в папке

компонент создадим новый компонент и

назовем его ip роутер в нем будет

описано логика навигации по страницам на

какие-то страницы сможет зайти любой

человек на какие-то только

авторизованный здесь нам понадобятся

следующие компоненты это switch road и


redirect из пакета реактор outer дом

который мы установили

чуть позже подробно о каждом поговорим и

чтобы в принципе навигация по странице

было возможно все наше приложение

необходимо обернуть браузер роутер

который также импортируем из react

раутер дом и сюда сам роутер добавляем

ип раутер который мы сделали следующим

этапом создадим файлик назовем его

road джесс там будут описаны все

маршруты конкретным страницам которые

есть в нашем приложении здесь у нас

будет два массива один массив мы назовем

aus роуз в нем будет список маршрутов


только до тех страниц которым имеет

доступ авторизованный пользователь и

второй массив public роуз на эти

маршруты может перейти абсолютно любой

пользователь сразу оба массива отсюда

экспортируем и в него добавляем объект у

каждого объекта будет путь это

соответственно ссылка по которой та или

иная страница будет отрабатывать и

компонент это непосредственно уже сама

страница здесь указываем компонент

админа в данном случае прл админ будет

вызываться компонент админа но вот так

вот виде строки указывать маршрут

является не очень хорошей практикой


представьте у вас 20 страниц

есть вложенные под страницы будет

путаница

для этого создадим папочку utils и в ней

файлик с константами отсюда будем

экспортировать константы

например админ road и внутри указываем

путь до этой папке в дальнейшем мы можем

эти константы просто экспортировать

использовать нужных местах не боясь

ошибиться в том или ином маршруте

создаем по такой константе для каждой

страницы для логина и для регистрации

эти маршруты отделяем компонент у нас

будет как бы один но страница разный


возвращаемся файлик роуз и теперь путь

передаем как константу просто пишем

админ road среда разработки подхватывает

и делает импорт скопируем и будет еще

одна страница на которую может зайти

только авторизованный пользователь эта

страница с корзиной то есть еще раз

страница админа

и страница с корзиной будет доступна

только для пользователя который

авторизован

именно поэтому мы сделали отдельный

массив теперь делаем road и для

публичных страниц это соответственно

страница самого магазина на нее может


зайти пользователи без авторизации

страница для логина

страница для регистрации и страница для

просмотра конкретного устройства но при

просмотре конкретного устройства вёл

через flash будет также

и айди конкретного устройства чтобы мы

могли делать запрос на сервер и это

устройство получать например у так

девайс с лишь один девайс flash 2

зависимости отойди будем переходить на

страницу конкретного устройства теперь

подправим компоненты

здесь у нас shop здесь у нас aus здесь

тоже us то есть для регистрации для


логина будет одна и та же компонента

то в зависимости от маршрута в строке

запроса будем выводить либо регистрацию

либо авторизацию на данном этапе

маршруты мы описали но они работать не

будут их необходимо оживить переходим в

протер и возвращаем отсюда components

which

switch работает таким образом мы

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

страница авторизации регистрации и

магазина и если ни один из этих

маршрутов не отработает то использовать

level какой-то не корректный адрес тот

работать самый последний который указан


в этом свече своего рода группировка

следующим этапом создадим какую нибуть

переменную это будет просто заглушка

маковая переменная назовем ее es aus она

будет показывать авторизован

пользователь или нет если она фолз он не

авторизован если труп соответственно

авторизован в дальнейшем мы будем

хранить это где-нибудь в створ

отправлять talkin' на сервер убеждаться

в том что он валидный и затем эту

переменную присваивать пока что сделаем

заглушку затем мы импортируем сюда

массив с роботами которые доступны

только авторизованному пользователю


пробегаемся по нему с помощью функции

map сразу делаем де структуризацию и

вытаскиваем из объекта путь и компонент

и для каждого элемента массива мы

отрисовываем road где указываем путь и

компонент который по этому пути должен

отрисовывать если сейчас сложно

поставьте на паузу вникните не только

потом продолжайте также укажем ключ

exact который говорит о том что путь

должен точно совпадать и поскольку мы

пробегаемся по массиву

не забываем указывать ключ качестве

ключа укажем путь поскольку

подразумевается что путь каждой странице


уникальный но если все оставить так то

эти маршруты будут доступны каждому

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

в данном случае проверяем если

пользователь авторизован

и эта переменная равняется true то этот

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

скопируем вот этот кусок кода вот это

условие мы убираем

для публичных раутов мы в любом случае

эти road и создаем то есть неважно

пользователь авторизован

или нет маршруты будут отрабатывать

открываем браузер сразу попадаем на

страницу шопов попробуем по переходить


откроем страницу девайса откроем

страницу логина

видим все маршруты отрабатывают но

попробуем открыть корзину не видим

пустую страницу поскольку на нее может

зайти только авторизованный пользователь

изменим значение переменной и сразу

попадаем на страницу вернем falls

и попробуем перейти по какой-нибудь

несуществующей страницы как видим мы на

ней и остаемся именно для этого мы свечи

сделали как я уже сказал если в свече не

отрабатывает ни один из маршрутов

отрабатывать самый последний поэтому

последним маршрутом добавим в директ на


страницу shope то есть магазина и как

видим теперь если написать какой-нибудь

левый url

нас redirected на страницу магазина но

если мы перейдем на пример на странице

устройство то она успешно открывается

теперь разберемся вот с этой вот

переменной она нам понадобится в

нескольких компонентах поэтому вынесем

ее в отдельное глобальное хранилища в

папке stor

создадим файлик назовем его users тор и

отсюда по дефолту

экспортируем одноименный класс сейчас мы

будем работать уже small bags


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

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

создании объекта данного класса здесь

создадим несколько переменных эта

переменная как раз и south нижнее

подчёркивание мы ставим для того чтобы

обозначить что эта переменная

изменяться не может это не какое-то

правило это скорее просто соглашение о

том что переменный с таким названием

нельзя изменять и обязательно вызываем

функцию made of the обзора был которую

импортируем и смог x и параметрам в нее

передаем объект здесь теперь мы bags

будет следить за изменениями этих


переменных и соответственно при их

изменении компоненты будут перри рендере

ваться теперь создадим

экшены это функции которые как то

состояние изменяют в данном случае это

простая функция которая параметрам

принимает булево значение и присваивает

его перемены и south здесь все

элементарно просто опять же если что то

непонятно можете посмотреть ролик промо

bags у меня на канале он небольшой но

информацией насыщен и также создаем

экшен для изменения пользователя

следующим этапом создадим одноименные

геттеры они нужны для того чтобы


получать какие-то переменные из нашего

состояния

но называемых уже без нижнего

подчеркивания к ним мы будем обращаться

как к обычным объектом это так

называемый компьютер функции они

вызываются только в том случае если

ременное которая используется внутри

была изменена своего рода оптимизация

теперь разберемся с тем как это

состояние прокидывать наши компоненты

здесь воспользуемся контекстом реактор

он создается с помощью функций crate

контекст не забываем импортировать его

не зря акт параметрам передадим на у и


теперь у этого контекстов есть компонент

провайдер

в него оборачиваем наше приложение тут

не забываем поставить запятую и помещаем

середину

и в props вылью теперь можно передавать

какие-то данные нашем случае передадим

туда объект и в поле юзер создадим новый

объект класса users top который мы

сделали теперь откроем браузер и

попробуем перемену

es aus из этого stora получить сразу

делаем де структуризацию вызываем фокус

контекст и туда передаем тот самый

контекст который мы создавали


единственное вернемся и экспортируем его

отсюда

возвращаемся в протер

импортируем его сюда

теперь попробуем вывести юзера влоги и

посмотрим что там находится

единственно вот здесь переменную и south

мы получаем теперь как раз из юзер стори

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

влогах объект которого как раз есть те

поля

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

образом у нас теперь есть глобальное

хранилище и в любом месте нашего

приложения мы можем получать из него


данные сразу создадим второй stor

назовем его девайс top по-хорошему бы

все это декомпозировать но у нас кроме

типов и бренда в принципе ничего не

будет поэтому их тоже засунем сюда

поменяем название

уберем вот эти вот поля

варим следующие здесь у нас будут

соответственно типы

это будет массив и до тех пор пока мы не

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

поместим туда пару объектов для того

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

делаем с брендами и с девайсами

объекты в массивах полностью


соответствует тем что описаны у нас

моделях на викенде далее уже по

известной схеме создаем экшены и

присваиваем соответствующим переменным

соответствующие значения и для каждой

переменной также делаем геттеры

теперь вернемся в яндекс джейс и здесь

помимо users to our добавим еще девайс

top точно также создаем объект и в

принципе на этом каркас приложение готов

можно приступать к верстке есть вот

такой макет фильма есть страница

авторизации

страница регистрации вот так выглядит

админ панель здесь будут всплывающие


окна так выглядит страница магазинов это

все прототипы не обязательно что в нашем

приложении должно выглядеть вот так

единственно вот здесь на странице

магазина сверху еще будет панель с

брендами так будет выглядеть страница

просмотра конкретного устройства

и корзину вы уже реализуете сами если

будете пытаться повторить

итак начнем снова баров в папке

компонент создаем компонент названием на

в бар

с помощью сниппет а разворачиваем

компонент нажимаем тab

здесь сразу получаем users top из


контекста поскольку в зависимости от

того авторизован пользователь или нет на

в бар будет отображаться по разному

как я уже говорил использовать мы будем

bootstrap откроем документацию вкладку

компонент и здесь найдем на в бар

открываем его

здесь есть разные варианты выберем

например вот такой

скопируем кусок кода

ставим его здесь

скопировал лишние удалим его

вам импортировать компоненты из

bootstrap вот эту вот форму мы удалим

она нам в принципе не нужно затем


перейдем в компоненту об и здесь надо

про утром добавим наш навбар он будет

отображаться на каждой странице

открываем приложение обновляем страницу

и вот такой набор у нас получился

возвращаемся к коду открываем компонент

вот этот бренд мы отсюда уберем и

сделаем на его месте обычный на blink из

реактора утер дом

и внутри напишем название магазинов

пусть он будет называться купить девайс

и пусть ссылка ведет у нас на главную

страницу магазина вот так вот это

выглядит

поменяем цвет чтобы не тратить время на


создание файлов со стилями какую-то

часть мы будем писать напрямую вот так

вот в онлайне и какую-то часть или будем

указывать bootstrap of скими классами на

навигационную панель сделаем virgin left

out a чтобы сдвинуть ее вправо и опять

же онлайн стилем поменяем цвет сделаем

его опять же белым

вот эти вот bootstrap of ski и ссылке мы

уберем и сделаем обычные кнопки

bootstrap они так и называются батон

только пишем с большой буквы

первая кнопка будет у нас соответственно

переводить на страницу авторизации

вот так вот она выглядит по дефолту мне


такой вариант не нравится поэтому можем

его поменять свой стиль вариант укажем

outline white и кнопка будет вот такой

также создадим вторую кнопку она будет

переводить на админ-панель так и напишем

но в зависимости от того авторизован

пользователь или нет нам надо будет

отображать разные кнопки здесь

воспользуемся тернарный оператор am если

пользователь авторизован будем

отображать первый блок если не

авторизован будем отображать второй блок

единственно если пользователь

авторизован здесь будет у нас админ

панель и кнопка выйти осени авторизован


кнопка авторизации если исправим users

top натру обновим страницу панель будет

выглядеть уже по-другому

но чтобы панель перри рендерилось в

режиме реального времени чтобы малыш

смог отслеживать изменения значений

состоянии

необходимо обернуть компонент функцию

observer убедимся в том что все работает

при клике на кнопку повесим слушатель

события и будем users top вызывать

функцию set is a us и делать ее в

значение true

откроем браузер нажмем на кнопку

авторизация и видим что панель сразу


перерисовывается единственно кнопки у

нас прилипли к друг другу поэтому для

кнопки выйти

сделаем отступ слева теперь чтобы все

это дело еще отцентровать чтобы у нас со

страницы это все была на одном уровне

обернем весь на в бар в контейнер и вот

эту всю начинку поместим внутрь

а ним и видим что он у все от центра

валось единственно вот этот суп я бы

сделал чуть поменьше вот так выглядит

получше теперь откроем макет фильма и

приступим к форме авторизации

и регистрации для этого у нас уже есть

созданный компонент он называется aus и


мы сделаем его универсальным он будет

как под регистрацию так и под

авторизацию все оборачиваем в контейнер

сразу делаем его flexo вaм и justify

контент и лай на этом сделаем центр

чтобы отцентровать содержимое как по

горизонтали так и по вертикали теперь он

лайн стилем зададим еще и высоту

контейнера и и мы будем получать от

высоты всего браузера минус высоты

навбара

если сейчас откроем браузер увидим что

надпись аусат центра валось теперь

сделаем саму форму внутри

создаем компонент форм тоже bootstrap


овский компонент импортируем его но саму

форму поместим в компонент карт тарт это

обычная карточка которая обрамлена

рамкой

и зададим ширину для карточки сделаем

наверное пикселей 600

также bootstrap of skin классом зададим

внутренние отступы

над формой сделаем надпись авторизация

поместим ее ваш 2

сделаем ргнф авто чтобы выровнять по

центру пока что выглядит это вот так

теперь займемся формой

форму сделаем flexo война направлении

flex контейнера сделаем калом


внутри формы добавим 2 input а

уже сделаем placeholder первым напишем

введите емейл и сразу же классовым

именем от лепим его от надписи с

авторизацией скопируем input и во втором

напишем введите пароль откроем браузер

выглядит на данный момент это вот так

единственно вот эти вот тупо можно чуть

увеличить до так лучше внизу под in

путами добавим кнопку внутри напишем

войти вариант сразу сделаем outline мне

такие кнопки нравятся большим сделаем

например зелененькой она растянулась на

всю свободную ширину и прилипла к input

он во первых от лепим и и сделаем


небольшое форматирование и во-вторых

сдвинем и и в правую часть для этого

элайн сел в сделаем and

вот теперь выглядит это вот так а слева

от кнопки у нас должна быть ссылка

перехода на страницу регистрации

поэтому добавим новую строку это

компонент ров в него мы переместим эту

кнопку

а перед кнопкой добавим наверно обычно

простой блок div и внутри напишем нет

акаунта зарегистрируйтесь и

зарегистрируйтесь завернем в навле нг из

роутер дом импортируемого из ссылки

укажем пробст у
чтобы она переводила на страницу

регистрации

вот так вот это выглядит корявенько

давайте отформатируем добавим классовое

имя на строку сделаем ее flexo вой гости

фай контент сделаем between чтобы кнопка

и надпись со ссылкой разъехались в

разные стороны и align сифу кнопки

уберем вот так выглядит лучше

единственно по-хорошему бы сделать еще

отступы слева и справа чтобы было все на

уровне сын путами

делаем и вот теперь вот так это выглядит

вполне симпатично теперь в зависимости

от того по какой ссылке мы находимся нам


надо отрисовывать либо страницу

регистрации либо страницу авторизации

для этого воспользуемся хуком use

locations is react роутер дом помощью

него можно получить маршрут в строке

запроса выведем влоги и посмотрим

открываем консоль

и видим здесь объект у которого есть

поле познаем в котором мы получаем

ссылку

сразу же сделаем переменную назовем ее

из логин

она будет труп в том случае если маршрут

у нас совпадает с лагин road и в

обратном случае значит у нас страница


регистрации

поэтому везде где у нас есть информация

которая отличается в данном случае в

заголовке если страница логина вводим

авторизация если страница регистрации

соответственно регистрации тоже самое

делаем и для ссылке которая будет

переключать как раз эти страницы случае

если у нас страница с регистрацией нам

надо возвращаться обратно на логин

поэтому вот эта мы скопируем вставим

здесь исправим надпись есть аккаунт

войдите

все по классике я

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


же делаем проверку учи тернарного

оператора либо пишем войти либо пишем

регистрация и вот здесь подправим ссылку

на страницу логина сохраняем открываем

браузер и при нажатии на ссылку у нас

вот так меняется формочка с этим мы

закончили идем дальше теперь займемся

страница их магазинов основной странице

в нашем приложении

примерно вот так она будет выглядеть нам

необходимо реализовать панель слева и

еще сверху вот здесь я забыл дорисовать

будут карточки с названиями брендов там

samsung lenovo apple и так далее при

нажатии на которую у нас на странице


будут появляться только устройство

принадлежащий этому бренду начнем опять

же полностью весь компонент оборачиваем

в контейнер

контейнера добавим строку кант компонент

ролл и уже внутрь строки

добавим колонки строка состоит из 12

колонок

эту левую панель с типами выделим три

колонки внутри будет у нас располагаться

вот как раз вот это вот панелька

вот это самое а вот под всю остальную

часть выделим 9 колонок по 3 на каждый

товар начнем с создания левой панели с

типами назовем ее той бар сразу же


обернем ее функцию observer для того

чтобы magix отслеживал все изменения

которые будут происходить состоянии

следующим этапом получим девайс top

сразу делаем реструктуризацию с помощью

хука юз контекст который мы передаем

контекст кроем документацию bootstrap а

здесь найдем компонент лист групп

примерно вот так будет выглядеть наш

список типов скопируем ставим сразу же

сделаем импорт и перейдем на компоненту

шопов и сразу же добавим вот сюда где у

нас три колонки наш той бар посмотрим

как это выглядит вреда то вот так

надписи слишком длинные


если их укоротить то будет вредить это

намного лучше и также добавим отступ

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

бара

вернемся к типам эту серединку мы уберем

здесь с помощью функции map мы

пробежимся по типам которые находятся в

нашем store и для каждого типа будем

отрисовывать как раз вот этот лист групп

айтем компонент

и внутри этого к

оппонента будем помещать название нашего

типа

и поскольку мы и тренируемся по списку

не забываем указать ключ


давайте откроем шторы в массив здесь

добавим еще пару типов не забываем

поменять язычники здесь напишем например

ноутбуки

а здесь телевизоры

сохраняем

нас по итогу получилось в принципе

выглядит нормально теперь сделаем

следующую логику при нажатии на какой-то

конкретный тип

нам надо будет его выделять но этот тип

выделены нам соответственно где-то нужно

хранить поэтому добавляем старт новое

поле называемого select a type

по умолчанию это будет пустой объект и


создаем сразу же action которым мы в это

поле будем присваивать значение и сразу

же делаем геттер здесь абсолютно все по

аналогии ничего нового

вернемся в компонентой бар здесь вот так

вот отформатируем и добавим onclick

слушатель события нажатия на айтем листа

здесь мы вызываем функцию у сто раз от

select a tight тот самый экшен и в него

передаем тип

чтобы выбранный элемент как-то визуально

отличался прокидываем в него props актив

или туда передаем условия если

айди типа элемента итерации совпадает с

типом который мы сохранили storm то


тогда он будет активным попробуем

понажимать

вот так вот у нас получилась если чтобы

было понятно что эти элементы

кликабельны

добавим inline стиль курсор сделаем

пойнтер чтобы при наведении сразу было

видно что они кликабельные теперь

создадим панельку с брендами назовем ее

соответственно по аналогии бренд бар

сразу 1

чего им компонент

все боксер гор здесь все по аналогии

их получения девайсов чтобы не повторять

код скопируем
не вaм элементом сделаем ролл сразу

зададим класса во имя сделаем этот

компонент люксовым и здесь с помощью

функции map пробегаемся по брендам

который получаем опять же из тора и для

каждого бренда будем отрисовывать

карточку

три слова им карточку

и внутрь

точки помещаем название бренда поскольку

и тренируемся по массиву не забываем

указать ключ качестве ключа используем

айдишник и также укажем класса во имя

сделаем внутренние отступы перейдем на

страницу магазина и уже во второй


колонке этот бренд бар добавляем

выглядит это вот так осталось сделать

тоже кликабельными поэтому открываем

stor

здесь по аналогии создаем selected бренд

пустой объект

копируем action подправим название здесь

будем присваивать selected бренд

их

и так же делаем гитлер

не и возвращ

самую переменную

возвращаемся в бренд бар по аналогии

вешаем слушатель события нажатия кнопки

мыши и здесь вызываем функцию set


selected бренд и туда передаем бренд

и остается опять же визуально как-то

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

so i xiv уже нет но мы можем поменять

цвет рамки будем зависимости от того

совпадает у нас тип айтишника

выделенного саидыч ником элемента

итерации будем отрисовывать рамку

разного цвета либо красную либо светлую

и курсор тоже сразу же делаем по enter

чтобы видеть что эти бренды кликабельны

сохраняем открываем браузер

нажатие видим появляется вот такая

красная рамка

астор и попробуем добавить десяток


брендов убедимся в том что они

переносятся на новую строку

эти дубликаты поудаляем и добавим пару

каких-нибудь адекватных значений

например lenovo и например asus и

подправим здесь айди

мелкие у нас получилось теперь можем

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

бренды

теперь займемся списком товаров

создадим новый компонент назовем его

девайс лист

чем компонент

все в обзоре

здесь нам тоже


на добиться девайс top с помощью cоюз

контекст получаем его

в ров задаем классово именно в строку

делаем клик savoy

внутри строки с помощью функции map

пробегаемся по списку устройств и для

каждого устройства будем отрисовывать

компонент который мы сейчас делаем

назовем его надевай сайтом

разворачиваем компонент

возвращать отсюда будем как я уже

говорил компонент колонки и занимать она

будет три столбца

то есть строке должно помещаться

получается четыре устройства


элемента списка отрисовываем этот

компонент передаем туда ключ и как

пробст девайс передаем туда текущий

элемент пить и рации тут этот девайс мы

принимаем

на страницу магазина и под бренд баром

добавим наш девайс лист

бля им сохраняем и видим что у нас как

раз из 144 девайса от рисовалась теперь

перейдем к самому элементу дивой сайта

мы сделаем картинку название обернем все

это карточку чтобы появилась рамках на

карточку сделаем онлайн стиль ширину

сделаем на на пикселей 150 чтобы

карточка была не слишком большой и


курсор pointer чтобы было понятно что

она кликабельная рамку сделаем светлого

цвета

внутри опять же мы добавляем bootstrap

овский компонент и мяч здесь указываем

как проб и сердце и если вы заметили в

объектах которые лежат в сторе в поле и

матч я положил ссылку на какое-то

рандомное изображение изображению также

делаем ширину и высоту по 150 пикселей

здесь у нас должна быть надпись пока что

ее просто за hard ходим samsung и затем

у нас должен отображаться рейтинг для

рейтинга тоже создаем блок внутри

создаем еще один блок туда мы помещаем


саму цифру а дальше нам необходимо

поместить звездочку из фильмы и и

экспортируем в корне папки проекта с

клиентской частью приложения создаем

папку assets и сюда эту звезду сохраняем

только зададим никакой более адекватной

название вот оно здесь появилась теперь

мы можем ее использовать под этим блоком

создаем опять же и мяч здесь указываем

как из сердца эту звезду только перед

этим и и импортируем с папке asset

и передаем как раз вот этот

импортированный грубо говоря объект как

из сердца

вот так это выглядит на данный момент


теперь это все надо выровнять в одну

строку

поэтому но вот этот вот блок вешаем

классовое название deflect чтобы сделать

его flexo вaм идет steve vai контент

делаем between чтобы надпись samsung и

рейтинг разъехались в разные стороны

теперь на вот этот вот блок с рейтингом

опять же вешаем flex чтобы звезда не

уходила на новую строку

вот так выглядит уже лучше самой звезде

зададим размер и пикселей по 20 и вот

здесь алайна этом тоже сделаем центр ну

вот так выглядит уже нормально

единственная звезду бы я еще чуть


уменьшил и добавим еще отступ сверху

чтобы отлепить от изображения отлично

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

звание самого устройства добавляем этот

блок у него просто выводим девайс name

и видимо да вот этот блок я добавил не

туда его надо было добавить ниже вот так

так выглядит уже почти как в макете

единственно сделаем название бренда

серого цвета для этого повесим класс

вот здесь сделаем текст black 50 и вот

теперь принципе очень похоже откроем

девайс стар и попробуем добавить еще

несколько устройств посмотрим как

поведет себя макет если их количество


будет больше они переносятся на новую

строку в принципе все правильно

единственно сделаем еще о небольшие

выступы

чтобы товары не слипались друг другу в

мэргэн топ сделаем 3 вот так вот уже

вообще отлично главная страница почти

готова потом чуть позже добавим

pagination а сейчас сделаем наше

устройство кликабельными чтобы

переходить на страницу детального

просмотра

для этого воспользуемся хуком и усы

history его мы импортируем

из реактора утер дом и с помощью него


можно динамически передвигаться по

страницам давайте выведем влоги history

и посмотрим что там находится там лежит

вот такой объект у которого есть функция

push которая нас частности интересует с

помощью нее можно переходить на

конкретную страницу вешаем слушатель

события нажатия на кнопку на корневой

элемент и здесь вызываем функцию пушу

history

не и передаем девайс road и к нему нам

необходимо добавить еще и айдишник

товара

сохраняем открываем браузер пробуем

нажать на какой-нибудь товар и как


видите верил у нас появляется нужный

айтишник нужного товара

затем этот айдишник мы будем выцеплять

делать запрос на сервер и получать

данные о товаре его характеристики и так

далее теперь займемся как раз вот этой

вот самой страницей и и оборачиваем

опять же контейнер

здесь у нас будет несколько колонок

откроем макет колонка с изображением

первая колонка с рейтингом 2 и добавить

корзину 3 разбиваем их по 4 столбца

чтобы все было поровну

начнем с колонки с изображением пока что

откроем скопируем один объект добавим


его здесь

чтобы было какое-то изображение какие-то

данные мы могли получать

первую колонку добавляем компоненты матч

в ширину сделать пикселей 300 высоту

тоже 300 и как src

добавляем и матч из девайса если мы

сейчас откроем то увидим изображение

единственно на контейнер сделаем отступ

сверху теперь надо сделать звездочку с

рейтингом и вывести название устройства

здесь добавим в прол

и h2 и в него как раз выведем название

устройства

о нем устройство нам необходимо сделать


звездочку с рейтингом у нее как раз тот

рейтинг из устройства получаем и на сам

блок повесим класс и сделаем его во

первых flexo вaм алайна этом седле steve

vai кантон сделаем центр чтобы цифра с

рейтингом была посередине теперь вот эту

звезду из фильме мы опять же

экспортируем до дими какого нибудь

другое название

и сохраняем теперь сюда и и на страницу

импортируем из папке asset

ее надо сделать как задний фон на блок

div добавляем здесь style in line стиль

в бэкграунде указываем как ёрл как раз

вот эту вот звезду


добавим еще но у рипит центр центр чтобы

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

отцентровано как по горизонтали так и по

вертикали ширину и высоту сделаем

пикселей по 240

и так же сделаем еще бэкграунд says

ковер и на саму вот эту строку также

повесим классы сделаем flex и

направление flex контейнера сделаем в

колонку и все от центруем вот так сейчас

это выглядит еще необходимо увеличить

размер шрифта в рейтингом вот здесь

онлайн стилем добавляем фон says и чтобы

колонки не переходили на новую строку

обернём их все draw


это мы отсюда вырезаем их внутрь

вставляем выглядит это вот так остается

сделать блок с кнопкой добавить в

корзину

этим сейчас и займемся внутрь 3 колонки

добавляем карточку внутрь карточки

добавим h3

внутри мы видим цены устройства под

ценой создадим кнопку напишем там

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

outline и допустим темную вот так сейчас

это выглядит

саму карточку определенно надо добавить

стили на первых зададим классовые мина

сделаем ее flex
направление в колонку от центруем по

горизонтали а по вертикали отодвинем

кнопку от стоимости на равное расстояние

зададим также онлайн стиле ширину для

карточки сделаем 300 пикселей и высоту

тоже 300 пикселей

как у изображение и фан-сайт сделаем

наверно 32 и добавим еще рамку потолще

сделаем ее в 5 пикселей светло-серую вот

так вот это выглядит

стоимостью добавим от и в конце добавим

рублей ну теперь принципе как в макете

осталось сделать набор характеристик

характеристики создадим отдельный массив

чуть позже мы все это будем получать


бэг-энда вот здесь я подготовил

несколько объектов у которых есть тайтл

и дискрипшн также как и у моделей на

сервере самый низ добавляем еще одну

строку и внутри этой строки будем по

массиву дискрипшн пробегаться с помощью

функции map и для каждого

для каждой характеристики будем

отрисовывать еще одну строку и внутрь

строки этой будем помещать

сначала заголовок потом : и описании

также на строку не забываем добавить

ключ ключом будет айдишник и добавим еще

пару классовых именно родительский роу

сделаем его flex & flex калом и добавим


еще отступ и вот так выглядит уже хорошо

теперь стилизуем сами строчки с

описанием добавим онлайн стиля и цвет

заднего фона для каждой строчке мы будем

делать по условию помимо самой

характеристики нам будет также нужен

индекс если остаток от деления на двойку

равен нулю тогда будем делать цвет

заднего фона светло-серый в ином случае

делаем его прозрачным также сделаем

внутренние отступы и вот так вот это

выглядит в принципе почти как на макете

единственно цвет чуть другой но не столь

важно

давим еще надпись характеристики


вот так выглядит вообще

нормально прим полноценный магазин

получается остается друзья у нас админ

панель и чтобы на нее переходить нам

необходимо оживить кнопку на-на бари

поэтому переходим на war' здесь

импортируем и us his story с которым мы

уже работали для того чтобы при нажатии

на кнопку

перемещаться на страницу админ панели с

помощью этого хука получаем history

вызываемого

таки вешаем слушатель события нажатия

вызываем функцию push для лучшей

читабельность и отформатируем
здесь нам необходимо переходить по

маршруту админ road

а при нажатии на кнопку выйти мы

переходим на страницу авторизации

поэтому передаем константу логин road

вот здесь ошибся написал войти я не

выйти поправим и приступаем

заключительной страницы к странице

админ-панели оборачиваем здесь все в

контейнер и добавляем несколько кнопок

внутри первой кнопке пишем добавить тип

во второй добавить бренд и в 3 добавить

устройство на сам контейнер повесим

классовые мина сделаем flex и

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


выглядят сделаем их outline

темными

и от лепим их друг от друга добавим

внешние отступы

чуть отформатируем

выглядит можно добавить еще и денги

ну вот так в принципе нормально

при нажатии на к

кнопку будет всплывать модальное окно в

котором будут всякие input и

поэтому находим в быстро пи компонент

модал вот такой вот модальное окно нас

устраивает

копируем начинку

олеся в код создаем папку называемые


modules у нас будет три модальных окна

подтип под бренд и под девайс и создаем

три компонента называем crate бренд

соответственно cray type

crate девайс

начнем с типа

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

окно

эти мы пока что удалим все лишнее тоже

поудаляем

здесь заголовок сделаем добавить новый

тип

с телом ада

все лишнее поудаляем кнопку также сюда

импортируем здесь передаем 2 проб сошел


отвечать за то виден компонент или нет а

он хайд эта функция которая модальное

окно скрывает сама модальное окно

прокидываем проб шоу и как раз функцию

он хайд

внутрь тела модального окна добавим

форму

тоже внутрь самой формы добавляем input

напишем placeholder

введите название типов

давим еще одну кнопку 1 будет закрывать

модальное окно 2 будет добавлять новый

тип сделаем их outline

чем-то не подсказывает среда

ки одну кнопку
ура закрывает делаем красный автору

зеленый

откроем юзер стори сделаем и south true

чтобы админ-панель всегда была доступна

теперь откроем страницы админки и сюда 3

созданных модальных окна три компонента

добавляем это crate бренд crate type и

crate девайс

эти компоненты принимают два про пса

попробуем сделать шоу в true и при

переходе на админ-панель сразу видим вот

такое модальное окно теперь вот это вот

мы все копируем

открываем crate бренд там у нас будут

абсолютно одинаковые модальные окна в


принципе можно было сделать

универсальный компонент но отделим чуть

логику

открыт девайс будет значительно

отличаться но сюда также добавляем всю

начинку и 2 про пса

далее откроем страницу админки и здесь

создадим три состояния они будут

отвечать за то видим мы модальное окно

или нет так и назовем первое называем

print визе был функция которая это

состояние будет изменять сет бренд везде

был и по умолчанию она будет равняться

фолз здесь заменяем на тип функции тоже

заменяем на тип и тоже самое делаем и


для девайса

теперь это состояние мы можем передавать

как проб шоу

здесь передаем соответственно бренд

визит был здесь девайс визе был а здесь

type дизейбл и также необходимо передать

функцию которая это модальное окно будет

закрывать здесь просто вызываем функцию

сайт и в нее передаем фолз единственно

подправим для каждого модального окна

соответствующую функцию здесь тип здесь

девайс

и остается повесить на кнопки слушатель

события нажатия чтобы при нажатии на

соответствующую кнопку у нас


открывалась соответствующие модальное

окно сразу на все три вешаем onclick и

вызываем функцию сет бренд везде был

девайс везде был type везде был

соответственно и передаем значение true

только подправим название функции все

теперь готова открываем браузер и при

нажатии на кнопку у нас всплывают

модальные окна если нажать вне

модального окна то она закрывается

ошибок влогах нет значит все хорошо

остается закончить модальное окно с

девайсом и мы на этом свёртка и

заканчиваем приступаем к интеграции с

брендом здесь нам понадобится девайс


stor поэтому получаем его с помощью cоюз

контекст по уже известной схеме

этот вот input мы пока что уберем и

вместо него добавим компонент

dropdown это выпадающее меню с помощью

него будем выбирать тип и бренд для

нового устройства внутри dropdown

добавляем вдруг down the gale это будет

кнопка с помощью которой будем как раз

тип и выбирать

лапкой добавляем друг down menu

внутри меню с помощью функции map

пробегаемся по типам которые получаем

издеваясь тора и для каждого типа

отрисовываем друг down айтем внутрь


которого помещаем название типа также не

забываем добавить ключ ключ опять же

айдишник попробуем открыть и вот такой

вот у нас выпадающее меню получилось

скопируем его продублируем и то же самое

сделаем и для бренда таким способом мы

будем выбирать соответствующий тип и

соответствующей бренд для нового

устройства здесь подправим название

сохраним и теперь у нас два выпадающих

меню в одном типы в одном бренды

единственно добавим еще отступим чтобы

они не были прилеплены друг другу

так уже получше

от выпада
7 списками добавим 1 input

placeholder это будет input для название

устройства placeholder это и напишем и

сразу же добавим отступ сверху чтобы

input не прилипал к выпадающем меню

input продублируем дважды для третьего

сделаем тип файл для второго сделаем тип

number 2 будет для стоимости устройства

а с помощью 3 мы будем загружать

изображения

а дым путами добавим разделительную

черту

вот так сейчас это выглядит на данный

момент здесь пишем цифры здесь выбираем

изображение также для каждого устройства


надо будет добавлять массив

характеристик сразу же сделаем для него

состояния назовем его info

и по умолчанию это будет пустой массив

от разделительной чертой добавим кнопку

и напишем в ней внутри добавить новое

свойство

форматируем

вариант для кнопки сделаем outline

например темные

и реализуем функцию с помощью которой мы

эти характеристики будем добавлять

назовем ее от info

сделаем ее стрелочной здесь вызываем

функцию которая состоянии изменяет в нее


передаем массив в этот массив мы

разворачиваем старый массив информации и

добавляем в него новый элемент

у которого есть тайтл description и для

того чтобы не париться с айтишниками

добавим еще поля намбер который будем

получать из времени для того чтобы в

дальнейшем если что мы эти

характеристики могли удалять при нажатии

на кнопку как раз эту функцию вызываем и

под кнопкой поэтому массиву с

информацией с помощью функции map мы

пробегаемся для каждого элемента для

каждой характеристики будем отрисовывать

row и внутри добавим пару колонок


сделаем их в ширину по 4 столбца

1 у нас будет input для заголовка для

тайтла

внутри 2 у нас будет input для

соответственно description сразу сделаем

placeholder и здесь напишем введите

название характеристики а во втором

сделала введите описание

также будет ещё кнопка в которой эту

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

добавили лишнюю

и нам ее необходимо удалить поэтому

делаем еще одну колонку внутри добавляем

кнопку вариант сразу делаем outline

делаем красный
что-то там какая-то ошибка посмотрим что

то с импортом о чем-то колонка

импортировалось по дефолту поправим это

сохраним и посмотрим что получилось

теперь при нажатии на кнопку у нас

добавляются вот такие вот строчки для

каждой характеристики только еще добавим

отступ и чтобы они не слипались вот так

получше даже чуть больше можно вот так

выглядит уже хорошо консоль ругается что

нет ключа поэтому в качестве ключа

укажем как раз вот тот самый номер

который мы указывали при добавлении info

сразу же реализуем функцию которая

характеристику будет удалять параметрам


она как раз этот номер и будет принимать

вызываем функцию site info

по существующему массиву инфа с помощью

функции фильтр пробегаемся и проверяем

совпадает ли номер элемента с номером

который вы передали параметрам

нажатие на кнопку удалить эту функцию

теперь необходимо будет вызывать

спускаемся ниже вешаем слушатель события

на кнопку вызываем эту функцию

параметрам передаем в нее номер текущей

характеристике добавим несколько свойств

что-нибудь напишем и как видите при

нажатии на кнопку удалить на это

свойство пропадает на что логику мы


реализовали правильно итак друзья на

этом этапе в принципе с визуальной

составляющей мы закончили сделали

страницу регистрации и авторизации

админ-панель главную страницу в общем

полноценный интернет-магазин

осталось соединить это все с нашим

брендом создадим папку назовем ее http

внутри создадим индекс с файл и здесь

настрой maximus

импортируем его сюда и создадим два

инстанса 1 будет для обычных запросов

которые не требуют авторизации назовем

его просто host во второй же инстанс

каждому запросу автоматически будет


подставляться хедер

авторизация и туда будет добавляться

talkin' здесь в опциях мы можем указать

ёрл на который будут отправляться

запросы арт котик моему не будем также

создадим файлик date and и здесь как

системную переменную укажем api к

серверу нашем случае это локалхост 5000

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

добавляйте react нижнее подчеркивание f

откроем индекс джесс файл и в логе

попробуем эту системную переменную

вывести убедимся что реакции считывает

кроем логе

обновим страницу и видим локалхост 5000


лично двигаем дальше открываем опять же

настройку нашего аксиос а

и как был передаем туда системную

переменную случае 2 инстанса нам

необходимо подставлять

автоматически talking каждому запросу

для этого существуют так называемые

интерцепторы это просто функция которая

параметрам принимает конфиг

здесь конфиге мы в поле headers

добавляем caider авторизация и указываем

наш talking который получать мы будем из

локального хранилища по ключу talkin'

при авторизации мы в это локальное

хранилище его будем добавлять затем


для instant south хост добавляем

interceptor для

именно запроса можно также повесить

интерцепторы для ответа

но мы вешаем на запрос и он будет

отрабатывать перед каждым запросом и

подставлять токен хедер авторизация так

как мы это делали в пост money вручную

папки архетипе создадим новый файлик

назовем его юзера pi здесь мы реализуем

функции регистрации авторизации и

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

функция чек импортируем сюда

aus хост простой хост сразу экспортируем

функцию сделаем ее стрелочной


параметрами она будет принимать email и

пароль сделаем и сразу же асинхронной в

переменную response будем помещать

ответ который будет возвращаться от

сервера это у нас post запрос базовые

rail у нас берется из системной

переменной и к нему добавляем еще api

aus и registration and point и которые

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

мы передаем email пароль и также укажем

еще роль сделаем админов чтобы не было

проблем с доступом и этот response из

этой функции будем возвращать сразу

продублируем у нас будут функции логин и

еще функция чек вот эта функция


параметрам принимать ничего не будет

весна подправим здесь юрл отсюда уберем

роль и теперь этими функциями

воспользуемся откроем страницу с

авторизацией

здесь создадим новую функцию и назовем

ее sein и опять же это будет просто

стрелочная функция сделаем ее

асинхронной

и здесь переменную response поместьем

вызов функции как раз registration

package

просто выведем блоге то что находится

внутри response теперь на кнопку

необходимо повесить
слушатель давайте все-таки переименуем

сделаем универсальную функцию под

регистрацию и под авторизацию внутри

функции просто сделаем проверку если из

лагин будем вызывать запрос на

авторизацию из линий с лагин

соответственно на регистрацию

и вот этот лог пока что перенесем вот

сюда но на данный момент в эти функции

нам необходимо передать email и пароль

но

input и у нас не живые сделаем их

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

помощью каю state одно будет содержать в

себе значение input as емейлом а второе


с паролем

зададим одноименные названия спустимся к

им потом в качестве вэлью мы как раз

передаем в input и

это состояние и в качестве функции он

чинишь будем это состоянии изменять

вызываем функцию сытый mail is set

password

соответственно здесь передаем e-mail

здесь пароль функцию которая изменяет

состояние передаем целью которая

находится в текущем и им пути грубо

говоря в input мы что-то вводим и сразу

перезаписываем состоянии теперь этот

e-mail и пароль
мы как параметрам передаем функцию

регистрация в консоли у нас какие-то

ошибки e-mail и пароль не определен

открою файлик use rapid да вот здесь вот

есть параметров удалил а из тела запроса

нет обновляем открываем страницу

регистрации пробуем написать

какой-нибудь емейл и пароль

единственно для input а с паролем

сделаем тип паспорта то пароль у нас в

открытом виде менее шифруются

править запросы получаем 404 попробуем

разобраться в чем причина

всей видимости они правильно указал юрл

вот здесь у нас юзер


а вот здесь я указал aus подправим это и

попробуем отправить запрос еще раз пишем

какой-нибудь email пароль и получаем

response в теле ответа мы видим talkin'

теперь этот токен мы можем сохранять в

локальное хранилище и пользователь будет

авторизован но также нам необходимо

сохранять информацию о пользователе

чтобы потом например на странице

пользователя в профиле и и отрисовывать

для этого нам понадобится модуль 9

decode с помощью которого мы сможем этот

токен распарсить импортируем его сюда

здесь мы сразу

сделайте структуризацию и будем получать


из response а тело запроса а возвращать

из этой функции будем результат

декодирование как раз таки на который

находится внутри этого тела

попробуем отправить запрос еще раз

напишем e-mail пароль и влогах получаем

информация пользователя его e-mail роль

яичник вернемся на страницу авторизации

же весь компонент обернем в observer

здесь мы уже будем изменять как то

состояние

как о функции

этих запросов нам будет возвращаться

пользователь создадим переменную вынесем

ее наверх функцию логин а также


передадим e-mail и пароль

здесь нам понадобится уже users top

поэтому с помощью хука юз контекст

добавляем его сюда

передаем контекст

теперь у нас имена пересекаются поэтому

юзер заменим на дейта

после того как запрос прошел мы users

top сохраняем данные о пользователе

is it a us делаем труп сейчас попробуем

залогиниться но перед этим откроем users

тор и перемену и south сделаем фолз при

нажатии на кнопку авторизации у нас там

как раз вызывается функция с это us на

фиг с ним попробуем зарегистрироваться


отправляем запрос получаем ошибку

откроем вкладку network и видим что в

теле запроса нам вернулась сообщение о

том что пользователь с таким емейлом

существует отправляем ещё раз с таким мы

видимо тоже создавали вот с таким уже не

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

попробуем под этими данными войти

пишем юзер 123 собака mail.ru и пароль

отправляем запрос

work

нам на запрос логина также вернулся

talkin' но так дело не пойдёт как

пользователь должен узнать о том что он

например вел неправильный пароль или что


пользователь с такими мелом уже

существуют для этого нам необходимо

обработать ошибки за вернемся в блок

трой кач и случай если ошибка все-таки

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

внутри allure то помещаем как раз

сообщение которое приходит в responses

также после того как пользователь

залогинился нам необходимо переводить

его на страницу магазина

поэтому опять же воспользуемся хуком

your history

импортируем его и если функция

выполнилась успешно делаем redirect на

страницу магазина
попробуем залогиниться

вводим email вводим пароль нажимаем

кнопку войти и нас redirected на

страницу магазина

данный момент мы просто логинимся

регистрируемся но нигде не сохраняем

talking откроем файлик use arrows и

после того как запрос прошел мы получили

данные будем в локальное хранилище по

ключу токен помещать токен из тела

запроса теперь разберемся с функцией чек

здесь нам уже понадобиться aus хост

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

talkin' напомню что вот здесь мы

указывали us медальер который это


talking будет проверять логика такая

пользователь авторизовался talkin'

сохранился и затем каждый раз при

обновлении страницы будет вызываться

функция чек если talkin' не валидны то

пользователь будет разлогиниваться

если валидный пользователь будет

попадать на страницу магазина под своим

аккаунтом и поскольку из этой функции

нам также возвращается токен опять же

его перезаписываем и возвращаем обратно

данные о пользователе теперь перейдем в

компоненту об опять же и и обернем баб

сервер

поскольку здесь нам понадобится


состоянии юзер users top сразу же с

помощью хука юз контекст мы это

состояние получаем затем прямо здесь в

компоненте с помощью хука

юз state сделаем локальное состояние

которое будет отвечать за то идет

загрузка страницы или нет то есть логика

следующая по дефолту это состояние

равняется true на страницу мы добавляем

какую-нибудь крутилку затем отправляется

запрос на проверку пользователя и после

того как нам вернулся ответ мы это

состояние делаем фолз и страница

загружается теперь этот запрос

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


при первом открытии приложения для этого

воспользуемся хуком usa эффект который

первым параметром принимает функцию

авторы массив зависимости если этот

массив зависимости пустой то функция от

работает лишь единожды при первом

запуске приложения внутри вызываем

функцию чек если она выполнилась успешно

делаем сет юзер труб и сайт и south тоже

делаем true значит пользователь

залогинился тем внутри файла ли loading

мы будем делать фолз неважно произошла у

нас ошибка или запрос прошел успешно

загрузку страниц и мы в любом случае

должны сделать фолз час постараюсь


наглядно объяснить зачем это нужно

сейчас по идее talkin' у нас находится

локальном хранилище и мы авторизованы

после того как мы обновим страницу

запрос улететь на сервер этот токен

проверится и только после этого мы

узнаем авторизованы мы или нет эта

операция не мгновенная запрос на сервер

занимает какое-то время и обратите

внимание на правый верхний угол navara

изначально у нас переменная es aus

равняется falls но так как пользователь

авторизован запрос проходит успешно эта

переменная становится труб из за этого

происходит перед enduring


сейчас я вам продемонстрирую из-за того

что сервер поднят локально этого

практически не заметно но она все-таки

есть

поэтому делать проверку если loading

true тогда будем возвращать спиннер из

bootstrap а это просто какая-то крутилка

и анимацию сделаем гром то есть она

будет ускоряться по нарастанию

сделаем некую имитацию запроса поставим

set time out и сделаем что он грубо

говоря у нас идет одну секунду засунем

самым запрос внутрь теперь при

обновлении страницы как видите

появляется крутилка
и затем страница отрисовывается жизни

конечно секунду запрос идти будет

наврятли только при очень медленном

соединении но как видите теперь при

обновлении страницы перри рендеринга на

в бара мы не видим набаром как раз

сейчас и займемся сейчас при нажатии на

кнопку выйти нас просто redirected на

страницу логина мы реализуем нормальную

функцию log out здесь мы будем сет юзер

присваивать пустой объект set & south

делать полз и при нажатии на кнопку

выйти теперь будем эту функцию вызывать

вот это мы удаляем и добавляем здесь

ragout
а при нажатии на кнопку авторизации как

раз нам надо переходить на страницу

логина здесь сделаем history push елагин

road сохраняем

вам кнопку выйти у нас переливается на

бар сразу попробуем авторизоваться

пишем логин пароль и все в принципе

работает как надо нас переводит на

странице магазина на в бар меняется

теперь научимся получать типы бренды

устройство

их создавать для этого в папке http

создаем новый файлик называемого девайс

api скопируем запросы из юзера пи-ип

отправим их первый запрос у нас будет на


создание типа и на получение

на получение назовем фич types здесь

параметрам у нас будет сам тип

раввин ю.л.

вот этот тип будем передавать

хранилища отсюда убираем и возвращать из

функции будем как раз то что получили в

ответе

функция h types никаких параметров

принимать не будет также подправим юрл

уберем тело запроса здесь у нас для того

чтобы создать тип нужно уже авторизация

мы должны быть админами опять же вот

здесь у нас есть me dr

чек roll a роль проверяется как раз


потоки ну поэтому нам нужен

авторизованный хост а там достаточно

обычного hasta поскольку любой

пользователь может список типов получить

здесь опять же из функций возвращаем то

что получили в ответе

созданием типов разберемся чуть позже

пока что просто их получим так как мы

через пасман уже несколько типов

создавали

возвращаемся на страницу магазина

оборачиваем его взор вверх здесь

получаем девайс торф с помощью хука юз

контекст опять же с помощью хука use

сект единожды при открытии страницы


shope

нам необходимо устройство подгружать

поэтому массив зависимости вторым

параметром визы фиг передаем пустым

затем вызываем функцию fish types

и в случае успешного запроса у девайс

вызываем функцию сет types и туда

передаем как раз то что вернулась нам в

запросе

теперь в девайс торе вот эти вот маковые

данные можно удалить

и оставить массив пустым открываем

страницу и видим что типы почему-то не

подгрузились откроем вкладку network

обновим страницу
видим что метод не найден потому что мы

отправляем post запрос меняем на get

ничего страшного такие ошибки случаются

и сразу видим что типы погрузились у нас

сервера холодильнике смартфоны и

почему-то lenovo видимо при создании я

перепутал бренды с типами и добавил туда

бренд

теперь сделаем то же самое с брендами

поменяем название функции здесь crate

бренд параметрам принимает бренд и телом

запроса тоже бренд отправим ёрл

здесь правим тоже названием fetch brands

тоже проверял

все на страницу shope


и помимо функции фи types также вызываем

функцию факт brains

i-stor также помещаем бренды

браузер видим как бренды подгружаются

маковые данные с девайс top также

удаляем ну и остается проделать всю ту

же самую процедуру еще и для девайсов

опять же копируем функции меняем

название

но также у нас еще есть запрос на

получение одного конкретного девайса

назовем функцию фишман девайс параметрам

она будет принимать айдишник этого

девайса

это идиш ник передаем как часть строки


запроса

он девайс тор и также почистим маковые

данные

оставляем пустой массив

переходим на страницу шопов здесь

добавляем еще один запрос вызываем

функцию сет девайс

роняем обновляем

и получаем ошибку все дело в том что мы

добавляли паги нацию на получение

девайсов и помимо самих дивайсов нам

также приходит их количество поэтому вот

здесь устройство мы получаем из поля

роуз обновляем страницу и получаем

список товаров
но есть какая-то проблема с

изображениями как видите сейчас мы это

поправим откроем компонент девайс ой там

и как вы помните в поле и мач мы храним

название файла

помимо этого название нам также

необходимо добавить и rl сервера поэтому

получаем его из системной переменной и

приплюсовываем к нему название

изображения

и они отлично подгружаются

теперь займемся девайс печь открываемые

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

убираем с помощью хука you state создаем

здесь локально и состоянии называемого


девайс

функция которая это состояние сайт

девайс

по умолчанию это будет пустой объект с

одним-единственным полем инфо

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

воспользуемся хуком use фейгт при

открытии страницы каждый раз единожды мы

это устройство должны подгружать но

здесь все по аналогии так мы уже делали

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

сервер нам необходимо знать айди

устройство для этого воспользуемся хуком

юсб и рамс из реактора утер дом и снова

здесь мы его импортируем


затем воспользуемся попробуем получить с

помощью него параметры строки запроса

и выведем их влоги посмотрим что там

лежит единственно влогах видим какую-то

ругань потому что дискрипшн у нас уже не

существует информацию мы получаем из

объекта девайс поля info

откроем консоль перейдем на какую-нибудь

страницу и влогах видим объект с

единственным полем айди это иди

получается и зверел здесь можем сделать

и структуризацию сразу этот айтишник

вытаскивать теперь делаем запрос

параметрам передаем в него айдишник и

после того как запрос прошел сайт девайс


передаем результат этого запроса

вот здесь вот с изображением сделаем

тоже самое сначала ёрл api и затем

название изображения

обновляем страницу видим название 12

прост рейтинг 0

изображение но характеристику этого

объекта нет с получением данных сервера

мы разобрались теперь давайте оживим

ношу админ-панель научимся добавлять

типы бренды и устройство начнем с типов

первую очередь при нажатии на кнопку

добавить мы должны вызывать функцию

назовем ее e-type

это опять же будет стрелочная функция


и в этой модальном окне у нас есть один

единственный input в котором мы

указываем название типа его опять же

надо оживить с помощью хука you state

создаем состоянии

назовем его вылью по умолчанию это будет

пустая строка передаем это вылью в input

и вешаем слушатель события onchange в

котором мы это состояние будем изменять

на то что находится сейчас в пути

затем после

как мы нажали на кнопку нам необходимо

отправлять запрос этот запрос называется

у нас функция которая этот запрос

отправляет называется край type и в


случае если запрос прошел успешно с

целью будем присваивать пустую строку то

есть input будем обнулять

и также не забываем что параметрам

запрос нам необходимо передать объект

типа у него указываем только имя которое

мы получаем из состояния после чего

вызываем функцию он хайд чтобы модальное

окно закрылось

давайте попробуем добавить тип пишем

здесь например кондиционер и нажмем

кнопку добавить

модальное окно закрылось и мы видим что

теперь при открытии главной странице у

нас в типах также есть и кондиционеры


добавим еще телевизор и все круто все

работает теперь разберемся с брендами

скопируем вот эту вот логику откроем

модальное окно с брендами ставим это

здесь единственно подправим название

и также будем вызывать вот здесь при

нажатии на кнопку эту функцию также

оживим input копируем вставляем

открываем браузер и пробуем добавить

пару брендов пишем название например

asus

вам ещё что-нибудь например и сир кроем

главным и видим что все это добавилась в

типы потому что я забыл поменять запрос

здесь у нас crate бренд


я сейчас поставил на паузу лишнее с базы

данных поудалял давайте теперь попробуем

добавить бренды

добавим например lenovo и добавим

например рейсер и видим что они сразу

появились в бренд барев

остается последняя модальное окно с

добавлением устройство здесь будет чуть

посложнее

давайте этим займемся

у нас здесь есть несколько input of для

характеристик для стоимости для названия

и для файла все этим путы нам сейчас

необходимо оживить поэтому для каждого

создаем одноименное состоянии это


соответственно для названия для

стоимости

называем прайс

а не будет просто нулем

соответственно для файла функция которая

изменяет сет файл по умолчанию будет

простонал

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

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

следующим этапом создадим функцию

назовем и select файл она будет

вызываться в том случае когда мы выбрали

файл на компьютере параметрам функция

принимает event-ы давайте посмотрим

влогах поле files удар гид и вешаем на


слушатель события onchange

эту функцию сохраняем

соль

какое-нибудь изображение

dim блогах массив состоящей из одного

элемента как раз с тем файлом которые мы

выбрали соответственно этот файл нам

состояние необходимо сохранить по

нулевому индексу обращаемся к массиву и

сохраняем его в состоянии

теперь оживляем и вот эти input и

передаем сюда вэлью сюда name сюда прайс

вешаем слушатель события он чинишь

ответственно для каждого input а

вызываем соответствующее изменение


состояния сюда сюжетным сюда сайт прайс

и в пути со стоимостью также приведем

его к числовому значению

этими минутами мы разобрались теперь

переходим к выпадающем меню

принципе а так подумал вот это состояние

можно убрать поскольку в сторону нас уже

есть два объекта которые отвечают за

выбраны типы за выбранный бренд

добавляем на элемент выпадающего списка

слушатель нажатие и у девайса вызываем

функцию сайт либо select a type либо

selected бренд соответственно сделаем

форматирование чтоб это не выезжала за

пределы экрана
доступ

поэтому здесь вызываем функцию set

selected бренд и передаем неё бренд

здесь передаем тип

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

это выпадающее меню открывает если у

девайса бренд выбран то есть тип в

данном случае

да оставляем его в обратном случае

напишем выберите тип и то же самое

сделаем и для бренда единственно вот

здесь подправим нас олег тот бренд

не мы отображаем даже не сами бренды и

типы

а нам необходимо их название пробуем


открыть открываем выпадающее меню и

видим пустой список

конечно ведь бренды и типы мы нигде не

подгружаем поэтому открываем shop

копируем вот эти вот запросы с хуком use

факт вместе и добавляю в модальное окно

то есть при открытии модального окна в

каждый раз мы должны будем бренды типы

подгружать

модальное окно видим что появились как

типы так и бренды

продолжаем работать обернем модальное

окно в observer чтобы мы могли типы

выбирать и сразу видеть рендеринг

большой достаточно компонент получился


сохраняем пробуем выбрать какой-нибудь

тип и видим как название в кнопке

меняется сын путами с выпадающими

менюшка my мы разобрались теперь нам

надо разобраться с характеристиками

как бы в массив добавляются но тайтлы

description для каждого объекта пустой

создадим функцию назовем очень zenfone

параметрами она будет принимать ключ это

либо тайтл либо description целью

значение которое мы по этому ключу будем

устанавливать и номер характеристики по

которой мы это значение будем изменять

здесь мы с помощью функции map

пробегаемся по массиву информации


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

элемента итерации то тогда мы возвращаем

объект новый объект разворачиваем в него

характеристику и по ключу

заменяем у нее поле то есть если ключ

еще раз у нас был тайтл то мы заменяем

на его на новое значение в ином случае

если номер не совпадает мы возвращаем

объект неизмененным вот здесь если не

поняли поставьте на паузу и

призадумайтесь что мы сделали и теперь

реализуем функцию которая уже будет

отправлять запрос на сервер и добавлять

нового устройства пока что просто влоги

выведем массив информации убедимся в том


что значение заполняются эту функцию

будем вызывать при нажатии на кнопку

добавить

и также вот эти input и с описанием

характеристики и и названием необходимо

оживить как в илью добавляем

соответственно тайтл который мы получаем

из объекта текущей операции а во втором

как description

и также вешаем слушать

события onchange в котором вызывая

функцию chain info

здесь мы передаем параметром тайтл как

ключ целью мы получаем из таргета здесь

все по аналогии с обычным ему там и


передаем номер

номер получаем из элемента текущей

итерации скопируем эту функцию

и вставим здесь единственное что мы

поменяем это ключ здесь у нас будет

description

его и модальное окно добавляем несколько

характеристик пробуем что-нибудь

написать и нажмем кнопку добавить у нас

массиве два элемента и как видите у них

заполнен и тайтл и description

вот такая вот форма у нас в общем

получилось остается отправлять запрос на

сервер возвращаемся к функции от девайс

здесь вызываем функцию крайт девайс


который мы отправляем запрос на сервер и

параметрам мы должны передать само

устройство вспоминаем когда мы

тестировали функцию создания девайсов

паства не

мы использовали не строку формате json а

форм дату данном случае сделаем все то

же самое создаем объект form даты и с

помощью функции append по ключу первым

параметром передаем ключ а вторым

параметром значения передаем название

единственно но нам подсказывает что

значение должно быть либо стоковым либо

блок блок это грубо говоря набор битов

данном случае мы можем отправлять файл


поэтому стоимость конвертируем в строку

затем как и мяч как раз мы передаем файл

затем нам необходимо передать брента и

div этой пойди их мы получаем из девайс

тора

из выбранного элемента соответственно с

электро type is elected бренд

мы оттуда забираем айдишник они

отправляем целиком объект и остается

массив date и вспоминаем когда мы делали

backend я говорю что массив невозможно

передать поскольку либо строках либо

blob поэтому массив перегоняем глисон

строку

а на сервере у нас уже и тот же сон


строка будет парсится обратно в массив

передаем форум дату как параметр функцию

crate девайс и если запрос прошел

успешно будем закрывать модальное окно

что же откроем браузер и протестируем

обновим страницу открываем модальное

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

пусть это будет samsung здесь напишем

какое не случайно и название введем

стоимость выберем изображение и добавим

пару свойств

напишем допустим объем пусть будет 5

литров и еще допустим цвет пускай будет

белый добавляем модальное окно

свернулась и как мы видим холодильник


появился в списке товаров если мы

откроем сразу же увидим характеристики

на самом деле выглядит это все немного

топорно но основная часть

интернет-магазина готова оформить это

все в красивую картинку нормально

обработать ошибки это будет уже

полноценный интернет-магазин

но есть еще часть функционала который мы

не реализовали поэтому продолжаем

во-первых нам сделал необходимо сделать

постраничную паги нацию во вторых при

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

бренда мы должны делать фильтрацию и

отображать только товары соответствующие


данным критериям начнем с pagination

открываем bootstrap здесь находим

компонент богиней шин здесь вот есть

примеры

чаем ся коду создадим новый компонент

назовем его пойдешь развернем здесь

компонент сразу же обернем его баб

сервер с помощью хука юз контекст

получаем девайс top передаем параметром

контекст

темат рисуем сами страничке пока что

создадим пустой массив и заполним его

цифрами от 1 до 5

то есть у нас будет 5 страниц создаем

компонент богиней шин внутреннего по


массиву страниц пробегаемся и для каждой

страницы отрисовываем богиней шиной там

помещаем номер страницы затем перейдем

на страницу шопом и под девайс листом

компонент печь добавим кроме приложения

не видим снизу вот такие вот странички

тем перейдем опять в девайс тор и

добавим еще пару новых полей во первых

это поле которое отвечает за текущую

страницу

по умолчанию это будет первая страница

totalcount будет отвечать за общее

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

данному запросу и лимит это количество

товаров на одной странице


сделаем по умолчанию 3 чтобы не

добавлять много товаров и нормально

протестировать эту паги нацию

здесь как обычно создаем для каждого

поля сеттеры и геттеры

здесь момент этот я перемотаю поскольку

никакой смысловой нагрузки новый он не

несет

им откроем девайс api и функции в

которой мы получаем устройство

параметрам будем передавать во первых а

идите по во вторых айди бренда в третьих

передаем номер страницы и лимит лимит по

умолчанию сделаем равным 5 например

затем в опциях мы можем эти параметры


все

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

типа иди

бренд айди номер страницы и лимит они

автоматически поставятся в строку

запроса если переменная не пустая

для тех кто может быть backend не

смотрела смотрит только frontend поясню

типа иди и бренд айди передается для

того чтобы получить товар и конкретно по

заданному типу и бренду то есть мы

нажали например на холодильнике у нас

подгрузились холодильники

а тем временем мы перешли на страницу

shop
и после первого получения товара нам

надо узнать сколько товаров мы получили

для того чтобы мы могли посчитать

количество страниц общее количество

товаров находится в поле каунт ответа от

сервера вот этот массив мы убираем и

теперь посчитаем общее количество

страниц

делается это простым способом мы делим

общее количество товаров на количество

товаров на одной странице этом число

которое получилось с помощью функций

sail

округляем в большую сторону то есть на

примере если всего у нас товаров 25 мы


отображаем 5 на одной странице

то страниц соответственно необходимо

отрисовать 5 потом мы пробегаемся в

цикле и в массив пейджер для им текущей

счетчик в цикле + 1 то есть это будет

номер страницы

затем нам необходимо как-то выделить

текущую страницу

вот здесь мы сейчас немного

отформатируем добавляем props актив и

здесь по условию если страница которая

находится у нас девайс top равняется

странице текущей то тогда она будет

активной также добавляем ключ и

слушатель события нажатия то есть при


нажатии на эту активную страницу будем

выделять по дефолту она равна единице

обновляем и как видим при нажатии на

страницу у нас меняется активная теперь

остается решить вопрос подгрузкой

конкретных устройств переходим на

страницу shop

и вот здесь функцию факт девайс мы

параметрами пока что type a brand eyki

передадим по нулям текущая страница

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

товаров на одной странице 2 кроем

браузер и почему-то все равно получили

все посмотрим на запрос и вот эти все

параметры конечно не faith brains надо


переносить of each девайс

и параметры самой функции тоже

переносим сюда сохраняем открываем и

получаем всего три устройства попробуем

вернуться на страницу шоб не передать

здесь допустим двоечку теперь мы

получаем только 2 товара теперь при

нажатии на страницу нам надо

соответственно эту страницу менять

воспользуемся хуком use фейгт который

параметрам вторым принимать массив

зависимостей если в этот массив

зависимости передать например номер

страницы то функция которая идет первым

параметром
эффект будет вызываться каждый раз когда

страница была изменена здесь уже первым

параметром передаем выбранный тип

который находится в девайс торе вторым

параметром выбранный бренд

этим параметрам текущую страницу и и

также получаем из тора

и четвертым параметрам лимит пока что

оставим двоечку и так как нам надо будет

подгружать товары и при смене типа и

бренда

них тоже добавляем как зависимость в usa

сект к вот здесь мы передаем айдишники

они сами объекты откроем браузер и при

переходе на другую страницу как видите у


меня сменяются товары при смене типа

также меняются единственно у нас нет

кондиционеров и телевизоров еще сделаем

так чтобы при смене типа или бренда у

нас каждый раз страница снова

становилась 1 и ходим стар и в

соответствующих экшенах сет пэйдж делаем

единичку теперь если даже мы перейдем на

вторую страницу и выберем новый

какой-нибудь тип то страница сразу

переключиться на первую друзья на этом

мы заканчиваем

если вы пытались повторить этот магазин

реализуйте также еще корзину

рейтинг обработайте все ошибки ну тут


совсем немного осталось основной

функционал мы сделали все что остальное

это уже детали и так если ты герой и

досмотрел этот ролик до конца если ты

посчитал что он был тебе полезным

пожалуйста да обратную связь в виде

лайка и комментария а я жду тебя в

следующих роликах