NextReceipt/internal/handlers/dashboard.go
cclohmar f0c576c543 feat: transform NextExpense into NextReceipt — receipt saver for warranty & returns
- Replace events+expenses with flat purchases table
- Add warranty_months, return_days, product_name fields
- Remove currency conversion, CSV/PDF reporting, event filing
- Simplify auth (no onboarding/department/profile)
- Update AI extraction prompts for product/warranty info
- Update all branding: templates, install.sh, Makefile, service file
2026-06-21 18:57:29 +00:00

68 lines
2.1 KiB
Go

// Package handlers provides HTTP request handlers for NextReceipt.
//
// This file implements the dashboard handler showing all purchases
// for the authenticated user.
package handlers
import (
"database/sql"
"log"
"net/http"
"time"
"github.com/cclohmar/NextReceipt/internal/database"
)
// ---------------------------------------------------------------------------
// DashboardHandler
// ---------------------------------------------------------------------------
// DashboardHandler groups HTTP handlers related to the main dashboard view.
type DashboardHandler struct {
DB *sql.DB
}
// NewDashboardHandler creates a new DashboardHandler with the given database handle.
func NewDashboardHandler(db *sql.DB) *DashboardHandler {
return &DashboardHandler{DB: db}
}
// ---------------------------------------------------------------------------
// GET /dashboard — Dashboard
// ---------------------------------------------------------------------------
// Dashboard renders the main dashboard page showing all purchases belonging
// to the authenticated user, along with the receipt upload controls.
func (h *DashboardHandler) Dashboard(w http.ResponseWriter, r *http.Request) {
userID := getUserID(r)
if userID == "" {
log.Printf("ERROR [%s] handlers: Dashboard: missing user ID", time.Now().Format(time.RFC3339))
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
purchases, err := database.GetPurchasesByUser(h.DB, userID)
if err != nil {
log.Printf("ERROR [%s] handlers: Dashboard: GetPurchasesByUser: %v",
time.Now().Format(time.RFC3339), err)
http.Error(w, "Failed to load purchases", http.StatusInternalServerError)
return
}
// Normalize ImagePath for all purchases.
for i := range purchases {
purchases[i].ImagePath = normalizeImagePath(purchases[i].ImagePath)
}
tmpl := getTemplate("dashboard.html")
data := map[string]interface{}{
"Purchases": purchases,
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.Execute(w, data); err != nil {
log.Printf("ERROR [%s] handlers: Dashboard: execute template: %v",
time.Now().Format(time.RFC3339), err)
}
}