Создание службы уведомлений о заказе еды в режиме реального времени в Vue.js

Уведомления заставляют пользователей обращать внимание на определенные фрагменты информации и поощряют взаимодействие пользователей с нашим контентом или веб-сайтом.

Что мы будем создавать

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

URL GitHub

https://github.com/Iheanacho-ai/appwrite-food-notification

Предварительные условия

Чтобы получить максимальную отдачу от этого проекта, нам необходимо следующее:

  • Базовое понимание CSS, JavaScript и Vue.js.
  • Docker Desktop установлен на компьютере, выполните команду docker -v, чтобы проверить, установлен ли у нас Docker Desktop, если нет, установите его из документации Get Docker
  • Экземпляр Appwrite, запущенный на нашем компьютере, ознакомьтесь с этой статьей, чтобы создать локальный экземпляр Appwrite, мы будем использовать надежную базу данных Appwrite и службу Realtime для управления нашим приложением.

Настройка нашего приложения Vue.js

Мы установим Vue CLI, выполнив эти команды терминала для создания нового проекта Vue.

    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli
Войти в полноэкранный режим Выйти из полноэкранного режима

После установки Vue CLI мы переходим в нужную нам директорию и создаем новый проект.

    vue create <name of our project>
Войти в полноэкранный режим Выход из полноэкранного режима

Мы меняем директорию на проект и запускаем сервер разработки:

    npm run serve
Войти в полноэкранный режим Выйти из полноэкранного режима

Чтобы посмотреть приложение, переходим на http://localhost:8080/.

Установка зависимостей

Установка Tailwind CSS

Tailwind CSS — это CSS-фреймворк, который позволяет быстро создавать пользовательские интерфейсы для веб-приложений.

Чтобы установить Tailwind CSS в наш проект, выполните следующие команды терминала.

    npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
    npx tailwindcss init -p
Войти в полноэкранный режим Выйти из полноэкранного режима

Эти команды создают два файла в корневом каталоге нашего проекта, tailwind.config.js и postcss.config.js.

В нашем tailwind.config.js мы добавляем пути ко всем нашим файлам шаблонов с помощью приведенного ниже кода.

    module.exports = {
      purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
      content: [],
      theme: {
        extend: {},
      },
      plugins: [],
    }
Вход в полноэкранный режим Выйти из полноэкранного режима

Далее мы добавляем директивы tailwind в наш файл src/index.css.

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
Войти в полноэкранный режим Выход из полноэкранного режима

Установка Vue Router

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

Мы выполним эту команду терминала, чтобы включить наше приложение для использования Vue Router.

    npm install vue-router@4

    #or 

    yarn add vue-router@4
Войти в полноэкранный режим Выход из полноэкранного режима

Установка Mosha Vue Toastify

Mosha Vue Toastify — это легкая библиотека Vue, которая позволяет нам создавать супер настраиваемые уведомления.

Выполним эти команды, чтобы установить библиотеку Mosha Vue Toastify в наш проект.

    npm install mosha-vue-toastify

    #or

    yarn add mosha-vue-toastify
Войти в полноэкранный режим Выйти из полноэкранного режима

Установка Appwrite

Appwrite — это сквозное серверное решение с открытым исходным кодом, которое позволяет разработчикам быстрее создавать приложения.

Чтобы использовать Appwrite в нашем приложении Vue, мы установим клиентский SDK Appwrite для веб-приложений.

    npm install appwrite
Вход в полноэкранный режим Выход из полноэкранного режима

Создание нового проекта Appwrite

Во время создания экземпляра Appwrite мы указали, какое имя хоста и порт мы видим в нашей консоли. Значение по умолчанию — localhost:80.

Мы переходим на localhost:80 и создаем новую учетную запись, чтобы увидеть нашу консоль.

На нашей консоли есть кнопка Create Project. Нажмите на нее, чтобы начать новый проект.

После создания проекта появится приборная панель нашего проекта. В верхней части страницы находится панель настроек. Нажмите на нее, чтобы получить доступ к ID проекта и конечной точке API.

Мы скопируем ID проекта и конечную точку API, которые нужны нам для инициализации Appwrite Web SDK.

