Создание приложения для заказа еды Jamstack с помощью Strapi, Gridsome и Snipcart 3/6

Эта статья является гостевой серией великого Ekene Eze . Он возглавляет команду опытных разработчиков в Flutterwave и написал это сообщение в блоге через программу Write for the Community.

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

Содержание: 1. Часть 1 - Создание приложения Strapi и создание продуктов 2. Часть 2 - Настройка проекта Gridsome 3. Часть 3 - Использование продуктов с помощью Gridsome и GraphQL 4. Часть 4 - Создание отдельных представлений продукта с помощью шаблонов Gridsome 5. Часть 5 - Реализация корзины и оформления заказа с помощью Snipcart 6. Часть 6 - Развертывание приложений

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

Потребление продуктов с помощью Gridsome и GraphQL

Получить продукты

Продукты, которые мы будем отображать в нашем приложении Gridsome, будут поступать из endpoint продуктов Strapi. К счастью для нас, Gridsome позволяет нам извлекать данные из конечной точки продуктов Strapi на уровень данных GraphQL, который управляет данными для нашего приложения Gridsome.

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

npm i axios

После установки Axios откройте gridsome.server.js файл проекта и обновите его приведенным ниже фрагментом:

//gridsome.server.js
const axios = require("axios");
module.exports = function(api) {
    // whitelist vuetify for webpack code here
  };

  api.loadSource(async (actions) => {
    const { data } = await axios.get("http://localhost:1337/products");
    const collection = actions.addCollection({
      typeName: "Product",
    });
    for (const product of data) {
      collection.addNode({
        id: product.id,
        title: product.title,
        price: product.price,
        rating: product.rating,
        description: product.description,
        image: product.image.formats.thumbnail.url,
        instructions: product.instructions,
      });
    }
  });
  api.createPages(({ createPage }) => {
    // Use the Pages API here: https://gridsome.org/docs/pages-api/
  });

Здесь мы выполняем базовый вызов API для получения списка продуктов из конечной точки продуктов Strapi, на которой я работаю локально localhost:1337/products. Вы можете рассматривать коллекцию в приведенном выше фрагменте как массив, в который мы будем отправлять каждый отдельный продукт, возвращаемый из конечной точки. Следовательно, collection.addNode эквивалентность регулярного array.push.

Каждый узел содержит все детали, которые мы хотим получить от продукта, такие как название, описание, цена и т. Д. В результате мы можем просмотреть все возвращенные данные и получить отдельные продукты, а также их соответствующие детали.

Показать продукты

Получив эти продукты из Strapi, мы можем отображать их, чтобы пользователи могли взаимодействовать с ними на веб-интерфейсе. Для этого сначала создадим новый src/components/Products.vue компонент. В этом компоненте мы создадим шаблон для организации продуктов с использованием компонентов карты Vuetify. Обновите его приведенным ниже фрагментом:

// src/components/Products.vue
<template>
  <div>
    <h1
      v-if="show"
      align="center"
      justify="center"
      class="py-5 orange white--text"
    >
      {{ banner }}
    </h1>
    <v-container class="mb-3">
      <v-row :align="align" no-gutters>
        <v-col md="4" v-for="edge in $page.products.edges" :key="edge.node.id">
          <g-link
            :to="`/products/${edge.node.id}`"
            style="text-decoration: none; color: inherit"
          >
            <v-card :loading="loading" class="ma-3" shaped>
              <v-img
                height="250"
                :src="`http://localhost:1337${edge.node.image}`"
              ></v-img>
              <v-card-title>{{ edge.node.title }}</v-card-title>
              <v-card-text>
                <v-row align="center" class="mx-0">
                  <v-rating
                    :value="edge.node.rating"
                    color="amber"
                    dense
                    half-increments
                    readonly
                    size="14"
                  ></v-rating>

                </v-row>
                <div class="my-4 subtitle-1">$ {{ edge.node.price }}</div>
                <div>
                  {{ `${edge.node.description.slice(0, 120)}...` }}
                </div>
              </v-card-text>
              <v-card-actions>
                <v-btn
                  rounded
                  outlined
                  color="orange"
                  text
                >
                  Add to cart
                </v-btn>
              </v-card-actions>
            </v-card>
          </g-link>
        </v-col>
      </v-row>
    </v-container>
  </div>
</template>
<script>
export default {
  props: ["banner", "show"],
};
</script>

На данный момент все, что мы сделали, - это создали шаблон template Vuetify, который будет содержать данные о продукте, поступающие из нашего уровня данных GraphQL. Мы подготовили поля для описания продукта, цены, названия, рейтинга и изображения (description, price, title, rating, and image). Чтобы показать этот компонент пользователям, нам нужно отобразить его Render на странице Index. Поэтому, давайте внесем небольшие изменения в index.vue файл.

В разделе скрипта импортируйте компонент Products следующим образом:

//index.vue
import Products from "@/components/Products.vue";

В разделе template сразу после рендеринга компонента Product:

//index.vue
<Products show="false" banner="Best Sellers" />

