【React/Firebase】TodoistCloneアプリに挑戦してみました

## 目次
- [目次](#%E7%9B%AE%E6%AC%A1)
- [はじめに](#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
  - [完成イメージ](#%E5%AE%8C%E6%88%90%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8)
  - [筆者について](#%E7%AD%86%E8%80%85%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
  - [経緯](#%E7%B5%8C%E7%B7%AF)
- [技術スタック](#%E6%8A%80%E8%A1%93%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF)
- [実装について](#%E5%AE%9F%E8%A3%85%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
  - [テーブル設計](#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E8%A8%AD%E8%A8%88)
  - [ディレクトリ構成](#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E6%88%90)
- [機能紹介](#%E6%A9%9F%E8%83%BD%E7%B4%B9%E4%BB%8B)
  - [未実装（今後やりたいこと）](#%E6%9C%AA%E5%AE%9F%E8%A3%85%E4%BB%8A%E5%BE%8C%E3%82%84%E3%82%8A%E3%81%9F%E3%81%84%E3%81%93%E3%81%A8)
- [まとめ](#%E3%81%BE%E3%81%A8%E3%82%81)
  - [最後に](#%E6%9C%80%E5%BE%8C%E3%81%AB)
  - [参考](#%E5%8F%82%E8%80%83)

## はじめに
ReactとFirebaseを使って、TodoistのCloneアプリケーションに挑戦してみました。

https://github.com/umekikazuya/Todoist-Clone

今回の記事では、リポジトリの紹介も兼ねて、**やろうと思った経緯**や**反省**等をまとめた活動記録となっております。
（量も膨れるので細部への技術紹介は省いています。気が向けば別記事出します。）

### 完成イメージ
![完成イメージ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/7648c70f-199f-a9e8-f15a-5beffcfd7f33.gif)

### 筆者について
ちょっとだけ紹介させてください。
普段は、Symfonyをベースとしたシステム開発を行っています（主にDrupal）。
パソコン触りだして1.5年ちょい。アクイア認定DrupalExpertの資格を保有しています。
興味があれば覗いてね→ [Certifications](https://dev.acquia.com/person/community/kazuya-umeki)

### 経緯
ここ最近「NetflixCloneアプリ」「DiscordCloneアプリ」といった、既存のサービスを題材にしたリポジトリを見かけることが多くなりましたよね。
そこで私は自身のフロントエンドの技術強化を図って「TodoistCloneアプリ」を実装してみました。

いつもはPHPを書くことが多いのですが、今回息抜きを兼ねてフロントエンドのフレームワークを触ってみようかなと...。

## 技術スタック
### フロントエンド
React(TS)
### データベース
Firestore(Firebase)
### ビルドツール
Vite
### デプロイ & ホスティング（予定）
Vercel

## 実装について
ほんの少しですが実装の解説をします。

### テーブル設計
こんな感じでテーブルを構築しました。
#### Project
| Field  | Type   |
|--------|--------|
| docId  | string |
| name   | string |
| userId | string |

#### Task
| Field    | Type           |
|----------|----------------|
| docId    | string         |
| name     | string         |
| projectId| string         |
| date     | Timestamp      |
| archived | boolean        |
| userId   | string         |

#### User
| Field     | Type   |
|-----------|--------|
| docId     | string |
| firstName | string |
| lastName  | string |

### ディレクトリ構成
```
src
├── assets/
├── components/
│   ├── Layout/
│   ├── Sidebar/
│   ├── Task/
│   └── UI/
│       ├── Button.tsx
│       ├── Input.tsx
│       ├── Link.tsx
│       ├── Modal.tsx
│       ├── Select.tsx
│       └── index.ts
├── firebase/
├── hook/
├── model/
│   ├── index.ts
│   ├── project.model.ts
│   ├── task.model.ts
│   └── user.model.ts
├── routes/
├── styles/
├── views/
├── App.tsx
└── main.tsx
```

#### components
UIコンポーネントや、機能別のコンポーネントを実装しています。
参考にしたリポジトリでは、細かいところまでコンポーネント化していませんでしたが、
今回再利用性を考慮して機能量のわりに、冗長にコンポーネント化を行いました。
#### firebase
Firebaseの接続設定やデータ同期の関数を実装しています。
#### hooks
カスタムフック（タスクの使用、API呼び出しの管理など）を実装しています。
#### model
型定義ファイルを実装しています。
#### routes
Routing設定を記載しています。
#### styles
GlobalCSSファイルを実装しています。
#### views
Routing単位でページを実装しています。

## 機能紹介
- Task操作: タスクの追加、削除、アーカイブが可能です。
- Project操作: プロジェクトの追加、削除が可能です。
- クイックフィルター機能: 以下の項目でタスクの絞り込みが可能です。
  - インボックス、今日、近日予定
  - プロジェクト
- リアルタイム同期: Firestoreを使用したデータのリアルタイム同期が可能です。

### 未実装（今後やりたいこと）
1. サブタスク
2. ログイン
   1. ユーザー管理
   2. アカウント切り替え
   3. アバター等、プロファイル設定
3. アーカイブ一覧
4. Update機能（Task, Project）
5. 操作の取り消し

限られた個人学習の範囲内で進めているため、エラーハンドリングが不十分な箇所や、細かいユーザビリティに十分対応できていない部分が多々あります。
今後のモチベーション等と相談して、よりよりリポジトリにしていければいいなと考えています。

## まとめ
今まで、Firebaseを扱う経験があまりなかったので、こんな簡単にデータベースを作成できるというのは少し意外でした。
普段はSSR実装が多いので、SPAとFirestoreのリアルタイム性にもびっくり。

どの程度、再利用性を持たせるのか、あえて局所的な実装にするのか等の判断はまだまだ不足しているなと感じしているところ。

さくっと終わらせるつもりが、実装を進めるほどにやりたい機能やこだわりたい箇所が増えてだらだらと開発を続けていたのは少し反省かもしれません。
あくまで、経験値向上目的であったため区切りをつけることを覚えたいと思います。
（ちょっとだけ真面目に反省）

### 最後に
リポジトリのREADMEを読めば、恐らく環境構築ができるように手順を記載しています。
なんかあればコメント下さい。

気が向けば、技術紹介記事も書こうかなと思っています。

### 参考
今回参考にした、リポジトリをこちらでご紹介させていただきます。

https://github.com/karlhadwen/todoist

https://github.com/thepuskar/todoist-clone

１つ目のリポジトリでは、開発者がYoutubeにて解説動画を挙げられています。
筆者も動画を参考にさせていただきました。