diff --git a/internal/web/handlers_itemtypes.go b/internal/web/handlers_itemtypes.go
index 95218c3..818c4c0 100644
--- a/internal/web/handlers_itemtypes.go
+++ b/internal/web/handlers_itemtypes.go
@@ -46,7 +46,7 @@ func (a *App) handleItemTypeCreate(w http.ResponseWriter, r *http.Request) {
a.Render(w, http.StatusBadRequest, "itemtypes_form", itemTypeFormData{User: currentUser(r), ItemType: it, FieldTypes: models.AllFieldTypes, Error: err.Error()})
return
}
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(it.ID, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(it.ID, 10)+"/edit", http.StatusSeeOther)
}
func (a *App) handleItemTypeEditForm(w http.ResponseWriter, r *http.Request) {
@@ -87,7 +87,7 @@ func (a *App) handleItemTypeUpdate(w http.ResponseWriter, r *http.Request) {
a.Render(w, http.StatusBadRequest, "itemtypes_form", itemTypeFormData{User: currentUser(r), ItemType: it, FieldTypes: models.AllFieldTypes, Error: err.Error()})
return
}
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
}
func (a *App) handleItemTypeDelete(w http.ResponseWriter, r *http.Request) {
@@ -97,10 +97,10 @@ func (a *App) handleItemTypeDelete(w http.ResponseWriter, r *http.Request) {
return
}
if err := a.ItemTypes.Delete(r.Context(), id); err != nil {
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(id, 10)+"/edit?error="+err.Error(), http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(id, 10)+"/edit?error="+err.Error(), http.StatusSeeOther)
return
}
- http.Redirect(w, r, "/item-types", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types", http.StatusSeeOther)
}
func (a *App) handleFieldCreate(w http.ResponseWriter, r *http.Request) {
@@ -124,7 +124,7 @@ func (a *App) handleFieldCreate(w http.ResponseWriter, r *http.Request) {
if err := a.ItemTypes.CreateField(r.Context(), f); err != nil {
a.Log.Warn("create field failed", "error", err)
}
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
}
func (a *App) handleFieldUpdate(w http.ResponseWriter, r *http.Request) {
@@ -159,7 +159,7 @@ func (a *App) handleFieldUpdate(w http.ResponseWriter, r *http.Request) {
if err := a.ItemTypes.UpdateField(r.Context(), f); err != nil {
a.Log.Warn("update field failed", "error", err)
}
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(itemTypeID, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(itemTypeID, 10)+"/edit", http.StatusSeeOther)
}
func (a *App) handleFieldDelete(w http.ResponseWriter, r *http.Request) {
@@ -176,7 +176,7 @@ func (a *App) handleFieldDelete(w http.ResponseWriter, r *http.Request) {
if err := a.ItemTypes.DeleteField(r.Context(), fieldID); err != nil {
a.Log.Warn("delete field failed", "error", err)
}
- http.Redirect(w, r, "/item-types/"+strconv.FormatInt(itemTypeID, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/item-types/"+strconv.FormatInt(itemTypeID, 10)+"/edit", http.StatusSeeOther)
}
func atoiDefault(s string, def int) int {
diff --git a/internal/web/handlers_users.go b/internal/web/handlers_users.go
index 3017780..64b440b 100644
--- a/internal/web/handlers_users.go
+++ b/internal/web/handlers_users.go
@@ -50,7 +50,7 @@ func (a *App) handleUserCreate(w http.ResponseWriter, r *http.Request) {
a.Render(w, http.StatusBadRequest, "users_form", userFormData{User: currentUser(r), EditUser: u, Error: err.Error()})
return
}
- http.Redirect(w, r, "/users", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/users", http.StatusSeeOther)
}
func (a *App) handleUserEditForm(w http.ResponseWriter, r *http.Request) {
@@ -92,7 +92,7 @@ func (a *App) handleUserUpdate(w http.ResponseWriter, r *http.Request) {
a.Render(w, http.StatusBadRequest, "users_form", userFormData{User: currentUser(r), EditUser: u, Error: err.Error()})
return
}
- http.Redirect(w, r, "/users", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/users", http.StatusSeeOther)
}
func (a *App) handleUserPassword(w http.ResponseWriter, r *http.Request) {
@@ -111,7 +111,7 @@ func (a *App) handleUserPassword(w http.ResponseWriter, r *http.Request) {
a.Log.Warn("set password failed", "error", err)
}
}
- http.Redirect(w, r, "/users/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/users/"+strconv.FormatInt(id, 10)+"/edit", http.StatusSeeOther)
}
func (a *App) handleUserDelete(w http.ResponseWriter, r *http.Request) {
@@ -123,5 +123,5 @@ func (a *App) handleUserDelete(w http.ResponseWriter, r *http.Request) {
if err := a.Users.Delete(r.Context(), id); err != nil {
a.Log.Warn("delete user failed", "error", err)
}
- http.Redirect(w, r, "/users", http.StatusSeeOther)
+ http.Redirect(w, r, "/settings/users", http.StatusSeeOther)
}
diff --git a/internal/web/router.go b/internal/web/router.go
index 81c4bc4..700ac6c 100644
--- a/internal/web/router.go
+++ b/internal/web/router.go
@@ -59,27 +59,9 @@ func (a *App) Router() http.Handler {
mux.HandleFunc("GET /export/assets.csv", a.requireLogin(a.handleExportCSV))
mux.HandleFunc("POST /import/assets.csv", a.requireAdmin(a.handleImportCSV))
- // Item types (admin, traditional pages)
- mux.HandleFunc("GET /item-types", a.requireAdmin(a.handleItemTypesList))
- mux.HandleFunc("GET /item-types/new", a.requireAdmin(a.handleItemTypeNewForm))
- mux.HandleFunc("POST /item-types", a.requireAdmin(a.handleItemTypeCreate))
- mux.HandleFunc("GET /item-types/{id}/edit", a.requireAdmin(a.handleItemTypeEditForm))
- mux.HandleFunc("POST /item-types/{id}", a.requireAdmin(a.handleItemTypeUpdate))
- mux.HandleFunc("POST /item-types/{id}/delete", a.requireAdmin(a.handleItemTypeDelete))
- mux.HandleFunc("POST /item-types/{id}/fields", a.requireAdmin(a.handleFieldCreate))
- mux.HandleFunc("POST /item-types/{id}/fields/{fieldID}", a.requireAdmin(a.handleFieldUpdate))
- mux.HandleFunc("POST /item-types/{id}/fields/{fieldID}/delete", a.requireAdmin(a.handleFieldDelete))
-
- // Users (admin, traditional pages)
- mux.HandleFunc("GET /users", a.requireAdmin(a.handleUsersList))
- mux.HandleFunc("GET /users/new", a.requireAdmin(a.handleUserNewForm))
- mux.HandleFunc("POST /users", a.requireAdmin(a.handleUserCreate))
- mux.HandleFunc("GET /users/{id}/edit", a.requireAdmin(a.handleUserEditForm))
- mux.HandleFunc("POST /users/{id}", a.requireAdmin(a.handleUserUpdate))
- mux.HandleFunc("POST /users/{id}/password", a.requireAdmin(a.handleUserPassword))
- mux.HandleFunc("POST /users/{id}/delete", a.requireAdmin(a.handleUserDelete))
-
- // Settings (admin, traditional page)
+ // Settings (admin, traditional pages) - Item Types, Users, and general
+ // settings all live under one unified /settings section with shared
+ // sub-navigation, rather than as separate top-level nav items.
mux.HandleFunc("GET /settings", a.requireAdmin(a.handleSettingsPage))
mux.HandleFunc("POST /settings/general", a.requireAdmin(a.handleSettingsGeneral))
mux.HandleFunc("POST /settings/statuses", a.requireAdmin(a.handleStatusCreate))
@@ -87,6 +69,24 @@ func (a *App) Router() http.Handler {
mux.HandleFunc("POST /settings/statuses/{id}/delete", a.requireAdmin(a.handleStatusDelete))
mux.HandleFunc("POST /settings/statuses/{id}/reorder", a.requireAdmin(a.handleStatusReorder))
+ mux.HandleFunc("GET /settings/item-types", a.requireAdmin(a.handleItemTypesList))
+ mux.HandleFunc("GET /settings/item-types/new", a.requireAdmin(a.handleItemTypeNewForm))
+ mux.HandleFunc("POST /settings/item-types", a.requireAdmin(a.handleItemTypeCreate))
+ mux.HandleFunc("GET /settings/item-types/{id}/edit", a.requireAdmin(a.handleItemTypeEditForm))
+ mux.HandleFunc("POST /settings/item-types/{id}", a.requireAdmin(a.handleItemTypeUpdate))
+ mux.HandleFunc("POST /settings/item-types/{id}/delete", a.requireAdmin(a.handleItemTypeDelete))
+ mux.HandleFunc("POST /settings/item-types/{id}/fields", a.requireAdmin(a.handleFieldCreate))
+ mux.HandleFunc("POST /settings/item-types/{id}/fields/{fieldID}", a.requireAdmin(a.handleFieldUpdate))
+ mux.HandleFunc("POST /settings/item-types/{id}/fields/{fieldID}/delete", a.requireAdmin(a.handleFieldDelete))
+
+ mux.HandleFunc("GET /settings/users", a.requireAdmin(a.handleUsersList))
+ mux.HandleFunc("GET /settings/users/new", a.requireAdmin(a.handleUserNewForm))
+ mux.HandleFunc("POST /settings/users", a.requireAdmin(a.handleUserCreate))
+ mux.HandleFunc("GET /settings/users/{id}/edit", a.requireAdmin(a.handleUserEditForm))
+ mux.HandleFunc("POST /settings/users/{id}", a.requireAdmin(a.handleUserUpdate))
+ mux.HandleFunc("POST /settings/users/{id}/password", a.requireAdmin(a.handleUserPassword))
+ mux.HandleFunc("POST /settings/users/{id}/delete", a.requireAdmin(a.handleUserDelete))
+
return a.loadSession(mux)
}
diff --git a/web/templates/layout.html b/web/templates/layout.html
index b70d491..2978919 100644
--- a/web/templates/layout.html
+++ b/web/templates/layout.html
@@ -20,8 +20,6 @@
diff --git a/web/templates/pages/itemtypes_form.html b/web/templates/pages/itemtypes_form.html
index c5a02c2..3011ae9 100644
--- a/web/templates/pages/itemtypes_form.html
+++ b/web/templates/pages/itemtypes_form.html
@@ -1,15 +1,21 @@
{{define "content"}}
-
+
+
Settings
+
+
+ {{template "settings_nav" "itemtypes"}}
+
+
{{if .Error}}
{{.Error}}
{{end}}
-
+
{{else}}
Save the item type first to add custom fields.
{{end}}
+
+
{{end}}
diff --git a/web/templates/pages/itemtypes_list.html b/web/templates/pages/itemtypes_list.html
index dd9f21e..5023d0e 100644
--- a/web/templates/pages/itemtypes_list.html
+++ b/web/templates/pages/itemtypes_list.html
@@ -1,27 +1,35 @@
{{define "content"}}
-
-
-
- | Icon | Name | Description | Custom Fields | Status | |
-
- {{range .ItemTypes}}
-
- |
- {{.Name}} |
- {{.Description}} |
- {{len .Fields}} |
- {{if .Enabled}}Enabled{{else}}Disabled{{end}} |
- Edit |
-
- {{else}}
- | No item types defined yet. |
- {{end}}
-
-
+
Settings
+
+
+ {{template "settings_nav" "itemtypes"}}
+
+
+
+
+
+ | Icon | Name | Description | Custom Fields | Status | |
+
+ {{range .ItemTypes}}
+
+ |
+ {{.Name}} |
+ {{.Description}} |
+ {{len .Fields}} |
+ {{if .Enabled}}Enabled{{else}}Disabled{{end}} |
+ Edit |
+
+ {{else}}
+ | No item types defined yet. |
+ {{end}}
+
+
+
+
{{end}}
diff --git a/web/templates/pages/settings.html b/web/templates/pages/settings.html
index c02b5eb..f3d8e77 100644
--- a/web/templates/pages/settings.html
+++ b/web/templates/pages/settings.html
@@ -1,6 +1,11 @@
{{define "content"}}
-
+
Settings
+
+
+ {{template "settings_nav" "general"}}
+
+
+
+
+
{{end}}
diff --git a/web/templates/pages/users_form.html b/web/templates/pages/users_form.html
index cd7916a..60df824 100644
--- a/web/templates/pages/users_form.html
+++ b/web/templates/pages/users_form.html
@@ -1,61 +1,69 @@
{{define "content"}}
-
-
-
{{if .EditUser}}Edit User{{else}}New User{{end}}
-
Back to Users
-
+
+
Settings
+
+
+ {{template "settings_nav" "users"}}
+
+
+
+
{{if .EditUser}}Edit User{{else}}New User{{end}}
+
Back to Users
+
- {{if .Error}}
{{.Error}}
{{end}}
+ {{if .Error}}
{{.Error}}
{{end}}
-
-
-
- {{if .EditUser}}
-
-
-
-
-
-
- {{end}}
{{end}}
diff --git a/web/templates/pages/users_list.html b/web/templates/pages/users_list.html
index b40b2bd..5c38bcb 100644
--- a/web/templates/pages/users_list.html
+++ b/web/templates/pages/users_list.html
@@ -1,24 +1,32 @@
{{define "content"}}
-
-
-
- | Username | Role | Status | Created | |
-
- {{range .Users}}
-
- | {{.Username}} |
- {{if .IsAdmin}}Admin{{else}}User{{end}} |
- {{if .Enabled}}Enabled{{else}}Disabled{{end}} |
- {{fmtDateShort .CreatedAt}} |
- Edit |
-
- {{end}}
-
-
+
Settings
+
+
+ {{template "settings_nav" "users"}}
+
+
+
+
+
+ | Username | Role | Status | Created | |
+
+ {{range .Users}}
+
+ | {{.Username}} |
+ {{if .IsAdmin}}Admin{{else}}User{{end}} |
+ {{if .Enabled}}Enabled{{else}}Disabled{{end}} |
+ {{fmtDateShort .CreatedAt}} |
+ Edit |
+
+ {{end}}
+
+
+
+
{{end}}
diff --git a/web/templates/partials/settings_nav.html b/web/templates/partials/settings_nav.html
new file mode 100644
index 0000000..d1dac96
--- /dev/null
+++ b/web/templates/partials/settings_nav.html
@@ -0,0 +1,13 @@
+{{define "settings_nav"}}
+
+{{end}}