В нашем файле utils/web-init.js мы инициализируем наш Web SDK с помощью этого фрагмента кода.

    import { Appwrite } from 'appwrite';
    export const sdk = new Appwrite();
    sdk
      .setEndpoint('http://localhost/v1') // Replace this with your endpoint
      .setProject('projectID'); // Replace this with your ProjectID
Вход в полноэкранный режим Выход из полноэкранного режима

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

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

Мы создадим анонимную сессию пользователя в нашем файле utils.js.

    import { Appwrite } from 'appwrite';
    export const sdk = new Appwrite();
    sdk
      .setEndpoint('http://localhost/v1') // Replace this with your endpoint
      .setProject('62532ce64d84a58176da'); // Replace this with your ProjectID

    // Create an anonymous user session

    sdk.account.createAnonymousSession().then(
       (response) => {
         console.log(response);
       },
       (error) => {
         console.log(error);
       }
    );
Вход в полноэкранный режим Выход из полноэкранного режима

Создание коллекции и атрибутов

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

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

На уровне коллекции мы хотим назначить доступ на чтение и доступ на запись со значением role:all. Мы можем изменить разрешения, чтобы указать, кто имеет доступ на чтение или запись в нашу базу данных.

В правой части страницы разрешений мы копируем идентификатор коллекции, который нам нужен для выполнения операций над документами коллекции.

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

Мы создаем строковый атрибут orderStatus.

Создаем наше приложение для уведомления о заказе еды.

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

Создание страницы заказа

Наша страница заказа будет состоять из кнопки для размещения заказа и списка выбора для обновления статуса заказа.

Мы создаем папку views в нашей папке src для создания пользовательского интерфейса. Эта папка src/views будет содержать файл Home.vue.

Мы создадим нашу страницу заказа в файле src/views/Home.vue.

    <template>
      <div class="home rounded overflow-hidden shadow-lg">
        <div class="home-container">
          <button type="button" class="bg-gray-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Place Order</button>
          <h3>Change Order Status to follow your order</h3>
          <select name="order-status" id="order-status" class ="relative w-150 bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
            <option value="Order Placed"  >Order Placed</option>
            <option value="Order Accepted" >Order Accepted</option>
            <option value="Prepared" >Prepared</option>
            <option value="En-route" >En-route</option>
            <option value="Delivered">Delivered</option>
          </select>
        </div>
      </div>
    </template>

    <style>
      #app {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 80vh;
        text-align: center;
      }

      .app-container{
        height: 400px;
      }

      .page-link{
        margin: 10px;
        text-decoration: underline;
      }
    </style>

Вход в полноэкранный режим Выход из полноэкранного режима

Маршрутизация на наши страницы

В нашем файле src/main.js мы разрешаем нашему приложению использовать router для перехода на различные страницы с помощью этого фрагмента кода.

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import './index.css';

    createApp(App).use(router).mount('#app')
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы создаем папку router в нашей папке src. Наша папка router будет содержать файл index.js. Этот файл будет отвечать за определение маршрутов, ведущих к определенным компонентам.

    // src/router/index.js
    import { createRouter,createWebHistory } from 'vue-router'
    import Home from '@/views/Home'
    import Notification from '@/views/Notifications'
    const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        }
    ]
    const router = createRouter({
        history: createWebHistory(process.env.BASE_URL),
        routes
    })
    export default router;
Вход в полноэкранный режим Выход из полноэкранного режима

Приведенный выше блок кода делает следующее:

  • Создает массив routes, содержащий путь маршрута и компонент, к которому он должен вести.
  • Облегчает маршрутизацию с помощью метода Vue createRouter, который получает объект в качестве параметра, этот объект имеет два поля, поле history и поле route, значением которого является наш массив route.

Далее, в нашем файле App.vue мы добавляем ссылки, которые будут ссылаться на эти страницы.

    <template>
      <div class="app-container">
        <router-view ></router-view>
        <router-link class="page-link" to="/">  Home Page</router-link>
      </div>
    </template>

    <script>
      export default {
        name: 'App',
      }
    </script>

    <style>
      #app {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 80vh;
        text-align: center;
      }

      .app-container{
        height: 400px;
      }

      .page-link{
        margin: 10px;
        text-decoration: underline;
      }
    </style>

