Samouczek: Tworzenie aplikacji do rezerwacji w muzeum z Vue.js i Timerise API

Ten samouczek poprowadzi Cię przez proces tworzenia aplikacji do rezerwacji muzeów przy użyciu Vue.js, TypeScript, Timerise API, Apollo Client i Tailwind CSS. Skupimy się na integracji bezgłowego API Timerise, demonstrując korzyści płynące z takiego rozwiązania.

Wymagania wstępne

  • Podstawowa znajomość TypeScript i Vue.js
  • Zainstalowany Node.js
  • Dostęp do interfejsu API Timerise

Krok 1: Konfiguracja projektu Vue.js

Pierwszym krokiem w tworzeniu naszej aplikacji do rezerwacji muzeów jest utworzenie nowego projektu Vue.js. Vue CLI zapewnia elastyczny i prosty sposób konfigurowania nowych projektów. Takie podejście pozwala nam skonfigurować podstawowe funkcje, takie jak Tailwind CSS, ESLint i inne, od samego początku, upraszczając początkową konfigurację projektu.

Tworzenie nowej aplikacji Vue.js
Uruchom polecenie, aby zainicjować tworzenie nowej aplikacji Vue.js. Będziesz mógł zintegrować Tailwind CSS i inne konfiguracje podczas procesu konfiguracji.

Bash
npm create vue@latest vue-museum-booking-app
cd vue-museum-booking-app
npm install
npm run format
npm run dev

Po wyświetleniu monitu wybierz preferowane konfiguracje:

  • Dodać TypeScript? … Nie / Tak
  • Dodać obsługę JSX? … Nie / Tak
  • Dodać Vue Router do tworzenia aplikacji jednostronicowych? … Nie / Tak
  • Dodać Pinię do zarządzania państwem? … Nie / Tak
  • Dodać Vitest do testów jednostkowych? … Nie / Tak
  • Dodać kompleksowe rozwiązanie do testowania? ’ Nie
  • Dodać ESLint dla jakości kodu? … Nie / Tak
  • Dodać Prettier do formatowania kodu? … Nie / Tak

Krok 2: Instalacja zależności

Po skonfigurowaniu naszego projektu Vue.js, musimy teraz zainstalować dodatkowe pakiety kluczowe dla naszej aplikacji, w szczególności Apollo Client do obsługi zapytań GraphQL i mutacji z Timerise API.

Instalacja klienta Apollo
Apollo Client to kompleksowa biblioteka zarządzania stanem, która umożliwia zarządzanie zarówno lokalnymi, jak i zdalnymi danymi za pomocą GraphQL. Będzie to nasze główne narzędzie do interakcji z API Timerise.

Bash
npm install @apollo/client graphql
npm install @vue/apollo-option @vue/apollo-components --save 

Dodatkowe zależności
W zależności od wymagań projektu mogą być potrzebne inne zależności. Na przykład, jeśli planujesz obsługiwać daty i godziny (powszechne w aplikacji do rezerwacji), rozważ zainstalowanie date-fns:

Bash
npm install date-fns

Krok 3: Konfiguracja klienta Apollo

Teraz, gdy nasz projekt jest skonfigurowany z niezbędnymi zależnościami, nadszedł czas, aby skonfigurować klienta Apollo. Taka konfiguracja umożliwia naszej aplikacji wydajne wykonywanie zapytań i mutacji, zarządzanie stanami ładowania, buforowanie danych i obsługę błędów.

Konfiguracja klienta Apollo w lib/apolloClient.ts

Utwórz instancję klienta Apollo wskazującą na punkt końcowy GraphQL API. Ta instancja będzie używana w całej aplikacji.

TypeScript
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'

const httpLink = createHttpLink({
  uri: 'https://sandbox-api.timerise.io/v1',
})

const cache = new InMemoryCache()

export const apolloClient = new ApolloClient({
  link: httpLink,
  cache,
})
  • The uri jest ustawiona na punkt końcowy interfejsu API Timerise.
  • InMemoryCache służy do buforowania wyników zapytań po ich pobraniu. Pomaga to zoptymalizować wydajność naszej aplikacji poprzez zmniejszenie liczby potrzebnych wywołań API.

Ta konfiguracja jest kluczowym krokiem w umożliwieniu naszej aplikacji skutecznej komunikacji z API Timerise. Ustawia to scenę dla kolejnych kroków, w których będziemy tworzyć i wykonywać zapytania GraphQL i mutacje do obsługi rezerwacji.

