iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
SideProject30

30 天用 Rust 打造 QR Code 製造機系列 第 17

Day 17 - 使用 Form 表單送出資料

  • 分享至 

  • xImage
  •  

上一篇文章示範了如何使用 GET 方法去取得 PNG 的 QR Code,這一篇文章則是要示範如何使用 POST 方法去取得 PNG 的 QR Code,並且會使用到 Form 表單來送出資料。

新增 Method

首先我們要在 client.ts 中新增一個 post 的方法,這個方法是用來發送 POST 請求的,程式碼如下:

interface PostData {
  url?: string
  phone?: string
  email?: string
  address?: string
  foreground?: string
  background?: string
  dimension?: string
}

class APIClient {
  client: AxiosInstance

  constructor() {
    this.client = axios.create({
      baseURL: process.env.NEXT_PUBLIC_API_URL,
      responseType: 'blob',
      headers: {
        'Content-Type': 'application/json'
      }
    })
  }

  get(path: string, params?: GetParams) {
    return this.client.get(path, { params })
  }

  post(path: string, data: PostData) {
    return this.client.post(path, data)
  }
}

export type { GetParams, PostData }
export default APIClient

這裡新增了一個 PostData 的型別,這個型別是用來定義 POST 請求的參數,這些參數都是可選的,所以我們使用 ? 來定義。

設定 API 路徑

接下來在 endpoints.ts 中新增路徑:

const Endpoints = {
  GenerateQrcode: {
    pngType: 'generate_qr',
    svgType: 'generate_qr_svg',
  }
}

export default Endpoints

新增 GenerateQrcode API

最後一個設定要在 generateQrcode 新增一個函式:

import APIClient, { GetParams, PostData } from './client'
import Endpoints from './endpoints'

const apiClient = new APIClient()

// 省略

const generateQrcode = {
  // 省略
  getSvg: (data: PostData) => {
    return apiClient.post(Endpoints.GenerateQrcode.svgType, data)
  }
}

export default generateQrcode

主要新增了一個 getSvg 的函式,這個函式是用來取得 SVG 的 QR Code,並且使用 apiClient.post 來發送 POST 請求。

表單送出資料

由於原本就已經設定好表單,接下來只要把表單都接上 state,並且在送出的時候,把 state 的資料傳遞進去就可以了。

'use client'
import { useState, FormEvent } from 'react'
import { TextInput, SelectType, SizeSlider, ColorPicker } from './components'
import Image from 'next/image'
import generateQrcode from './lib/api/generateQrcode'

export default function Home() {
  const [text, setText] = useState<string>('')
  const [qrType, setQrType] = useState<string>('URL')
  const [qrSize, setQrSize] = useState<number>(500)
  const [qrColor, setQrColor] = useState<string>('#000000')
  const [qrBgColor, setQrBgColor] = useState<string>('#ffffff')
  const [imgSrc, setImgSrc] = useState<string | null>(null)

  const fetchQrcodeSvg = async () => {
    try {
      const typeMapping: { [key: string]: string } = {
        URL: 'url',
        電話: 'phone',
        地址: 'address',
        Email: 'email'
      }

      const key = typeMapping[qrType as keyof typeof typeMapping]

      const data = {
        [key]: text,
        foreground: qrColor,
        background: qrBgColor,
        dimensions: qrSize
      }
      const response = await generateQrcode.getSvg(data)
      const blob = new Blob([response.data], { type: 'image/svg+xml' })
      const objectURL = URL.createObjectURL(blob)
      setImgSrc(objectURL)
    } catch (_) {
      console.error('Error fetching image:')
    }
  }

  const generateQRCode = async (e: FormEvent) => {
    e.preventDefault()
    await fetchQrcodeSvg()
  }

  return (
    <main className='flex min-h-screen flex-col items-center justify-between p-24'>
      <div className='container mx-auto p-4'>
        <h1 className='text-3xl mb-4'>QR Code 製造器</h1>
        <form onSubmit={generateQRCode} className='flex flex-col gap-y-5'>
          <SelectType qrType={qrType} setQrType={setQrType} />
          <TextInput text={text} setText={setText} />
          <div className='flex items-center justify-evenly'>
            <SizeSlider qrSize={qrSize} setQrSize={setQrSize} />
            <ColorPicker
              label='選擇顏色'
              color={qrColor}
              setColor={setQrColor}
            />
            <ColorPicker
              label='選擇背景顏色'
              color={qrBgColor}
              setColor={setQrBgColor}
            />
          </div>
          <div className='flex justify-center mt-5'>
            <button
              type='submit'
              className='bg-green-500 hover:bg-green-100 text-white hover:text-slate-700 font-bold py-2 px-4 rounded text-center'
            >
              產生 QR Code
            </button>
          </div>
        </form>
        {imgSrc ? (
          <div className='flex justify-center mt-10'>
            <Image src={imgSrc} width={500} height={500} alt='QR Code Image' />
          </div>
        ) : (
          '請點擊「產生 QR Code」按鈕'
        )}
      </div>
    </main>
  )
}

現在可以判斷不同類型的 QR Code,並且可以設定顏色、背景顏色、大小,並且可以產生 SVG 的 QR Code,這樣子就完成了!

總結

這篇文章示範了如何使用 Form 表單來送出資料,並且使用 POST 方法來取得 SVG 的 QR Code,不過這個表單還有一些問題需要解決,明天見👋!


上一篇
Day 16 - 如何用 Axios 來管理 API
下一篇
Day 18 - React Hook Form 做好你的表單驗證
系列文
30 天用 Rust 打造 QR Code 製造機30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言