diff --git a/backend/cmd/main.go b/backend/cmd/main.go index d51398b..a638c3d 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -14,12 +14,12 @@ func main() { // 1. Konek Database config.ConnectDatabase() - // 2. AutoMigrate (Tambahkan ClassSchedule di sini agar dikenali GORM) + // 2. AutoMigrate config.DB.AutoMigrate(&models.User{}, &models.Room{}, &models.Booking{}, &models.ClassSchedule{}) r := gin.Default() - // 3. CORS Middleware (Agar Frontend bisa masuk) + // 3. CORS Middleware (Panggil fungsinya di sini) r.Use(CORSMiddleware()) r.GET("/", func(c *gin.Context) { @@ -58,35 +58,34 @@ func main() { // Admin (Manage Rooms) protected.PUT("/admin/rooms/:id/status", controllers.UpdateRoomStatus) - // 🌟 RUTE BARU: Jadwal Kuliah (Untuk Halaman Web Admin) + // Jadwal Kuliah (Untuk Halaman Web Admin) protected.GET("/schedules", controllers.GetSchedules) + protected.POST("/schedules", controllers.CreateSchedule) + protected.PUT("/schedules/:id", controllers.UpdateSchedule) + protected.DELETE("/schedules/:id", controllers.DeleteSchedule) } + // 5. Jalur IoT ESP32 r.POST("/api/sensor/energy", controllers.UpdateRoomPower) - - // RUTE BARU: Untuk menerima ketukan pintu dari Hardware ESP32 r.POST("/api/hardware/verify", controllers.VerifyHardwareCode) - - // PASTIKAN BARIS INI ADA DI SINI: r.POST("/api/hardware/control", controllers.ControlHardware) - r.GET("/api/hardware/status", controllers.GetHardwareStatus) - r.GET("/api/hardware/power-status", controllers.GetPowerStatus) - r.POST("/api/power/global", controllers.GlobalPowerControl) r.Run(":8080") } -// ... (fungsi CORSMiddleware tetap sama) ... - +// ========================================================================= +// FUNGSI MIDDLEWARE HARUS DITULIS DI LUAR FUNGSI MAIN +// ========================================================================= func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { 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") + // Pastikan DELETE sudah masuk di sini + c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) @@ -94,4 +93,4 @@ func CORSMiddleware() gin.HandlerFunc { } c.Next() } -} +} \ No newline at end of file diff --git a/backend/controllers/schedulecontroller.go b/backend/controllers/schedulecontroller.go index 725b216..9d7dc3b 100644 --- a/backend/controllers/schedulecontroller.go +++ b/backend/controllers/schedulecontroller.go @@ -2,15 +2,26 @@ package controllers import ( "net/http" + "s-class-backend/config" + "s-class-backend/models" "github.com/gin-gonic/gin" - - // UBAH DUA BARIS INI MENJADI s-class-backend - "s-class-backend/config" - "s-class-backend/models" ) -// Fungsi untuk mengambil semua jadwal dari database +// Struktur data untuk menerima input dari Frontend (Form Modal) +type ScheduleInput struct { + KodeMK string `json:"kode_mk" binding:"required"` + NamaMK string `json:"nama_mk" binding:"required"` + RoomID int `json:"room_id" binding:"required"` // 🌟 PERBAIKAN: Ubah uint menjadi int + Hari string `json:"hari" binding:"required"` + JamMulai string `json:"jam_mulai" binding:"required"` + JamSelesai string `json:"jam_selesai" binding:"required"` + JumlahSks int `json:"jumlah_sks" binding:"required"` +} + +// ========================================================= +// 1. GET SCHEDULES (Menampilkan Data ke Tabel/Kalender) +// ========================================================= func GetSchedules(c *gin.Context) { var schedules []models.ClassSchedule @@ -20,8 +31,100 @@ func GetSchedules(c *gin.Context) { return } - // Kirim data ke frontend (React) c.JSON(http.StatusOK, gin.H{ "data": schedules, }) } + +// ========================================================= +// 2. CREATE SCHEDULE (Menambah Jadwal Baru) +// ========================================================= +func CreateSchedule(c *gin.Context) { + var input ScheduleInput + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Format data tidak valid: " + err.Error()}) + return + } + + newSchedule := models.ClassSchedule{ + KodeMK: input.KodeMK, + NamaMK: input.NamaMK, + RoomID: input.RoomID, + Hari: input.Hari, + JamMulai: input.JamMulai, + JamSelesai: input.JamSelesai, + JumlahSks: input.JumlahSks, + } + + if err := config.DB.Create(&newSchedule).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal menyimpan jadwal baru ke database"}) + return + } + + c.JSON(http.StatusCreated, gin.H{ + "message": "Jadwal berhasil ditambahkan", + "data": newSchedule, + }) +} + +// ========================================================= +// 3. UPDATE SCHEDULE (Mengedit Jadwal Saat UTS/Berubah) +// ========================================================= +func UpdateSchedule(c *gin.Context) { + scheduleID := c.Param("id") + + var input ScheduleInput + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Format data tidak valid"}) + return + } + + var schedule models.ClassSchedule + // Cari jadwal lama di database berdasarkan ID + if err := config.DB.First(&schedule, scheduleID).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Jadwal tidak ditemukan"}) + return + } + + // Timpa data lama dengan inputan baru dari Admin + schedule.KodeMK = input.KodeMK + schedule.NamaMK = input.NamaMK + schedule.RoomID = input.RoomID + schedule.Hari = input.Hari + schedule.JamMulai = input.JamMulai + schedule.JamSelesai = input.JamSelesai + schedule.JumlahSks = input.JumlahSks + + // Simpan perubahan ke database + if err := config.DB.Save(&schedule).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal memperbarui jadwal"}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Jadwal berhasil diperbarui", + "data": schedule, + }) +} + +// ========================================================= +// 4. DELETE SCHEDULE (Menghapus Jadwal) +// ========================================================= +func DeleteSchedule(c *gin.Context) { + scheduleID := c.Param("id") + + var schedule models.ClassSchedule + // Pastikan data yang mau dihapus itu memang ada + if err := config.DB.First(&schedule, scheduleID).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Jadwal tidak ditemukan"}) + return + } + + // Hapus secara permanen dari database + if err := config.DB.Delete(&schedule).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal menghapus jadwal"}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Jadwal berhasil dihapus"}) +} \ No newline at end of file