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

【権限説明】roleDescriptionで各権限の意味を画面に表示する

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

このページでやること

このページでは、権限を選ぶときに「その権限で何ができるのか」を画面に表示します。

前のページでは、ChoiceChip で権限を選べるようにしました。

今回は、選んだ権限に合わせて説明文を出します。

管理者を選択
↓
タスク削除・メンバー管理ができます

メンバーを選択
↓
タスク作成・編集ができます

閲覧者を選択
↓
見るだけです

今日のゴール

メンバー追加ボトムシートで、権限チップの下に説明文を表示します。

権限

[ 管理者 ] [ メンバー ] [ 閲覧者 ]

タスク作成・編集・削除、メンバー管理ができます。

説明文を出すことで、初心者でも権限の違いが分かりやすくなります。


npmや環境変数は必要?

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

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

FlutterのDartコードだけで進めます。

main.dartを開く
↓
roleDescription() を作る
↓
ボトムシートに説明文を表示する
↓
保存して確認する

Step 1:main.dartを開く

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

lib/main.dart

ターミナルから開く場合はこちらです。

code lib/main.dart

Step 2:selectedMemberRoleを確認する

_MemberListPageState の中に、次があるか確認します。

String selectedMemberRole = 'member';

これは、現在選ばれている権限を保存する変数です。

admin
member
viewer

のどれかが入ります。


Step 3:roleDescriptionを作る

_MemberListPageState の中に、次の関数を追加します。

String roleDescription(String role) {
  switch (role) {
    case 'admin':
      return 'タスク作成・編集・削除、メンバー管理ができます。';
    case 'viewer':
      return 'タスクやメンバーを確認できます。作成・編集・削除はできません。';
    case 'member':
    default:
      return 'タスクの作成・編集ができます。削除やメンバー管理はできません。';
  }
}

これで、選んだ権限に合わせて説明文を出せます。


Step 4:roleDescriptionの意味

この部分を見ます。

case 'admin':
  return 'タスク作成・編集・削除、メンバー管理ができます。';

selectedMemberRoleadmin のとき、管理者向けの説明を返します。

admin
↓
タスク削除やメンバー管理ができる

次は viewer です。

case 'viewer':
  return 'タスクやメンバーを確認できます。作成・編集・削除はできません。';

viewer は見るだけです。

最後は member です。

case 'member':
default:
  return 'タスクの作成・編集ができます。削除やメンバー管理はできません。';

member はタスク作業用の通常メンバーです。


Step 5:権限チップの下に説明文を追加する

showAddMemberSheet() の中で、ChoiceChipWrap を探します。

Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    ChoiceChip(...),
    ChoiceChip(...),
    ChoiceChip(...),
  ],
),

この Wrap の下に、次を追加します。

const SizedBox(height: 10),
Container(
  decoration: BoxDecoration(
    color: AppColors.bg,
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: AppColors.border),
  ),
  padding: const EdgeInsets.all(12),
  child: Text(
    roleDescription(selectedMemberRole),
    style: const TextStyle(
      color: AppColors.subText,
      height: 1.5,
      fontWeight: FontWeight.w700,
    ),
  ),
),

これで、選んだ権限の説明が表示されます。


Step 6:説明文が変わる理由

チップを押すと、ここが動きます。

setSheetState(() {
  selectedMemberRole = 'admin';
});

selectedMemberRole が変わると、次の表示も変わります。

roleDescription(selectedMemberRole)

流れはこうです。

チップを押す
↓
selectedMemberRoleが変わる
↓
roleDescriptionの結果が変わる
↓
説明文が変わる

Step 7:showAddMemberSheetの完成イメージ

権限部分だけ見ると、次の形になります。

const SizedBox(height: 16),
const Text(
  '権限',
  style: TextStyle(
    color: AppColors.text,
    fontWeight: FontWeight.w900,
  ),
),
const SizedBox(height: 8),
Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    ChoiceChip(
      label: const Text('管理者'),
      selected: selectedMemberRole == 'admin',
      onSelected: (_) {
        setSheetState(() {
          selectedMemberRole = 'admin';
        });
      },
    ),
    ChoiceChip(
      label: const Text('メンバー'),
      selected: selectedMemberRole == 'member',
      onSelected: (_) {
        setSheetState(() {
          selectedMemberRole = 'member';
        });
      },
    ),
    ChoiceChip(
      label: const Text('閲覧者'),
      selected: selectedMemberRole == 'viewer',
      onSelected: (_) {
        setSheetState(() {
          selectedMemberRole = 'viewer';
        });
      },
    ),
  ],
),
const SizedBox(height: 10),
Container(
  decoration: BoxDecoration(
    color: AppColors.bg,
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: AppColors.border),
  ),
  padding: const EdgeInsets.all(12),
  child: Text(
    roleDescription(selectedMemberRole),
    style: const TextStyle(
      color: AppColors.subText,
      height: 1.5,
      fontWeight: FontWeight.w700,
    ),
  ),
),

この部分を、メールアドレス入力欄の下に入れます。


Step 8:説明文を短くしたい場合

文字を読むのが苦手な人向けには、もっと短くしてもOKです。

String roleDescription(String role) {
  switch (role) {
    case 'admin':
      return '管理できます。タスク削除もできます。';
    case 'viewer':
      return '見るだけです。編集はできません。';
    case 'member':
    default:
      return 'タスク作成・編集ができます。';
  }
}

