---
# System prepended metadata

title: COMEBUY 資料視覺化系統技術文件

---

本文為臺大資管團隊與長沂國際實業股份有限公司（COMEBUY）產學合作專案所開發之系統技術文件，由專案團隊撰寫，可提供公司人員在未來實際使用系統時參考。

本文共分為四節，依序說明系統環境、資料庫 schema、後端及前端撰寫。

---
## 1. 系統環境

### 1.1 系統安裝說明

1. 安裝 Node.js、Yarn、Python、miniconda、Postgresql 等必要軟體。
2. 在 `COMEBUY_SALES\frontend` 底下執行 `yarn` 指令，安裝所需套件。
    
    ```
    // under COMEBUY_SALES\frontend
    yarn
    ```
3. 建置前端 build 檔：在 `COMEBUY_SALES\frontend` 下執行 `yarn build`。
    ```
    // under COMEBUY_SALES\frontend
    yarn build
    ```
4. 建立一個 Postgresql database。
5. 編輯環境變數檔 `.env`，內容參照 `.env.example` 設定資料庫連接資訊以及希望伺服器運行之連接阜（在 `COMEBUY_SALES\frontend`、`COMEBUY_SALES\backend`、`COMEBUY_SALES\database` 下各有一個 `env` 檔，兩者皆需進行設定。）
6. 在 `COMEBUY_SALES\database` 下執行 `createTable.py` 檔建立資料庫的表格。
    ```
    // under COMEBUY_SALES\database
    python createTable.py
    ```
