スナックの予約管理アプリをflutterで作成

---
flutterでアプリ自作
---
# はじめに
職場近くのよく通うスナックは人気なので、満員なことが多い、電話で予約や席状況確認はめんどくさいので、予約アプリで確認できたらと思い作成した。
（お店には事前許可を頂いている）

# 環境
- visual studio code
- xcode
- android studio
- flutter 3.7.8
- dart 2.19.4
- firebase_auth
- firebase_core
- cloud_firestore

# 機能
今回のアプリの機能としてはシンプルで以下である
#### ユーザ側 
- 店の開き具合確認できる
- 予約できる

#### 店側 
- お客様の予約状況を確認できる
- 完了した予約を削除できる
- 状況に合わせてアプリ予約上限変更
- 定休日以外の急な休みを設定できる

### ホーム画面

<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/b283c376-2616-17d2-cefd-9e2f639ed636.png">　<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/f92ca5fa-f535-19e5-2446-e16b7bdb4b98.png">

起動時はお店のロゴが立ち上がり
上へとフェードインしながらホーム画面へと遷移していく

左のドロワーにこれから遷移先のページがある
- 事前にアカウントを作成する必要があり、ログイン済みの場合はそのままホーム画面へ遷移する
- 初めてアプリを起動した場合は、サイン画面から始まるのでそこで新規登録することになる

<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/977aedff-e20a-bdfd-7b72-2bd45d9a2bf5.png">　<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/c03bf0eb-ca37-b6c2-37d4-9de8d16a45ce.png">

### サインイン、サインアップ画面

<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/8f505782-95ac-b8d9-a876-1b71d1181022.png">　<img width="200" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/c2e91fd9-6c6d-17bc-2093-450f818990e1.png">


### 予約画面
予約画面は下のようになっている
ここではユーザーの登録名が表示されるようになっており、以下のことが行われている
- 選択日が定休日かどうか確認
- 予約の時間帯は営業時間内であるか確認
- 選択日の予約人数を下の数字で表し、予約した場合常時更新される



<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/855e2523-6e8e-4164-0612-3aa1990abfea.png">　<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/8f5bfe50-63b8-7081-c194-e255f2f3596f.png">　<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/8b4e278a-7590-f689-31d4-3e7546945650.png">


### アカウント画面
この画面では、ユーザが自分の情報を更新するときに使うことができる

<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/1d36d674-6411-1b23-7d65-da229bba563b.png">　<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/a1ce0b71-b169-7127-cc42-b60de6f56c2d.png">

### 管理者側の画面

管理者側も基本的に画面構成は同じだが、Bookingの画面の代わりにManagementの画面がある

<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/7035b032-2984-c323-efe3-a1506173750b.png">　<img width="300" alt="アイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332071/b9724717-7092-9393-6aa7-d7626c958aaa.png">

管理者側日付でソートしたりして予約状況を確認できる、カードをタップすると裏面に人数と電話番号が記載されている。
また、右上の設定項目から、休みの追加と、予約の上限人数を変更することができる

# GIF画像
実際にそれぞれので操作をGIF画像で確認できるようにする
GitHub　READMEにて掲載
https://github.com/ethanVodka/coa_project


# おわりに
BundleIDが原因でAppleStoreへのリリース手続きでかなり戸惑った(約3日)
また、web版のがリリースにおいてスマートフォンをメインで画面構成を行ったため、PCで開くと巨大に表示されてしまう問題を確認できた、これはResponsivePageを使うことで解決できるようである。
サンプルは下で記載

```dart
import 'package:flutter/material.dart';

void main() => runApp(const LayoutBuilderExampleApp());

class LayoutBuilderExampleApp extends StatelessWidget {
  const LayoutBuilderExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: LayoutBuilderExample(),
    );
  }
}

class LayoutBuilderExample extends StatelessWidget {
  const LayoutBuilderExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('LayoutBuilder Example')),
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          if (constraints.maxWidth > 600) {
            //ワイド画面へ
            return _buildWideContainers();
          } else {
            //ノーマル画面へ
            return _buildNormalContainer();
          }
        },
      ),
    );
  }

  Widget _buildNormalContainer() {
    return Center(
      child: Container(
        height: 100.0,
        width: 100.0,
        color: Colors.red,
      ),
    );
  }

  Widget _buildWideContainers() {
    return Center(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Container(
            height: 100.0,
            width: 100.0,
            color: Colors.red,
          ),
          Container(
            height: 100.0,
            width: 100.0,
            color: Colors.yellow,
          ),
        ],
      ),
    );
  }
}

```
もう一つはriverpodなどのパッケージの存在を知らずにstatfullWidgetだけで制作した。実践的に考えてriverpodやflutter_fooksなどのパッケージは必須である思うので、これらを用いて、このアプリへのフィードバックを活かせて改良していこうと思います。

web版のリンクを記載しますが、なかなか時間取れず未修正なのでご覧になる場合スマホでお願い致します....
https://coa-web-6e861.web.app