Вход в полноэкранный режим Выход из полноэкранного режима
  • Компонент router-view представляет наш компонент. В блоке кода выше мы указываем, в какой позиции находится наше приложение.
  • Компонент router-link действует как тег якоря, создавая ссылки, ведущие к различным маршрутам.

Чтобы избежать ошибок, возникающих из-за не многоуровневых имен компонентов, создайте файл ..eslintrc.js в нашей папке views.

Этот файл views/..eslintrc.js будет содержать следующий код.

    module.exports = {
      rules: {
        'vue/multi-word-component-names': 0,
      },
    }
Вход в полноэкранный режим Выйдите из полноэкранного режима

Перейдите на наш сайт http://localhost:8080/, чтобы увидеть нашу главную страницу.

Создание страницы уведомлений

В папке src/views мы создадим файл Notifications.vue для отображения статуса нашего заказа.

    <template>
        <div class="notifications rounded overflow-hidden shadow-lg">
            <div class="order-container">
                <h2>Order Placed</h2>
            </div>
        </div>
    </template>

    <style scoped>
        .notifications{
            width: 350px;
            height: 100px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    </style>
Вход в полноэкранный режим Выход из полноэкранного режима

Мы добавляем маршрут в объект routes в файле src/router/index.js для просмотра страницы уведомлений в браузере.

    // src/router/index.js

    const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/notification-page',
            name: 'Notification',
            component: Notification
        }
    ]
Вход в полноэкранный режим Выход из полноэкранного режима

Вот как выглядит наш файл src/router/index.js.

    import { createRouter,createWebHistory } from 'vue-router'
    import Home from '@/views/Home'
    import Notification from '@/views/Notifications'
    const routes = [
        {
            path: '/',
            name: 'Home',
            component: Home
        },
        {
            path: '/notification-page',
            name: 'Notification',
            component: Notification
        }
    ]
    const router = createRouter({
        history: createWebHistory(process.env.BASE_URL),
        routes
    })
    export default router;
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы добавляем еще один router-link в наш файл App.vue в качестве тега якоря для ссылки на страницу уведомлений.

    <template>
      <div class="app-container">
        <router-view ></router-view>
        <router-link class="page-link" to="/">  Home Page</router-link>

        <!-- link to notification page -->

        <router-link class="page-link" to="/notification-page">Notification Page</router-link>
      </div>
    </template>
Вход в полноэкранный режим Выход из полноэкранного режима

Чтобы увидеть нашу страницу уведомлений, перейдите по адресу http://localhost:8080/notification-page.

Добавьте взаимодействие с нашей базой данных

Когда пользователь размещает заказ, мы создаем документ в нашей базе данных, который содержит строку «Заказ размещен». Любые обновления статуса заказа с помощью списка выбора будут автоматически обновлять документ в нашей базе данных Appwrite.

Наш файл src/views/Home.vue будет отвечать за создание и обновление документа нашей базы данных.

Создание документа базы данных

    <script>
      import { sdk } from "../../utils";
      export default {
        name: 'Home',
        data(){
            return{
              documentID: null,
            }
          },
          methods: {
            placeOrder: async function(){
              try {
                let promise = await sdk.database.createDocument('collectionID', 'unique()', {
                  "orderStatus": "Order Placed"
                })

                this.documentID = promise.$id;
                alert("order successfully placed")
              } catch (error) {
                console.log(error)
              }
            },
            updateOrder: async function(e){
              try {
                let orderValue = e.target.value 
                await sdk.database.updateDocument('collectionID', this.documentID, {
                  "orderStatus": orderValue
                })
                alert(orderValue);

              } catch (error) {
                console.log(error)
              }
            }
          }

      }
    </script>
Войдите в полноэкранный режим Выход из полноэкранного режима

