🤖
【NextJs14】NextJs14 と 便利なライブラリ【#37Clerk Organization Todos】
【#37Clerk Organization Todos】
YouTube: https://youtu.be/K98ZCAWwaCw
今回は各OrganizaitonごとにTodoを作成し、
表示する部分について実装します。
actions/todo-create.ts
"use server";
import * as z from "zod";
import { CreateTodoSchema } from "@/types/schema";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
import { auth } from "@clerk/nextjs";
export const createTodo = async (values: z.infer<typeof CreateTodoSchema>) => {
const { userId, orgId } = auth();
if (!userId || !orgId) {
return {
error: "Unauthorized",
};
}
const validatedFields = CreateTodoSchema.safeParse(values);
if (!validatedFields.success) {
return {
error: "Invalid fields",
};
}
const { title } = validatedFields.data;
const todo = await db.todo.create({
data: {
title,
clerkId: userId,
orgId,
},
});
console.log(todo);
revalidatePath("/account");
return { success: "New todo created!" };
};
ここまで出来ましたら、
新しく「service」というフォルダを作成して
「getTodos」を移動します。
service/todo-get.ts
import { db } from "@/lib/db";
export const getTodos = async () => {
const todos = await db.todo.findMany({
orderBy: {
createdAt: "asc",
},
});
return todos;
};
export const getTodosByOrgId = async (orgId: string | null | undefined) => {
if (!orgId) {
return [];
}
const todos = await db.todo.findMany({
where: {
orgId,
},
orderBy: {
createdAt: "asc",
},
});
return todos;
};
最後に上記の「getTodosByOrgId」を呼び出します。
app/(main)/account/page.tsx
import { auth } from "@clerk/nextjs";
import { formatDistanceToNow } from "date-fns";
import { Separator } from "@/components/ui/separator";
import { TodoForm } from "./_components/todo-form";
import { TodoActions } from "./_components/todo-actions";
import { OrgNavbar } from "./_components/org-navbar";
import { getTodosByOrgId } from "@/service/todo-get";
const AccountPage = async () => {
const { orgId } = auth();
const todos = await getTodosByOrgId(orgId);
return (
<div className="p-6 w-full h-full">
<div className="w-full h-full flex flex-col gap-y-3">
<OrgNavbar />
<div className="flex flex-col md:flex-row items-center justify-between gap-2">
<h2 className="text-center md:text-left text-3xl font-bold">Todos</h2>
<TodoForm />
</div>
<Separator />
<ul className="w-full space-y-3">
{todos.map((todo, idx) => (
<li
key={todo.id}
className="flex flex-col md:flex-row items-center justify-between gap-x-4 gap-y-2"
>
<div className="flex flex-col md:flex-row flex-1 items-center justify-between gap-x-3">
<p className="text-xl font-semibold">
<span className="pr-2">{idx + 1}</span>
<span className={todo.isCompleted ? "line-through" : ""}>
{todo.title}
</span>
</p>
<p>
{formatDistanceToNow(todo.createdAt, { addSuffix: true })}
</p>
</div>
<TodoActions todoId={todo.id} isCompleted={todo.isCompleted} />
</li>
))}
</ul>
</div>
</div>
);
};
export default AccountPage;
Discussion