184 lines
4.9 KiB
Go
184 lines
4.9 KiB
Go
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"strconv"
|
||
|
|
|
||
|
|
"github.com/patel-mann/poll-system/app/internal/models"
|
||
|
|
"github.com/patel-mann/poll-system/app/internal/utils"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
type User struct {
|
||
|
|
ID int
|
||
|
|
Name string
|
||
|
|
}
|
||
|
|
|
||
|
|
type TeamLead struct {
|
||
|
|
ID int
|
||
|
|
Name string
|
||
|
|
Volunteers []User
|
||
|
|
}
|
||
|
|
|
||
|
|
type TeamBuilderData struct {
|
||
|
|
TeamLeads []TeamLead
|
||
|
|
UnassignedVolunteers []User
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
func TeamBuilderHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
|
// GET request: show team leads and unassigned volunteers
|
||
|
|
if r.Method == http.MethodGet {
|
||
|
|
var teamLeads []TeamLead
|
||
|
|
var unassignedVolunteers []User
|
||
|
|
|
||
|
|
CurrentUserID := models.GetCurrentUserID(w, r)
|
||
|
|
username,_ := models.GetCurrentUserName(r)
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Get all team leads (role_id = 2)
|
||
|
|
tlRows, err := models.DB.Query(`SELECT u.user_id, u.first_name || ' ' || u.last_name AS name
|
||
|
|
FROM users u
|
||
|
|
JOIN admin_volunteers x ON x.volunteer_id = u.user_id
|
||
|
|
WHERE u.role_id = 2 AND x.admin_id = $1`, CurrentUserID)
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Error fetching team leads", http.StatusInternalServerError)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer tlRows.Close()
|
||
|
|
for tlRows.Next() {
|
||
|
|
var tl TeamLead
|
||
|
|
tlRows.Scan(&tl.ID, &tl.Name)
|
||
|
|
|
||
|
|
// Get assigned volunteers for this team lead
|
||
|
|
vRows, _ := models.DB.Query(`SELECT u.user_id, u.first_name || ' ' || u.last_name AS name
|
||
|
|
FROM users u
|
||
|
|
JOIN team t ON u.user_id = t.volunteer_id
|
||
|
|
WHERE t.team_lead_id = $1`, tl.ID)
|
||
|
|
|
||
|
|
for vRows.Next() {
|
||
|
|
var vol User
|
||
|
|
vRows.Scan(&vol.ID, &vol.Name)
|
||
|
|
tl.Volunteers = append(tl.Volunteers, vol)
|
||
|
|
}
|
||
|
|
|
||
|
|
teamLeads = append(teamLeads, tl)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get unassigned volunteers (role_id = 3)
|
||
|
|
vRows, _ := models.DB.Query(`SELECT u.user_id, u.first_name || ' ' || u.last_name AS name
|
||
|
|
FROM users u
|
||
|
|
LEFT JOIN team t ON u.user_id = t.volunteer_id
|
||
|
|
JOIN admin_volunteers x ON x.volunteer_id = u.user_id
|
||
|
|
WHERE u.role_id = 3 AND x.admin_id = $1
|
||
|
|
AND t.volunteer_id IS NULL`, CurrentUserID )
|
||
|
|
for vRows.Next() {
|
||
|
|
var vol User
|
||
|
|
vRows.Scan(&vol.ID, &vol.Name)
|
||
|
|
unassignedVolunteers = append(unassignedVolunteers, vol)
|
||
|
|
}
|
||
|
|
|
||
|
|
utils.Render(w, "volunteer/team_builder.html", map[string]interface{}{
|
||
|
|
"Title": "Team Builder",
|
||
|
|
"IsAuthenticated": true,
|
||
|
|
"ShowAdminNav": true,
|
||
|
|
"TeamLeads": teamLeads,
|
||
|
|
"UserName": username,
|
||
|
|
"UnassignedVolunteers": unassignedVolunteers,
|
||
|
|
"ActiveSection": "team_builder",
|
||
|
|
})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// POST request: assign volunteer to a team lead
|
||
|
|
if r.Method == http.MethodPost {
|
||
|
|
if err := r.ParseForm(); err != nil {
|
||
|
|
http.Error(w, "Invalid form", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
volunteerIDStr := r.FormValue("volunteer_id")
|
||
|
|
teamLeadIDStr := r.FormValue("team_lead_id")
|
||
|
|
|
||
|
|
if volunteerIDStr == "" || teamLeadIDStr == "" {
|
||
|
|
http.Error(w, "Volunteer ID and Team Lead ID are required", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
volunteerID, err := strconv.Atoi(volunteerIDStr)
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Invalid volunteer ID", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
teamLeadID, err := strconv.Atoi(teamLeadIDStr)
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Invalid team lead ID", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Optional: check if volunteer is already assigned
|
||
|
|
var exists int
|
||
|
|
err = models.DB.QueryRow(`SELECT COUNT(*) FROM team WHERE volunteer_id = $1`, volunteerID).Scan(&exists)
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Database error", http.StatusInternalServerError)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if exists > 0 {
|
||
|
|
http.Error(w, "Volunteer is already assigned to a team", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Assign volunteer to team lead
|
||
|
|
_, err = models.DB.Exec(`INSERT INTO team (volunteer_id, team_lead_id) VALUES ($1, $2)`, volunteerID, teamLeadID)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
http.Error(w, "Failed to assign volunteer", http.StatusInternalServerError)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
http.Redirect(w, r, "/team_builder", http.StatusSeeOther)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
func RemoveVolunteerHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if r.Method != http.MethodPost {
|
||
|
|
http.Redirect(w, r, "/team_builder", http.StatusSeeOther)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := r.ParseForm(); err != nil {
|
||
|
|
http.Error(w, "Invalid form", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
volunteerID, err := strconv.Atoi(r.FormValue("volunteer_id"))
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Invalid volunteer ID", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
teamLeadID, err := strconv.Atoi(r.FormValue("team_lead_id"))
|
||
|
|
fmt.Print(teamLeadID)
|
||
|
|
if err != nil {
|
||
|
|
http.Error(w, "Invalid team lead ID", http.StatusBadRequest)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remove volunteer from the team
|
||
|
|
_, err = models.DB.Exec(`DELETE FROM team WHERE team_lead_id = $1 AND volunteer_id = $2`, teamLeadID, volunteerID)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
http.Error(w, "Failed to remove volunteer from team", http.StatusInternalServerError)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
http.Redirect(w, r, "/team_builder", http.StatusSeeOther)
|
||
|
|
}
|
||
|
|
|