diff --git a/.gitignore b/.gitignore index ba7c2d9..3ba3f40 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ backend/*.exe backend/s-class-backend # Mengabaikan file environment (kalau nanti ada) -.env \ No newline at end of file +.env +.env.local \ No newline at end of file diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 2dd608d..98067f8 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -79,7 +79,7 @@ func main() { func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { - c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000") + c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH") diff --git a/frontend/app/admin/approvals/page.tsx b/frontend/app/admin/approvals/page.tsx index 1f201ad..ec4e197 100644 --- a/frontend/app/admin/approvals/page.tsx +++ b/frontend/app/admin/approvals/page.tsx @@ -13,7 +13,7 @@ export default function ApprovalsPage() { try { const token = localStorage.getItem("token"); // Mengambil dari fungsi GetAllBookings di backend - const res = await axios.get("http://localhost:8080/api/bookings", { + const res = await axios.get("http://172.17.110.6:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }); setBookings(res.data.data); @@ -32,7 +32,7 @@ export default function ApprovalsPage() { const token = localStorage.getItem("token"); // Mengirim UUID booking_id ke backend Golang await axios.put( - `http://localhost:8080/api/bookings/${bookingId}/status`, + `http://172.17.110.6:8080/api/bookings/${bookingId}/status`, { status: newStatus }, { headers: { Authorization: `Bearer ${token}` } } ); diff --git a/frontend/app/admin/monitoring/page.tsx b/frontend/app/admin/monitoring/page.tsx index ed64e62..413e84d 100644 --- a/frontend/app/admin/monitoring/page.tsx +++ b/frontend/app/admin/monitoring/page.tsx @@ -8,7 +8,7 @@ export default function PowerMonitoringPage() { const fetchPowerStatus = async () => { try { - const response = await fetch("http://localhost:8080/api/hardware/power-status"); + const response = await fetch("http://172.17.110.6:8080/api/hardware/power-status"); const data = await response.json(); // Asumsikan data dari HA berupa string angka, kita update ke room D101 @@ -74,7 +74,7 @@ useEffect(() => { try { // Tembak API Golang (Ganti dengan endpoint aslimu jika berbeda) - const response = await fetch("http://localhost:8080/api/hardware/control", { + const response = await fetch("http://172.17.110.6:8080/api/hardware/control", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ device: backendDevice, action: actionType }), diff --git a/frontend/app/admin/page.tsx b/frontend/app/admin/page.tsx index b955846..4febfe7 100644 --- a/frontend/app/admin/page.tsx +++ b/frontend/app/admin/page.tsx @@ -21,7 +21,7 @@ export default function AdminDashboard() { const token = localStorage.getItem("token"); // 1. Ambil SEMUA booking pakai endpoint yang sudah ada, lalu filter di Frontend - const bookRes = await axios.get("http://localhost:8080/api/bookings", { + const bookRes = await axios.get("http://172.17.110.6:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }); @@ -31,7 +31,7 @@ export default function AdminDashboard() { setPendingBookings(pendingOnly); // 2. Ambil daftar ruangan biasa, lalu kita sisipkan "Dummy Power" untuk UI - const roomRes = await axios.get("http://localhost:8080/api/rooms", { + const roomRes = await axios.get("http://172.17.110.6:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }); @@ -54,7 +54,7 @@ export default function AdminDashboard() { try { const token = localStorage.getItem("token"); // Mengirim status 'Approved' atau 'Rejected' ke backend - await axios.put(`http://localhost:8080/api/bookings/${id}/status`, + await axios.put(`http://172.17.110.6:8080/api/bookings/${id}/status`, { status: status }, { headers: { Authorization: `Bearer ${token}` } } ); diff --git a/frontend/app/admin/rooms/page.tsx b/frontend/app/admin/rooms/page.tsx index a7febc3..228e62b 100644 --- a/frontend/app/admin/rooms/page.tsx +++ b/frontend/app/admin/rooms/page.tsx @@ -11,7 +11,7 @@ export default function ManageRoomsPage() { const fetchRooms = async () => { try { const token = localStorage.getItem("token"); - const res = await axios.get("http://localhost:8080/api/rooms", { + const res = await axios.get("http://172.17.110.6:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }); setRooms(res.data.data); @@ -33,7 +33,7 @@ export default function ManageRoomsPage() { try { const token = localStorage.getItem("token"); - await axios.put(`http://localhost:8080/api/admin/rooms/${roomId}/status`, + await axios.put(`http://172.17.110.6:8080/api/admin/rooms/${roomId}/status`, { status: newStatus }, { headers: { Authorization: `Bearer ${token}` } } ); diff --git a/frontend/app/admin/schedules/page.tsx b/frontend/app/admin/schedules/page.tsx index 207313d..651ae7b 100644 --- a/frontend/app/admin/schedules/page.tsx +++ b/frontend/app/admin/schedules/page.tsx @@ -19,7 +19,7 @@ export default function SchedulesPage() { const fetchSchedules = async () => { try { const token = localStorage.getItem("token"); - const res = await axios.get("http://localhost:8080/api/schedules", { + const res = await axios.get("http://172.17.110.6:8080/api/schedules", { headers: { Authorization: `Bearer ${token}` } }); setSchedules(res.data.data || []); diff --git a/frontend/app/dashboard/bookings/add/page.tsx b/frontend/app/dashboard/bookings/add/page.tsx index 15530b6..a70ae70 100644 --- a/frontend/app/dashboard/bookings/add/page.tsx +++ b/frontend/app/dashboard/bookings/add/page.tsx @@ -22,7 +22,7 @@ export default function AddBookingPage() { const fetchRooms = async () => { try { const token = localStorage.getItem("token"); - const res = await axios.get("http://localhost:8080/api/rooms", { + const res = await axios.get("http://172.17.110.6:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` }, }); setRooms(res.data.data); @@ -46,7 +46,7 @@ export default function AddBookingPage() { const startISO = new Date(startTime).toISOString(); const endISO = new Date(endTime).toISOString(); - await axios.post("http://localhost:8080/api/bookings", { + await axios.post("http://172.17.110.6:8080/api/bookings", { room_id: parseInt(selectedRoomId), start_time: startISO, end_time: endISO, diff --git a/frontend/app/dashboard/bookings/calendar/page.tsx b/frontend/app/dashboard/bookings/calendar/page.tsx index a03e733..4ced007 100644 --- a/frontend/app/dashboard/bookings/calendar/page.tsx +++ b/frontend/app/dashboard/bookings/calendar/page.tsx @@ -58,9 +58,9 @@ export default function CalendarViewPage() { const token = localStorage.getItem("token"); // 2. FETCH DATA SCHEDULES BERSAMAAN DENGAN ROOMS & BOOKINGS const [roomsRes, bookingsRes, schedulesRes] = await Promise.all([ - axios.get("http://localhost:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }), - axios.get("http://localhost:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }), - axios.get("http://localhost:8080/api/schedules", { headers: { Authorization: `Bearer ${token}` } }) + axios.get("http://172.17.110.6:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }), + axios.get("http://172.17.110.6:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }), + axios.get("http://172.17.110.6:8080/api/schedules", { headers: { Authorization: `Bearer ${token}` } }) ]); setRooms(roomsRes.data.data || []); diff --git a/frontend/app/dashboard/page.tsx b/frontend/app/dashboard/page.tsx index 511fe80..a41a59f 100644 --- a/frontend/app/dashboard/page.tsx +++ b/frontend/app/dashboard/page.tsx @@ -45,7 +45,7 @@ export default function Dashboard() { const fetchRooms = async (token: string) => { try { - const response = await axios.get("http://localhost:8080/api/rooms", { + const response = await axios.get("http://172.17.110.6:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` }, }); setRooms(response.data.data); @@ -79,7 +79,7 @@ export default function Dashboard() { const endISO = new Date(endTime).toISOString(); await axios.post( - "http://localhost:8080/api/bookings", + "http://172.17.110.6:8080/api/bookings", { room_id: selectedRoom?.room_id, start_time: startISO, diff --git a/frontend/app/history/page.tsx b/frontend/app/history/page.tsx index 7a3888f..9e231b1 100644 --- a/frontend/app/history/page.tsx +++ b/frontend/app/history/page.tsx @@ -36,7 +36,7 @@ export default function HistoryPage() { const fetchHistory = async (token: string) => { try { // PERBAIKAN: Ubah /api/bookings menjadi /api/my-bookings - const response = await axios.get("http://localhost:8080/api/my-bookings", { + const response = await axios.get("http://172.17.110.6:8080/api/my-bookings", { headers: { Authorization: `Bearer ${token}` }, }); setBookings(response.data.data || []); diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx index cf289db..329869c 100644 --- a/frontend/app/login/page.tsx +++ b/frontend/app/login/page.tsx @@ -22,18 +22,22 @@ export default function LoginPage() { setError(""); try { - // Tembak API Backend Golang - // Opsional: Kamu bisa mengirimkan loginRole juga ke backend jika API-mu membutuhkannya - const response = await axios.post("http://localhost:8080/api/auth/login", { + // Tembak API Backend Golang menggunakan IP Laptop + const response = await axios.post("http://172.17.110.6:8080/api/auth/login", { nrp_nip: nrp, password: password, // role_attempt: loginRole // Buka komentar ini jika backend Golang minta parameter role }); const { token, user } = response.data; + + // 1. Simpan di localStorage (untuk dipakai di axios frontend) localStorage.setItem("token", token); localStorage.setItem("user", JSON.stringify(user)); + // 2. Simpan di Cookie agar bisa dibaca oleh middleware.ts Next.js + document.cookie = `token=${token}; path=/; max-age=86400; SameSite=Lax`; + // Redirect berdasarkan role dari backend DAN pilihan di UI if (user.role === "admin" && loginRole === "admin") { router.push("/admin"); @@ -43,6 +47,7 @@ export default function LoginPage() { // Mencegah user biasa login lewat tab admin, atau sebaliknya setError("Role tidak sesuai dengan tipe akun Anda."); localStorage.clear(); // Bersihkan token yang terlanjur masuk + document.cookie = "token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"; // Hapus cookie } } catch (err: any) {