Skip to content

Commit dec3c05

Browse files
committed
feat(admin): add admin handlers and routes
1 parent 6a6d0d6 commit dec3c05

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

admin_handlers.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package main
2+
3+
import (
4+
"html/template"
5+
"net/http"
6+
)
7+
8+
func renderPublic(w http.ResponseWriter, view string, data map[string]interface{}) {
9+
tmpl, err := template.ParseFiles(view)
10+
if err != nil {
11+
http.Error(w, "template error: "+err.Error(), http.StatusInternalServerError)
12+
return
13+
}
14+
if err := tmpl.Execute(w, data); err != nil {
15+
http.Error(w, "render error: "+err.Error(), http.StatusInternalServerError)
16+
}
17+
}
18+
19+
func renderAdmin(w http.ResponseWriter, view string, data map[string]interface{}) {
20+
tmpl, err := template.ParseFiles(
21+
"web/templates/layout/base.html",
22+
"web/templates/layout/sidebar.html",
23+
"web/templates/layout/header.html",
24+
view,
25+
)
26+
if err != nil {
27+
http.Error(w, "template error: "+err.Error(), http.StatusInternalServerError)
28+
return
29+
}
30+
if err := tmpl.Execute(w, data); err != nil {
31+
http.Error(w, "render error: "+err.Error(), http.StatusInternalServerError)
32+
}
33+
}
34+
35+
func AdminMapHandler(w http.ResponseWriter, r *http.Request) {
36+
renderAdmin(w, "web/templates/views/map.html", map[string]interface{}{
37+
"Title": "Live Map",
38+
"Page": "map",
39+
})
40+
}
41+
42+
func AdminLoginHandler(w http.ResponseWriter, r *http.Request) {
43+
renderPublic(w, "web/templates/views/login.html", map[string]interface{}{
44+
"Title": "Welcome",
45+
"Mode": "login",
46+
"LoginEndpoint": "/api/v1/auth/login",
47+
"SignupEndpoint": "/api/v1/auth/signup",
48+
})
49+
}
50+
51+
func AdminSignupHandler(w http.ResponseWriter, r *http.Request) {
52+
renderPublic(w, "web/templates/views/login.html", map[string]interface{}{
53+
"Title": "Create Account",
54+
"Mode": "signup",
55+
"LoginEndpoint": "/api/v1/auth/login",
56+
"SignupEndpoint": "/api/v1/auth/signup",
57+
})
58+
}
59+
60+
func AdminDashboardHandler(w http.ResponseWriter, r *http.Request) {
61+
renderAdmin(w, "web/templates/views/dashboard.html", map[string]interface{}{
62+
"Title": "Dashboard",
63+
"Page": "dashboard",
64+
"TotalVehicles": "24",
65+
"ActiveVehicles": "18",
66+
"TotalDrivers": "32",
67+
"ActiveTrips": "15",
68+
"RecentVehicles": []map[string]string{
69+
{"Name": "Bus 001", "Route": "Route A", "Status": "active", "LastSeen": "2 min ago"},
70+
{"Name": "Bus 002", "Route": "Route B", "Status": "active", "LastSeen": "5 min ago"},
71+
{"Name": "Bus 003", "Route": "Route C", "Status": "idle", "LastSeen": "12 min ago"},
72+
{"Name": "Bus 004", "Route": "Route A", "Status": "active", "LastSeen": "1 min ago"},
73+
{"Name": "Bus 005", "Route": "Route D", "Status": "active", "LastSeen": "3 min ago"},
74+
},
75+
})
76+
}
77+
78+
func AdminVehiclesHandler(w http.ResponseWriter, r *http.Request) {
79+
renderAdmin(w, "web/templates/views/vehicles.html", map[string]interface{}{
80+
"Title": "Vehicles",
81+
"Page": "vehicles",
82+
"Vehicles": []map[string]string{
83+
{"ID": "V001", "Name": "Bus 001", "Route": "Route A", "Driver": "Chaitanya K", "Status": "active", "LastSeen": "2 min ago"},
84+
{"ID": "V002", "Name": "Bus 002", "Route": "Route B", "Driver": "Aron", "Status": "active", "LastSeen": "5 min ago"},
85+
{"ID": "V003", "Name": "Bus 003", "Route": "Route C", "Driver": "Brad Pitt", "Status": "idle", "LastSeen": "12 min ago"},
86+
},
87+
})
88+
}
89+
90+
func AdminUsersHandler(w http.ResponseWriter, r *http.Request) {
91+
renderAdmin(w, "web/templates/views/users.html", map[string]interface{}{
92+
"Title": "Users",
93+
"Page": "users",
94+
"Users": []map[string]string{
95+
{"Name": "Chaitanya K", "Email": "kbc@transit.co.ke", "Role": "driver", "LastSeen": "Today"},
96+
{"Name": "To Holland", "Email": "tom@transit.co.ke", "Role": "driver", "LastSeen": "Today"},
97+
{"Name": "Open transit", "Email": "brian@transit.co.ke", "Role": "driver", "LastSeen": "Yesterday"},
98+
},
99+
})
100+
}
101+
102+
func AdminTripsHandler(w http.ResponseWriter, r *http.Request) {
103+
renderAdmin(w, "web/templates/views/trips.html", map[string]interface{}{
104+
"Title": "Trips",
105+
"Page": "trips",
106+
"Trips": []map[string]string{
107+
{"ID": "T001", "Vehicle": "Bus 001", "Driver": "Tom Hiddlestone", "Route": "Route A", "Start": "07:00", "End": "08:45", "Status": "completed"},
108+
{"ID": "T002", "Vehicle": "Bus 002", "Driver": "Chris Hensworth", "Route": "Route B", "Start": "07:15", "End": "\u2014", "Status": "active"},
109+
{"ID": "T003", "Vehicle": "Bus 003", "Driver": "Bruce Wayne", "Route": "Route C", "Start": "06:45", "End": "08:30", "Status": "completed"},
110+
},
111+
})
112+
}

main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,21 @@ func main() {
7777
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
7878
})
7979

80+
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static"))))
81+
8082
authMiddleware := requireAuth(jwtSecret)
8183

8284
mux.Handle("POST /api/v1/locations", authMiddleware(handlePostLocation(store, tracker, rateLimiter)))
8385

86+
// Admin UI — no auth for demo/pitch
87+
mux.HandleFunc("GET /admin/login", AdminLoginHandler)
88+
mux.HandleFunc("GET /admin/signup", AdminSignupHandler)
89+
mux.HandleFunc("GET /admin/map", AdminMapHandler)
90+
mux.HandleFunc("GET /admin/dashboard", AdminDashboardHandler)
91+
mux.HandleFunc("GET /admin/vehicles", AdminVehiclesHandler)
92+
mux.HandleFunc("GET /admin/users", AdminUsersHandler)
93+
mux.HandleFunc("GET /admin/trips", AdminTripsHandler)
94+
8495
srv := &http.Server{
8596
Addr: ":" + port,
8697
Handler: requestLogger(mux),

0 commit comments

Comments
 (0)