iT邦幫忙

2024 iThome 鐵人賽

DAY 16
2
Software Development

透過 nestjs 框架,讓 nodejs 系統維護度增加系列 第 27

nestjs 系統設計 - 活動訂票管理系統 - client code part 1

  • 分享至 

  • xImage
  •  

nestjs 系統設計 - 活動訂票管理系統 - client code part 1

目標

今天主要會是來實做取用票券的 mobile app 。預計會使用 ReactNative 這樣的技術來達成。並且透過 expo 來實做對應的處理流程。

今天主要會先實做關於 layout 的部份。

概念

Mobile application 負責的部份是處理用戶端的一些狀態處理。是一個系統中,用戶能夠直接操作到的部份,用戶對這個部份最能直接感受。

選用 expo 來實做 React Native 應用,好處是能夠使用跨平台的特性。並且有一系列的週邊配置。

expo 開發環境配置

基礎需求:

  1. 需要有 nodejs runtime
  2. mobile 模擬器,或是有手機

建立專案資料夾

mkdir ticket-booking-app
cd ticket-booking-app
npx create-expo-app@latest

資料夾目錄

image

驗證設置

這邊需要先開啟模擬器
image

設置自己安裝 Android 位置,一般透過 Android Studio 會在 $HOME 目錄下

export ANDROID_HOME=/home/yuanyu/Android/Sdk

啟動 expo start --android

npm run android

如果成功,預設看到的畫面如下
image

移除不需要的 component 與 hooks

只留下 navigation

實做 layout

目標 layout

image

基礎

主要的 layout 都在 app 資料夾下,登入之後的畫面預設有四個 navigation tab。各自對應到要執行的動作。

而程式資料夾結構如下:
image

最外層的 layout 是透過 _layout.tsx 與 login.tsx。這兩個依據狀態來 render。登入之後,就會是分 Events , Ticket , Scan Ticket 與 Setting 四個 component 各自擺放。

每個階層都有各自的 layout 。然後在各自一個自的功能切分 component 。 以下分別針對主要 layout 跟 tickets 的 layout 作元件講解其他則放到 repository 。

app 下的 layout

import { Slot } from 'expo-router';
import { StatusBar } from 'expo-status-bar';

export default function Root() {
  return (
    <>
      <StatusBar style='dark' />
      {/* Authentication provider */}
      <Slot />
      {/* */}
    </>
  );
}

這是主要的頁面元件被包在一個大元件有兩個元件,基礎的 StatusBar 與 Slot 。 Slot 是 expo-router 的元件透過一些基礎 navigation 渲染畫面。

authed 下的 layout

import { Redirect, Stack } from 'expo-router';

export default function AppLayout() {
  // check from context if user is logged in
  const isLogggedIn = true;
  if (!isLogggedIn) {
    return <Redirect href="/login" />
  }
  return <Stack screenOptions={{ headerShown: false }} />
}

這個 layout 會根據當下有沒有登入作不同顯示。

tab 下的 layout

import { TabBarIcon } from '@/components/navigation/TabBarIcon';
import { Ionicons } from '@expo/vector-icons';
import { Tabs } from 'expo-router';
import { ComponentProps } from 'react';
import { Text } from 'react-native';

export default function TabLayout() {
  const tabs = [
    {
      showFor: [],
      name: '(events)',
      displayName: 'Events',
      icon: 'calendar',
      options: {
        headerShown: false
      }
    },
    {
      showFor: [],
      name: '(tickets)',
      displayName: 'My Tickets',
      icon: 'ticket',
      options: {
        headerShown: false
      }
    },
    {
      showFor: [],
      name: 'scan-ticket',
      displayName: 'Scan Ticket',
      icon: 'scan',
      options: {
        headerShown: true
      }
    },
    {
      showFor: [],
      name: 'settings',
      displayName: 'Settings',
      icon: 'cog',
      options: {
        headerShown: true
      }
    },
  ];
  return <Tabs>
    { tabs.map(tab => (
      <Tabs.Screen 
        key={tab.name}
        name={tab.name}
        options={{
          ...tab.options,
          headerTitle: tab.displayName,
          // href: tab.showFor.includes()
          tabBarLabel: ({focused}) => (
            <Text style={{color: focused ? 'black': 'gray', fontSize: 12 }}>
              {tab.displayName}
            </Text>
          ),
          tabBarIcon: ({focused}) => (
            <TabBarIcon
              name={tab.icon as ComponentProps<typeof Ionicons>['name']} 
              color={focused? 'black': 'gray'}
            />
          )
        }}
      />
    )) }
  </Tabs>;
}

顯示四的 tab 一些內容。

ticket 下的 layout

import { Stack } from 'expo-router';

export default function TicketsLayout() {
  return (
    <Stack screenOptions={{ headerBackTitle: 'Tickets' }}>
      <Stack.Screen name='index' />
      <Stack.Screen name='ticket/[id]'/>
    </Stack>
  )
}

基礎 ticket 導覽與其連結。

event 下的 layout

import { Stack } from 'expo-router';

export default function EventsLayout() {
  return (
    <Stack screenOptions={{ headerBackTitle: 'Events' }}>
      <Stack.Screen name='index' />
      <Stack.Screen name='new' />
      <Stack.Screen name='event/[id]'/>
    </Stack>
  )
}

基礎 event 導覽與其連結。

reload app 為更新好的 app

  1. 啟動 expo
npx expo start

image

  1. 按下 r
    畫面都可以 reload 如下

image

image

備註

本文目前提到的是有實做內容的 component 。其他對應,比如 event 與 ticket 資料夾下的 new.tsx 等等都需要自行實做回傳空的 component 。如下

export default function NewEvent() {
  return <></>;
}

結論

client code 雖然跟 nestjs 本身無關,但屬於這個系統的一部分。因此,會花篇幅來實做,並且與之前實做的 api 來作整合。完成一整個系統的開發。

這部份的實做細節都可以參考 expo 官方文件 去搜尋相關的元件實做。


上一篇
nestjs 系統設計 - 活動訂票管理系統 - fly.io
系列文
透過 nestjs 框架,讓 nodejs 系統維護度增加27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言