Zawijanie aplikacji za pomocą ApolloProvider
W pliku main.ts (lub main.ts, jeśli używasz TypeScript) zaimportuj ApolloProvider i instancję Apollo Client. Następnie użyj funkcji właściwości globalnych Vue, aby globalnie udostępnić instancję klienta Apollo.

TypeScript
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

import { apolloClient } from './lib/apolloClient'
import { createApolloProvider } from '@vue/apollo-option'

const apolloProvider = createApolloProvider({
  defaultClient: apolloClient,
})

const app = createApp(App)

app.use(apolloProvider)

app.use(router)

app.mount('#app')

Krok 4: Tworzenie zapytań i mutacji GraphQL

Zdefiniuj zapytania GraphQL i mutacje potrzebne do interakcji z interfejsem API Timerise w celu pobierania usług i rezerwacji slotów w src/graphql/queries.ts i src/graphql/mutations.ts.

Definiowanie operacji GraphQL w pliku graphql/queries.ts

TypeScript
import { gql } from '@apollo/client/core';

export const SERVICE_QUERY = gql`
  query Service($serviceId: ID!, $slotType: SlotType!) {
    service(serviceId: $serviceId) {
      serviceId
      title
      description
      media {
        title
        url
      }
      slots(slotType: $slotType) {
        slotId
        dateTimeFrom
        dateTimeTo
        duration
        quantity
      }
    }
  }
`;

export const BOOKING_QUERY = gql`
  query Booking($bookingId: ID!) {
    booking(bookingId: $bookingId) {
      bookingId
      shortId
      shortUrl
      qrUrl
      status
    }
  }
`;

Zdefiniuj mutację w pliku graphql/mutations.ts

TypeScript
import { gql } from '@apollo/client/core';

export const BOOKING_CREATE_MUTATION = gql`
  mutation BookingCreate($serviceId: ID!, $slots: [ID]) {
    bookingCreate(serviceId: $serviceId, slots: $slots) {
      bookingId
      qrUrl
      shortUrl
      status
    }
  }
`;

Krok 5: Tworzenie komponentów aplikacji

Mając zdefiniowane interakcje API, skupiamy się teraz na budowaniu komponentów React. Komponenty te zapewnią interfejs do wybierania slotów i potwierdzania rezerwacji, wykorzystując zapytania i mutacje, które skonfigurowaliśmy.

Komponent wyboru slotów (SlotSelection.vue)
Kod i wyjaśnienie tworzenia komponentu do wybierania dostępnych slotów.

TypeScript
<template>
  <div>
    <h2>Select a slot to book</h2>
    <ul>
      <li v-for="slot in service.slots" :key="slot.slotId">
        <a
          @click="handleSlotSelect(slot.slotId)"
        >
          {{ new Date(slot.dateTimeFrom).toLocaleString() }}
      </a>
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
import { provideApolloClient } from '@vue/apollo-composable';
import { apolloClient } from '../lib/apolloClient';
import { defineComponent, ref, watchEffect } from 'vue'
import { useQuery, useMutation } from '@vue/apollo-composable'
import { SERVICE_QUERY } from '@/graphql/queries'
import { BOOKING_CREATE_MUTATION } from '@/graphql/mutations'
import { useRouter } from 'vue-router'

export default defineComponent({
  props: {
    serviceId: String
  },
  setup(props) {
    provideApolloClient(apolloClient);
    const router = useRouter()
    const selectedSlot = ref<string | null>(null)
    const { result, loading, error } = useQuery(SERVICE_QUERY, () => ({
      serviceId: props.serviceId,
      slotType: 'AVAILABLE'
    }))

    const service = ref<any>({});

    watchEffect(() => {
      if (result.value && result.value.service) {
        service.value = result.value.service;
      }
    });

    const {
      mutate: createBooking,
      loading: bookingLoading,
      error: bookingError
    } = useMutation(BOOKING_CREATE_MUTATION)

    const handleSlotSelect = async (slotId: string) => {
      selectedSlot.value = slotId;
      try {
        const result = await createBooking({ serviceId: props.serviceId, slots: [slotId] });
        if (result && 'data' in result) {
          const { data } = result;
          if (data.bookingCreate && data.bookingCreate.bookingId) {
            router.push(`/confirmation/${data.bookingCreate.bookingId}`);
          }
        } else {
          console.error('No data returned from booking creation');
        }
      } catch (error) {
        console.error('Error creating booking:', error);
        // Handle booking error here
      }
    };

    return {
      service,
      loading,
      error,
      bookingLoading,
      bookingError,
      selectedSlot,
      handleSlotSelect
    }
  }
})
</script>

