chore: add Close Event button + cleanup download tokens on reopen
This commit is contained in:
parent
5aa5523e8b
commit
5e66e849fc
3 changed files with 63 additions and 0 deletions
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -182,11 +184,58 @@ func (h *EventHandler) ReopenEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up any stale download packages — user must regenerate after reopening.
|
||||||
|
if oldFiles, err := database.DeleteDownloadTokensByEvent(h.DB, eventID); err == nil {
|
||||||
|
for _, fn := range oldFiles {
|
||||||
|
os.Remove(filepath.Join("storage", "postbox", fn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect to dashboard so the full page renders with updated status.
|
// Redirect to dashboard so the full page renders with updated status.
|
||||||
w.Header().Set("HX-Redirect", "/dashboard")
|
w.Header().Set("HX-Redirect", "/dashboard")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// POST /events/{id}/close — CloseEvent
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CloseEvent sets an event's status to "closed". Only the event owner may
|
||||||
|
// close it. On success, redirects to the dashboard.
|
||||||
|
func (h *EventHandler) CloseEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
|
eventID := chi.URLParam(r, "id")
|
||||||
|
if eventID == "" {
|
||||||
|
http.Error(w, "Missing event ID", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userID := getUserID(r)
|
||||||
|
if userID == "" {
|
||||||
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event, err := database.GetEventByID(h.DB, eventID)
|
||||||
|
if err != nil || event == nil {
|
||||||
|
http.Error(w, "Event not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if event.UserID != userID {
|
||||||
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.UpdateEventStatus(h.DB, eventID, "closed"); err != nil {
|
||||||
|
log.Printf("ERROR [%s] handlers: CloseEvent: UpdateEventStatus(%s): %v",
|
||||||
|
time.Now().Format(time.RFC3339), eventID, err)
|
||||||
|
http.Error(w, "Failed to close event", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("HX-Redirect", "/dashboard")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// GET /events/{id}/expenses — ViewEventExpenses
|
// GET /events/{id}/expenses — ViewEventExpenses
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
1
main.go
1
main.go
|
|
@ -218,6 +218,7 @@ func main() {
|
||||||
r.Get("/events/{id}/edit", eventHandler.EditEvent)
|
r.Get("/events/{id}/edit", eventHandler.EditEvent)
|
||||||
r.Delete("/events/{id}", eventHandler.DeleteEvent)
|
r.Delete("/events/{id}", eventHandler.DeleteEvent)
|
||||||
r.Put("/events/{id}/reopen", eventHandler.ReopenEvent)
|
r.Put("/events/{id}/reopen", eventHandler.ReopenEvent)
|
||||||
|
r.Post("/events/{id}/close", eventHandler.CloseEvent)
|
||||||
r.Get("/events/{id}/expenses", eventHandler.ViewEventExpenses)
|
r.Get("/events/{id}/expenses", eventHandler.ViewEventExpenses)
|
||||||
|
|
||||||
// Expenses.
|
// Expenses.
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,19 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
<!-- Close (only if open) -->
|
||||||
|
{{if eq .Event.Status "open"}}
|
||||||
|
<div style="margin-top: 1.5rem; text-align: center;">
|
||||||
|
<button class="btn btn-secondary" style="color: #fca5a5; border-color: #7f1d1d;"
|
||||||
|
hx-post="/events/{{.Event.ID}}/close"
|
||||||
|
hx-target="body"
|
||||||
|
hx-push-url="true"
|
||||||
|
onclick="return confirm('Close this event? You can reopen it later.')">
|
||||||
|
Close Event
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<!-- Reopen (only if closed) -->
|
<!-- Reopen (only if closed) -->
|
||||||
{{if eq .Event.Status "closed"}}
|
{{if eq .Event.Status "closed"}}
|
||||||
<div style="margin-top: 2rem; text-align: center;">
|
<div style="margin-top: 2rem; text-align: center;">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue