v2.0: 3-Raum-System - Hauptraum, Saal A, Saal B mit 18 Tischen, Raum-Buchungen, API-Doku
This commit is contained in:
+773
@@ -0,0 +1,773 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"reservation-system/backend/internal/auth"
|
||||
"reservation-system/backend/internal/db"
|
||||
"reservation-system/backend/internal/models"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
db *db.DB
|
||||
}
|
||||
|
||||
func NewHandler(database *db.DB) *Handler {
|
||||
return &Handler{db: database}
|
||||
}
|
||||
|
||||
func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
||||
// Auth
|
||||
mux.HandleFunc("/api/auth/login", h.handleLogin)
|
||||
mux.HandleFunc("/api/auth/refresh", h.handleRefresh)
|
||||
|
||||
// Rooms (protected)
|
||||
mux.HandleFunc("/api/rooms", h.authMiddleware(h.handleRooms))
|
||||
mux.HandleFunc("/api/rooms/", h.authMiddleware(h.handleRoomDetail))
|
||||
|
||||
// Tables (protected)
|
||||
mux.HandleFunc("/api/tables", h.authMiddleware(h.handleTables))
|
||||
mux.HandleFunc("/api/tables/", h.authMiddleware(h.handleTableDetail))
|
||||
mux.HandleFunc("/api/tables/merge", h.authMiddleware(h.handleMergeTables))
|
||||
|
||||
// NEW: Room tables endpoint
|
||||
mux.HandleFunc("/api/rooms/", h.authMiddleware(h.handleRoomTables))
|
||||
|
||||
// Reservations (protected)
|
||||
mux.HandleFunc("/api/reservations", h.authMiddleware(h.handleReservations))
|
||||
mux.HandleFunc("/api/reservations/", h.authMiddleware(h.handleReservationDetail))
|
||||
mux.HandleFunc("/api/reservations/date/", h.authMiddleware(h.handleReservationsByDate))
|
||||
|
||||
// NEW: Room Bookings
|
||||
mux.HandleFunc("/api/room-bookings", h.authMiddleware(h.handleRoomBookings))
|
||||
mux.HandleFunc("/api/room-bookings/", h.authMiddleware(h.handleRoomBookingDetail))
|
||||
|
||||
// Availability
|
||||
mux.HandleFunc("/api/availability", h.authMiddleware(h.handleAvailability))
|
||||
mux.HandleFunc("/api/availability/room", h.authMiddleware(h.handleRoomAvailability))
|
||||
|
||||
// Email config
|
||||
mux.HandleFunc("/api/email-config", h.authMiddleware(h.handleEmailConfig))
|
||||
|
||||
// Dashboard stats
|
||||
mux.HandleFunc("/api/dashboard", h.authMiddleware(h.handleDashboard))
|
||||
}
|
||||
|
||||
func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.db.GetUserByUsername(req.Username)
|
||||
if err != nil {
|
||||
http.Error(w, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil || bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)) != nil {
|
||||
http.Error(w, "Invalid credentials", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
token, err := auth.GenerateToken(user.Username, user.IsAdmin)
|
||||
if err != nil {
|
||||
http.Error(w, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"token": token,
|
||||
"user": user.Username,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) handleRefresh(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
http.Error(w, "Missing token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
claims, err := auth.ValidateToken(tokenString)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
newToken, err := auth.GenerateToken(claims.Username, claims.IsAdmin)
|
||||
if err != nil {
|
||||
http.Error(w, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"token": newToken,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) authMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
http.Error(w, "Missing token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
if _, err := auth.ValidateToken(tokenString); err != nil {
|
||||
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Rooms Handler
|
||||
func (h *Handler) handleRooms(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
rooms, err := h.db.GetRooms()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(rooms)
|
||||
|
||||
case http.MethodPost:
|
||||
var room models.Room
|
||||
if err := json.NewDecoder(r.Body).Decode(&room); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if room.Name == "" {
|
||||
http.Error(w, "Name required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := h.db.CreateRoom(&room); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(room)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleRoomDetail(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if it's /api/rooms/:id/tables
|
||||
path := r.URL.Path
|
||||
if strings.HasSuffix(path, "/tables") {
|
||||
h.handleRoomTables(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
idStr := strings.TrimPrefix(path, "/api/rooms/")
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
room, err := h.db.GetRoom(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if room == nil {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(room)
|
||||
|
||||
case http.MethodPut:
|
||||
var room models.Room
|
||||
if err := json.NewDecoder(r.Body).Decode(&room); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
room.ID = id
|
||||
if err := h.db.UpdateRoom(&room); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(room)
|
||||
|
||||
case http.MethodDelete:
|
||||
if err := h.db.DeleteRoom(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// NEW: Room Tables Handler - GET /api/rooms/:id/tables
|
||||
func (h *Handler) handleRoomTables(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
path := r.URL.Path
|
||||
idStr := strings.TrimSuffix(strings.TrimPrefix(path, "/api/rooms/"), "/tables")
|
||||
roomID, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid room ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
tables, err := h.db.GetTablesByRoom(roomID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(tables)
|
||||
} else {
|
||||
// POST - create table for room
|
||||
var table models.Table
|
||||
if err := json.NewDecoder(r.Body).Decode(&table); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
table.RoomID = roomID
|
||||
if table.MaxGuests == 0 {
|
||||
http.Error(w, "Max guests required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := h.db.CreateTable(&table); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(table)
|
||||
}
|
||||
}
|
||||
|
||||
// Tables Handler
|
||||
func (h *Handler) handleTables(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
roomID := r.URL.Query().Get("room_id")
|
||||
var tables []models.Table
|
||||
var err error
|
||||
|
||||
if roomID != "" {
|
||||
rid, _ := strconv.Atoi(roomID)
|
||||
tables, err = h.db.GetTablesByRoom(rid)
|
||||
} else {
|
||||
tables, err = h.db.GetAllTables()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(tables)
|
||||
|
||||
case http.MethodPost:
|
||||
var table models.Table
|
||||
if err := json.NewDecoder(r.Body).Decode(&table); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if table.MaxGuests == 0 {
|
||||
http.Error(w, "Max guests required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := h.db.CreateTable(&table); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(table)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleTableDetail(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := strings.TrimPrefix(r.URL.Path, "/api/tables/")
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
table, err := h.db.GetTable(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if table == nil {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(table)
|
||||
|
||||
case http.MethodPut:
|
||||
var table models.Table
|
||||
if err := json.NewDecoder(r.Body).Decode(&table); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
table.ID = id
|
||||
if err := h.db.UpdateTable(&table); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(table)
|
||||
|
||||
case http.MethodDelete:
|
||||
if err := h.db.DeleteTable(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// Reservations Handler
|
||||
func (h *Handler) handleReservations(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
date := r.URL.Query().Get("date")
|
||||
if date == "" {
|
||||
date = time.Now().Format("2006-01-02")
|
||||
}
|
||||
reservations, err := h.db.GetReservationsByDate(date)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(reservations)
|
||||
|
||||
case http.MethodPost:
|
||||
var res models.Reservation
|
||||
if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check availability
|
||||
available, err := h.db.CheckAvailability(res.TableID, res.Date, res.TimeFrom, res.TimeTo)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !available {
|
||||
http.Error(w, "Table not available at this time", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
// Check table capacity
|
||||
table, err := h.db.GetTable(res.TableID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if table != nil && res.Guests > table.MaxGuests {
|
||||
http.Error(w, "Guest count exceeds table capacity", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Source == "" {
|
||||
res.Source = "manual"
|
||||
}
|
||||
|
||||
if err := h.db.CreateReservation(&res); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(res)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleReservationDetail(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := strings.TrimPrefix(r.URL.Path, "/api/reservations/")
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
res, err := h.db.GetReservation(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if res == nil {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
|
||||
case http.MethodPut:
|
||||
var res models.Reservation
|
||||
if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
res.ID = id
|
||||
if err := h.db.UpdateReservation(&res); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
|
||||
case http.MethodDelete:
|
||||
if err := h.db.DeleteReservation(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleReservationsByDate(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
date := strings.TrimPrefix(r.URL.Path, "/api/reservations/date/")
|
||||
if date == "" {
|
||||
http.Error(w, "Date required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
reservations, err := h.db.GetReservationsByDate(date)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(reservations)
|
||||
}
|
||||
|
||||
// NEW: Room Bookings Handlers
|
||||
func (h *Handler) handleRoomBookings(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
roomID := r.URL.Query().Get("room_id")
|
||||
date := r.URL.Query().Get("date")
|
||||
var bookings []models.RoomBooking
|
||||
var err error
|
||||
|
||||
if roomID != "" {
|
||||
rid, _ := strconv.Atoi(roomID)
|
||||
bookings, err = h.db.GetRoomBookingsByRoom(rid)
|
||||
} else if date != "" {
|
||||
bookings, err = h.db.GetRoomBookingsByDate(date)
|
||||
} else {
|
||||
// Get all bookings for today
|
||||
bookings, err = h.db.GetRoomBookingsByDate(time.Now().Format("2006-01-02"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(bookings)
|
||||
|
||||
case http.MethodPost:
|
||||
var rb models.RoomBooking
|
||||
if err := json.NewDecoder(r.Body).Decode(&rb); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check room availability
|
||||
available, err := h.db.CheckRoomAvailability(rb.RoomID, rb.Date, rb.TimeFrom, rb.TimeTo)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !available {
|
||||
http.Error(w, "Room not available at this time", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
// Check room capacity
|
||||
room, err := h.db.GetRoom(rb.RoomID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if room != nil && rb.Guests > room.Capacity {
|
||||
http.Error(w, "Guest count exceeds room capacity", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if rb.Status == "" {
|
||||
rb.Status = "confirmed"
|
||||
}
|
||||
|
||||
if err := h.db.CreateRoomBooking(&rb); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(rb)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleRoomBookingDetail(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := strings.TrimPrefix(r.URL.Path, "/api/room-bookings/")
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
rb, err := h.db.GetRoomBooking(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if rb == nil {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(rb)
|
||||
|
||||
case http.MethodPut:
|
||||
var rb models.RoomBooking
|
||||
if err := json.NewDecoder(r.Body).Decode(&rb); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
rb.ID = id
|
||||
if err := h.db.UpdateRoomBooking(&rb); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(rb)
|
||||
|
||||
case http.MethodDelete:
|
||||
if err := h.db.DeleteRoomBooking(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// Availability Handler
|
||||
func (h *Handler) handleAvailability(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
date := r.URL.Query().Get("date")
|
||||
if date == "" {
|
||||
date = time.Now().Format("2006-01-02")
|
||||
}
|
||||
|
||||
tables, err := h.db.GetAllTables()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var availability []map[string]interface{}
|
||||
for _, table := range tables {
|
||||
reservations, _ := h.db.GetReservationsByTable(table.ID, date)
|
||||
availability = append(availability, map[string]interface{}{
|
||||
"table_id": table.ID,
|
||||
"table_name": table.RoomName + " - Tisch " + strconv.Itoa(table.ID),
|
||||
"max_guests": table.MaxGuests,
|
||||
"reservations": reservations,
|
||||
})
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(availability)
|
||||
}
|
||||
|
||||
// NEW: Room Availability Handler
|
||||
func (h *Handler) handleRoomAvailability(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
date := r.URL.Query().Get("date")
|
||||
if date == "" {
|
||||
date = time.Now().Format("2006-01-02")
|
||||
}
|
||||
|
||||
rooms, err := h.db.GetRooms()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var availability []map[string]interface{}
|
||||
for _, room := range rooms {
|
||||
bookings, _ := h.db.GetRoomBookingsByRoom(room.ID)
|
||||
availability = append(availability, map[string]interface{}{
|
||||
"room_id": room.ID,
|
||||
"room_name": room.Name,
|
||||
"capacity": room.Capacity,
|
||||
"bookings": bookings,
|
||||
})
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(availability)
|
||||
}
|
||||
|
||||
func (h *Handler) handleMergeTables(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
ParentTableID int `json:"parent_table_id"`
|
||||
ChildTableID int `json:"child_table_id"`
|
||||
MergedName string `json:"merged_name"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
parentTable, err := h.db.GetTable(req.ParentTableID)
|
||||
if err != nil || parentTable == nil {
|
||||
http.Error(w, "Parent table not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
childTable, err := h.db.GetTable(req.ChildTableID)
|
||||
if err != nil || childTable == nil {
|
||||
http.Error(w, "Child table not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if parentTable.RoomID != childTable.RoomID {
|
||||
http.Error(w, "Tables must be in the same room", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
merge := models.TableMerge{
|
||||
ParentTableID: req.ParentTableID,
|
||||
ChildTableID: req.ChildTableID,
|
||||
MergedName: req.MergedName,
|
||||
Active: true,
|
||||
}
|
||||
|
||||
if err := h.db.CreateTableMerge(&merge); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(merge)
|
||||
}
|
||||
|
||||
func (h *Handler) handleEmailConfig(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
cfg, err := h.db.GetEmailConfig()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if cfg != nil {
|
||||
cfg.Password = "***"
|
||||
}
|
||||
json.NewEncoder(w).Encode(cfg)
|
||||
|
||||
case http.MethodPost, http.MethodPut:
|
||||
var cfg models.EmailConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := h.db.SaveEmailConfig(&cfg); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json.NewEncoder(w).Encode(cfg)
|
||||
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
today := time.Now().Format("2006-01-02")
|
||||
totalGuests, _ := h.db.GetTotalGuestsForDate(today)
|
||||
reservations, _ := h.db.GetReservationsByDate(today)
|
||||
roomBookings, _ := h.db.GetRoomBookingsByDate(today)
|
||||
|
||||
dashboard := map[string]interface{}{
|
||||
"today": today,
|
||||
"total_guests": totalGuests,
|
||||
"reservation_count": len(reservations),
|
||||
"room_booking_count": len(roomBookings),
|
||||
"reservations": reservations,
|
||||
"room_bookings": roomBookings,
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(dashboard)
|
||||
}
|
||||
Reference in New Issue
Block a user