CSV Import is now working
This commit is contained in:
240
app/internal/handlers/volunteer_dashboard.go
Normal file
240
app/internal/handlers/volunteer_dashboard.go
Normal file
@@ -0,0 +1,240 @@
|
||||
// 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, "dashboard/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
|
||||
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user