iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
Modern Web

TypeScript 啟動!系列 第 23

[Day 23] TypeScript 零售業者模擬演練

  • 分享至 

  • xImage
  •  

在目前的前端生態中,TypeScript 與 React 已成為前端工程師的主要工具之一,使用 TypeScript 能確保我們專案的更加的完善(可讀性高、錯誤降低)和 React 提供彈性的組件架構,讓大家能夠快速建構。結合這兩個語言的幫忙,相信能創造出來很棒的專案作品~不過在這之前我還是先來繼續把基礎打好,接下來我們將著眼於一個零售業者模擬演練的前端呈現,透過這個例子。預計能在表單控制、數據和前端呈現方面有更進一步吧。

Step1. 設定專案與安裝依賴

首先,我們使用 npx create 來建立一個新的 React 專案。接著,為了畫出圖表,我們將安裝 react-chartjs-2chart.js

npx create-react-app retail-simulation
npm install react-chartjs-2 chart.js

Step2. 建立資料型別 (types.ts)

定義了一個 SaleRecord 型別,這將用於定義每週的銷售記錄。(X軸)

// types.ts
export type SaleRecord = {
    week: number;
    remainingStock: number;
};

Step3. 線圖組件 (LineChart.tsx)

使用 react-chartjs-2 套件來建立一個線圖。這個套件接收每組 SaleRecord 數據,並將其轉換程圖所需的格式。另外在使用的過程中!!!必須註冊 Chart.js 的組件。為了確保能夠正常使用所有的圖表功能。當然用一種確引入所有圖表有點猛,所以後續有機會再來介紹每一種圖片。

// components/LineChart.tsx
import React from 'react';
import { Line } from 'react-chartjs-2';
import { SaleRecord } from './types';
import { Chart, registerables } from 'chart.js';

type Props = {
    data: SaleRecord[];
};

const LineChart: React.FC<Props> = ({ data }) => {
  Chart.register(...registerables);
    const chartData = {
        labels: data.map(record => `Week ${record.week}`),
        datasets: [
            {
                label: 'Remaining Stock',
                data: data.map(record => record.remainingStock),
                fill: false,
                backgroundColor: 'rgb(75, 192, 192)',
                borderColor: 'rgba(75, 192, 192, 0.2)',
            },
        ],
    };

    return <Line data={chartData} />;
};

export default LineChart;
  • Chart.register(...registerables); :這一行可以進行 Chart 的圖表初始化,並透過 registerables 來讓所有圖都先載入,相當的方便,一開始沒想到還得初始化XD,想說為何總是出現型態錯誤,害我搞混了。
  • React.FC<Props> :當說到 React.FC,其實就是 Function Component 的縮寫。在 React 中,有兩種主要的方式來定義組件:1. 類組件(Class Component)和 2. 函數組件(Function Component)。隨著 React Hooks 的出現,函數組件的功能變得更加強大(畢竟是函式功能導向,很符合函式程式的主旨,因此它們現在被廣泛地使用。) 所以也能寫成**React.FunctionComponent**。當使用它來定義組件時,能確保組件接受 props 且返回正確的 JSX 元素,還提供了自動完成和型別檢查,這在開發過程中非常有幫助。
  • chartData 的部分就是為了畫一個折線圖,去控制資料內的部分( SaleRecord 內的 week 和 remainingStock ),每週的數值,其他就是一些常見圖表參數。未來在詳細說明。
  • 最後就是當資料有變化會更動,並且呈現折現圖表的部份 <Line data={chartData} />;

Step3. 價格控制(PricingControl.tsx)

// components/PricingControl.tsx
import React from 'react';

type Props = {
    onSelect: (discount: number) => void;
};

const PricingControl: React.FC<Props> = ({ onSelect }) => {
    const discounts = [100, 90, 80, 70, 50];

    return (
        <div>
            {discounts.map((discount) => (
                <button key={discount} onClick={() => onSelect(discount)}>
                    {discount}% of the price
                </button>
            ))}
        </div>
    );
};

export default PricingControl;

暫時透過點選的方式來控制每週的商品價值(販售價格,預設從1000元開始折價,畢竟東西應該會越來越便宜XD)。

  • Props :一樣有一個負責傳遞資訊,主要傳遞點選的數字,在進行折扣的處理。
  • const discounts = [100, 90, 80, 70, 50]; :定義常數,當作有100%~50%的這週販售價格。
  • 最後想當然就是回傳 JSX 的按鈕羅~對於 discounts 陣列中的每一個折扣,都創建一個按鈕,當按鈕被點擊時,它會調用 onSelect 函數,並將當前的 discount 值作為參數傳遞。

Step4. 模擬銷售的邏輯(salesLogic.ts)

// logic/salesLogic.ts

export const simulateSales = (stock: number, discount: number): number => {
    let sold = Math.floor(stock * (1 - discount / 100) * (Math.random() * 0.1 + 0.9));
    return stock - sold;
};

主要當作最簡單的銷售邏輯基本上就是普通的亂數隨機。

  • (1 - discount / 100): 計算打折後的價格。
  • Math.random() * 0.1 + 0.9: 這部分假裝模擬了,基於隨機性的銷售變動。它生成一個在0.9到1之間的隨機數字,而實際販售則會稍微變成這會由隨機值之類的處理。
  • 乘上 stock: 基於當前存貨和計算出的售價以及隨機變動,計算預期的售出數量。當然這一塊我還不知道多少就是了。
  • Math.floor(): 使用 Math.floor 確保銷售數量是整數。

Step5. 結合大家

// App.tsx
import React, { useState } from 'react';
import LineChart from './Component/LineChart';
import PricingControl from './Component/PricingControl';
import { SaleRecord } from './Component/types';
import { simulateSales } from './Component/salesLogic';

const INITIAL_STOCK = 1000;

const App: React.FC = () => {
    const [salesData, setSalesData] = useState<SaleRecord[]>([
        { week: 1, remainingStock: INITIAL_STOCK },
    ]);

    const handlePricingSelect = (discount: number) => {
        const currentWeek = salesData.length;
        const previousStock = salesData[currentWeek - 1].remainingStock;
        const newStock = simulateSales(previousStock, discount);
        setSalesData([...salesData, { week: currentWeek + 1, remainingStock: newStock }]);
    };

    return (
        <div className="App">
            <h1>Retail Simulation</h1>
            <PricingControl onSelect={handlePricingSelect} />
            <LineChart data={salesData} />
        </div>
    );
};

export default App;
  • import :想當然先引入各自所需的程式碼,包含自己撰寫的部分。
  • const INITIAL_STOCK = 1000; :先隨便預設基底。
  • useState Hook :透過 hook 來掌控我們目前的銷售數據,也就是之前定義的 SaleRecord
  • const handlePricingSelect :定義用來控制我們點選折扣的時候,來模擬該週的銷售結果跟更新結果。
  • 最後就是回傳 JSX 的部分,先大概隨便寫一個標題、選項、折線圖~

成果大概就如下。
https://ithelp.ithome.com.tw/upload/images/20231008/20163107iBAt2psKZI.png


上一篇
[Day 22] TypeScript tsconfig.json 常見設定
下一篇
[Day 24] TypeScript 零售業者模擬演練 II
系列文
TypeScript 啟動!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言