В приведенном выше блоке кода мы делаем следующее:

  • Создаем переменную documentID в нашем объекте data, которая будет содержать идентификатор нашего недавно созданного документа.
  • Создаем функцию placeOrder для создания документа в нашей базе данных с помощью createDocument от Appwrite
  • Создайте функцию updateOrder, которую мы передадим в список выбора позже в этом руководстве, где функция будет собирать значение элемента option и использовать его для обновления нашего документа в базе данных.

В нашем файле Home.vue мы передаем функцию placeOrder слушателю события on-click для нашей кнопки и функцию updateDocument слушателю события on-change для нашего списка select.

    <template>
      <div class="home rounded overflow-hidden shadow-lg">
        <div class="home-container">
          <button type="button" @click = 'placeOrder' class="bg-gray-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Place Order</button>
          <h3>Change Order Status to follow your order</h3>
          <select name="order-status" id="order-status" v-on:change = "updateOrder" class ="relative w-150 bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
            <option value="Order Placed"  >Order Placed</option>
            <option value="Order Accepted" >Order Accepted</option>
            <option value="Prepared" >Prepared</option>
            <option value="En-route" >En-route</option>
            <option value="Delivered">Delivered</option>
          </select>
        </div>
      </div>
    </template>
Вход в полноэкранный режим Выход из полноэкранного режима

Вот как выглядит наш файл Home.vue.

(https://gist.github.com/Iheanacho-ai/9e47a71adb7fc17b1c5df85c7387dfef)

Мы размещаем заказ на просмотр нашего документа в нашей базе данных.

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

Мы подписываемся на наш документ базы данных Appwrite в нашем src/views/Notifications.vue.

    <script>
        import { sdk } from "../../utils";

        export default {
            name: 'Notification',
            data(){
                return{
                    orderStatus: ""
                }
            },
            mounted(){
                if(sdk.account.get !== null){
                    try {
                    sdk.subscribe('collections.collectionID.documents', response => {
                        this.orderStatus = response.payload.orderStatus
                    });

                    } catch (error) {
                    console.log(error, 'error')
                    }
                }
            }
        }
    </script>
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше блоке кода мы делаем следующее:

  • Создаем переменную orderStatus для хранения полезной нагрузки нашего ответа
  • Проверяем наличие активной сессии пользователя перед подпиской на наш канал коллекций
  • Подписываемся на канал с помощью метода subscribe Appwrite, который получает два параметра, канал, на который мы подписываемся, и функцию обратного вызова; чтобы узнать больше о различных каналах, на которые мы можем подписаться, ознакомьтесь с Каналы реального времени Appwrite
  • Обновление переменной orderStatus

Далее мы отобразим нашу переменную orderStatus как текст в файле Notifications.vue.

    <template>
        <div class="notifications rounded overflow-hidden shadow-lg">
            <div class="order-container">
                <h2>{{orderStatus}}</h2>
            </div>
        </div>
    </template>
Вход в полноэкранный режим Выход из полноэкранного режима

Вот как выглядит наш файл Notifications.vue.

(https://gist.github.com/Iheanacho-ai/0f23cf72b2a43be4251f2fb2aa22b7d8)

Создание нашего уведомления

Чтобы использовать уведомление mosha-vue-toastify в нашем приложении, мы импортируем его в наш src/views/Notifications.vue.

    import { sdk } from "../../utils";
    import { createToast } from 'mosha-vue-toastify';
    import 'mosha-vue-toastify/dist/style.css'
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы используем объект watch для прослушивания изменения переменной в нашем приложении. Прослушивая переменную orderStatus, мы можем запускать метод createToast каждый раз, когда переменная обновляется.

    export default {
        name: 'Notification',
        data(){
            return{
                orderStatus: ""
            }
        },
        watch: {
            orderStatus: function(){
                createToast(this.orderStatus)
            }
        },
        mounted(){
           ...
        }
    }

Вход в полноэкранный режим Выход из полноэкранного режима

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


Заключение

В этой статье мы рассмотрели использование функции Realtime в Appwrite для подписки на события приложения.

Ресурсы

  • Начало работы с Appwrite для веб
  • Mosha Vue Toastify
  • Что такое Appwrite и как его эффективно использовать.

Оцените статью
Procodings.ru
Добавить комментарий