Делаем клон сервиса по доставке еды, используя Nuxt.js, GraphQL, Strapi и Stripe. Часть 2/7

image

В предыдущей части мы настроили структуру приложения, в данной статье мы настроим Strapi API и выведем список ресторанов.

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

Создаем рестораны

Первым делом нам нужно отобразить список ресторанов в нашем приложении. Разумеется, данным списком мы будем управлять через Strapi API, поэтому давайте его настроим.

Устанавливаем Content Type

Content Type, также называется моделью (model). Strapi API по умолчанию включает в себя модель user. Сейчас нам нужны рестораны, поэтому новая модель как вы уже догадываетесь будет называться restaurant(модели именуются в единственном числе).

Вот что нам нужно сделать:

  • Перейти в конструктор моделей http://localhost:1337/admin/plugins/content-type-builder
  • Нажать на Create new content-type
  • Установить restaurant в качестве имени и нажать кнопку "Continue"
  • Далее создать следующие поля:
    • name с типом Text
    • description с типом Rich Text
    • image с типом Media
  • Нажать кнопки "Finish" и после "Save"

image

После этого сервер должен автоматически перезагрузится и новая ссылка Restaurant появится в левом меню.

Добавляем записи

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

Теперь мы находимся в плагине Content Manager, интерфейс которого позволяет просматривать, изменять и добавлять записи.

  • Нажмите на Add New Restaurant
  • Укажите name,  description и перетащите картинку в поле image
  • Сохраните

Создайте еще столько ресторанов сколько хотите увидеть в приложении.

image

Разрешаем доступ

У нас есть записи в базе данных — это хорошо. Однако возможность делать запросы к базе из API еще лучше. Когда мы создали модель restaurant, под капотом Strapi создал ряд файлов расположенные в api/restaurant. Эти файлы включают в себя основную логику, предоставляя полностью кастомизируемое CRUD API. Метод для получения ресторанов find доступен здесь: http://localhost:1337/restaurants.

Попытавшись посетить данный URL, вы будете удивлены увидев 403 ошибку. На самом деле это нормально: новые Strapi API спроектированы такими по умолчанию.

Не волнуйтесь, сделать роут публичным просто и интуитивно понятно:

Важно: сделайте тоже самое для роли authenticated

  • Перейдите  на вкладкуRoles & Permissions  http://localhost:1337/admin/plugins/users-permissions.
  • Выберите Authenticated
  • Поставьте галочку в чекбоксах find и findone  секции Restaurant
  • Сохраните.

Вернемся назад на http://localhost:1337/restaurants, теперь мы должны увидеть список ресторанов.

image

Включаем GraphQL

По умолчанию API генерируется в REST формате. Что если я скажу вам, что мы можем его превратить в GraphQL в течении 10 секунд?

Давайте проверим что это так.

Плагин для GraphQL доступен в Strapi, установим его следующей командой в директории /backend:

yarn strapi install graphql # или npm run strapi install graphql

На этом все, с бекендом мы закончили.

https://blog.strapi.io/content/images/2018/07/Screen-Shot-2018-07-02-at-17.03.38.png

  • Перезагрузите сервер (yarn develop или npm run develop)
  • Перейдем на http://localhost:1337/graphql и попробуем следующий запрос:

{       restaurants {         id # Или _id если вы используете MongoDB         name       } }

https://blog.strapi.io/content/images/2019/09/graphql-1.gif

Если мы увидим список ресторанов, то можно переходить к следующем шагу:

  • Установим GraphQL и @nuxt-apollo в нашу /frontend директорию

yarn add @nuxtjs/apollo graphql # или npm install @nuxtjs/apollo graphql

Модули и настройки для apollo должны быть установлены в nuxt.config.js:

    ...     modules: [ '@nuxtjs/apollo',     ],     apollo: { clientConfigs: { default: { httpEndpoint: 'http://localhost:1337/graphql' } }     },     ...

Показываем рестораны

Пока что мы движемся в правильном направлении. Что делать если мы хотим отобразить рестораны в Nuxt приложении? Давайте поместим необходимые для этого файлы в соответствующие директории.

  • Создадим ./pages/restaurants/index.vue файл и скопируем в него следующий код:

<template>         <div>           // Поиск ресторанов           <form class="uk-search uk-search-large uk-align-center uk-margin">               <span uk-search-icon></span>               <input class="uk-search-input" v-model="query" type="search" placeholder="Search...">           </form>            // Карточки с ресторанами           <div class="uk-card uk-card-default uk-grid-collapse uk-child-width-1-2@m uk-margin" v-for="restaurant in filteredList" v-bind:key="restaurant" uk-grid>               <div class="uk-card-media-left uk-cover-container">                   <img :src="'http://localhost:1337/' + restaurant.image.url" alt="" uk-cover>                   <canvas width="600" height="400"></canvas>               </div>               <div>                   <div class="uk-card-body">                       <h3 class="uk-card-title">{{ restaurant.name }}</h3>                       <p>{{ restaurant.description }}</p>                       // Ссылка на рестораны                       <router-link :to="{ name: 'restaurants-id', params: { id: restaurant.id }}" tag="a" class="uk-button uk-button-primary">See dishes                       </router-link>                   </div>               </div>           </div>            // Если ресторанов не найдено           <div class="uk-container uk-container-center uk-text-center" v-if="filteredList.length == 0">            <img src="https://assets-ouch.icons8.com/preview/19/52de2377-696e-4194-8c63-0a81aef60b4f.png" height="800" width="800">            <p>No restaurants found</p>          </div>        </div>  </template>  <script>       // Импортируем запрос ресторанов     import restaurantsQuery from '~/apollo/queries/restaurant/restaurants'      export default {         data() {         return {           // Инициализируем пустую переменную с ресторанами           restaurants: [],           query: ''         }       },       apollo: {         restaurants: {           prefetch: true,           query: restaurantsQuery         }       },       computed: {         // Ищем рестораны         filteredList() {           return this.restaurants.filter(restaurant => {             return restaurant.name.toLowerCase().includes(this.query.toLowerCase())           })         },       }     } </script>

Что мы написали?

Две главные части — шаблон и скрипт. Эти составляющие типичны для Vue.js приложений.

Раздел с шаблоном устанавливает структуру страницы, как вы видите некоторые атрибуты специфичны для Vue.js:

  1. v-for: повторяет тег количество раз равное длине массива (restaurants в нашем случае).
  2. v-if: отображает тег только если переданное условие валидно.
  3. v-model: связывает переменную со значением инпута. Применяется в данном случае для фильтрации ресторанов по их названию.
  4. vue-router: создает ссылку на страницу.

В скриптовой части мы импортируем необходимые компоненты и модули.

GraphQL запрос

Как вы могли заметить, мы вызываем restaurantsQuery GraphQL запрос с помощью apollo здесь:

... apollo: { restaurants: { prefetch: true, query: restaurantsQuery } }, ...

Для этого мы создадим директорию которая содержит запрос к Strapi API.

  • Создаем /frontend/apollo/queries/restaurant/restaurants.gql и вставляем следующий код:

    query Restaurants {         restaurants {         id         name         description         image {           url         }       }     }

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


В следующей части вы узнаете как отобразить список блюд.

ссылка на оригинал статьи https://habr.com/ru/post/490332/

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *