package api import ( "fmt" "log" "net/http" "sprintpadawan/lib" ) func handleNewStoryForm(w http.ResponseWriter, r *http.Request) { roomID, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } room, err := lib.GetRoomByID(roomID) if err != nil { http.Error(w, "room not found", http.StatusNotFound) return } renderTemplate(w, "story_form.html", room) } func handleAddStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) title := r.FormValue("title") if _, err := lib.CreateStory(id, title); err != nil { log.Printf("create story error: %v", err) http.Error(w, "failed to create story", http.StatusInternalServerError) return } broadcast(id, "stories") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleSetActiveStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getFormInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.SetActiveStory(id, sid); err != nil { http.Error(w, "failed to set active story", http.StatusInternalServerError) return } broadcast(id, "stories") broadcast(id, "members") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleResetStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getPathInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.UnrevealStory(sid); err != nil { http.Error(w, "failed to reset story", http.StatusInternalServerError) return } if err := lib.ClearVotesForStory(sid); err != nil { http.Error(w, "failed to clear votes", http.StatusInternalServerError) return } broadcast(id, "stories") broadcast(id, "members") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleVote(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) value := r.FormValue("value") sid, err := getFormInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.VoteOnStory(sid, user.ID, value); err != nil { http.Error(w, "failed to vote", http.StatusInternalServerError) return } broadcast(id, "members") story, storyErr := lib.GetStoryByID(sid) if storyErr == nil && story.Voted { broadcast(id, "stories") } if isHTMX(r) { if storyErr != nil { http.Error(w, "story not found", http.StatusNotFound) return } room, err := lib.GetRoomByID(id) if err != nil { http.Error(w, "room not found", http.StatusNotFound) return } tmplData := struct { RoomID int Story lib.Story Scale string UserVote string }{ RoomID: id, Story: *story, Scale: room.Scale, UserVote: value, } renderTemplate(w, "vote_form.html", tmplData) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleReveal(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getFormInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.RevealVotes(sid); err != nil { http.Error(w, "failed to reveal votes", http.StatusInternalServerError) return } broadcast(id, "stories") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleUnrevealStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getPathInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.UnrevealStory(sid); err != nil { http.Error(w, "failed to hide votes", http.StatusInternalServerError) return } broadcast(id, "stories") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleEditStoryForm(w http.ResponseWriter, r *http.Request) { roomID, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } storyID, err := getPathInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } story, err := lib.GetStoryByID(storyID) if err != nil { http.Error(w, "story not found", http.StatusNotFound) return } data := struct { RoomID int Story lib.Story }{ RoomID: roomID, Story: *story, } renderTemplate(w, "story_edit.html", data) } func handleRenameStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getPathInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } title := r.FormValue("title") if err := lib.RenameStory(sid, title); err != nil { http.Error(w, "failed to rename story", http.StatusInternalServerError) return } broadcast(id, "stories") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) } func handleDeleteStory(w http.ResponseWriter, r *http.Request) { id, err := getRoomID(r) if err != nil { http.Error(w, "invalid room id", http.StatusBadRequest) return } user := r.Context().Value(userKey).(*lib.User) sid, err := getPathInt(r, "story_id") if err != nil { http.Error(w, "invalid story id", http.StatusBadRequest) return } if err := lib.DeleteStory(sid); err != nil { http.Error(w, "failed to delete story", http.StatusInternalServerError) return } broadcast(id, "stories") if isHTMX(r) { renderRoomStories(w, id, user) return } http.Redirect(w, r, fmt.Sprintf("/rooms/%d", id), http.StatusSeeOther) }