npx create-next-app@latest
✔ What is your project named? … trello-appwrite-clone-yt
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias? … No / Yes
componentsフォルダ作成
npm install @heroicons/react
npm install react-avatar --save
Board.tsx

npm install react-beautiful-dnd --save
npm install appwrite
Database作成
Attributes作成
title
status
appwriteのattributes enumは、appwriteのAPIを使用する際にリクエストやレスポンスに含めることができる属性(attribute)の一覧を示す列挙型(enum)です。
Appwriteは、バックエンドの機能を提供するオープンソースのプラットフォームであり、ユーザー認証、データベース、ストレージ、リアルタイムメッセージングなどの機能を提供します。APIを介してこれらの機能にアクセスする際に、リクエストのパラメータやレスポンスのデータにattributes enumを使用して、特定の属性を指定したり取得したりすることができます。具体的には、ユーザーのプロフィール情報やデータのフィールドなどがattributes enumを通じて操作されます。
image
Document
attributesで設定したtitle、status、imageが
Permissions設定
Storage
images
Permissions設定
npm i zustand
storeフォルダ作成
TypedColumnの型はtodo”、”inprogress”、”done” のいずれかの値を取ります。
type TypedColumn = "todo" | "inprogress" | "done";
bucketId
とfileId
という2つのプロパティを持つ。
interface Image {
bucketId: string;
fileId: string;
}
id
は一般的な一意の識別子であり、どんなデータ構造でも使うことができますが、$id
は特殊な用途の識別子であり、特定のデータベースやデータストレージサービスなどで使われることがより一般的
$id
: タスクの一意のIDを表す文字列$createdAt
: タスクが作成された日時を表す文字列title
: タスクのタイトルを表す文字列status
: タスクのステータスを示すTypedColumn
型の値image
: オプションのImage
型のオブジェクトで、タスクに関連付けられる画像の情報を保持します。
interface Todo {
$id: string;
$createdAt: string;
title: string;
status: TypedColumn;
image?: Image;
}
storeフォルダ作成
interface BoardState
は、Zustandと呼ばれる状態管理ライブラリを使用して、ボード(タスク管理のためのカンバンボード)の状態を管理するための型定義。BoardState
インターフェースは、ボードの状態を表すプロパティや、それを更新するための関数を含んでいます。
interface BoardState {
board: Board;
getBoard: () => void;
newTaskType: TypedColumn;
newTaskInput: string;
image: File | null;
searchString: string;
}
BoardState
型はその機能が含まれるファイル(BoardStore.ts
)内に定義することが推奨されます。なぜなら、BoardState
はuseBoardStore
という独自のZustandのStoreの一部として、そのファイル内でのみ使用されるものだからです。typings.d.ts
は主に、プロジェクト全体で共通の型定義を行いたい場合に使用します。たとえば、外部のライブラリやフレームワークから提供される型定義を追加したり、カスタムのグローバルな型を定義したりする際に利用します。BoardState
型がプロジェクト全体で共有される必要がない場合は、BoardStore.ts
内に定義することでスコープを限定しておくことがより安全で適切です。
board
: ボードの状態を表すオブジェクト。getBoard
: ボードの状態を非同期に取得して更新するための関数
libフォルダ作成
指定されたコレクション内のドキュメントを一覧表示するために使用されます。
const data = await databases.listDocuments(
process.env.NEXT_PUBLIC_DATABASE_ID!
の部分では、process.env.NEXT_PUBLIC_DATABASE_ID
がnullまたはundefinedではないことを表明しています。process.env.NEXT_PUBLIC_DATABASE_ID
がnullまたはundefinedの場合にエラーが発生します。
process.env.NEXT_PUBLIC_DATABASE_ID!
Column
オブジェクトを値とするMapを持つオブジェクトですcolumns
はタスクのカラムを管理するためのMapであり、初期値は空のMapとして定義されています。
keyはTypedColumnでvalueはColumn
board: {
columns: new Map<TypedColumn, Column>(),
},
初期状態を定義
getTodosGroupedByColumn
という関数を呼び出して、タスクをカラムごとにグループ化したboard
オブジェクトを取得します。取得したboard
オブジェクトをZustandのset
コールバックを使用して更新します。
初期状態を定義
newTaskType: "todo",
//
newTaskInput: "",
//初期値としてnull
image: null,
//初期値として空の文字列
searchString: "",
状態を更新するアクションを定義
// imageという名前のファイルまたはnullを引数として受け取り、imageという状態を更新します。
setImage: (image: File | null) => set({ image }),
//columnIdという名前のTypedColumn型を引数として受け取り、newTaskTypeという状態をcolumnIdで更新します。
setNewTaskType: (columnId: TypedColumn) => set({ newTaskType: columnId }),
//inputという名前の文字列を引数として受け取り、newTaskInputという状態をinputで更新します。
setNewTaskInput: (input: string) => set({ newTaskInput: input }),
//searchStringという名前の文字列を引数として受け取り、searchStringという状態をsearchStringで更新します。
setSearchString: (searchString: string) => set({ searchString }),
set({ board })
では、board
をプロパティ名とするオブジェクトが渡されており、zustand
はそのオブジェクトを解釈してboard
の値を更新します。
getBoard: async () => {
const board = await getTodosGroupedByColumn();
set({ board });
},
acc.get(todo.status)
で、acc
(Mapオブジェクト)から現在のTodoのステータスに対応するカラム情報を取得。ラム情報がない場合は新しいカラム情報を作成し、acc
に追加id
にはTodoのステータス、todos
には空の配列
columnTypesという配列に[“todo”, “inprogress”, “done”]のTypedColumn
型の要素を定義columnTypes
配列の各要素を順番に取り出し
もし指定したキーに対応する値がnull
またはundefined
であれば、columns
に新しいキーとそれに対応する値(オブジェクト)が追加されます。