Наконец, чтобы получить все данные о продуктах, которые нам нужно отобразить из нашего слоя данных, давайте определим запрос query GraphQL для нашего типа Product:

// src/pages/index.vue
<page-query>
query{
  products: allProduct{
    edges{
      node{
        id,
        title,
        description,
        rating,
        price,
        image
      }
    }
  }
}
</page-query>

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

{
  "data": {
    "products": {
      "edges": [
        {
          "node": {
            "id": "7",
            "title": "Seafood",
            "description": "Seafood is any form of sea life regarded as food by humans. Seafood prominently includes fish and shellfish. Shellfish include various species of molluscs, crustaceans, and echinoderms. Historically, sea mammals such as whales and dolphins have been consumed as food, though that happens to a lesser extent in modern times",
            "price": 300,
            "rating": 5,
            "image": "/uploads/thumbnail_seafood_d3e69aad71.png"
          }
        },
        {
          "node": {
            "id": "6",
            "title": "Sandwich",
            "description": "Spread mayo, butter or cream cheese all the way to the edges of each slice of bread to create a seal against wet sandwich fillings. Also, try packing high moisture ingredients, like tomatoes, pickles, and cucumbers, separately",
            "price": 150,
            "rating": 3,
            "image": "/uploads/thumbnail_miscellaneous_e0812098cf.png"
          }
        },
        {
          "node": {
            "id": "5",
            "title": "Dessert",
            "description": "Dessert is a course that concludes a meal. The course usually consists of sweet foods, such as confections dishes or fruit, and possibly a beverage such as dessert wine or liqueur, however in the United States it may include coffee, cheeses, nuts, or other savory items regarded as a separate course elsewhere",
            "price": 100,
            "rating": 4,
            "image": "/uploads/thumbnail_dessert_4fdacb1066.png"
          }
        },
        {
          "node": {
            "id": "4",
            "title": "Lamb",
            "description": "Lamb, hogget, and mutton are the meat of domestic sheep (species Ovis aries) at different ages. A sheep in its first year is called a lamb, and its meat is also called lamb",
            "price": 250,
            "rating": 3,
            "image": "/uploads/thumbnail_lamb_8f452bb9a3.png"
          }
        },
        {
          "node": {
            "id": "3",
            "title": "Chicken wings",
            "description": "Chicken is a type of domesticated fowl, a subspecies of the red junglefowl. It is one of the most common and widespread domestic animals",
            "price": 400,
            "rating": 3,
            "image": "/uploads/thumbnail_chicken_c6742f8df3.png"
          }
        },
        {
          "node": {
            "id": "2",
            "title": "Homemade pasta",
            "description": "Pasta is a staple food of traditional Italian cuisine, with the first reference dating to 1154 in Sicily. Humans have been eating beef since prehistoric times",
            "price": 400,
            "rating": 5,
            "image": "/uploads/thumbnail_pasta_1e163eb9f7.png"
          }
        },
        {
          "node": {
            "id": "1",
            "title": "Grilled Beef",
            "description": "Beef is the culinary name for meat from cattle, particularly skeletal muscle. Humans have been eating beef since prehistoric times. Beef is a source of high-quality protein and essential nutrients. Check below for preparation instructions",
            "price": 300,
            "rating": 4,
            "image": "/uploads/thumbnail_beef_b95f539dc8.png"
          }
        }
      ]
    }
  }
}

На этом этапе, если вы сохраните все обновления, внесенные в index.vue файл, мы должны получить обновленный вид в браузере по адресу localhost:8080:

На данный момент мы достигли нашей цели по рендерингу продуктов из нашего приложения Strapi во внешнем интерфейсе Gridsome.

Вы могли заметить, что при нажатии на любой из продуктов открывается новый маршрут, http://localhost:8080/products/{id} который представляет собой одностраничный маршрут для этого конкретного продукта. Это возможно, потому что мы заключили каждую отдельную карточку продукта в <g-link> тег, который в основном предоставляет возможности маршрутизации на стороне клиента для нашего приложения Gridsome:

<g-link
    :to="`/products/${edge.node.id}`"
    style="text-decoration: none; color: inherit"
>
// product card here
</g-link>

Вывод

Итак краткое резюме. В этой части мы использовали эндпойнт продукта, созданную с помощью Strapi в первой части этой серии. Слой данных GraphQL от Gridsome сыграл важную роль в этом процессе, как мы видели. Это упростило доступ к нужным нам данным в любом месте. Мы также испачкали руки с Vuetify, создавая компоненты и стилизацию карточек продуктов, ровно также как развлечение. В следующей части мы рассмотрим, как отображать сведения о продукте на одной странице просмотра продукта, где клиенты могут размещать заказы.


Эндпоинт (Endpoint - конечная точка) — это само обращение к маршруту отдельным HTTP методом. Эндпоинт выполняют конкретную задачу, принимают параметры и возвращают данные Клиенту.

Поделиться Комментарии

Поделиться новостью

comments powered by Disqus