0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

大掃除タスク管理webアプリの開発

0
Last updated at Posted at 2026-09-22

家族の大掃除タスクを、Firebase + React の自作PWAで管理してみた

概要

年末の大掃除、口頭やLINEでの分担だと「誰が何をやったか」「どこまで終わったか」が見えづらくなりがちです。また、「去年はどこを掃除したっけ」「この掃除にどれくらいの時間がかかるか」など、毎年のことなのに忘れてしまいがちです。
そこで今回、家族で共有できる大掃除タスク管理アプリを自作しました。複数端末からのリアルタイム反映を優先し、Firebase (Firestore) + React の PWA として構築しました。

  • 想定利用者: 家族4人程度
  • 利用環境: iPhone(Safari, Chrome) + 開発機はWindows
  • 開発期間: 2日程度

やりたかったこと

  • 掃除する箇所ごとにタスクを管理
  • タスクの完了をチェックできるようにしたい
  • タスクごとに予定時間と実績時間を記録し、工数を可視化したい
  • 全体・場所別・担当者別の進捗率を見たい
  • 家族の誰でも、自分のスマホから同じデータを見られるようにしたい

image.png

スクリーンショット 2026-09-22 135653.png

技術スタック

  • フロントエンド: React 19 (JavaScript, Viteでビルド)
  • データベース: Cloud Firestore
  • 認証: Firebase Authentication
  • ホスティング: Firebase Hosting
  • 開発環境: Windows + VS Code + Node.js + Firebase CLI

データ設計

Firestoreに、フラットな2つのコレクションを用意しました。場所(area)や担当者(assigneeId)でグルーピングする設計にすることで、コレクションを分けずに柔軟な集計ができるようにしています。

tasks コレクション

フィールド 型 内容
area string 掃除する場所(キッチン、浴室など)
title string タスク名
assigneeId string 担当者のID(membersのドキュメントID、空文字なら未割当)
estimateMin number 予定時間(分)
actualMin number 実績時間(分)
done boolean 完了フラグ
doneAt number | null 完了日時(タイムスタンプ)
note string メモ
createdAt number 作成日時(並び順に使用)

members コレクション

フィールド 型 内容
name string 表示名
color string 表示用のカラーコード
createdAt number 作成日時

担当者はアプリ内の「家族」タブから追加・改名・削除でき、コード内に固定リストを持たない設計にしました。担当者を削除すると、担当していたタスクは自動で「未割当」に戻ります。

進捗率の考え方

進捗率は2種類を併用しています。

  • 件数ベース: 完了タスク数 ÷ 全タスク数
  • 時間ベース: 完了タスクの予定時間合計 ÷ 全タスクの予定時間合計

件数だけだと「重い掃除も軽い掃除も1件」として扱われてしまうため、時間ベースの指標も加えることで、体感に近い進捗が見えるようにしています。これを全体・場所別・担当者別の3軸で表示しています。

スクリーンショット 2026-09-22 135628.png

計算ロジックはシンプルな関数にまとめています。

export function calcStats(tasks) {
  const total = tasks.length
  const doneTasks = tasks.filter((t) => t.done)
  const est = sum(tasks.map((t) => t.estimateMin || 0))
  const estDone = sum(doneTasks.map((t) => t.estimateMin || 0))
  return {
    total,
    done: doneTasks.length,
    countPct: total ? Math.round((doneTasks.length / total) * 100) : 0,
    est,
    estDone,
    timePct: est ? Math.round((estDone / est) * 100) : 0,
  }
}

画面構成

タブは「タスク」「進捗」「家族」の3つです。

  • タスク: 場所ごとにグルーピングされた一覧。丸をタップして完了、行をタップして編集。担当者で絞り込み可能。
  • 進捗: 全体・場所別・担当者別の進捗をバーとパーセントで表示。
  • 家族: メンバーの追加・改名・色変更・削除。

スクリーンショット 2026-09-22 135637.png

認証まわりで工夫した点

当初はGoogleログイン(許可したアカウントのみ)で実装していましたが、開発中の環境(Chromeのセキュリティ設定)でポップアップ認証が通らない問題があり、家族共通の合言葉(日本語の文章)によるログインに切り替えました。

仕組みとしては、Firebase Authenticationの「メール/パスワード認証」を流用し、内部的に固定のメールアドレスを1つ用意して、パスワード部分に合言葉を入力してもらう形にしています。

// 合言葉ログイン: 固定メールアドレス + 合言葉(=パスワード)
const FAMILY_EMAIL = 'family@example.com'

const login = async (phrase) => {
  await signInWithEmailAndPassword(auth, FAMILY_EMAIL, phrase.trim())
}

Firestore側のセキュリティルールも、このメールアドレス1件のみ許可する形にしています。

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    function isFamily() {
      return request.auth != null
        && request.auth.token.email == 'family@example.com';
    }
    match /tasks/{id} {
      allow read, write: if isFamily();
    }
    match /members/{id} {
      allow read, write: if isFamily();
    }
  }
}

image.png

合言葉方式は「誰が操作したか」を区別できません。家族内での利用など、性善説で運用できる範囲を想定しています。

今後の拡張案

  • タスクに締め切り日を設定する
  • 完了時に実績時間の入力を促す
  • 年次サイクルへの対応
    • 来年、大掃除のタスク一覧をコピーした上で、進捗率だけをリセットして使い直せるようにする
    • 年ごとの記録を残して、前年の所要時間と比較する(ダッシュボードにしようかな)

まとめ

Firestoreのリアルタイム同期を使うことで、「誰かがチェックした瞬間に他の端末にも反映される」という、家族でのタスク共有に向いた体験を、無料枠の範囲で作ることができました。件数と時間の両方で進捗を見せる設計にしたことで、「終わった感」と「残りの大変さ」が両方伝わる仕上がりになったと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?