7. 安裝完 miniconda 後，在 window 左下角搜尋欄輸入 anaconda prompt，開啟後輸入 `conda init powershell`，關閉 anaconda prompt。
    ![](https://hackmd.io/_uploads/SJUcA04o2.png =350x350)
8. 接著回到 `COMEBUY_SALES\backend` 下，輸入以下指令。
    ```
    // under COMEBUY_SALES\backend
    conda create --name CB_NTU_2 python=3.9.16
    conda activate CB_NTU_2
    ```
9. 安裝後端所需套件：在 `COMEBUY_SALES\backend` 下，輸入以下指令。
    ```
    // under COMEBUY_SALES\backend
    pip install -r requirements.txt
    ```
10. 啟動：在 `COMEBUY_SALES\backend` 底下執行以下指令，若無錯誤系統即安裝完成開始運行。
    ```
    // under COMEBUY_SALES\backend
    uvicorn main:app --host 0.0.0.0 --port 8000
    ```
## 2. 資料庫
### 2.1 資料庫說明
本專案使用 PostgreSQL。使用前須先安裝相關軟體。
### 2.2 資料表說明
資料表共 21 張，各表說明如下。
    
1. :::spoiler status
    <table border="0" style="text-align:center;">
     <tr>
        <td colspan="6"><b style="font-size:20px">status</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>狀態名稱</td>
        <td>Varchar</td>
        <td>販賣中</td>
      </tr>
    </table>
2. :::spoiler categories
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">categories</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>種類名稱</td>
        <td>Varchar</td>
        <td>原葉鮮萃茶</td>
      </tr>
    </table>
3. :::spoiler drinks
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">drinks</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>飲品名稱</td>
        <td>Varchar</td>
        <td>海神</td>
      </tr>
      <tr>
        <td>category</td>
        <td>F</td>
        <td>Y</td>
        <td>種類</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>status</td>
        <td>F</td>
        <td>Y</td>
        <td>狀態</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>comebuy_id</td>
        <td></td>
        <td>Y</td>
        <td>公司飲品代號</td>
        <td>Varchar</td>
        <td>A020006</td>
      </tr>
    </table>
4. :::spoiler sweets
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">sweets</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>甜度名稱</td>
        <td>Varchar</td>
        <td>無糖</td>
      </tr>
    </table>
5. :::spoiler ices
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">ices</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>冰塊名稱</td>
        <td>Varchar</td>
        <td>去冰</td>
      </tr>
    </table>
6. :::spoiler tastes
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">tastes</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>口味名稱</td>
        <td>Varchar</td>
        <td>去籽</td>
      </tr>
    </table>
7. :::spoiler toppins
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">toppins</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>加料名稱</td>
        <td>Varchar</td>
        <td>布丁</td>
      </tr>
    </table>
8. :::spoiler regions
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">regions</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>區域名稱</td>
        <td>Varchar</td>
        <td>東區</td>
      </tr>
    </table>
9. :::spoiler counties
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">counties</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>縣市名稱</td>
        <td>Varchar</td>
        <td>台北市</td>
      </tr>
    </table>
10. :::spoiler districts
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">districts</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>行政區名稱</td>
        <td>Varchar</td>
        <td>士林區</td>
      </tr>
    </table>
11. :::spoiler stores
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">stores</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>name</td>
        <td></td>
        <td>Y</td>
        <td>門市名稱</td>
        <td>Varchar</td>
        <td>新店光明</td>
      </tr>
      <tr>
        <td>region</td>
        <td>F</td>
        <td>Y</td>
        <td>區域</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>county</td>
        <td>F</td>
        <td>Y</td>
        <td>縣市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>district</td>
        <td>F</td>
        <td>Y</td>
        <td>行政區</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>comebuy_id</td>
        <td></td>
        <td>Y</td>
        <td>公司儲存的代號</td>
        <td>Varchar</td>
        <td>0045</td>
      </tr>
    </table>
12. :::spoiler tempSales
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">tempSales</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>store</td>
        <td></td>
        <td>Y</td>
        <td>門市代號</td>
        <td>Varchar</td>
        <td>0045</td>
      </tr>
      <tr>
        <td>time</td>
        <td></td>
        <td>Y</td>
        <td>訂單時間</td>
        <td>Timestamp</td>
        <td>2023/07/04 11:25:00</td>
      </tr>
      <tr>
        <td>drink</td>
        <td></td>
        <td>Y</td>
        <td>飲料代號</td>
        <td>Varchar</td>
        <td>A020006</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar</td>
        <td>少奶/少冰/無糖</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar</td>
        <td>布丁/椰果</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
13. :::spoiler sales
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">Sales</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>store</td>
        <td>F</td>
        <td>Y</td>
        <td>門市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>time</td>
        <td></td>
        <td>Y</td>
        <td>訂單時間</td>
        <td>Timestamp</td>
        <td>2023/07/04 11:25:00</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
14. :::spoiler aggregateSalesDay
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesDay</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>store</td>
        <td>F</td>
        <td>Y</td>
        <td>門市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
15. :::spoiler aggregateSalesDayDistrict
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesDayDistrict</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>district</td>
        <td>F</td>
        <td>Y</td>
        <td>行政區</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
16. :::spoiler aggregateSalesDayCounty
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesDayCounty</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>county</td>
        <td>F</td>
        <td>Y</td>
        <td>縣市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
17. :::spoiler aggregateSalesDayRegion
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesDayRegion</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>region</td>
        <td>F</td>
        <td>Y</td>
        <td>區域</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
18. :::spoiler aggregateSalesHour
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesHour</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>store</td>
        <td>F</td>
        <td>Y</td>
        <td>門市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>hour</td>
        <td></td>
        <td>Y</td>
        <td>時間 <div>(12 表示12:00-12:59）</div> </td>
        <td>Integer</td>
        <td>12</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>N</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>Y</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
19. :::spoiler aggregateSalesHourDistrict
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesHourDistrict</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>district</td>
        <td>F</td>
        <td>Y</td>
        <td>行政區</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>hour</td>
        <td></td>
        <td>Y</td>
        <td>時間 <div>(12 表示12:00-12:59）</div> </td>
        <td>Integer</td>
        <td>12</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
20. :::spoiler aggregateSalesHourCounty
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesHourCounty</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>county</td>
        <td>F</td>
        <td>Y</td>
        <td>縣市</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>hour</td>
        <td></td>
        <td>Y</td>
        <td>時間 <div>(12 表示12:00-12:59）</div> </td>
        <td>Integer</td>
        <td>12</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
21. :::spoiler aggregateSalesHourRegion
    <table border="0" style="text-align:center">
     <tr>
        <td colspan="6"><b style="font-size:20px">aggregateSalesHourRegion</b></td>
     </tr>
     <tr>
        <th>Variable</th>
        <th>Primary/Foreign</th>
        <th>Not null</th>
        <th>Description</th>
        <th>Type</th>
        <th>Example</th>
     </tr>
     <tr>
        <td>id</td>
        <td>P</td>
        <td>Y</td>
        <td>Serial number</td>
        <td>Integer</td>
        <td>1</td>
     </tr>
     <tr>
        <td>region</td>
        <td>F</td>
        <td>Y</td>
        <td>區域</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>date</td>
        <td></td>
        <td>Y</td>
        <td>日期</td>
        <td>Date</td>
        <td>2023-04-30</td>
      </tr>
      <tr>
        <td>hour</td>
        <td></td>
        <td>Y</td>
        <td>時間 <div>(12 表示12:00-12:59）</div> </td>
        <td>Integer</td>
        <td>12</td>
      </tr>
      <tr>
        <td>drink</td>
        <td>F</td>
        <td>Y</td>
        <td>飲料</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>ice</td>
        <td>F</td>
        <td>N</td>
        <td>冰塊</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>sweet</td>
        <td>F</td>
        <td>N</td>
        <td>甜度</td>
        <td>Integer</td>
        <td>1</td>
      </tr>
      <tr>
        <td>taste</td>
        <td></td>
        <td>N</td>
        <td>口味</td>
        <td>Varchar[]</td>
        <td>[少奶, 去籽]</td>
      </tr>
      <tr>
        <td>topping</td>
        <td></td>
        <td>N</td>
        <td>加料</td>
        <td>Varchar[]</td>
        <td>[布丁, 椰果]</td>
      </tr>
      <tr>
        <td>price</td>
        <td></td>
        <td>Y</td>
        <td>訂單總價</td>
        <td>Integer</td>
        <td>55</td>
      </tr>
      <tr>
        <td>amount</td>
        <td></td>
        <td>Y</td>
        <td>杯數</td>
        <td>Integer</td>
        <td>2</td>
      </tr>
    </table>
### 2.3 注意事項:
與外接資料有關的資料表只有 tempSales，只要注意匯入的資料符合該表欄位即可，資料中需注意門市代號、飲品代號、冰塊、甜度需事先儲存在 stores、 drinks、 sweets、ices 表中，若不存在該筆交易會被移除，請確保需要的資料都有事先透過 sql 加入或是從網站頁面操作加入。詳細的匯入流程請參閱另一份[文件資料庫建立及匯入詳細說明](https://drive.google.com/file/d/1RbFoQBiQmXDRMl0d0i9iccFx1aN1a3G_/view?usp=drive_link)。</div>

## 3. 後端
本專案後端由以 python 建立的 fastapi 框架所撰寫，故下列說明皆為 python 語法及用語。後端共提供 6 支 API，以下分別敘述每一支的功能。
1. /data
    - 請求方式：`get`
    - 輸入說明：`None`
    - 輸出說明：`dictionary`，按照各維度建立出的 `dictionary`, 詳見 [Schema](#Schema1)
    - 功能說明：用於獲取各維度的數據。包含地區、飲品、甜度、冰塊、口味及加料。而地區與飲品會依照層級回傳以便前端呈現，如新店光明店會下屬於北區、新北市、新店區，而海神會下屬於原葉鮮萃茶類。
2. /search_item
    - 請求方式：`post`
    - 輸入說明：
        ```python
        class SearchInput(BaseModel):
            start_date: date=None # 搜尋日期的開始時間（e.g. 2023-01-23）
            end_date: date=None # 搜尋日期的結束時間（e.g. 2023-01-26）
            start_hour: int=None # 搜尋的開始小時（e.g. 10，自 10:00 開始的銷售數據）
            end_hour: int=None # 搜尋的結束小時（e.g. 14，至 13:59 的銷售數據）
            counties: List[str]=None # 欲比較之縣市層級（e.g. [新北市]）則輸入，無需則不用
            districts: List[str]=None # 欲比較之地方行政區層級（e.g. [新店區]）則輸入，無需則不用
            regions: List[str]=None # 欲比較之區域層級（e.g. [北區]）則輸入，無需則不用
            stores: List[str]=None # 欲比較之門市層級（e.g. [新店光明店]）則輸入，無需則不用
            drink: List[str]=None # 欲查詢之飲品名稱（e.g. [海神, 鮮萃大麥紅茶]）
            toppings: List[str]=None # 配料（e.g. [布丁, 椰果]）
            tastes: List[str]=None # 口味（e.g. [少奶, 去籽]）
            sweets: List[str]=None # 甜度（e.g. [正常糖, 少糖]）
            ices: List[str]=None #冰塊（e.g. [少冰, 去冰]）   
            part: bool=None #是否需計算部分佔比
        ```
    - 輸出說明：`Array[dictionary]`，`dictionary`為
        ```json
        {
            date：交易日期,
            location：地區名稱,
            drink：飲品名稱,
            constraints：欲查詢之額外條件,
            all：所有條件,
            price：飲品總金額,
            amount：飲品總數量,
            total_price：地區總金額,
            total_amount：地區總數量,
            price_proportion：飲品金額佔比,
            amount_proportion：飲品數量佔比,
        }
        ```
    - 功能說明：根據使用者所選擇的維度篩選對應的總表資料。將彙整後擁有不同額外條件的飲品數據除以全品項數據會得到佔比，用於得知每日特定條件飲品的銷售狀況。
3. /bar_item
    - 請求方式：`post`
    - 輸入說明：`int period`，欲查詢之期數
    - 輸出說明：`Array[dictionary]`，`dictionary` 為
        ```json
        {
            location：地區名稱,
            start_date：開始日期,
            end_date：結束日期,
            drink：飲品名稱,
            constraint：額外條件,
            price：飲品總金額,
            amount：飲品總數量,
            total_price：地區總金額,
            total_amount：地區總數量,
            price_proportion：飲品金額佔比,
            amount_proportion：飲品數量佔比,
        }
        ```
    - 功能說明：根據輸入的期數以呈現若干時段的銷售趨勢。期數所劃分出的時間區段意義如下。假設查詢區段為 2023/01/01 至 2023/01/05 共 5 天，並選擇 3 期。上一期的時間區間則為 2022/12/27 至 2022/12/31，更上一期則為 2022/12/22 至 2022/ 12/26。 在不勾選分別飲品統整的條件下，數據計算方式為「特定條件的飲品數據 / 全品項數據」;而在勾選的狀況下，分母會變成「特定飲品數據」。舉例來說，假設春假期間海神在新店光明店共賣出 560 杯，其中去冰有 80 杯。而新店光明店在春假期間的總銷售杯數為 56000 杯。那麼前者則在計算「春假期間去冰海神在新店光明店的杯數占比」，即 $\dfrac{80}{56000}$；而後者代表「去冰海神在海神銷售中的杯數占比」，即 $\dfrac{80}{560}$。若並無查詢特定條件，那麼計算方式則為「特定飲品數據 / 全品項數據」，即「海神在所有銷售杯數中的佔比」，算式為 $\dfrac{560}{56000}$。
4. /line_item
    - 請求方式：`post`
    - 輸入說明：`int year`，欲查詢之年份總數
    - 輸出說明：`Array[dictionary]`，`dictionary` 為
        ```json
        {
            location：地區名稱,
            year：年份,
            drink：飲品名稱,
            constraint：額外條件,
            price：飲品總金額,
            amount：飲品總數量,
            total_price：地區總金額,
            total_amount：地區總數量,
            price_proportion：飲品金額佔比,
            amount_proportion：飲品數量佔比,
        }
        ```
    - 功能說明：根據輸入的年分以呈現若干年的銷售趨勢。假設查詢區段為 2023/01/01 至 2023/01/05 ，並選擇 3 年，會呈現 2021 至 2023 年在 01/01 到 01/05 的銷售數據，數據計算方式與期數銷售趨勢的計算方式相同。若期間有跨年資訊，則會將該筆數據歸類在後一年。舉例，2022/12/25 至 2023/01/02 的數據在圖上會被歸類在 2023 年，而 2021/12/25 至 2022/01/02 的數據則會被歸類在 2022 年。
5. /update
    - 請求方式：`post`
    - 輸入說明：
        ```python
        class UpdateInput(BaseModel):
            # 以下 list 若有輸入則須包含兩個元素
            # 第一個是原始數據，第二個是欲更新之名稱，e.g. [北區, 北北區]
            counties: List[str]=None
            districts: List[str]=None
            regions: List[str]=None
            stores: List[str]=None
            drinks: List[str]=None
            categories: List[str]=None
            toppings: List[str]=None
            tastes: List[str]=None
            sweets: List[str]=None
            ices: List[str]=None         
        ```
    - 輸出說明：`{status: "success"}`
    - 功能說明：用於更新資料庫中的各維度品項名稱。有鑑於公司會不定期更改門市或飲品名稱，因此更新的需求隨之誕生，更新方式即透過選擇既有名稱再輸入新名稱即可，唯注意需在匯入修改名稱後的新數據之前便在本系統進行更新，才不會造成往後的數據計算疏漏。
6. /new
    - 請求方式：`post`
    - 輸入說明：
        ```python
        class CreateInput(BaseModel):
            # 每一個 dictionary 會包含兩個 key, 分別是 value, new
            # value 是欲新增的名稱, 是 Array 或單一物件, new 代表是否是新增的名稱, 是 bool
            # e.g. toppings: {value: 新配料, new: true}, stores: {value: [新門市, comebuy_id], new: true}, regions: {value: 北區, new: false}
            counties: dict=None
            districts: dict=None
            regions: dict=None
            stores: dict=None
            categories: dict=None
            drinks: dict=None
            toppings: dict=None
            tastes: dict=None
            sweets: dict=None
            ices: dict=None
        ```
    - 輸出說明：`{status: "success"}`
    - 功能說明：用於新增各維度的品項。在新增門市與飲品前，須按照層級一步步輸入，如「北區、新北市、新店區」最後再輸入門市名稱「新店光光店」，日後才得以比較不同地區層級的銷售數據。而飲品則需要先輸入 飲品類別，如「原葉先萃茶」再輸入「海霸王」。如同更新所言，需在匯入 新資料前便在本平台進行新增，以確保後續數據計算的正確性。 

## 4. 前端
前端由建於 javascript 上的 React 框架撰寫，主要程式碼位於 `frontend/src`  之下，以下將以 `src` 下一層之資料夾逐一說明功能
### 1. `components`：提供在專案內重複使用之 UI layout
#### `Drawer.js`：在視覺化分析頁面之滑抽及選項
:::spoiler **props**
#### <div style="font-weight:700">open</div>
如果為 `true`，顯示元件。
#### Type: `boolean`
---
#### <div style="font-weight:700">setOpen</div>
控制 [`open`](#open) prop 值。
#### Type: `React.Dispatch<React.SetStateAction<boolean>>`
---
#### <div style="font-weight:700">showType</div>
圖上顯示之數值類型。
#### Type: `'杯數' | '杯數佔比' | '金額' | '金額佔比'`
---
#### <div style="font-weight:700">setShowType</div>
控制 [`showType`](#showType) prop 值。
#### Type: `React.Dispatch<React.SetStateAction<string>>`
---
#### <div style="font-weight:700">graphType</div>
圖類。
#### Type: `'長條圖' | '折線圖'`
---
#### <div style="font-weight:700">setGraphType</div>
控制 [`graphType`](#graphType) prop 值。
#### Type: `React.Dispatch<React.SetStateAction<string>>`
---
#### <div style="font-weight:700">calType</div>
圖上顯示的最終結果之數值計算方法。
#### Type: `'分開計算' | '合併計算'`
---
#### <div style="font-weight:700">setCalType</div>
控制 [`calType`](#calType) prop 值。
#### Type: `React.Dispatch<React.SetStateAction<string>>`
---
#### <div style="font-weight:700">constraint</div>
圖上顯示的最終結果之限制的額外條件。
#### Type: `string` (the union of constraints in database)
---
#### <div style="font-weight:700">setConstraint</div>
控制 [`constraint`](#constraint) prop 值。
#### Type: `React.Dispatch<React.SetStateAction<string>>`
---
#### <div style="font-weight:700">constraints</div>
所有提供的額外條件選項。
#### Type: `Array[string (the union of constraints in database)]`
:::

---
#### `Graph.js`：視覺化分析之圖形，包含長條圖及折線圖
:::spoiler **props**
#### [graphType](#graphType)
---
#### <div style="font-weight:700">THEME</div>
圖上每個元素的代表顏色。
#### Type: `Array[string (hex color)]`
---
#### <div style="font-weight:700">handleLegendClick</div>
當各圖例被點擊時觸發的 Callback。
#### Type: `func`
---
#### <div style="font-weight:700">graphKey</div>
The render key. 改變時會觸發圖的動畫顯示。
#### Type: `number`
---

:::success 
:art: **Graph Props**
#### 見更多 [recharts.js guideline](https://recharts.org/en-US/api).
* cartesianGridProps
* xAxisProps
* yAxisProps
* tooltipProps
* legendProps
:::

---
#### `GridToolBar.js`：表格上方之客製化工具列
:::spoiler **props**
#### <div style="font-weight:700">fileName</div>
匯出 excel 之檔案名稱。
#### Type: `string`
:::

---
### 2. `hooks`：提供 customed React hooks
#### `useCondition.js`：useContext 全局提供傳送到後端的資料群
:::spoiler **returns**
#### <div style="font-weight:700">condition</div>
傳送到後端的全局資料，包含時間、地點、飲品等等。
#### Schema:
```json
{
  time: {
    time: {
      start: dayjs(dayjs().format().slice(0, 11) + "T00:00"),
      end: dayjs(dayjs().format().slice(0, 11) + "T23:59"),
    },
    date: {
      start: dayjs("2023-01-07"),
      end: dayjs("2023-01-07"),
    },
  },
  location: [
    {
      name: "新店光明店",
      level: "store",
      route: ["北區", "新北市", "新店區"],
    },
    {
      name: "花蓮中山店",
      level: "store",
      route: ["東區", "花蓮縣", "花蓮市"],
    },
  ],
  beverage: [
    { name: "海神", category: "原葉鮮萃茶" },
    { name: "鮮萃大麥紅茶", category: "原葉鮮萃茶" },
  ],
  ice: [],
  sweet: [],
  flavor: [],
  topping: [],
  part: false,
}
```
---
#### <div style="font-weight:700">DATA</div>
全局資料，用於顯示主頁的篩選選項。
#### Schema:
```json
{
  "全台": {
    "北區": {
      "新北市": {
        "新店區": [
          "新店光明店"
        ]
      }
    },
    "東區": {
      "花蓮縣": {
        "花蓮市": [
          "花蓮中山店"
        ]
      }
    }
  },
  "飲品": {
    "原葉鮮萃茶": [
      "海神",
      "鮮萃大麥紅茶"
    ]
  },
  "甜度": ["半蜜", "多糖", "微糖", "少糖", "正常糖", "標準糖", "微蜜", "多蜜", "半糖"...],
  "冰塊": ["熱品", "正常冰", "微冰", "少冰", "溫飲", "去冰", "標準冰", "熱飲", "溫品"...],
  "加料": ["紫米", "蘆薈", "搖果樂", "愛玉", "小紫蘇", "荔枝凍", "新雙Q", "雙Q條"...],
  "口味": ["少奶", "去籽", "多籽", "紅茶", "換奶綠", "多奶", "改小珍", "改鬥陣", "芋"...]
}
```
---
#### <div style="font-weight:700">systemState</div>
目前系統狀況， 包含「地區級別」和「是否為個別佔比計算」。每一次送出 request 都會更新。
#### Schema:
```json
{
  "locationLevel": "region",
  "part": false
}
```
---
#### <div style="font-weight:700">setSystemState</div>
控制 `systemState` 值。
#### Type: `React.Dispatch<React.SetStateAction<{}>>`
---
#### <div style="font-weight:700">setCondition</div>
控制 `condition` 值。
#### Type: `React.Dispatch<React.SetStateAction<{}>>`
---
#### <div style="font-weight:700">setDATA</div>
控制 `DATA` 值。
#### Type: `React.Dispatch<React.SetStateAction<{}>>`
---
#### <div style="font-weight:700">loading</div>
如果為 `true`，會顯示加載元件。在送出 request 至接收 response 以前為 `true`
#### Type: `boolean`
---
#### <div style="font-weight:700">setLoading</div>
控制 `loading` 值。
#### Type: `React.Dispatch<React.SetStateAction<boolean>>`
---
#### <div style="font-weight:700">addLocationCondtion</div>
當未被選取之地區被選取時觸發的 Callback。
#### Type: `func`
---
#### <div style="font-weight:700">deleteLocationCondition</div>
當被選取之地區被選取時觸發的 Callback。
#### Type: `func`
---
#### <div style="font-weight:700">addBeverageCondition</div>
當未被選取之飲品被選取時觸發的 Callback。
#### Type: `func`
---
#### <div style="font-weight:700">deleteBeverageCondition</div>
當被選取之飲品被選取時觸發的 Callback。
:::

---
#### `useGraph.js`：提供視覺化所需 states 及 effects
:::spoiler **returns**
#### <div style="font-weight:700">period</div>
圖上顯示的時間區間數。
#### Type: `number`
---
#### [showType](#showType)
---
#### [setShowType](#setShowType)
---
#### [graphType](#graphType)
---
#### [setGraphType](#setGraphType)
---
#### [calType](#calType)
---
#### [setCalType](#setCalType)
---
#### [constraint](#constraint)
---
#### [setConstraint](#setConstraint)
---
#### <div style="font-weight:700">points</div>
圖的資料點元素。
#### Schema:
```json
{
  data: [
    {
      year: "2023-01-05 2023-01-05",
      "新店光明 海神": 48.04,
      "新店光明 鮮萃大麥紅茶": 51.96,
      "花蓮中山 海神": 51.85,
      "花蓮中山 鮮萃大麥紅茶": 48.15
    },
    {
      year: "2023-01-06 2023-01-06",
      "新店光明 海神": 54.2,
      "新店光明 鮮萃大麥紅茶": 45.8,
      "花蓮中山 海神": 51.49,
      "花蓮中山 鮮萃大麥紅茶": 48.51
    },
    {
      year: "2023-01-07 2023-01-07",
      "新店光明 海神": 50,
      "新店光明 鮮萃大麥紅茶": 50,
      "花蓮中山 海神": 50.44,
      "花蓮中山 鮮萃大麥紅茶": 49.56
    }
  ],
  point: [
    { name: "新店光明 海神", hide: false },
    { name: "新店光明 鮮萃大麥紅茶", hide: false},
    { name: "花蓮中山 海神", hide: false },
    { name: "花蓮中山 鮮萃大麥紅茶", hide: false }
  ]
}
```
---
#### [key](#graphKey)
---
#### <div style="font-weight:700">handlePeriodChange</div>
當 [period](#period) 改變時觸發的 Callback
#### Type: `func`
---
#### [handleLegendClick](#handleLegendClick)
---
:::success
:star: **Effects**
#### 1. 當任何圖類相關變數改變時重建構 [`points`](#points) 值。
```javascript=111
useEffect(() => {
  setPoints(dataFormatProcessing(rawData, period, showType, constraint));
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, [rawData, showType, constraint, dataFormatProcessing]);
```
#### 2. 當任何圖類相關變數改變時改變 [`key`](#graphKey) 值<text style="color:#c62828">以觸發內建動畫</text>。
```javascript=140
useEffect(() => {
  setKey((prev) => (prev % 10) + 1);
}, [showType, constraint, rawData, graphType, calType]);
```
:::

---


### 3. `Manipulate`：`/manipluate` 頁面
#### `Add.js`：服務「新增」頁面
#### `constant.js`：各式 mapping object
#### `index.js`：`/manipluate` 彙整頁面，包含 Tab Pages
#### `Rename.js`：服務「修改」頁面

### 4. `middleware`：提供 Data Fetching function
#### `axios.js`：
* create general instance for single endpoint base.
* provide interceptor during data fetching.
#### `const.js`：provide function to fetch `GET /data`.
#### `index.js`：provide collection of all data-fetching function. 
#### `simplePost.js`：provide functions to fetch `post`-related endpoints.
* `POST /search_item`
* `POST /line_item`
* `POST /bar_item`
* `POST /new`
* `POST /update`

### 5. `Options`：提供主頁（搜尋頁）的各式選項
#### `assets`：Every images and GIFs used in Options.
#### `Beverage`：飲品選項
#### `Ice`：冰塊選項
#### `Location`：地區選項
* **`Modal.js`：地區的彈出視窗**
* **`Recursive_Component.js`：遞迴的 components shown in Modal.js**
#### `Sweet`：甜度選項
#### `Time`：時間選項
#### `Flavor.js`：口味選項
#### `SieveType`：彙整所有選項
#### `Topping`：加料選項
### 6. `utils`：專案內使用的工具
#### `day.js`：提供全局 dayjs 的額外配置（e.g. 設置 sameElse，不使用 dayjs 內建顯示時間）
### 7. `Visualization`：視覺化分析
#### `Aggregate.js`：提供「數據統計」表
:::spoiler **props**
#### <div style="font-weight:700">data</div>
表格的資料。
#### Schema:
```json
[
  {
    location: "新店光明",
    start_date: "2023-01-07",
    end_date: "2023-01-07",
    drink: "海神",
    price: 3275,
    amount: 57,
    total_price: 6465,
    total_amount: 114,
    price_proportion: 50.66,
    amount_proportion: 50
  }...
]
```
:::

---
#### `index.js`：彙整所有視覺化之圖表
#### `PeriodAnalysis.js`：提供「過去若干時段趨勢」分析圖
:::spoiler **props**
#### <div style="font-weight:700">data</div>
圖上元素依賴的資料。
#### [Schema](#Schema4)
---
#### [THEME](#THEME)
---
#### <div style="font-weight:700">setTheme</div>
控制 `THEME` prop 值。
#### Type: `React.Dispatch<React.SetStateAction<[]>>`
:::

---
#### `StoreBeverage.js`：提供「總表」，是後臺資料庫的原始數據
:::spoiler **props**
#### <div style="font-weight:700">data</div>
表格的資料。
#### Schema:
```json
[
  {
    date: "2023-01-07",
    location: "新店光明",
    drink: "海神",
    price: 435,
    amount: 9,
    total_price: 6465,
    total_amount: 114,
    price_proportion: 0.0673,
    amount_proportion: 0.0789,
    constraints: [],
    all: ["正常冰", "半糖", "椰果"]
  }...
]
```
:::

---
#### `YearAnalysis.js`：提供「過去若干年趨勢」分析圖
:::spoiler **props**
#### <div style="font-weight:700">data</div>
圖上元素依賴的資料。
#### Schema:
```json
[
  {
    location: "新店光明",
    drink: "海神",
    year: 2021,
    price: 3535,
    amount: 62,
    total_price: 6655,
    total_amount: 117,
    price_proportion: 53.12,
    amount_proportion: 52.99
  }...  
]
```
---
#### [THEME](#THEME)
---
#### [setTheme](#setTheme)
:::
