Files
Poll-system/app/internal/handlers/admin_map.go
2025-09-03 14:35:47 -06:00

186 lines
5.0 KiB
Go

package handlers
import (
"encoding/json"
"log"
"net/http"
"github.com/patel-mann/poll-system/app/internal/models"
)
// ValidatedAddress represents a validated address with coordinates
type ValidatedAddress struct {
AddressID int `json:"address_id"`
Address string `json:"address"`
Longitude float64 `json:"longitude"`
Latitude float64 `json:"latitude"`
HouseNumber string `json:"house_number"`
StreetName string `json:"street_name"`
StreetType string `json:"street_type"`
Quadrant string `json:"street_quadrant"`
UpdatedAt string `json:"updated_at"`
}
// GetValidatedAddressesHandler returns all validated addresses with their coordinates as JSON
func GetValidatedAddressesHandler(w http.ResponseWriter, r *http.Request) {
// Only allow GET requests
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Optional: Check if user is authenticated (depending on your auth system)
// _, authenticated := models.GetCurrentUserName(r)
// if !authenticated {
// http.Error(w, "Unauthorized", http.StatusUnauthorized)
// return
// }
// Query validated addresses from database
addresses, err := fetchValidatedAddresses()
if err != nil {
log.Printf("Error fetching validated addresses: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
// Set response headers for JSON
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") // Adjust based on your CORS policy
// Encode and send JSON response
if err := json.NewEncoder(w).Encode(addresses); err != nil {
log.Printf("Error encoding JSON response: %v", err)
http.Error(w, "Error encoding response", http.StatusInternalServerError)
return
}
log.Printf("Successfully returned %d validated addresses", addresses)
}
// fetchValidatedAddresses retrieves all validated addresses from the database
func fetchValidatedAddresses() ([]ValidatedAddress, error) {
query := `
SELECT
address_id,
address,
longitude,
latitude,
COALESCE(house_number, '') as house_number,
COALESCE(street_name, '') as street_name,
COALESCE(street_type, '') as street_type,
COALESCE(street_quadrant, '') as street_quadrant,
updated_at::text
FROM address_database
WHERE visited_validated = true
AND longitude IS NOT NULL
AND latitude IS NOT NULL
AND longitude != 0
AND latitude != 0
ORDER BY updated_at DESC
`
rows, err := models.DB.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var addresses []ValidatedAddress
for rows.Next() {
var addr ValidatedAddress
err := rows.Scan(
&addr.AddressID,
&addr.Address,
&addr.Longitude,
&addr.Latitude,
&addr.HouseNumber,
&addr.StreetName,
&addr.StreetType,
&addr.Quadrant,
&addr.UpdatedAt,
)
if err != nil {
log.Printf("Error scanning address row: %v", err)
continue
}
addresses = append(addresses, addr)
}
if err = rows.Err(); err != nil {
return nil, err
}
return addresses, nil
}
// GetValidatedAddressesStatsHandler returns statistics about validated addresses
func GetValidatedAddressesStatsHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
stats, err := getValidatedAddressesStats()
if err != nil {
log.Printf("Error fetching address stats: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(stats)
}
// AddressStats represents statistics about addresses
type AddressStats struct {
TotalValidated int `json:"total_validated"`
TotalAddresses int `json:"total_addresses"`
ValidatedWithCoords int `json:"validated_with_coords"`
RecentlyValidated int `json:"recently_validated_24h"`
}
// getValidatedAddressesStats gets statistics about validated addresses
func getValidatedAddressesStats() (AddressStats, error) {
var stats AddressStats
// Get total validated count
err := models.DB.QueryRow("SELECT COUNT(*) FROM address_database WHERE visited_validated = true").
Scan(&stats.TotalValidated)
if err != nil {
return stats, err
}
// Get total addresses count
err = models.DB.QueryRow("SELECT COUNT(*) FROM address_database").
Scan(&stats.TotalAddresses)
if err != nil {
return stats, err
}
// Get validated with coordinates count
err = models.DB.QueryRow(`
SELECT COUNT(*) FROM address_database
WHERE visited_validated = true
AND longitude IS NOT NULL
AND latitude IS NOT NULL
AND longitude != 0
AND latitude != 0
`).Scan(&stats.ValidatedWithCoords)
if err != nil {
return stats, err
}
// Get recently validated (last 24 hours)
err = models.DB.QueryRow(`
SELECT COUNT(*) FROM address_database
WHERE visited_validated = true
AND updated_at > NOW() - INTERVAL '24 hours'
`).Scan(&stats.RecentlyValidated)
if err != nil {
return stats, err
}
return stats, nil
}