admin core func done

This commit is contained in:
Mann Patel
2025-08-27 13:21:11 -06:00
parent 9148f011ad
commit 6edd4ee030
29 changed files with 2152 additions and 1139 deletions

View File

@@ -31,33 +31,37 @@ type PageNumber struct {
IsCurrent bool
}
// AddressWithDetails extends AddressDatabase with appointment and user info
type AddressWithDetails struct {
models.AddressDatabase
UserName string
UserEmail string
AppointmentDate string
AppointmentTime string
}
func AddressHandler(w http.ResponseWriter, r *http.Request) {
// Get pagination parameters from query string
pageStr := r.URL.Query().Get("page")
pageSizeStr := r.URL.Query().Get("pageSize")
username,_ := models.GetCurrentUserName(r)
// Default values
page := 1
pageSize := 20 // Default page size
// Parse page number
pageSize := 20
if pageStr != "" {
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
page = p
}
}
// Parse page size
if pageSizeStr != "" {
if ps, err := strconv.Atoi(pageSizeStr); err == nil && ps > 0 && ps <= 100 {
pageSize = ps
}
}
// Calculate offset
offset := (page - 1) * pageSize
// Get total count first
// Get total count
var totalRecords int
err := models.DB.QueryRow(`SELECT COUNT(*) FROM "address_database"`).Scan(&totalRecords)
if err != nil {
@@ -65,27 +69,43 @@ func AddressHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Database error", http.StatusInternalServerError)
return
}
// Calculate pagination info
totalPages := (totalRecords + pageSize - 1) / pageSize
if totalPages == 0 {
totalPages = 1
}
// Ensure current page is within bounds
if page > totalPages {
page = totalPages
offset = (page - 1) * pageSize
}
// Get paginated results
// Query addresses with appointment + user info
rows, err := models.DB.Query(`
SELECT address_id, address, street_name, street_type,
street_quadrant, house_number, house_alpha, longitude,
latitude, visited_validated
FROM "address_database"
WHERE street_quadrant = 'ne'
ORDER BY address_id
SELECT
a.address_id,
a.address,
a.street_name,
a.street_type,
a.street_quadrant,
a.house_number,
COALESCE(a.house_alpha, '') as house_alpha,
a.longitude,
a.latitude,
a.visited_validated,
a.created_at,
a.updated_at,
CASE
WHEN ap.sched_id IS NOT NULL THEN true
ELSE false
END as assigned,
COALESCE(u.first_name || ' ' || u.last_name, '') as user_name,
COALESCE(u.email, '') as user_email,
COALESCE(ap.appointment_date::text, '') as appointment_date,
COALESCE(ap.appointment_time::text, '') as appointment_time
FROM address_database a
LEFT JOIN appointment ap ON a.address_id = ap.address_id
LEFT JOIN users u ON ap.user_id = u.user_id
WHERE a.street_quadrant = 'ne'
ORDER BY a.address_id
LIMIT $1 OFFSET $2
`, pageSize, offset)
if err != nil {
@@ -95,9 +115,10 @@ func AddressHandler(w http.ResponseWriter, r *http.Request) {
}
defer rows.Close()
var addresses []models.AddressDatabase
var addresses []AddressWithDetails
for rows.Next() {
var a models.AddressDatabase
var a AddressWithDetails
var houseAlpha string
err := rows.Scan(
&a.AddressID,
&a.Address,
@@ -105,28 +126,68 @@ func AddressHandler(w http.ResponseWriter, r *http.Request) {
&a.StreetType,
&a.StreetQuadrant,
&a.HouseNumber,
&a.HouseAlpha,
&houseAlpha,
&a.Longitude,
&a.Latitude,
&a.VisitedValidated,
&a.CreatedAt,
&a.UpdatedAt,
&a.Assigned,
&a.UserName,
&a.UserEmail,
&a.AppointmentDate,
&a.AppointmentTime,
)
if err != nil {
log.Println("Scan error:", err)
continue
}
// Handle nullable house_alpha
if houseAlpha != "" {
a.HouseAlpha = &houseAlpha
}
addresses = append(addresses, a)
}
// Calculate start and end record numbers for display
// Get users associated with this admin
currentAdminID := r.Context().Value("user_id").(int)
userRows, err := models.DB.Query(`
SELECT u.user_id, u.first_name || ' ' || u.last_name AS name
FROM users u
JOIN admin_volunteers av ON u.user_id = av.volunteer_id
WHERE av.admin_id = $1 AND av.is_active = true
`, currentAdminID)
if err != nil {
log.Println("Failed to fetch users:", err)
http.Error(w, "Database error", http.StatusInternalServerError)
return
}
defer userRows.Close()
type UserOption struct {
ID int
Name string
}
var users []UserOption
for userRows.Next() {
var u UserOption
if err := userRows.Scan(&u.ID, &u.Name); err != nil {
log.Println("User scan error:", err)
continue
}
users = append(users, u)
}
// Pagination info
startRecord := offset + 1
endRecord := offset + len(addresses)
if totalRecords == 0 {
startRecord = 0
}
// Generate page numbers for pagination controls
pageNumbers := generatePageNumbers(page, totalPages)
pagination := PaginationInfo{
CurrentPage: page,
TotalPages: totalPages,
@@ -147,9 +208,11 @@ func AddressHandler(w http.ResponseWriter, r *http.Request) {
"Title": "Addresses",
"IsAuthenticated": true,
"ShowAdminNav": true,
"ActiveSection": "address", // Add this line
"ActiveSection": "address",
"Addresses": addresses,
"Role": "admin",
"Users": users,
"UserName": username,
"Role": "admin",
"Pagination": pagination,
})
}
@@ -182,3 +245,83 @@ func generatePageNumbers(currentPage, totalPages int) []PageNumber {
return pageNumbers
}
func AssignAddressHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Redirect(w, r, "/addresses", http.StatusSeeOther)
return
}
if err := r.ParseForm(); err != nil {
http.Error(w, "Invalid form", http.StatusBadRequest)
return
}
userIDStr := r.FormValue("user_id")
addressIDStr := r.FormValue("address_id")
if userIDStr == "" || addressIDStr == "" {
http.Error(w, "User ID and Address ID are required", http.StatusBadRequest)
return
}
userID, err := strconv.Atoi(userIDStr)
if err != nil {
http.Error(w, "Invalid user ID", http.StatusBadRequest)
return
}
addressID, err := strconv.Atoi(addressIDStr)
if err != nil {
http.Error(w, "Invalid address ID", http.StatusBadRequest)
return
}
// Verify the user exists and is associated with the current admin
currentAdminID := r.Context().Value("user_id").(int)
var userExists int
err = models.DB.QueryRow(`
SELECT COUNT(*) FROM admin_volunteers av
JOIN users u ON av.volunteer_id = u.user_id
WHERE av.admin_id = $1 AND u.user_id = $2 AND av.is_active = true
`, currentAdminID, userID).Scan(&userExists)
if err != nil {
log.Println("User verification error:", err)
http.Error(w, "Database error", http.StatusInternalServerError)
return
}
if userExists == 0 {
http.Error(w, "Invalid user selection", http.StatusBadRequest)
return
}
// Check if this address is already assigned to any user
var exists int
err = models.DB.QueryRow(`
SELECT COUNT(*) FROM appointment
WHERE address_id = $1
`, addressID).Scan(&exists)
if err != nil {
log.Println("Assignment check error:", err)
http.Error(w, "Database error", http.StatusInternalServerError)
return
}
if exists > 0 {
http.Error(w, "This address is already assigned to another user", http.StatusBadRequest)
return
}
// Assign the address - create appointment
_, err = models.DB.Exec(`
INSERT INTO appointment (user_id, address_id, appointment_date, appointment_time, created_at, updated_at)
VALUES ($1, $2, CURRENT_DATE, CURRENT_TIME, NOW(), NOW())
`, userID, addressID)
if err != nil {
log.Println("Assignment error:", err)
http.Error(w, "Failed to assign address", http.StatusInternalServerError)
return
}
// Redirect back to addresses page with success
http.Redirect(w, r, "/addresses?success=assigned", http.StatusSeeOther)
}