2025-09-05 15:39:06 -06:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
2025-09-11 16:54:30 -06:00
|
|
|
"database/sql"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
2025-09-09 10:42:24 -06:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/patel-mann/poll-system/app/internal/models"
|
2025-09-11 16:54:30 -06:00
|
|
|
"github.com/patel-mann/poll-system/app/internal/utils"
|
2025-09-05 15:39:06 -06:00
|
|
|
)
|
|
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
/////////////////////
|
|
|
|
|
// Core Validation //
|
|
|
|
|
/////////////////////
|
2025-09-09 10:42:24 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
// ValidateAvailability checks if a user is available at a specific time
|
|
|
|
|
func ValidateAvailability(checkDate time.Time, checkTime time.Time, userID int) bool {
|
|
|
|
|
var startTime, endTime time.Time
|
|
|
|
|
day := checkDate.Format("2006-01-02")
|
2025-09-09 10:42:24 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
err := models.DB.QueryRow(`
|
|
|
|
|
SELECT start_time, end_time
|
|
|
|
|
FROM availability
|
|
|
|
|
WHERE user_id = $1 AND day_of_week = $2`,
|
|
|
|
|
userID, day).Scan(&startTime, &endTime)
|
2025-09-09 10:42:24 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
if err != nil {
|
|
|
|
|
if err != sql.ErrNoRows {
|
|
|
|
|
log.Printf("DB error in ValidateAvailability: %v", err)
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return checkTime.After(startTime) && checkTime.Before(endTime)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////
|
|
|
|
|
// Volunteer CRUD //
|
|
|
|
|
////////////////////
|
|
|
|
|
|
|
|
|
|
// View volunteer availability
|
|
|
|
|
func VolunteerGetAvailabilityHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
userID := models.GetCurrentUserID(w, r)
|
|
|
|
|
username, _ := models.GetCurrentUserName(r)
|
|
|
|
|
role, _ := r.Context().Value("user_role").(int)
|
2025-09-09 10:42:24 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
rows, err := models.DB.Query(`
|
|
|
|
|
SELECT availability_id, day_of_week, start_time, end_time, created_at
|
|
|
|
|
FROM availability
|
|
|
|
|
WHERE user_id = $1
|
|
|
|
|
ORDER BY day_of_week DESC`, userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println("Error fetching availability:", err)
|
|
|
|
|
http.Error(w, "Database error", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
|
|
var availability []models.Availability
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var a models.Availability
|
|
|
|
|
if err := rows.Scan(&a.AvailabilityID, &a.DayOfWeek, &a.StartTime, &a.EndTime, &a.CreatedAt); err != nil {
|
|
|
|
|
log.Println("Row scan error:", err)
|
|
|
|
|
continue
|
2025-09-09 10:42:24 -06:00
|
|
|
}
|
2025-09-11 16:54:30 -06:00
|
|
|
availability = append(availability, a)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utils.Render(w, "volunteer_schedule.html", map[string]interface{}{
|
|
|
|
|
"Title": "My Schedule",
|
|
|
|
|
"ShowVolunteerNav": true,
|
|
|
|
|
"IsVolunteer": true,
|
|
|
|
|
"IsAuthenticated": true,
|
|
|
|
|
"Availability": availability,
|
|
|
|
|
"UserName": username,
|
|
|
|
|
"Role": role,
|
|
|
|
|
"ActiveSection": "schedule",
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add or update schedule
|
|
|
|
|
func VolunteerPostScheduleHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Redirect(w, r, "/volunteer/schedule", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userID := models.GetCurrentUserID(w, r)
|
|
|
|
|
day := r.FormValue("day")
|
|
|
|
|
start := r.FormValue("start_time")
|
|
|
|
|
end := r.FormValue("end_time")
|
|
|
|
|
|
|
|
|
|
if day == "" || start == "" || end == "" {
|
|
|
|
|
http.Error(w, "All fields required", http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := models.DB.Exec(`
|
|
|
|
|
INSERT INTO availability (user_id, day_of_week, start_time, end_time, created_at)
|
|
|
|
|
VALUES ($1, $2, $3, $4, NOW())
|
|
|
|
|
ON CONFLICT (user_id, day_of_week)
|
|
|
|
|
DO UPDATE SET start_time = $3, end_time = $4`,
|
|
|
|
|
userID, day, start, end)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println("Insert availability error:", err)
|
|
|
|
|
http.Error(w, "Could not save schedule", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
http.Redirect(w, r, "/volunteer/schedule", http.StatusSeeOther)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete schedule
|
|
|
|
|
func VolunteerDeleteScheduleHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userID := models.GetCurrentUserID(w, r)
|
|
|
|
|
idStr := r.FormValue("id")
|
|
|
|
|
|
|
|
|
|
_, err := models.DB.Exec(`DELETE FROM availability WHERE availability_id = $1 AND user_id = $2`, idStr, userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println("Delete availability error:", err)
|
|
|
|
|
http.Error(w, "Could not delete schedule", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-09-05 15:39:06 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
http.Redirect(w, r, "/volunteer/schedule", http.StatusSeeOther)
|
2025-09-05 15:39:06 -06:00
|
|
|
}
|