Files
Poll-system/app/internal/handlers/volunteer_dashboard.go
Mann Patel b21e76eed0 Update: Few issues to resolve see readme
this push will conclude the majority of pulls. this repos will now, not be actively be managed or any further code pushes will not be frequent.
2025-09-11 16:54:30 -06:00

242 lines
6.3 KiB
Go

// Add this to your handlers package (create volunteer_posts.go or add to existing file)
package handlers
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/patel-mann/poll-system/app/internal/models"
"github.com/patel-mann/poll-system/app/internal/utils"
)
type VolunteerStatistics struct {
AppointmentsToday int
AppointmentsTomorrow int
AppointmentsThisWeek int
TotalAppointments int
PollsCompleted int
PollsRemaining int
LawnSignsRequested int
BannerSignsRequested int
PollCompletionPercent int
}
type TeamMate struct {
UserID int
FullName string
Phone string
Role string
IsLead bool
}
// VolunteerPostsHandler - Dashboard view for volunteers with posts and statistics
func VolunteerPostsHandler(w http.ResponseWriter, r *http.Request) {
// Only allow GET requests for volunteers
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Get user info from context
role := r.Context().Value("user_role").(int)
CurrentUserID := models.GetCurrentUserID(w, r)
username, _ := models.GetCurrentUserName(r)
// Fetch posts from database
rows, err := models.DB.Query(`
SELECT p.post_id, p.author_id, u.first_name || ' ' || u.last_name AS author_name,
p.content, COALESCE(p.image_url, '') as image_url, p.created_at
FROM post p
JOIN users u ON p.author_id = u.user_id
JOIN admin_volunteers x ON u.user_id = x.admin_id
WHERE x.volunteer_id = $1
ORDER BY p.created_at DESC
`, CurrentUserID)
if err != nil {
fmt.Printf("Database query error: %v\n", err)
http.Error(w, "Failed to fetch posts", http.StatusInternalServerError)
return
}
defer rows.Close()
var posts []models.Post
for rows.Next() {
var p models.Post
err := rows.Scan(&p.PostID, &p.AuthorID, &p.AuthorName, &p.Content, &p.ImageURL, &p.CreatedAt)
if err != nil {
fmt.Printf("Row scan error: %v\n", err)
continue
}
posts = append(posts, p)
}
// Add cache busting parameter to image URLs
for i := range posts {
if posts[i].ImageURL != "" {
posts[i].ImageURL += "?t=" + strconv.FormatInt(time.Now().UnixNano(), 10)
}
}
// Fetch teammates
teammatesRows, err := models.DB.Query(`
SELECT u.user_id,
u.first_name || ' ' || u.last_name AS full_name,
COALESCE(u.phone, '') AS phone,
r.name AS role
FROM users u
JOIN role r ON u.role_id = r.role_id
JOIN team tm ON u.user_id = tm.volunteer_id OR u.user_id = tm.team_lead_id
WHERE tm.team_id = (
SELECT team_id
FROM team
WHERE volunteer_id = $1 or team_lead_id = $2
)
ORDER BY CASE WHEN r.name = 'team_lead' THEN 0 ELSE 1 END, u.first_name;
`, CurrentUserID, CurrentUserID)
if err != nil {
fmt.Printf("Database query error (teammates): %v\n", err)
}
defer teammatesRows.Close()
var teammates []TeamMate
for teammatesRows.Next() {
var t TeamMate
if err := teammatesRows.Scan(&t.UserID, &t.FullName, &t.Phone, &t.Role); err != nil {
fmt.Printf("Row scan error (teammates): %v\n", err)
continue
}
teammates = append(teammates, t)
}
// Get volunteer statistics
stats, err := getVolunteerStatistics(CurrentUserID)
if err != nil {
fmt.Printf("Failed to fetch statistics: %v\n", err)
// Continue with empty stats rather than failing
stats = &VolunteerStatistics{}
}
// Get navigation flags
showAdminNav, showVolunteerNav := getNavFlags(role)
fmt.Printf("Volunteer viewing %d posts\n", len(posts))
utils.Render(w, "volunteer_dashboard.html", map[string]interface{}{
"Title": "Volunteer Dashboard",
"IsAuthenticated": true,
"ShowAdminNav": showAdminNav,
"ShowVolunteerNav": showVolunteerNav,
"UserName": username,
"Posts": posts,
"Statistics": stats,
"Teammates": teammates,
"ActiveSection": "dashboard",
"IsVolunteer": true,
})
}
func getVolunteerStatistics(userID int) (*VolunteerStatistics, error) {
stats := &VolunteerStatistics{}
today := time.Now().Format("2006-01-02")
// Get start of current week (Monday)
now := time.Now()
oneDayLater := now.Add(time.Hour * 12)
weekday := now.Weekday()
if weekday == time.Sunday {
weekday = 7
}
// Get start of the week (Monday)
weekStart := now.AddDate(0, 0, -int(weekday)+1)
// Get end of the week (Sunday)
weekEnd := weekStart.AddDate(0, 0, 6)
fmt.Println("Week Start:", weekStart.Format("2006-01-02"))
fmt.Println("Week End:", weekEnd.Format("2006-01-02"))
// Appointments today
err := models.DB.QueryRow(`
SELECT COUNT(*)
FROM appointment
WHERE user_id = $1 AND DATE(appointment_date) = $2
`, userID, today).Scan(&stats.AppointmentsToday)
if err != nil {
return nil, err
}
// Appointments tomorrow
err = models.DB.QueryRow(`
SELECT COUNT(*)
FROM appointment
WHERE user_id = $1 AND DATE(appointment_date) = $2
`, userID, oneDayLater).Scan(&stats.AppointmentsTomorrow)
if err != nil {
return nil, err
}
// Appointments this week
err = models.DB.QueryRow(`
SELECT COUNT(*)
FROM appointment
WHERE user_id = $1 AND DATE(appointment_date) >= $2 AND DATE(appointment_date) <= $3
`, userID, weekStart, weekEnd).Scan(&stats.AppointmentsThisWeek)
if err != nil {
return nil, err
}
// Total appointments
err = models.DB.QueryRow(`
SELECT COUNT(*)
FROM appointment
WHERE user_id = $1
`, userID).Scan(&stats.TotalAppointments)
if err != nil {
return nil, err
}
// Polls completed
err = models.DB.QueryRow(`
SELECT COUNT(DISTINCT pr.poll_response_id)
FROM poll p
JOIN poll_response pr ON p.poll_id = pr.poll_id
WHERE p.user_id = $1
`, userID).Scan(&stats.PollsCompleted)
if err != nil {
return nil, err
}
// Polls remaining (appointments without poll responses)
stats.PollsRemaining = stats.TotalAppointments - stats.PollsCompleted
fmt.Print(stats.PollsRemaining)
// Calculate completion percentage
if stats.TotalAppointments > 0 {
stats.PollCompletionPercent = (stats.PollsCompleted * 100) / stats.TotalAppointments
} else {
stats.PollCompletionPercent = 0
}
// Signs requested
err = models.DB.QueryRow(`
SELECT
COALESCE(SUM(pr.question3_lawn_signs), 0),
COALESCE(SUM(pr.question4_banner_signs), 0)
FROM poll p
JOIN poll_response pr ON p.poll_id = pr.poll_id
WHERE p.user_id = $1
`, userID).Scan(&stats.LawnSignsRequested, &stats.BannerSignsRequested)
if err != nil {
return nil, err
}
return stats, nil
}