Flutterアプリケーション開発概論

【ステータス分類】todo・doing・doneで未対応・進行中・完了に分ける

28LINE風チームタスク管理アプリを作りながら、ログイン・データベース・権限管理を学ぶ
FlutteriOSAndroidMacOSWindows基礎から学ぶ開発アプリ開発

このページでやること

このページでは、タスクの状態を3つに分けます。

タスクの状態とは、「今そのタスクがどこまで進んでいるか」です。

今回使う値は、この3つです。

保存する値画面表示意味
todo未対応まだ作業していない
doing進行中今作業している
done完了作業が終わった

Firestoreには英語の短い値で保存します。

画面には日本語で表示します。


今日のゴール

Firestoreの status を見て、画面に分かりやすい日本語ラベルを表示します。

status: todo
↓
未対応

status: doing
↓
進行中

status: done
↓
完了

このページでは、まだステータス変更ボタンは作りません。

まずは、表示を分けるところまで進めます。


このページで出てくる単語

単語一言説明
statusタスクの進行状況
todo未対応
doing進行中
done完了
switch値によって処理を分ける書き方
label画面に表示する短い文字
defaultどれにも当てはまらない場合の処理

npmや環境変数はこのページで必要?

このページでは、npmは使いません。

環境変数も設定しません。

やることは、TaskCard の中で status を日本語表示に変えるだけです。

main.dartを開く
↓
TaskCardを探す
↓
statusLabel()を確認する
↓
画面表示を確認する

Step 1:main.dartを開く

次のファイルを開きます。

lib/main.dart

ターミナルから開く場合は、次を実行します。

code lib/main.dart

code が使えない場合は、VS Codeの左側から lib/main.dart を開いてください。


Step 2:TaskCardを探す

main.dart の中で、次を検索します。

class TaskCard

VS Codeなら、次で検索できます。

command + F

TaskCard は、タスク1件分を表示する部品です。


Step 3:statusを受け取る部分を確認する

TaskCard の最初が、次のようになっているか確認します。

class TaskCard extends StatelessWidget {
  const TaskCard({
    super.key,
    required this.title,
    required this.description,
    required this.status,
    required this.priority,
    required this.assigneeEmail,
  });

  final String title;
  final String description;
  final String status;
  final String priority;
  final String assigneeEmail;

この中の、次が大事です。

final String status;

これは、Firestoreから取得したタスクの状態を受け取るための変数です。


Step 4:Firestoreからstatusを取り出す部分を確認する

TaskListPage の中で、タスクデータを取り出している部分を確認します。

final title = (data['title'] ?? '無題のタスク').toString();
final description = (data['description'] ?? '').toString();
final status = (data['status'] ?? 'todo').toString();
final priority = (data['priority'] ?? 'normal').toString();
final assigneeEmail = (data['assigneeEmail'] ?? '').toString();

この行が、Firestoreの status を取り出しています。

final status = (data['status'] ?? 'todo').toString();

?? 'todo' は、status がなかった場合は todo として扱うという意味です。


Step 5:TaskCardへstatusを渡す

TaskCard を呼び出す部分が、次のようになっているか確認します。

return TaskCard(
  title: title,
  description: description,
  status: status,
  priority: priority,
  assigneeEmail: assigneeEmail,
);

ここで、Firestoreから取得した statusTaskCard に渡しています。

Firestoreのstatus
↓
TaskListPageで取り出す
↓
TaskCardに渡す
↓
画面に表示する

Step 6:statusLabel()を作る

TaskCard の中に、次の関数を入れます。

String statusLabel(String value) {
  switch (value) {
    case 'doing':
      return '進行中';
    case 'done':
      return '完了';
    case 'todo':
    default:
      return '未対応';
  }
}

switch は、値によって返す文字を変える書き方です。

ここでは、status の値を日本語に変えています。

todo → 未対応
doing → 進行中
done → 完了

Step 7:statusLabel()の意味

この部分を見ます。

case 'doing':
  return '進行中';

これは、valuedoing のとき、画面には 進行中 と表示するという意味です。

次の部分も同じです。

case 'done':
  return '完了';

valuedone なら、画面には 完了 と表示します。

最後はこれです。

case 'todo':
default:
  return '未対応';

todo の場合、または知らない値が入っていた場合は、未対応 と表示します。


Step 8:TaskCardの中で表示する

TaskCard の中で、次のように使います。

_Label(text: statusLabel(status)),

つまり、Firestoreの保存値をそのまま見せるのではなく、日本語に変えて表示しています。

status
↓
statusLabel(status)
↓
未対応・進行中・完了

Step 9:TaskCardの完成形を確認する

TaskCard は、次のようになっていればOKです。

class TaskCard extends StatelessWidget {
  const TaskCard({
    super.key,
    required this.title,
    required this.description,
    required this.status,
    required this.priority,
    required this.assigneeEmail,
  });

  final String title;
  final String description;
  final String status;
  final String priority;
  final String assigneeEmail;

