Table of Contents
Open Table of Contents
Pengenalan
Platform e-learning membutuhkan fitur seperti manajemen materi, diskusi, dan integrasi chatbot untuk meningkatkan interaksi pengguna. Dalam panduan ini, kita akan membangun platform e-learning menggunakan Next.js untuk frontend dan backend, Prisma untuk manajemen database, dan TypeScript untuk keamanan tipe data.
Struktur Projek
Berikut struktur projek yang akan kita gunakan:
project/
├── pages/
│ ├── api/
│ │ ├── courses/
│ │ │ ├── index.ts # CRUD courses
│ │ │ └── [id].ts # Detail course
│ │ ├── discussions/
│ │ │ ├── index.ts # CRUD discussions
│ │ │ └── [id].ts # Detail discussion
│ │ └── materials/
│ │ └── index.ts # CRUD materials
│ └── index.ts # Landing page
├── prisma/
│ └── schema.prisma # Prisma schema
├── components/ # Reusable components
├── utils/
│ └── db.ts # Prisma client instance
└── ...
Setup Prisma
Schema Database
Buat schema Prisma untuk User
, Course
, Material
, dan Discussion
.
model User {
id Int @id @default(autoincrement())
name String
email String @unique
role String // "student" or "teacher"
courses Course[] // Courses the user is enrolled in or teaches
discussions Discussion[]
}
model Course {
id Int @id @default(autoincrement())
title String
description String
teacherId Int
teacher User @relation(fields: [teacherId], references: [id])
materials Material[]
discussions Discussion[]
students User[]
}
model Material {
id Int @id @default(autoincrement())
title String
content String
courseId Int
course Course @relation(fields: [courseId], references: [id])
}
model Discussion {
id Int @id @default(autoincrement())
title String
content String
courseId Int
course Course @relation(fields: [courseId], references: [id])
userId Int
user User @relation(fields: [userId], references: [id])
}
Migrasi Database
Jalankan migrasi untuk membuat tabel di database:
npx prisma migrate dev --name init
API Routes
CRUD Materi
Buat API route untuk mengelola materi di pages/api/materials/index.ts
:
import { NextApiRequest, NextApiResponse } from "next";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === "POST") {
const { title, content, courseId } = req.body;
try {
const material = await prisma.material.create({
data: { title, content, courseId },
});
res.status(201).json(material);
} catch (error) {
res.status(500).json({ message: "Failed to add material" });
}
} else if (req.method === "GET") {
const { courseId } = req.query;
try {
const materials = await prisma.material.findMany({
where: { courseId: Number(courseId) },
});
res.status(200).json(materials);
} catch (error) {
res.status(500).json({ message: "Failed to fetch materials" });
}
} else {
res.status(405).json({ message: "Method not allowed" });
}
}
CRUD Diskusi
Buat API route untuk mengelola diskusi di pages/api/discussions/index.ts
:
import { NextApiRequest, NextApiResponse } from "next";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === "POST") {
const { title, content, courseId, userId } = req.body;
try {
const discussion = await prisma.discussion.create({
data: { title, content, courseId, userId },
});
res.status(201).json(discussion);
} catch (error) {
res.status(500).json({ message: "Failed to create discussion" });
}
} else if (req.method === "GET") {
const { courseId } = req.query;
try {
const discussions = await prisma.discussion.findMany({
where: { courseId: Number(courseId) },
include: { user: true },
});
res.status(200).json(discussions);
} catch (error) {
res.status(500).json({ message: "Failed to fetch discussions" });
}
} else {
res.status(405).json({ message: "Method not allowed" });
}
}
Frontend dengan Next.js
Fetching Data
Contoh fetching materi di React:
import { useEffect, useState } from "react";
const fetchMaterials = async (courseId: number) => {
const res = await fetch(`/api/materials?courseId=${courseId}`);
return res.json();
};
export default function CourseMaterials({ courseId }) {
const [materials, setMaterials] = useState([]);
useEffect(() => {
fetchMaterials(courseId).then(setMaterials);
}, [courseId]);
return (
<div>
{materials.map(material => (
<div key={material.id}>
<h3>{material.title}</h3>
<p>{material.content}</p>
</div>
))}
</div>
);
}
Menampilkan Diskusi
Contoh fetching diskusi di React:
import { useEffect, useState } from "react";
const fetchDiscussions = async (courseId: number) => {
const res = await fetch(`/api/discussions?courseId=${courseId}`);
return res.json();
};
export default function CourseDiscussions({ courseId }) {
const [discussions, setDiscussions] = useState([]);
useEffect(() => {
fetchDiscussions(courseId).then(setDiscussions);
}, [courseId]);
return (
<div>
{discussions.map(discussion => (
<div key={discussion.id}>
<h3>{discussion.title}</h3>
<p>{discussion.content}</p>
<p>By: {discussion.user.name}</p>
</div>
))}
</div>
);
}
Integrasi Chatbot dengan OpenAI
Buat API route untuk chatbot di pages/api/chatbot.ts
:
import { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === "POST") {
const { message } = req.body;
try {
const response = await axios.post(
"https://api.openai.com/v1/chat/completions",
{
model: "gpt-4",
messages: [{ role: "user", content: message }],
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
}
);
res.status(200).json(response.data.choices[0].message.content);
} catch (error) {
res
.status(500)
.json({ message: "Failed to fetch response from chatbot" });
}
} else {
res.status(405).json({ message: "Method not allowed" });
}
}
Kesimpulan
Dengan Next.js, Prisma, dan TypeScript, Anda dapat membangun platform e-learning yang kuat dan mudah dikelola. Fitur seperti manajemen materi, diskusi, dan integrasi chatbot dapat meningkatkan pengalaman pengguna. Selamat mencoba!