最初は、この短い版でも大丈夫です。


Step 9:保存するroleは今まで通り

説明文を追加しても、Firestoreに保存する値は変わりません。

保存部分は、前のページと同じです。

await memberRef.set({
  'uid': uid,
  'email': userEmail,
  'displayName': displayName,
  'role': selectedMemberRole,
  'joinedAt': FieldValue.serverTimestamp(),
});

画面では日本語説明を出します。

Firestoreには英語で保存します。

管理者を選択
↓
role: admin

メンバーを選択
↓
role: member

閲覧者を選択
↓
role: viewer

Step 10:保存する

main.dart を保存します。

Macの場合:

command + S

Windowsの場合:

Ctrl + S

Step 11:実行する

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

flutter run

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

r

うまく反映されない場合は、R を押します。

R

Step 12:画面を確認する

アプリを開きます。

ログイン
↓
トーク一覧
↓
チームをタップ
↓
右上のメンバーアイコン
↓
右下の+

メンバー追加ボトムシートを開きます。

権限チップの下に説明文が出ていれば成功です。

メンバー
↓
タスクの作成・編集ができます。削除やメンバー管理はできません。

Step 13:チップを押して確認する

それぞれのチップを押します。

管理者

管理者
↓
タスク作成・編集・削除、メンバー管理ができます。

メンバー

メンバー
↓
タスクの作成・編集ができます。削除やメンバー管理はできません。

閲覧者

閲覧者
↓
タスクやメンバーを確認できます。作成・編集・削除はできません。

押すたびに説明文が変わればOKです。


よくあるエラーと直し方

エラー原因直し方
roleDescription isn't defined関数がないroleDescription() を追加
説明文が変わらないsetSheetState を使っていないチップの中で setSheetState を使う
ずっとメンバー説明になるselectedMemberRole が変わっていないselectedMemberRole = 'admin' などを確認
画面が変わらない保存していないcommand + S
レイアウトが詰まる余白が足りないSizedBox(height: 10) を入れる
roleが保存されない保存処理が固定値のまま'role': selectedMemberRole にする

ownerの説明は必要?

この追加画面では、owner は選ばせません。

そのため、基本的には owner の説明は不要です。

ただし、メンバー一覧や権限変更画面で使い回したい場合は、次のように入れてもOKです。

String roleDescription(String role) {
  switch (role) {
    case 'owner':
      return 'チームの最上位権限です。チーム削除や権限管理ができます。';
    case 'admin':
      return 'タスク作成・編集・削除、メンバー管理ができます。';
    case 'viewer':
      return 'タスクやメンバーを確認できます。作成・編集・削除はできません。';
    case 'member':
    default:
      return 'タスクの作成・編集ができます。削除やメンバー管理はできません。';
  }
}

後で使い回すなら、この4種類版がおすすめです。


最短作業まとめ

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

1. roleDescriptionを作る

String roleDescription(String role) {
  switch (role) {
    case 'admin':
      return 'タスク作成・編集・削除、メンバー管理ができます。';
    case 'viewer':
      return 'タスクやメンバーを確認できます。作成・編集・削除はできません。';
    case 'member':
    default:
      return 'タスクの作成・編集ができます。削除やメンバー管理はできません。';
  }
}

2. ChoiceChipの下に説明を表示

Container(
  decoration: BoxDecoration(
    color: AppColors.bg,
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: AppColors.border),
  ),
  padding: const EdgeInsets.all(12),
  child: Text(
    roleDescription(selectedMemberRole),
    style: const TextStyle(
      color: AppColors.subText,
      height: 1.5,
      fontWeight: FontWeight.w700,
    ),
  ),
),

3. チップはsetSheetStateで更新

setSheetState(() {
  selectedMemberRole = 'admin';
});

チェックリスト

□ main.dartを開いた
□ MemberListPageを探した
□ selectedMemberRoleを確認した
□ roleDescription()を作った
□ adminの説明を書いた
□ memberの説明を書いた
□ viewerの説明を書いた
□ ChoiceChipの下に説明文を表示した
□ setSheetStateで説明文が変わるようにした
□ 保存した
□ flutter runで確認した
□ 管理者チップで説明が変わった
□ メンバーチップで説明が変わった
□ 閲覧者チップで説明が変わった

ミニ確認問題

Q1. roleDescriptionは何をする関数ですか?

回答

選択中の権限に合わせて、説明文を返す関数です。


Q2. admin の説明には何を書きますか?

回答

タスク作成・編集・削除、メンバー管理ができることを書きます。


Q3. viewer は何ができますか?

回答

確認だけできます。

作成・編集・削除はできません。


Q4. 説明文を変えるために、チップの中では何を使いますか?

回答

setSheetState() を使います。


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

回答

必要ありません。

Dartの関数とFlutterの表示を追加するだけです。


このページのまとめ

  • roleDescription() で権限の説明文を返す。
  • admin は管理者。
  • member は通常メンバー。
  • viewer は見るだけ。
  • ChoiceChip の下に説明文を表示する。
  • チップを押すと selectedMemberRole が変わる。
  • selectedMemberRole が変わると、説明文も変わる。
  • Firestoreへの保存値は今まで通り selectedMemberRole を使う。
  • このページではnpmや環境変数は不要。

次のページでやること

次のページでは、既存メンバーの権限を変更できるようにします。

メンバー一覧からユーザーをタップして、adminmemberviewer に変更する画面を作ります。

教材トップへ戻る