  @override
  Widget build(BuildContext context) {
    return AppCard(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              _Label(text: statusLabel(status)),
              const SizedBox(width: 8),
              _Label(text: priorityLabel(priority)),
            ],
          ),
          const SizedBox(height: 10),
          Text(
            title,
            style: const TextStyle(
              color: AppColors.text,
              fontSize: 16,
              fontWeight: FontWeight.w900,
            ),
          ),
          if (description.isNotEmpty) ...[
            const SizedBox(height: 6),
            Text(
              description,
              style: const TextStyle(
                color: AppColors.subText,
                fontWeight: FontWeight.w600,
              ),
            ),
          ],
          if (assigneeEmail.isNotEmpty) ...[
            const SizedBox(height: 10),
            Text(
              '担当:$assigneeEmail',
              style: const TextStyle(
                color: AppColors.subText,
                fontSize: 12,
                fontWeight: FontWeight.w700,
              ),
            ),
          ],
        ],
      ),
    );
  }

  String statusLabel(String value) {
    switch (value) {
      case 'doing':
        return '進行中';
      case 'done':
        return '完了';
      case 'todo':
      default:
        return '未対応';
    }
  }

  String priorityLabel(String value) {
    switch (value) {
      case 'high':
        return '優先度:高';
      case 'low':
        return '優先度:低';
      case 'normal':
      default:
        return '優先度:中';
    }
  }
}

このページで特に大事なのは、次の部分です。

String statusLabel(String value) {
  switch (value) {
    case 'doing':
      return '進行中';
    case 'done':
      return '完了';
    case 'todo':
    default:
      return '未対応';
  }
}

Step 10:保存する

main.dart を保存します。

Macの場合:

command + S

Windowsの場合:

Ctrl + S

Step 11:実行する

ターミナルで実行します。

flutter run

すでに起動している場合は、ターミナルで r を押します。

r

うまく反映されない場合は、R でホットリスタートします。

R

Step 12:画面で確認する

チームをタップして、タスク一覧画面を開きます。

タスクがある場合、カードの上に次のようなラベルが表示されます。

未対応

または、

進行中

または、

完了

表示されれば成功です。


Step 13:Firestoreで手動確認する

まだタスク作成機能がない場合は、Firebase Consoleで手動でタスクを作って確認できます。

Firebase Consoleを開きます。

https://console.firebase.google.com/

次の場所を開きます。

Firestore Database
↓
teams
↓
作成したteamId
↓
tasks

テスト用のタスクを作ります。

title: テストタスク
description: ステータス表示確認
status: todo
priority: normal
assigneeEmail: test@example.com

アプリに戻って、未対応 と表示されればOKです。


Step 14:statusを変えて確認する

Firebase Consoleで、status の値を変えてみます。

todo

から

doing

に変更します。

アプリに戻ると、表示が次のように変わります。

進行中

次に、done に変えてみます。

done

画面表示が次のようになればOKです。

完了

snapshots() を使っているので、Firestoreの変更が画面に反映されます。


よくあるエラーと直し方

エラー原因直し方
statusLabel isn't defined関数がないTaskCard の中に追加する
ずっと未対応になるFirestoreのstatusがない、または値が違うtododoingdone にする
TaskCardでstatusが使えないfinal String status; がないTaskCardにstatusを追加
TaskCard呼び出しでエラーstatusを渡していないstatus: status, を追加
表示が変わらない保存していないcommand + S
Firestore変更が反映されないsnapshotsではなくgetを使っているsnapshots() を使う

statusの値が違うとどうなる?

今回の statusLabel() は、知らない値が来た場合、未対応 と表示します。

たとえば、間違えてFirestoreにこう入れた場合です。

status: doing_now

これは、tododoingdone のどれでもありません。

そのため、default に入り、画面では 未対応 と表示されます。

最初は、Firestoreの値をこの3つにそろえてください。

todo
doing
done

最短作業まとめ

読むのが大変な人は、ここだけ見てください。

1. Firestoreからstatusを取る

final status = (data['status'] ?? 'todo').toString();

2. TaskCardに渡す

return TaskCard(
  title: title,
  description: description,
  status: status,
  priority: priority,
  assigneeEmail: assigneeEmail,
);

3. 日本語表示に変える

String statusLabel(String value) {
  switch (value) {
    case 'doing':
      return '進行中';
    case 'done':
      return '完了';
    case 'todo':
    default:
      return '未対応';
  }
}

4. 表示に使う

_Label(text: statusLabel(status)),

5. 保存して実行

flutter run

チェックリスト

□ main.dartを開いた
□ TaskListPageを探した
□ Firestoreからstatusを取り出した
□ TaskCardにstatusを渡した
□ TaskCardにfinal String statusを書いた
□ statusLabel()を作った
□ todoを未対応にした
□ doingを進行中にした
□ doneを完了にした
□ _Labelで表示した
□ 保存した
□ flutter runで確認した

ミニ確認問題

Q1. todo は画面では何と表示しますか?

回答

未対応 と表示します。


Q2. doing は画面では何と表示しますか?

回答

進行中 と表示します。


Q3. done は画面では何と表示しますか?

回答

完了 と表示します。


Q4. なぜFirestoreには日本語ではなく todo などで保存しますか?

回答

コードで扱いやすくするためです。

画面表示だけ日本語に変えると、内部処理が分かりやすくなります。


Q5. このページでnpmや環境変数は必要ですか?

回答

必要ありません。

このページでは、status の表示を分類するだけです。


このページのまとめ

  • タスクの状態は status で管理する。
  • 保存する値は tododoingdone の3つ。
  • 画面表示では 未対応進行中完了 に変える。
  • statusLabel() を作ると、表示変換を1か所にまとめられる。
  • 知らない値が来た場合は、未対応 として扱う。
  • snapshots() を使っていれば、Firestoreで値を変えると画面にも反映される。
  • このページではnpmや環境変数は不要。

次のページでやること

次のページでは、優先度を分類します。

lownormalhigh を使って、低・中・高の優先度ラベルを表示します。

教材トップへ戻る