package httpapi import ( "net/http" "strconv" "time" "spin/internal/models" ) // handleDashboard returns a role-tailored summary. Members get their own work / // incentive / project snapshot; admins additionally get company-wide widgets. func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) { email := s.email(r) year := time.Now().Year() out := map[string]interface{}{"isAdmin": s.isAdmin(r), "year": year} // my projects count out["myProjects"] = len(s.myProjectIDs(email)) // my applied incentive points this year var myPoints float64 s.db.Model(&models.UserIncentive{}). Where("lower(member_email) = ? AND year = ? AND (fix_status = ? OR fix_status = ?)", email, year, models.FixApplied, models.FixPaid). Select("COALESCE(SUM(points),0)").Scan(&myPoints) out["myPoints"] = myPoints // my pending requests var myPending int64 s.db.Model(&models.LeaveRequest{}).Where("lower(member_email) = ? AND status = ?", email, models.StatusPending).Count(&myPending) out["myPendingRequests"] = myPending if s.isAdmin(r) { var pendingLeave, pendingOT, activeProjects int64 s.db.Model(&models.LeaveRequest{}).Where("status = ?", models.StatusPending).Count(&pendingLeave) s.db.Model(&models.OvertimeRequest{}).Where("status = ?", models.StatusPending).Count(&pendingOT) s.db.Model(&models.Project{}).Where("status = ?", "active").Count(&activeProjects) out["pendingApprovals"] = pendingLeave + pendingOT out["activeProjects"] = activeProjects // cash position this year var cashIn, cashOut float64 yr := strconv.Itoa(year) s.db.Model(&models.Transaction{}).Where("date LIKE ? AND kind = ?", yr+"%", models.TxnIncome). Select("COALESCE(SUM(amount),0)").Scan(&cashIn) s.db.Model(&models.Transaction{}).Where("date LIKE ? AND kind <> ?", yr+"%", models.TxnIncome). Select("COALESCE(SUM(ABS(amount)),0)").Scan(&cashOut) out["cashIn"] = cashIn out["cashOut"] = cashOut out["cashNet"] = cashIn - cashOut // upcoming payment splits (expected, unpaid) var upcoming []models.PaymentSplit s.db.Where("paid = ? AND expected_date <> ''", false).Order("expected_date asc").Limit(8).Find(&upcoming) out["upcomingPayments"] = upcoming } writeJSON(w, http.StatusOK, out) }