Table of Contents
Open Table of Contents
Pengenalan
Dalam bagian ketiga ini, kita akan menambahkan fitur CRUD (Create, Read, Update, Delete) untuk item di platform e-learning kita. Kita juga akan mengelola akses berdasarkan peran pengguna, sehingga hanya pengguna dengan peran tertentu yang dapat menambah atau menghapus item.
Model Item di Prisma
Pertama, kita perlu menambahkan model Item
di file prisma/schema.prisma
:
model Item {
id Int @id @default(autoincrement())
title String
description String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId Int
user User @relation(fields: [userId], references: [id])
}
Setelah menambahkan model, jalankan migrasi untuk memperbarui database:
npx prisma migrate dev --name add_item_model
API Routes untuk CRUD Item
Create Item
Buat API route untuk menambah item di pages/api/items/index.ts
:
import { NextApiRequest, NextApiResponse } from "next";
import { PrismaClient } from "@prisma/client";
import { authenticate } from "../../../lib/auth";
import { authorize } from "../../../lib/authorize";
const prisma = new PrismaClient();
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
await authenticate(req, res, async () => {
if (req.method === "POST") {
const { title, description } = req.body;
const userId = req.user.id; // Ambil userId dari token
try {
const item = await prisma.item.create({
data: {
title,
description,
userId,
},
});
res.status(201).json(item);
} catch (error) {
res.status(500).json({ message: "Failed to create item" });
}
} else {
res.status(405).json({ message: "Method not allowed" });
}
});
}
Read Items
Buat API route untuk mengambil semua item di pages/api/items/index.ts
:
if (req.method === "GET") {
try {
const items = await prisma.item.findMany({
include: { user: true }, // Menyertakan informasi pengguna
});
res.status(200).json(items);
} catch (error) {
res.status(500).json({ message: "Failed to fetch items" });
}
}
Update Item
Buat API route untuk memperbarui item di pages/api/items/[id].ts
:
import { NextApiRequest, NextApiResponse } from "next";
import { PrismaClient } from "@prisma/client";
import { authenticate } from "../../../lib/auth";
import { authorize } from "../../../lib/authorize";
const prisma = new PrismaClient();
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
await authenticate(req, res, async () => {
const { id } = req.query;
if (req.method === "PUT") {
const { title, description } = req.body;
try {
const item = await prisma.item.update({
where: { id: Number(id) },
data: { title, description },
});
res.status(200).json(item);
} catch (error) {
res.status(500).json({ message: "Failed to update item" });
}
} else {
res.status(405).json({ message: "Method not allowed" });
}
});
}
Delete Item
Buat API route untuk menghapus item di pages/api/items/[id].ts
:
if (req.method === "DELETE") {
try {
const item = await prisma.item.delete({
where: { id: Number(id) },
});
res.status(200).json(item);
} catch (error) {
res.status(500).json({ message: "Failed to delete item" });
}
}
Mengelola Akses Berdasarkan Peran
Kita perlu memastikan bahwa hanya pengguna dengan peran tertentu (misalnya, “admin” atau “teacher”) yang dapat menambah atau menghapus item. Kita dapat menggunakan middleware authorize
yang telah kita buat sebelumnya.
Contoh Penggunaan Middleware untuk Create dan Delete:
await authorize(["admin", "teacher"])(req, res, async () => {
// Logic untuk menambah atau menghapus item
});
Contoh Penggunaan di Create Item
await authenticate(req, res, async () => {
await authorize(["admin", "teacher"])(req, res, async () => {
// Logic untuk menambah item
});
});
Contoh Penggunaan di Delete Item
await authenticate(req, res, async () => {
await authorize(["admin", "teacher"])(req, res, async () => {
// Logic untuk menghapus item
});
});
Frontend untuk Mengelola Item
Buat komponen untuk menampilkan dan mengelola item. Contoh komponen untuk menampilkan daftar item:
import { useEffect, useState } from "react";
interface Item {
id: number;
title: string;
description: string;
}
const ItemList: React.FC = () => {
const [items, setItems] = useState<Item[]>([]);
const fetchItems = async () => {
const res = await fetch("/api/items");
const data = await res.json();
setItems(data);
};
useEffect(() => {
fetchItems();
}, []);
return (
<div>
<h1 className="text-2xl font-bold">Item List</h1>
<ul>
{items.map(item => (
<li key={item.id} className="border p-2">
<h2 className="font-semibold">{item.title}</h2>
<p>{item.description}</p>
</li>
))}
</ul>
</div>
);
};
export default ItemList;
Form untuk Menambah Item
Buat form untuk menambah item:
import { useState } from "react";
const AddItem: React.FC = () => {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const handleAddItem = async () => {
const res = await fetch("/api/items", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify({ title, description }),
});
if (res.ok) {
// Reset form or update UI
} else {
// Handle error
}
};
return (
<div>
<h1 className="text-2xl font-bold">Add Item</h1>
<input
type="text"
value={title}
onChange={e => setTitle(e.target.value)}
placeholder="Title"
className="border p-2"
/>
<textarea
value={description}
onChange={e => setDescription(e.target.value)}
placeholder="Description"
className="border p-2"
/>
<button onClick={handleAddItem} className="bg-blue-500 p-2 text-white">
Add Item
</button>
</div>
);
};
export default AddItem;
Kesimpulan
Dengan menambahkan fitur CRUD untuk item dan mengelola akses berdasarkan peran pengguna, Anda telah memperkuat platform e-learning yang sedang dibangun. Menggunakan Next.js, Prisma, dan TypeScript bersama dengan kontrol akses berbasis peran memberikan fondasi yang kuat untuk aplikasi web yang aman dan terkelola dengan baik. Selamat mencoba!