394 lines
11 KiB
TypeScript
394 lines
11 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import supabase from '@/lib/db';
|
|
|
|
// Define the MataKuliah type
|
|
interface MataKuliah {
|
|
id_mk: number;
|
|
kode_mk: string;
|
|
nama_mk: string;
|
|
sks: number;
|
|
semester: number;
|
|
jenis_mk: 'Wajib' | 'Pilihan Wajib' | 'Pilihan';
|
|
id_prasyarat: number | null;
|
|
nama_prasyarat?: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
|
|
// GET - Ambil semua data mata kuliah atau satu mata kuliah spesifik berdasarkan ID
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get('id');
|
|
const search = searchParams.get('search');
|
|
const semester = searchParams.get('semester');
|
|
|
|
if (id) {
|
|
// Ambil mata kuliah spesifik berdasarkan ID dengan join untuk prasyarat
|
|
const { data, error } = await supabase
|
|
.from('mata_kuliah')
|
|
.select(`
|
|
id_mk,
|
|
kode_mk,
|
|
nama_mk,
|
|
sks,
|
|
semester,
|
|
jenis_mk,
|
|
id_prasyarat,
|
|
created_at,
|
|
updated_at,
|
|
prasyarat:mata_kuliah!id_prasyarat(kode_mk, nama_mk)
|
|
`)
|
|
.eq('id_mk', id)
|
|
.single();
|
|
|
|
if (error || !data) {
|
|
return NextResponse.json({ message: 'Mata kuliah not found' }, { status: 404 });
|
|
}
|
|
|
|
// Transformasi data untuk meratakan field yang di-join
|
|
const transformedData = {
|
|
...data,
|
|
nama_prasyarat: (data.prasyarat as any)?.nama_mk || null
|
|
};
|
|
delete (transformedData as any).prasyarat;
|
|
|
|
return NextResponse.json(transformedData);
|
|
} else {
|
|
// Ambil semua mata kuliah terlebih dahulu
|
|
let query = supabase
|
|
.from('mata_kuliah')
|
|
.select('*');
|
|
|
|
// Add search condition if provided
|
|
if (search) {
|
|
query = query.or(`kode_mk.ilike.%${search}%,nama_mk.ilike.%${search}%`);
|
|
}
|
|
|
|
// Add semester filter if provided
|
|
if (semester && semester !== 'all') {
|
|
query = query.eq('semester', parseInt(semester));
|
|
}
|
|
|
|
// Add order by
|
|
query = query.order('semester', { ascending: true }).order('kode_mk', { ascending: true });
|
|
|
|
const { data: mataKuliahData, error } = await query;
|
|
|
|
if (error) {
|
|
console.error('Error fetching data:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
|
|
// Ambil data prasyarat untuk semua mata kuliah yang memiliki prasyarat
|
|
const prasyaratIds = mataKuliahData
|
|
.filter(mk => mk.id_prasyarat)
|
|
.map(mk => mk.id_prasyarat);
|
|
|
|
let prasyaratData: any[] = [];
|
|
if (prasyaratIds.length > 0) {
|
|
const { data: prasyaratResult, error: prasyaratError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('id_mk, kode_mk, nama_mk')
|
|
.in('id_mk', prasyaratIds);
|
|
|
|
if (!prasyaratError) {
|
|
prasyaratData = prasyaratResult || [];
|
|
}
|
|
}
|
|
|
|
// Gabungkan data mata kuliah dengan data prasyarat
|
|
const transformedData = mataKuliahData.map(item => {
|
|
const prasyarat = prasyaratData.find(p => p.id_mk === item.id_prasyarat);
|
|
return {
|
|
...item,
|
|
nama_prasyarat: prasyarat ? prasyarat.nama_mk : null
|
|
};
|
|
});
|
|
|
|
return NextResponse.json(transformedData);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching data:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// POST - Buat data mata kuliah baru
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json();
|
|
const {
|
|
kode_mk,
|
|
nama_mk,
|
|
sks,
|
|
semester,
|
|
jenis_mk,
|
|
id_prasyarat
|
|
} = body;
|
|
|
|
// Validasi field yang wajib diisi
|
|
if (!kode_mk || !nama_mk || !sks || !semester || !jenis_mk) {
|
|
return NextResponse.json(
|
|
{ message: 'Missing required fields: kode_mk, nama_mk, sks, semester, jenis_mk' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Validasi nilai sks dan semester
|
|
if (sks <= 0 || semester <= 0) {
|
|
return NextResponse.json(
|
|
{ message: 'SKS and semester must be greater than 0' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Validasi jenis mata kuliah
|
|
const validJenisMK = ['Wajib', 'Pilihan Wajib', 'Pilihan'];
|
|
if (!validJenisMK.includes(jenis_mk)) {
|
|
return NextResponse.json(
|
|
{ message: 'Invalid jenis_mk value. Must be one of: Wajib, Pilihan Wajib, Pilihan' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Cek apakah kode mata kuliah sudah ada
|
|
const { data: existing, error: checkError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('kode_mk')
|
|
.eq('kode_mk', kode_mk)
|
|
.single();
|
|
|
|
if (existing) {
|
|
return NextResponse.json(
|
|
{ message: 'Mata kuliah with this code already exists' },
|
|
{ status: 409 }
|
|
);
|
|
}
|
|
|
|
// Validasi prasyarat jika ada
|
|
if (id_prasyarat) {
|
|
const { data: prasyaratExists, error: prasyaratError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('id_mk')
|
|
.eq('id_mk', id_prasyarat)
|
|
.single();
|
|
|
|
if (prasyaratError || !prasyaratExists) {
|
|
return NextResponse.json(
|
|
{ message: 'Prasyarat mata kuliah not found' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
}
|
|
|
|
// Insert mata kuliah baru
|
|
const { data, error } = await supabase
|
|
.from('mata_kuliah')
|
|
.insert({
|
|
kode_mk,
|
|
nama_mk,
|
|
sks: parseInt(sks),
|
|
semester: parseInt(semester),
|
|
jenis_mk,
|
|
id_prasyarat: id_prasyarat || null
|
|
})
|
|
.select()
|
|
.single();
|
|
|
|
if (error) {
|
|
console.error('Error creating mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{ message: 'Mata kuliah created successfully', id: data.id_mk },
|
|
{ status: 201 }
|
|
);
|
|
} catch (error) {
|
|
console.error('Error creating mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// PUT - Update data mata kuliah yang sudah ada
|
|
export async function PUT(request: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get('id');
|
|
|
|
if (!id) {
|
|
return NextResponse.json({ message: 'ID is required' }, { status: 400 });
|
|
}
|
|
|
|
const body = await request.json();
|
|
const {
|
|
kode_mk,
|
|
nama_mk,
|
|
sks,
|
|
semester,
|
|
jenis_mk,
|
|
id_prasyarat
|
|
} = body;
|
|
|
|
// Validasi field yang wajib diisi
|
|
if (!kode_mk || !nama_mk || !sks || !semester || !jenis_mk) {
|
|
return NextResponse.json(
|
|
{ message: 'Missing required fields: kode_mk, nama_mk, sks, semester, jenis_mk' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Validasi nilai sks dan semester
|
|
if (sks <= 0 || semester <= 0) {
|
|
return NextResponse.json(
|
|
{ message: 'SKS and semester must be greater than 0' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Validasi jenis mata kuliah
|
|
const validJenisMK = ['Wajib', 'Pilihan Wajib', 'Pilihan'];
|
|
if (!validJenisMK.includes(jenis_mk)) {
|
|
return NextResponse.json(
|
|
{ message: 'Invalid jenis_mk value. Must be one of: Wajib, Pilihan Wajib, Pilihan' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Cek apakah mata kuliah ada
|
|
const { data: existing, error: checkError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('*')
|
|
.eq('id_mk', id)
|
|
.single();
|
|
|
|
if (checkError || !existing) {
|
|
return NextResponse.json({ message: 'Mata kuliah not found' }, { status: 404 });
|
|
}
|
|
|
|
// Cek apakah kode mata kuliah sudah digunakan oleh mata kuliah lain
|
|
const { data: duplicateCode, error: duplicateError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('id_mk')
|
|
.eq('kode_mk', kode_mk)
|
|
.neq('id_mk', id)
|
|
.single();
|
|
|
|
if (duplicateCode) {
|
|
return NextResponse.json(
|
|
{ message: 'Mata kuliah with this code already exists' },
|
|
{ status: 409 }
|
|
);
|
|
}
|
|
|
|
// Validasi prasyarat jika ada
|
|
if (id_prasyarat) {
|
|
// Pastikan prasyarat tidak sama dengan mata kuliah itu sendiri
|
|
if (parseInt(id_prasyarat) === parseInt(id)) {
|
|
return NextResponse.json(
|
|
{ message: 'Mata kuliah cannot be prerequisite of itself' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const { data: prasyaratExists, error: prasyaratError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('id_mk')
|
|
.eq('id_mk', id_prasyarat)
|
|
.single();
|
|
|
|
if (prasyaratError || !prasyaratExists) {
|
|
return NextResponse.json(
|
|
{ message: 'Prasyarat mata kuliah not found' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
}
|
|
|
|
// Update mata kuliah
|
|
const { error } = await supabase
|
|
.from('mata_kuliah')
|
|
.update({
|
|
kode_mk,
|
|
nama_mk,
|
|
sks: parseInt(sks),
|
|
semester: parseInt(semester),
|
|
jenis_mk,
|
|
id_prasyarat: id_prasyarat || null,
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id_mk', id);
|
|
|
|
if (error) {
|
|
console.error('Error updating mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json({ message: 'Mata kuliah updated successfully' });
|
|
} catch (error) {
|
|
console.error('Error updating mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// DELETE - Hapus data mata kuliah
|
|
export async function DELETE(request: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get('id');
|
|
|
|
if (!id) {
|
|
return NextResponse.json({ message: 'ID is required' }, { status: 400 });
|
|
}
|
|
|
|
// Check if mata kuliah exists
|
|
const { data: existing, error: checkError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('id_mk, kode_mk, nama_mk')
|
|
.eq('id_mk', id)
|
|
.single();
|
|
|
|
if (checkError || !existing) {
|
|
return NextResponse.json({ message: 'Mata kuliah not found' }, { status: 404 });
|
|
}
|
|
|
|
// Check if mata kuliah is used as prerequisite by other mata kuliah
|
|
const { data: dependents, error: dependentsError } = await supabase
|
|
.from('mata_kuliah')
|
|
.select('kode_mk, nama_mk')
|
|
.eq('id_prasyarat', id);
|
|
|
|
if (dependentsError) {
|
|
console.error('Error checking dependents:', dependentsError);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
|
|
if (dependents && dependents.length > 0) {
|
|
const dependentNames = dependents.map(d => `${d.kode_mk} - ${d.nama_mk}`).join(', ');
|
|
return NextResponse.json(
|
|
{
|
|
message: `Cannot delete mata kuliah. It is used as prerequisite by: ${dependentNames}`
|
|
},
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Hapus mata kuliah
|
|
const { error } = await supabase
|
|
.from('mata_kuliah')
|
|
.delete()
|
|
.eq('id_mk', id);
|
|
|
|
if (error) {
|
|
console.error('Error deleting mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json({ message: 'Mata kuliah deleted successfully' });
|
|
} catch (error) {
|
|
console.error('Error deleting mata kuliah:', error);
|
|
return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 });
|
|
}
|
|
}
|