一週間でモバイルオーダーアプリを作ってみる_その２（設計とプロトタイプ開発）

# はじめに
[一週間でモバイルオーダーアプリを作ってみる_その１](https://qiita.com/HIDE03/items/fab953489f14100acbb3)の続き
業務の確認と要件定義してワークフローも確認したので次はどうやって実装するか設計を考えてプロトタイプの開発までやります。


# 設計と開発
いきなり詳細設計をしないで、まずは技術選定やプラットフォームの選定をします。
技術選定はこの段階では参考程度でも大丈夫ですが、プラットフォームを後から変更するのは大きなコストがかかることが多いです。慎重に選びます。


## 初期設計

### 設計思想
今回意識しているのは以下の通りです
- 何はなくとも低コスト（特に費用面）
- React + TypeScript使いたい
- あとから色々カジュアルに改修して遊べるようにドキュメントDB使いたい
    - ドキュメントDBはできることが限られる代わりに、特定の要件に対してはめちゃくちゃカジュアルに使える印象です
    - 社内業務の改善だと、ゴールの仕様が最初からわかっていて実現できるとは限らなくて、とりあえずやってみて判断するって事が多いので、特に最初の開発フェーズにおいてはかなり強い味方だと考えています
    - 実物を見て運用するとだんだんゴールが見えてくることが多く、そうなってきたら細かい設計や別の種類のDB利用を検討するという柔軟な対応が社内業務改善においては大事なことだと考えています
- 全体的にどんどん機能を追加していく予定なので、構成は臨機応変に色々変える
- 変える前提だけどわかりやすいのと低コストは忘れない

### 技術選定（アーキテクチャ構成）
ChatGPTクンと会話しながら以下のように決定しました。
- フロントエンド
    - React + TypeScriptを使用してユーザーインターフェースを構築する
- バックエンド
    - Firebaseを利用して、ユーザー認証やデータの管理（FireStoreなど）を行う
- デプロイ
    - Firebase Hostingを使用してアプリをデプロイする

### ページ構成
基本的なページは以下の通り
- ログインページ
    - Google認証を利用したログイン機能を提供
- メインメニュー画面
    - ジャンルごとに商品リストを表示、詳細確認、注文ができる
- 管理者ダッシュボード
    - 材料・商品管理、注文履歴確認ができる
- 注文履歴ページ(ユーザ向け)
    - 一般ユーザーが自分の注文を確認できる

### データベースの構成
コレクション（テーブル）>ドキュメント（レコード）のフィールドのつもりで書いてます。

- `owners`：オーナーを管理する
    - ドキュメントID: `email`の値
    - フィールド: 
        - `email` (`string`): メールアドレス
- `users`：ユーザデータを格納する
    - ドキュメントID: 自動生成
    - フィールド: 
        - `displayName` (`string`): 表示名
        - `email` (`string`): メールアドレス
        - `isApproved` (`boolean`):  管理者による承認済みか否か 

- `materials`：商品に使う材料データを格納する
    - ドキュメントID: 自動生成
    - フィールド:
        - `name` (`string`): 材料名
        - `quantity` (`number`): 在庫数量
        - `unit` (`string`): 単位（例：kg、L、個など）

- `products`：商品データを格納する
    - ドキュメントID: 自動生成
    - フィールド:
        - `name` (`string`): 商品名
        - `category` (`string`): カテゴリ
        - `price` (`number`): 価格
        - `stock` (`number`): 在庫数
        - `description` (`string`): 商品の説明
        - `imageUrl` (`string`): 商品画像のURL
        - `materials` (`array`): 必要な材料のIDリスト

- `orders`：注文データを格納する
    - ドキュメントID: 自動生成
    - フィールド:
        - `userId` (`string`): ユーザーID
        - `products` (`array`): 商品のリスト（productId, name, quantity, price を含む）
        - `totalPrice` (`number`): 合計金額
        - `status` (`string`): 注文の状態（例: "未処理", "処理中", "完了"）
        - `createdAt` (`timestamp`): 注文日時
        - `note` (`string`): 備考


## プロトタイプ（or 初期リリース）開発

### 着手前の小話

**【プロトタイプは必要か】**

もちろん作った方が良いのは前提として、社内業務の文脈において実際に作るかどうかは開発の規模や納期によると考えています。
スプシ * GASで作るツールならさっと作って即リリース！となる事も多いですが、今回みたいに明らかにUIUXデザインや機能について改善の余地がある場合は、プロトタイプ作ってアジャイルに完成度上げていくことが重要だと考えています。
当然、開発も改修することを意識して行います。
また、社内向けの開発だとプロトタイプと初期リリースが厳密に分かれていないこともあったりします。
（プロトタイプだと思ってUIUXのデザインを全然考慮してないものだったとしても、機能的に使えるのであれば実戦投入したいです！となることもあります。要はステークホルダー次第ですね）


**【Firebaseの利用について】**

プラットフォームとしては当然知ってましたが、今まで利用する機会が無くて今回初めて触りました。
なので今回の開発に入る前、少しチュートリアルして何となく流れをつかんでから開発に臨んでいます。
2日ぐらい？練習してるかな～機会があればどこかで記事にする予定。

**～閑話休題～**

### プロトタイプにおける実装の流れ
今回は下記の流れで実装します。
1. プロジェクトのセットアップ
1. ユーザー認証機能の実装
1. メインメニュー表示機能の実装
1. 注文機能の実装
1. 支払い管理機能の実装
1. 管理者向け機能の実装

ちなみに、今回のプロトタイプ開発における目的は、
- 実装物の最低限のイメージをつかむため
- ReactやFirebaseに慣れるため

なので、必ずしもこの段階でリリースに必要な機能が完全に実装されていません。

### アウトプット
- 今回開発したものはこちらのブランチの内容です。
- https://github.com/HIDEOMI/bar-app/tree/ver_240917

### 実装ステップ
それぞれ細かく書くと永遠に長くなるので、箇条書き程度にひたすら書いていきます。
- 要点としては、今回基本的にはChatGPTのアドバイス通りに作っていて、要所で変だったり、個人的に違う方法の方がよさそうと思った場合には適宜修正しました
    - 生成AIの使い方や共同作業する際の注意点は言語化した方が良いとは思うものの、話が広がるため、何となく経験でやってるということにしますmm
    - 最近、個人的に仕事ではChatGPT + GithubCopilotでの開発が当たり前になっていたため、今回のプライベート開発ではCopilotが使えなくてとても不便でした
    - 既にAIに依存した働き方になってると思いました（ChatGPTは個人でPLUSの契約しましたw）

というわけでやったことを淡々と書いていきます。
ちなみにプロトタイプ実装自体は1人日かかりました、目安までに、、、

1. **プロジェクトのセットアップ（React + TypeScript + Firebaseの初期設定）**
    - Create React App の作成
        - `npx create-react-app bar-app --template typescript`
        - `cd bar-app`
        - `npm install firebase`
        - `npm install react-router-dom`
        - `npm install @types/react-router-dom`
    - Firebaseプロジェクトを作成
    - Firebase SDK（アプリ）を追加
    - Firebaseプロジェクトの設定ファイル作成
        - ※シークレット情報は`.env`に保存して読み込む。`.env`はignore追加。直接コードに書かない。

1. **ユーザー認証機能の実装**
    - Firebase AuthenticationでGoogleサインインを有効化
    - Firestoreに`users`コレクションを追加
    - `src/services/auth.ts`にGoogleサインイン用のロジックを追加
    - `src/components/AuthProvider.tsx`に認証状態管理用のコンポーネントを追加
    - `src/pages/Login.tsx`にログインページを追加
    - `src/App.tsx`に認証状態によって表示するページを切り替えるための、認証状態を確認するロジックを追加

1. **メインメニュー表示機能の実装**
    - Firestoreに`products`コレクション追加
    - `src/services/products.ts`にFirestoreから商品データを取得するロジックを追加
    - `src/pages/MainMenu.tsx`にカテゴリごとの商品リストを表示する機能を追加
    - `src/types/types.ts`に型定義を追加
    - 動作テスト

1. **注文機能の実装**
    - Firestoreに`orders`コレクション追加
    - `src/services/orders.ts`に注文をFirestoreに保存するロジックを追加
    - `src/pages/MainMenu.tsx`にユーザーが商品を選択し、注文を確定できる機能を追加
    - `src/types/types.ts`に型定義を追加
    - 動作テスト


1. **支払い管理機能の実装**
    - `src/services/orders.ts`に注文履歴を取得するロジックを追加
    - `src/pages/OrderHistory.tsx`に注文履歴を表示するページを作成
    - `src/services/orders.ts`に、未払いの注文を取得するロジックを追加
    - `src/pages/Payment.tsx`に支払いページを追加
    - `src/App.tsx`に`OrderHistory`, `Payment`ページを追加
    - 動作テスト

1. **管理者向け機能の実装**
    - Firestoreの`users`コレクションについて、オーナー属性を追加
    - `src/services/auth.ts`を修正
    - `src/services/users.ts`にユーザー情報を取得する関数を追加
    - `src/components/AuthProvider.tsx`に管理者情報を追加
    - `src/App.tsx`に管理者専用ルートを設定
    - `src/pages/AdminDashboard.tsx`に管理者ダッシュボードを作成
    - Firestoreに`materials`コレクションを作成
    - `src/pages/admin/Materials.tsx`に材料管理ページを作成
    - `src/services/materials.ts`に材料サービスの作成
    - Firestoreに`products`コレクションを
    - `src/pages/admin/Products.tsx`に商品管理ページの作成
    - `src/services/products.ts`に商品サービスの作成
    - `src/pages/MainMenu.tsx`に商品が売り切れの場合、その旨表示するように変更
    - `src/services/orders.ts`に`orders`コレクションから注文データを取得する関数を追加
    - `src/pages/admin/Orders.tsx`に管理者が注文を確認してステータス変更できるページを追加
    - `src/pages/AdminDashboard.tsx`材料管理ページ、商品管理ページ、注文確認ページのルートを追加
    - 動作テスト


（結局長すぎるしわかりづらい？やりたいことの概要を書いてった方が良い気がしてきた）

とりあえずプロトタイプの実装が終わりました。
動作確認してみて、何となく全体的なシステムのイメージができてリリースの解像度が高くなってきたので、次は初期リリースに足りないところをどんどん実装していきます。