🔖
【NextJs14】NextJs14 と 便利なライブラリ【#29GetTodo & date-fns】
【#29GetTodo & date-fns】
YouTube: https://youtu.be/d25GONgHm_4
今回は前回作成したtodoのデータを取得して
アプリに表示します。
日付の部分で以下のライブラリを使用します。
npm i date-fns
まず、Shadcnのボタンに新しく「Completed」のvariantを追加します。
components/ui/button.tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
primary: "bg-indigo-600 hover:bg-indigo-500 text-white",
Completed: "bg-emerald-600 hover:bg-emerald-500 text-white",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = "Button";
export { Button, buttonVariants };
次に、表示するページは「Account」が現在空いている状態ですので
こちらに作成します。
※liに後の動画でkeyを設定します。
もし現状でコード上の赤線が出て気になる場合は
keyにtodoのid設定してみてください。
app/(main)/account/page.tsx
import { CheckCircle, Trash2 } from "lucide-react";
import { formatDistanceToNow } from "date-fns";
import { db } from "@/lib/db";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
const getTodos = async () => {
const todos = await db.todo.findMany({
orderBy: {
createdAt: "asc",
},
});
return todos;
};
const AccountPage = async () => {
const todos = await getTodos();
return (
<div className="p-6 w-full h-full">
<div className="w-full h-full flex flex-col gap-y-3">
<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>
<div>form</div>
</div>
<Separator />
<ul className="w-full space-y-3">
{todos.map((todo, idx) => (
<li 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>
<div className="flex items-center gap-x-2">
<Button variant={todo.isCompleted ? "Completed" : "secondary"}>
<CheckCircle className="h-5 w-5" />
</Button>
<Button variant="destructive">
<Trash2 className="h-5 w-5" />
</Button>
</div>
</li>
))}
</ul>
</div>
</div>
);
};
export default AccountPage;
Discussion