161 lines
4.3 KiB
Go
161 lines
4.3 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
type availabilitySlot struct {
|
|
DayOfWeek string `json:"day_of_week"`
|
|
StartTime string `json:"start_time"` // HH:MM
|
|
EndTime string `json:"end_time"` // HH:MM
|
|
}
|
|
|
|
func (h *Handler) GetMyAvailability(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := middleware.UserIDFromContext(r.Context())
|
|
if !ok {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
serverID := r.URL.Query().Get("server_id")
|
|
if serverID == "" {
|
|
http.Error(w, "server_id query param required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
rows, err := h.db.Query(
|
|
`SELECT day_of_week, start_time, end_time FROM availability
|
|
WHERE user_id = $1 AND server_id = $2
|
|
ORDER BY array_position(ARRAY['monday','tuesday','wednesday','thursday','friday','saturday','sunday'], day_of_week), start_time`,
|
|
userID, serverID,
|
|
)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
var slots []availabilitySlot
|
|
for rows.Next() {
|
|
var s availabilitySlot
|
|
var st, et time.Time
|
|
if err := rows.Scan(&s.DayOfWeek, &st, &et); err != nil {
|
|
continue
|
|
}
|
|
s.StartTime = st.Format("15:04")
|
|
s.EndTime = et.Format("15:04")
|
|
slots = append(slots, s)
|
|
}
|
|
if slots == nil {
|
|
slots = []availabilitySlot{}
|
|
}
|
|
json.NewEncoder(w).Encode(slots)
|
|
}
|
|
|
|
func (h *Handler) PutMyAvailability(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := middleware.UserIDFromContext(r.Context())
|
|
if !ok {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
serverID := r.URL.Query().Get("server_id")
|
|
if serverID == "" {
|
|
http.Error(w, "server_id query param required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var slots []availabilitySlot
|
|
if err := json.NewDecoder(r.Body).Decode(&slots); err != nil {
|
|
http.Error(w, "invalid json", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
tx, err := h.db.Begin()
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
if _, err := tx.Exec(`DELETE FROM availability WHERE user_id = $1 AND server_id = $2`, userID, serverID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
for _, s := range slots {
|
|
_, err := tx.Exec(
|
|
`INSERT INTO availability (user_id, server_id, day_of_week, start_time, end_time) VALUES ($1,$2,$3,$4::time,$5::time)`,
|
|
userID, serverID, s.DayOfWeek, s.StartTime, s.EndTime,
|
|
)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(slots)
|
|
}
|
|
|
|
// GetServerAvailability returns all members' availability for a server, aggregated by user.
|
|
func (h *Handler) GetServerAvailability(w http.ResponseWriter, r *http.Request) {
|
|
serverID := chi.URLParam(r, "serverID")
|
|
|
|
rows, err := h.db.Query(
|
|
`SELECT a.user_id, u.display_name, a.day_of_week, a.start_time, a.end_time
|
|
FROM availability a
|
|
JOIN users u ON u.id = a.user_id
|
|
WHERE a.server_id = $1
|
|
ORDER BY u.display_name, array_position(ARRAY['monday','tuesday','wednesday','thursday','friday','saturday','sunday'], a.day_of_week), a.start_time`,
|
|
serverID,
|
|
)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
type slot struct {
|
|
DayOfWeek string `json:"day_of_week"`
|
|
StartTime string `json:"start_time"`
|
|
EndTime string `json:"end_time"`
|
|
}
|
|
type userAvail struct {
|
|
UserID string `json:"user_id"`
|
|
Username string `json:"username"`
|
|
Slots []slot `json:"slots"`
|
|
}
|
|
|
|
userMap := make(map[string]*userAvail)
|
|
for rows.Next() {
|
|
var uid, uname, dow string
|
|
var st, et time.Time
|
|
if err := rows.Scan(&uid, &uname, &dow, &st, &et); err != nil {
|
|
continue
|
|
}
|
|
ua, ok := userMap[uid]
|
|
if !ok {
|
|
ua = &userAvail{UserID: uid, Username: uname}
|
|
userMap[uid] = ua
|
|
}
|
|
ua.Slots = append(ua.Slots, slot{DayOfWeek: dow, StartTime: st.Format("15:04"), EndTime: et.Format("15:04")})
|
|
}
|
|
|
|
result := make([]userAvail, 0, len(userMap))
|
|
for _, ua := range userMap {
|
|
result = append(result, *ua)
|
|
}
|
|
if result == nil {
|
|
result = []userAvail{}
|
|
}
|
|
json.NewEncoder(w).Encode(result)
|
|
} |