Komponent potwierdzenia (BookingConfirmation.vue)
Kod i objaśnienia dotyczące tworzenia komponentu wyświetlającego szczegóły potwierdzenia rezerwacji, w tym kod QR.

TypeScript
<template>
  <div v-if="!loading && !error" style="text-align: center;">
    <h2>Booking status: {{ booking.status }}</h2>
    <p style="margin-bottom: 8px;">Booking ID: {{ booking.shortId }}</p>
    <div>
      <img :src="booking.qrUrl" alt="QR Code" width="200" />
    </div>
    <a :href="booking.shortUrl" target="_blank">View booking page</a>
  </div>
  <p v-if="loading">Loading booking...</p>
  <p v-if="error">Error loading booking.</p>
</template>

<script lang="ts">
import { provideApolloClient } from '@vue/apollo-composable';
import { apolloClient } from '../lib/apolloClient';
import { defineComponent, ref, watchEffect } from 'vue'
import { useQuery } from '@vue/apollo-composable'
import { BOOKING_QUERY } from '@/graphql/queries'

export default defineComponent({
  props: {
    bookingId: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    provideApolloClient(apolloClient);

    const { result, loading, error } = useQuery(BOOKING_QUERY, () => ({
      bookingId: props.bookingId,
    }));

    const booking = ref<any>({});

    watchEffect(() => {
      if (result.value && result.value.booking) {
        booking.value = result.value.booking;
      }
    });

    return { booking, loading, error };
  },
});
</script>

Krok 6: Wdrożenie za pomocą Netlify lub Vercel

Po utworzeniu aplikacji Vue.js można ją wdrożyć za pomocą Netlify lub Vercel dla projektów Vue.js. Upewnij się, że Twój projekt został wypchnięty do repozytorium GitHub, a następnie postępuj zgodnie z dokumentacją odpowiedniej platformy dotyczącą wdrażania aplikacji Vue.js.

Przesyłanie kodu do serwisu GitHub
Przed wdrożeniem upewnij się, że projekt został wypchnięty do repozytorium GitHub:

Bash
git init
git add .
git commit -m "Init commit"
git branch -M main
git remote add origin https://github.com/your-username/your-repo-name.git
git push -u origin main

Konfiguracja wdrożenia w Vercel

  1. Zaloguj się do Vercel i połącz swoje konto GitHub.
  2. Wybierz właśnie wypchnięte repozytorium.
  3. Vercel automatycznie wykrywa, że jest to aplikacja Next.js i sugeruje ustawienia kompilacji. Zaakceptuj je lub zmodyfikuj w razie potrzeby.
  4. Kliknij„Deploy„, aby rozpocząć proces wdrażania. Vercel zajmuje się kompilacją i wdrażaniem, zapewniając aktywny adres URL.

Vercel zapewnia funkcje takie jak automatyczny HTTPS, obsługa niestandardowych domen i analiza w czasie rzeczywistym. Możesz także ustawić zmienne środowiskowe i zarządzać innymi ustawieniami bezpośrednio z pulpitu nawigacyjnego Vercel.

Dostęp do pełnego kodu aplikacji

Aby uzupełnić ten samouczek, pełny kod źródłowy aplikacji do rezerwacji muzeów zostanie udostępniony w serwisie GitHub. Jest to doskonała okazja do zbadania bazy kodu, eksperymentowania z modyfikacjami oraz bardziej szczegółowego zrozumienia struktury i funkcjonalności aplikacji.

Klonowanie repozytorium
Aby pracować z kodem na komputerze lokalnym, sklonuj repozytorium za pomocą Git:

Bash
git clone https://github.com/timerise-io/vue-museum-booking-app.git
cd vue-museum-booking-app

Eksploruj i modyfikuj
Po uzyskaniu kodu można go swobodnie eksplorować i modyfikować. Niezależnie od tego, czy chcesz zrozumieć określone funkcje, dodać nowe funkcje, czy dostosować interfejs użytkownika, ta baza kodu może służyć jako praktyczny punkt wyjścia.

Wnioski

Ten samouczek zawiera przewodnik krok po kroku dotyczący konfigurowania aplikacji Vue.js, integracji z bezgłowym interfejsem API, takim jak Timerise, i jej wdrażania. Fragmenty kodu są kluczowymi częściami aplikacji, pokazującymi, jak zintegrować interfejs API Timerise z aplikacją Vue.js przy użyciu klienta Apollo dla GraphQL.