package handlers import ( "encoding/json" "net/http" "github.com/go-chi/chi/v5" ) func (app *App) HandleAdminMenu(w http.ResponseWriter, r *http.Request) { var in struct { Action string `json:"action"` ID int `json:"id"` Name string `json:"name"` Category string `json:"category"` } if err := json.NewDecoder(r.Body).Decode(&in); err != nil { http.Error(w, "invalid request", http.StatusBadRequest) return } switch in.Action { case "add": _, err := app.DB.Exec("INSERT INTO menu_items (category, name) VALUES (?, ?)", in.Category, in.Name) if err != nil { http.Error(w, err.Error(), 500) return } case "update": _, err := app.DB.Exec("UPDATE menu_items SET name = ? WHERE id = ?", in.Name, in.ID) if err != nil { http.Error(w, err.Error(), 500) return } case "delete": _, err := app.DB.Exec("DELETE FROM menu_items WHERE id = ?", in.ID) if err != nil { http.Error(w, err.Error(), 500) return } } // return updated menu rows, _ := app.DB.Query("SELECT id, category, name FROM menu_items ORDER BY id ASC") defer rows.Close() var items []map[string]any for rows.Next() { var id int var category, name string rows.Scan(&id, &category, &name) items = append(items, map[string]any{"id": id, "category": category, "name": name}) } writeJSON(w, items) } func (app *App) HandleAdminUpdateOrderStatus(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") var in struct { Status string `json:"status"` } if err := json.NewDecoder(r.Body).Decode(&in); err != nil { http.Error(w, "invalid request", http.StatusBadRequest) return } _, err := app.DB.Exec("UPDATE orders SET status = ? WHERE id = ?", in.Status, id) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } switch in.Status { case "history": // If status is history -> send deleted event msg := map[string]any{"id": id, "status": "history", "event": "deleted"} if data, err := json.Marshal(msg); err == nil { app.Broker.broadcast <- data } case "active": // If status is active -> send new order var o Order row := app.DB.QueryRow("SELECT id, username, soup, main, side, created_at, status FROM orders WHERE id = ?", id) if err := row.Scan(&o.ID, &o.Username, &o.Soup, &o.Main, &o.Side, &o.CreatedAt, &o.Status); err == nil { if data, err := json.Marshal(o); err == nil { app.Broker.broadcast <- data } } } writeJSON(w, map[string]string{"status": "ok"}) } func (app *App) HandleAdminDeleteOrder(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") // Step 1: set to history (so user views update immediately) _, _ = app.DB.Exec("UPDATE orders SET status = 'history' WHERE id = ?", id) // Step 2: broadcast history update msg := map[string]any{"id": id, "status": "history", "event": "deleted"} if data, err := json.Marshal(msg); err == nil { app.Broker.broadcast <- data } // Step 3: hard delete from DB _, err := app.DB.Exec("DELETE FROM orders WHERE id = ?", id) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } writeJSON(w, map[string]string{"status": "deleted"}) } func (app *App) HandleGetUsers(w http.ResponseWriter, r *http.Request) { rows, err := app.DB.Query("SELECT id, username, role FROM users ORDER BY id") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer rows.Close() var users []map[string]any for rows.Next() { var id, role int var username string rows.Scan(&id, &username, &role) users = append(users, map[string]any{"id": id, "username": username, "role": role}) } writeJSON(w, users) } func (app *App) HandleUpdateUser(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") var req struct { Username string `json:"username"` Password string `json:"password"` Role *int `json:"role"` // pointer = optional } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "invalid request", http.StatusBadRequest) return } if req.Username == "" && req.Password == "" && req.Role == nil { http.Error(w, "nothing to update", http.StatusBadRequest) return } // build dynamic UPDATE query := "UPDATE users SET " args := []any{} first := true if req.Username != "" { if !first { query += ", " } first = false query += "username = ?" args = append(args, req.Username) } if req.Password != "" { if !first { query += ", " } first = false query += "password = ?" args = append(args, req.Password) } if req.Role != nil { if !first { query += ", " } first = false query += "role = ?" args = append(args, *req.Role) } query += " WHERE id = ?" args = append(args, id) res, err := app.DB.Exec(query, args...) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if n, _ := res.RowsAffected(); n == 0 { http.Error(w, "user not found", http.StatusNotFound) return } writeJSON(w, map[string]string{"status": "updated"}) } func (app *App) HandleDeleteUser(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") res, err := app.DB.Exec("DELETE FROM users WHERE id = ?", id) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } n, _ := res.RowsAffected() if n == 0 { http.Error(w, "user not found", http.StatusNotFound) return } writeJSON(w, map[string]string{"status": "deleted"}) } func (app *App) HandleGetAllOrders(w http.ResponseWriter, r *http.Request) { rows, err := app.DB.Query("SELECT id, username, soup, main, side, created_at, status FROM orders ORDER BY id DESC") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer rows.Close() var out []Order for rows.Next() { var o Order if err := rows.Scan(&o.ID, &o.Username, &o.Soup, &o.Main, &o.Side, &o.CreatedAt, &o.Status); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } out = append(out, o) } writeJSON(w, out) }