進捗管理アプリを作る!NokoriClock 設計ドキュメント編! | オーガスタロウの館

進捗管理アプリを作る!NokoriClock 設計ドキュメント編!

投稿日:2024-11-24, 08:56

某資格試験を受験予定ですが、合格までの目安学習時間が200時間といった記載があったので、せっかくのなので合格達成に必要な時間に対する進捗管理アプリを作成します。一旦はローカルストレージを利用した静的なアプリとして作成しますが、将来的には学習も兼ねてバックエンドを実装していきたいところです。   


1. アプリ概要

概要

NokoriClockは、目標達成のために必要な時間管理と進捗の可視化を提供するアプリです。


目的

  • ユーザーが設定した目標(例:資格試験の合格)に向けて、必要な学習時間や進捗状況を簡単に確認できるようにします。
  • 目標までの日数や学習進捗を直感的に把握できるインターフェースを提供します。
  • 初期段階では、シングルページアプリケーション(SPA)として動作し、ユーザーサイドのみで完結します。

機能

初回起動に表示するページ

  • プレビュー用のコンポーネントをを表示し、目標の進捗状況を確認可能。
  • プレビュー画面から詳細設定ページへの遷移が可能。

プレビューコンポーネント

  1. タイトル表示領域:
    • ユーザーが設定した目標タイトルを表示(例:「資格試験合格」)。
    • 未入力の場合、デフォルト値(例:「目標を設定してください」)を表示。
  2. 進捗表示領域:
    • 以下2つの進捗スライダーを配置。
      • 達成時間スライダー: 必要な学習時間に対して現在の進捗状況を表示。
      • 残日数スライダー: 目標期間に対して残りの日数を表示。
  3. スタートボタン:
    • 目標取り組み時間を記録するモーダルを表示。
  4. 編集ボタン:
    • 目標設定や編集を行うモーダルを表示。

記録モーダル

  • 学習時間を記録するモーダルを表示。
    • 手動で記録可能。
    • カウントアップタイマー(実装保留)。

編集モーダル

  • ユーザーが以下の設定を入力可能:
    • 目標タイトル
    • 目標期日(例:試験日)
    • 総学習時間(例:100時間)
    • 目標スタート日(デフォルトで当日)

2. 使用する技術

主要技術

  • Next.js: (App Routerを使用)せっかくだしvercelにあげようかと思うが今まで通りcloudflareでホストしてもいいかなっといったところ。
  • TypeScript: 必須!!。
  • TailwindCSS / DaisyUI: 個人的に好きなDaisyUI。

備考

データはクライアントサイドのローカルストレージで管理するものとするが、学習も兼ねてnextのバックエンド、特にvercelのサーバレス関数を使って最終的にはDB管理なども検討したい。


3. コンポーネントの構成

ディレクトリ構造(仮)

src/
├── app/
│   ├── page.tsx          # 初回起動ページ
│   ├── [goalId]/         # 各目標の詳細ページ
│   │   └── page.tsx      # 詳細ページ
├── components/
│   ├── AppHeader.tsx     # ヘッダー
│   ├── PreviewComponent/
│   │   ├── index.tsx     # プレビューの親コンポーネント
│   │   ├── GoalTitle.tsx # タイトル表示
│   │   ├── ProgressSliders.tsx # 進捗スライダーの親
│   │   ├── TimeProgressSlider.tsx # 時間スライダー
│   │   └── DaysProgressSlider.tsx # 日数スライダー
│   ├── Modals/
│   │   ├── GoalInputModal.tsx # 記録モーダル
│   │   └── EditGoalModal.tsx  # 編集モーダル
│   └── Buttons/
│       ├── StartButton.tsx    # スタートボタン
│       └── EditButton.tsx     # 編集ボタン
├── hooks/
│   ├── useLocalStorage.ts # ローカルストレージ操作
│   └── useProgress.ts     # 進捗計算ロジック
├── lib/
│   ├── dateUtils.ts       # 日付計算
│   ├── progressUtils.ts   # 進捗率計算
│   └── constants.ts       # 初期値や定数
├── types/
│   ├── goal.ts            # 目標データ型
│   └── common.ts          # 共通型

・いったん仮でこんな感じを想定しているけど、規模が小さいので、抽象度の高いコンポーネントをまとめたディレクトリ、それらを集合させて粒度デカめの機能を実装するコンポーネントを配置するディレクトリ(organisms)の二種類くらいに分けてしまってもいいかなと考える。

4. データフロー

データモデル

type Goal = {
  id: string;           // 目標を一意に識別
  title: string;        // 目標タイトル
  targetDate: Date;     // 目標期日
  totalHours: number;   // 必要学習時間
  startDate: Date;      // 取り組み開始日
  progressHours: number;// 達成学習時間
};

データの流れ

1. 初期化

  • アプリ起動時にローカルストレージからデータを読み込み、グローバル状態に設定。
  • データが存在しない場合はデフォルト値で初期化。

2. データ更新

  • 編集モーダルでデータ入力後、グローバル状態を更新。
  • 更新されたデータをローカルストレージに保存。

3. 進捗計算

  • 進捗スライダーの値は以下のロジックで計算:
    • 達成時間の進捗率: (progressHours / totalHours) * 100
    • 残日数の進捗率: ((今日の日付 - startDate) / (targetDate - startDate)) * 100

状態管理

  • グローバル状態:
    • goals(目標のリスト)をuseContextで管理。
  • ローカル状態:
    • 各モーダルの入力値をuseStateで管理。

例: Contextの定義

typescript

コードをコピーする

type AppState = { goals: Goal[]; setGoals: (goals: Goal[]) => void; updateProgress: (id: string, progress: number) => void; };


ローカルストレージ連携

  • 保存:
    • データ更新時にlocalStorage.setItemで保存。
  • 読み込み:
    • アプリ起動時にlocalStorage.getItemでデータを取得。

イベントの流れ例

目標編集

  1. 編集モーダルを開き、目標を設定。
  2. 保存ボタン押下時にグローバル状態を更新。
  3. 更新データをローカルストレージに保存。