Compare commits

..

3 commits

Author SHA1 Message Date
JACS
e4b0969ecf tabla clientes ejemplo 2026-05-03 02:29:05 -05:00
JACS
f06d22072e tempalte admin users 2026-05-03 01:58:18 -05:00
JACS
7f3bfb7d59 tempalte profile 2026-05-03 01:29:32 -05:00
9 changed files with 654 additions and 15 deletions

View file

@ -0,0 +1,111 @@
package controllers
// Person represents a single person in the sample data.
// Migrated from liquid/data/people.json.
type Person struct {
ID string
FirstName string
LastName string
FullName string
AvatarID string
Email string
City string
Country string
JobTitle string
Department string
Status string
Date string
Tags []string
Category string
}
// CustomerTableRow is the display-friendly version of a person for the customers table.
type CustomerTableRow struct {
FullName string
Email string
City string
Country string
JobTitle string
Department string
Status string
Date string
Tags []string
AvatarID string
}
// SamplePeople returns all 50 sample people from liquid/data/people.json.
func SamplePeople() []Person {
return []Person{
{ID: "1", FirstName: "Paweł", LastName: "Kuna", FullName: "Paweł Kuna", AvatarID: "000m", Email: "paweluna@howstuffworks.com", City: "Peimei", Country: "China", JobTitle: "UI Designer", Department: "Training", Status: "VIP", Date: "2025-04-07", Tags: []string{"High Volume"}, Category: "B2B"},
{ID: "2", FirstName: "Jeffie", LastName: "Lewzey", FullName: "Jeffie Lewzey", AvatarID: "052f", Email: "jlewzey1@seesaa.net", City: "Indaial", Country: "Brazil", JobTitle: "Chemical Engineer", Department: "Support", Status: "New", Date: "2024-12-12", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "3", FirstName: "Mallory", LastName: "Hulme", FullName: "Mallory Hulme", AvatarID: "002m", Email: "mhulme2@domainmarket.com", City: "Cimuncang", Country: "Indonesia", JobTitle: "Geologist IV", Department: "Support", Status: "VIP", Date: "2025-01-09", Tags: []string{"High Value", "No Refunds", "Loyal"}, Category: "B2C"},
{ID: "4", FirstName: "Dunn", LastName: "Slane", FullName: "Dunn Slane", AvatarID: "003m", Email: "dslane3@epa.gov", City: "Liutang", Country: "China", JobTitle: "Research Nurse", Department: "Sales", Status: "Regular", Date: "2022-10-01", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "5", FirstName: "Emmy", LastName: "Levet", FullName: "Emmy Levet", AvatarID: "000f", Email: "elevet4@senate.gov", City: "Kaliprak", Country: "Indonesia", JobTitle: "VP Product Management", Department: "Accounting", Status: "Regular", Date: "2025-05-18", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "6", FirstName: "Maryjo", LastName: "Lebarree", FullName: "Maryjo Lebarree", AvatarID: "001f", Email: "mlebarree5@unc.edu", City: "Hantai", Country: "China", JobTitle: "Civil Engineer", Department: "Product Management", Status: "Regular", Date: "2025-06-06", Tags: []string{"No Refunds", "Loyal"}, Category: "B2B"},
{ID: "7", FirstName: "Egan", LastName: "Poetz", FullName: "Egan Poetz", AvatarID: "004m", Email: "epoetz6@free.fr", City: "Villaguay", Country: "Argentina", JobTitle: "Research Nurse", Department: "Engineering", Status: "New", Date: "2024-08-21", Tags: []string{"No Refunds"}, Category: "B2B"},
{ID: "8", FirstName: "Kellie", LastName: "Skingley", FullName: "Kellie Skingley", AvatarID: "002f", Email: "kskingley7@columbia.edu", City: "Sidon", Country: "Lebanon", JobTitle: "Teacher", Department: "Services", Status: "VIP", Date: "2025-02-23", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "9", FirstName: "Christabel", LastName: "Charlwood", FullName: "Christabel Charlwood", AvatarID: "003f", Email: "ccharlwood8@nifty.com", City: "Recarei", Country: "Portugal", JobTitle: "Tax Accountant", Department: "Engineering", Status: "Regular", Date: "2024-09-26", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "10", FirstName: "Haskel", LastName: "Shelper", FullName: "Haskel Shelper", AvatarID: "063m", Email: "hshelper9@woothemes.com", City: "Porto Alto", Country: "Portugal", JobTitle: "Staff Scientist", Department: "Legal", Status: "Regular", Date: "2023-06-11", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "11", FirstName: "Lorry", LastName: "Mion", FullName: "Lorry Mion", AvatarID: "006m", Email: "lmiona@livejournal.com", City: "Embu", Country: "Kenya", JobTitle: "Automation Specialist IV", Department: "Accounting", Status: "Regular", Date: "2023-12-11", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "12", FirstName: "Leesa", LastName: "Beaty", FullName: "Leesa Beaty", AvatarID: "004f", Email: "lbeatyb@alibaba.com", City: "Quaraí", Country: "Brazil", JobTitle: "Editor", Department: "Services", Status: "Regular", Date: "2025-04-06", Tags: []string{"Standard"}, Category: "B2B"},
{ID: "13", FirstName: "Perren", LastName: "Keemar", FullName: "Perren Keemar", AvatarID: "007m", Email: "pkeemarc@yahoo.com", City: "Dadiya", Country: "Nigeria", JobTitle: "Analog Circuit Design manager", Department: "Services", Status: "Regular", Date: "2025-01-26", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "14", FirstName: "Sunny", LastName: "Airey", FullName: "Sunny Airey", AvatarID: "", Email: "saireyd@prlog.org", City: "Hamburg", Country: "Germany", JobTitle: "Nuclear Power Engineer", Department: "Engineering", Status: "VIP", Date: "2023-05-22", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "15", FirstName: "Geoffry", LastName: "Flaunders", FullName: "Geoffry Flaunders", AvatarID: "009m", Email: "gflaunderse@loc.gov", City: "Kavār", Country: "Iran", JobTitle: "Software Test Engineer II", Department: "Accounting", Status: "Regular", Date: "2023-11-05", Tags: []string{"No Refunds", "Loyal"}, Category: "B2B"},
{ID: "16", FirstName: "Thatcher", LastName: "Keel", FullName: "Thatcher Keel", AvatarID: "010m", Email: "tkeelf@blogger.com", City: "Nanchoc", Country: "Peru", JobTitle: "VP Sales", Department: "Business Development", Status: "Regular", Date: "2023-10-06", Tags: []string{"No Refunds"}, Category: "B2B"},
{ID: "17", FirstName: "Dyann", LastName: "Escala", FullName: "Dyann Escala", AvatarID: "005f", Email: "descalag@usatoday.com", City: "Nóvita", Country: "Colombia", JobTitle: "Mechanical Systems Engineer", Department: "Sales", Status: "Regular", Date: "2023-10-15", Tags: []string{"Standard"}, Category: "B2B"},
{ID: "18", FirstName: "Avivah", LastName: "Mugleston", FullName: "Avivah Mugleston", AvatarID: "006f", Email: "amuglestonh@intel.com", City: "Kista", Country: "Sweden", JobTitle: "Actuary", Department: "Sales", Status: "Regular", Date: "2023-03-28", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "19", FirstName: "Arlie", LastName: "Armstead", FullName: "Arlie Armstead", AvatarID: "", Email: "aarmsteadi@yellowpages.com", City: "Jacobina", Country: "Brazil", JobTitle: "VP Quality Control", Department: "Accounting", Status: "Regular", Date: "2022-11-22", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "20", FirstName: "Tessie", LastName: "Curzon", FullName: "Tessie Curzon", AvatarID: "008f", Email: "tcurzonj@hp.com", City: "Hetang", Country: "China", JobTitle: "Research Nurse", Department: "Product Management", Status: "Regular", Date: "2024-11-02", Tags: []string{"Frequent Returns"}, Category: "B2C"},
{ID: "21", FirstName: "Flossi", LastName: "Uttley", FullName: "Flossi Uttley", AvatarID: "009f", Email: "futtleyk@google.cn", City: "Gaomiaoji", Country: "China", JobTitle: "Engineer I", Department: "Research and Development", Status: "New", Date: "2025-03-08", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "22", FirstName: "Cesya", LastName: "Spritt", FullName: "Cesya Spritt", AvatarID: "010f", Email: "csprittl@mapquest.com", City: "Göteborg", Country: "Sweden", JobTitle: "Human Resources Manager", Department: "Support", Status: "Regular", Date: "2024-02-29", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "23", FirstName: "Johnnie", LastName: "Gilby", FullName: "Johnnie Gilby", AvatarID: "011m", Email: "jgilbym@loc.gov", City: "Panayagan", Country: "Indonesia", JobTitle: "Structural Engineer", Department: "Marketing", Status: "VIP", Date: "2022-11-06", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "24", FirstName: "Ban", LastName: "Rzehor", FullName: "Ban Rzehor", AvatarID: "012m", Email: "brzehorn@deliciousdays.com", City: "Denver", Country: "United States", JobTitle: "General Manager", Department: "Sales", Status: "Regular", Date: "2022-09-29", Tags: []string{"No Refunds"}, Category: "B2B"},
{ID: "25", FirstName: "Carroll", LastName: "Erat", FullName: "Carroll Erat", AvatarID: "011f", Email: "cerato@dion.ne.jp", City: "Šentilj v Slov. Goricah", Country: "Slovenia", JobTitle: "Assistant Professor", Department: "Product Management", Status: "Regular", Date: "2023-03-29", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "26", FirstName: "Marsha", LastName: "Labat", FullName: "Marsha Labat", AvatarID: "012f", Email: "mlabatp@npr.org", City: "Cabrero", Country: "Chile", JobTitle: "Research Associate", Department: "Legal", Status: "Regular", Date: "2023-04-04", Tags: []string{"No Refunds", "Loyal"}, Category: "B2B"},
{ID: "27", FirstName: "Elston", LastName: "Muffett", FullName: "Elston Muffett", AvatarID: "013m", Email: "emuffettq@marketwatch.com", City: "Terara", Country: "Indonesia", JobTitle: "Account Coordinator", Department: "Training", Status: "Regular", Date: "2024-09-20", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "28", FirstName: "Leigha", LastName: "Gorce", FullName: "Leigha Gorce", AvatarID: "013f", Email: "lgorcer@goodreads.com", City: "Barrie", Country: "Canada", JobTitle: "Geologist II", Department: "Training", Status: "Regular", Date: "2023-06-21", Tags: []string{"Standard"}, Category: "B2B"},
{ID: "29", FirstName: "Tallie", LastName: "Bettis", FullName: "Tallie Bettis", AvatarID: "", Email: "tbettiss@fastcompany.com", City: "Pojan", Country: "Albania", JobTitle: "Director of Sales", Department: "Training", Status: "New", Date: "2025-08-27", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "30", FirstName: "Merrily", LastName: "Garforth", FullName: "Merrily Garforth", AvatarID: "015f", Email: "mgarfortht@edublogs.org", City: "Tupaciguara", Country: "Brazil", JobTitle: "Structural Engineer", Department: "Business Development", Status: "Regular", Date: "2023-09-26", Tags: []string{"No Refunds", "Loyal"}, Category: "B2B"},
{ID: "31", FirstName: "Errol", LastName: "Blackley", FullName: "Errol Blackley", AvatarID: "", Email: "eblackleyu@addthis.com", City: "Poroj", Country: "Macedonia", JobTitle: "Safety Technician I", Department: "Accounting", Status: "Regular", Date: "2023-05-02", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "32", FirstName: "Ninon", LastName: "Don", FullName: "Ninon Don", AvatarID: "016f", Email: "ndonv@a8.net", City: "Baiguo", Country: "China", JobTitle: "Senior Cost Accountant", Department: "Marketing", Status: "Regular", Date: "2022-12-09", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "33", FirstName: "Delaney", LastName: "Cairney", FullName: "Delaney Cairney", AvatarID: "015m", Email: "dcairneyw@bandcamp.com", City: "Linhares", Country: "Portugal", JobTitle: "Media Manager IV", Department: "Human Resources", Status: "Regular", Date: "2024-06-27", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "34", FirstName: "Gratia", LastName: "Gooley", FullName: "Gratia Gooley", AvatarID: "017f", Email: "ggooleyx@google.es", City: "Ruma", Country: "Serbia", JobTitle: "Engineer II", Department: "Product Management", Status: "New", Date: "2024-05-30", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "35", FirstName: "Odelinda", LastName: "McCosh", FullName: "Odelinda McCosh", AvatarID: "018f", Email: "omccoshy@sun.com", City: "Chengxiang", Country: "China", JobTitle: "Tax Accountant", Department: "Research and Development", Status: "New", Date: "2024-02-05", Tags: []string{"No Refunds"}, Category: "Wholesale"},
{ID: "36", FirstName: "Wilburt", LastName: "Siegertsz", FullName: "Wilburt Siegertsz", AvatarID: "016m", Email: "wsiegertszz@google.ru", City: "Veiga", Country: "Portugal", JobTitle: "Project Manager", Department: "Marketing", Status: "Regular", Date: "2023-08-07", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "37", FirstName: "Julietta", LastName: "Coke", FullName: "Julietta Coke", AvatarID: "019f", Email: "jcoke10@nba.com", City: "Malaga", Country: "Philippines", JobTitle: "Technical Writer", Department: "Legal", Status: "Regular", Date: "2024-11-07", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "38", FirstName: "Portie", LastName: "Christou", FullName: "Portie Christou", AvatarID: "017m", Email: "pchristou11@wordpress.org", City: "Gaoping", Country: "China", JobTitle: "VP Product Management", Department: "Sales", Status: "Regular", Date: "2024-02-06", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "39", FirstName: "Emmott", LastName: "Dowsett", FullName: "Emmott Dowsett", AvatarID: "018m", Email: "edowsett12@clickbank.net", City: "Roanoke", Country: "United States", JobTitle: "Human Resources Assistant III", Department: "Accounting", Status: "Regular", Date: "2023-11-05", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "40", FirstName: "Rooney", LastName: "Cassy", FullName: "Rooney Cassy", AvatarID: "019m", Email: "rcassy13@symantec.com", City: "Mulan", Country: "China", JobTitle: "Registered Nurse", Department: "Product Management", Status: "Regular", Date: "2022-11-17", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "41", FirstName: "Haze", LastName: "Hubbert", FullName: "Haze Hubbert", AvatarID: "020m", Email: "hhubbert14@studiopress.com", City: "El Arenal", Country: "Mexico", JobTitle: "Project Manager", Department: "Engineering", Status: "Regular", Date: "2024-10-26", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
{ID: "42", FirstName: "Mata", LastName: "Codlin", FullName: "Mata Codlin", AvatarID: "021m", Email: "mcodlin15@4shared.com", City: "Mar del Plata", Country: "Argentina", JobTitle: "Speech Pathologist", Department: "Business Development", Status: "Regular", Date: "2023-12-19", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "43", FirstName: "Parker", LastName: "Oaten", FullName: "Parker Oaten", AvatarID: "022m", Email: "poaten16@deliciousdays.com", City: "Witzenhausen", Country: "Germany", JobTitle: "Accounting Assistant II", Department: "Engineering", Status: "Regular", Date: "2023-12-29", Tags: []string{"No Refunds"}, Category: "B2C"},
{ID: "44", FirstName: "Johannes", LastName: "Paternoster", FullName: "Johannes Paternoster", AvatarID: "023m", Email: "jpaternoster17@last.fm", City: "Pirallahı", Country: "Azerbaijan", JobTitle: "Assistant Manager", Department: "Engineering", Status: "Regular", Date: "2025-06-18", Tags: []string{"No Refunds"}, Category: "B2B"},
{ID: "45", FirstName: "Cary", LastName: "Baleine", FullName: "Cary Baleine", AvatarID: "024m", Email: "cbaleine18@gov.uk", City: "Pokrovka", Country: "Kyrgyzstan", JobTitle: "Automation Specialist III", Department: "Training", Status: "Regular", Date: "2025-02-17", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "46", FirstName: "Riane", LastName: "Milward", FullName: "Riane Milward", AvatarID: "020f", Email: "rmilward19@soup.io", City: "Erling", Country: "China", JobTitle: "Quality Engineer", Department: "Legal", Status: "Regular", Date: "2025-02-08", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "47", FirstName: "Reynold", LastName: "Indgs", FullName: "Reynold Indgs", AvatarID: "025m", Email: "rindgs1a@netlog.com", City: "Huayllo", Country: "Peru", JobTitle: "Payment Adjustment Coordinator", Department: "Human Resources", Status: "Regular", Date: "2024-05-20", Tags: []string{"Standard"}, Category: "B2C"},
{ID: "48", FirstName: "Parke", LastName: "Moneypenny", FullName: "Parke Moneypenny", AvatarID: "026m", Email: "pmoneypenny1b@reuters.com", City: "Karawatung", Country: "Indonesia", JobTitle: "Senior Cost Accountant", Department: "Support", Status: "Regular", Date: "2024-08-21", Tags: []string{"No Refunds", "Loyal"}, Category: "B2B"},
{ID: "49", FirstName: "Sandi", LastName: "Keys", FullName: "Sandi Keys", AvatarID: "021f", Email: "skeys1c@dailymail.co.uk", City: "Samannūd", Country: "Egypt", JobTitle: "Paralegal", Department: "Marketing", Status: "VIP", Date: "2025-01-19", Tags: []string{"High Volume", "High Value", "No Refunds", "Loyal"}, Category: "B2C"},
{ID: "50", FirstName: "Peria", LastName: "Errichiello", FullName: "Peria Errichiello", AvatarID: "022f", Email: "perrichiello1d@nbcnews.com", City: "Xukou", Country: "China", JobTitle: "Senior Editor", Department: "Legal", Status: "Regular", Date: "2022-09-04", Tags: []string{"No Refunds", "Loyal"}, Category: "B2C"},
}
}
// SampleCustomersTable returns customers table rows from the people data.
func SampleCustomersTable() []CustomerTableRow {
people := SamplePeople()
rows := make([]CustomerTableRow, 0, len(people))
for _, p := range people {
rows = append(rows, CustomerTableRow{
FullName: p.FullName,
Email: p.Email,
City: p.City,
Country: p.Country,
JobTitle: p.JobTitle,
Department: p.Department,
Status: p.Status,
Date: p.Date,
Tags: p.Tags,
AvatarID: p.AvatarID,
})
}
return rows
}

View file

@ -225,6 +225,77 @@ func UserLock(c *core.Context) *core.Response {
return c.Response.Template("apptabler_auth-lock.html", data) return c.Response.Template("apptabler_auth-lock.html", data)
} }
// AdminCustomers renders the admin customers listing page.
func AdminCustomers(c *core.Context) *core.Response {
type adminCustomersPageData struct {
TablerPageData
AdminCustomers AdminCustomersPage
}
data := adminCustomersPageData{
TablerPageData: TablerPageData{
PageTitle: "Customers",
PageDescription: "Manage customers",
ShowTopbar: true,
Sidebar: false,
PageHeader: "Customers",
PagePretitle: "Customer Management",
UserName: "Jane Doe",
UserRole: "Administrator",
NavbarMenu: SampleNavbarMenu(),
},
AdminCustomers: AdminCustomersPage{
Customers: SampleCustomersTable(),
},
}
return c.Response.Template("apptabler_admincustomers.html", data)
}
// AdminUsers renders the admin users listing page.
func AdminUsers(c *core.Context) *core.Response {
type adminUsersPageData struct {
TablerPageData
AdminUsers AdminUsersPage
}
data := adminUsersPageData{
TablerPageData: TablerPageData{
PageTitle: "Admin Users",
PageDescription: "Manage system users",
ShowTopbar: true,
Sidebar: false,
PageHeader: "Admin Users",
PagePretitle: "User Management",
UserName: "Jane Doe",
UserRole: "Administrator",
NavbarMenu: SampleNavbarMenu(),
},
AdminUsers: SampleAdminUsers(),
}
return c.Response.Template("apptabler_admin-users.html", data)
}
// UserSettings renders the user settings page.
func UserSettings(c *core.Context) *core.Response {
type userSettingsPageData struct {
TablerPageData
UserSettings FormtablerUserSettingsPage
}
data := userSettingsPageData{
TablerPageData: TablerPageData{
PageTitle: "Account Settings",
PageDescription: "User account settings",
ShowTopbar: true,
Sidebar: false,
PageHeader: "Account Settings",
PagePretitle: "User Profile",
UserName: "Jane Doe",
UserRole: "Administrator",
NavbarMenu: SampleNavbarMenu(),
},
UserSettings: SampleUserSettings(),
}
return c.Response.Template("apptabler_usersettings.html", data)
}
// TablerHome renders the homepage/dashboard layout // TablerHome renders the homepage/dashboard layout
func TablerHome(c *core.Context) *core.Response { func TablerHome(c *core.Context) *core.Response {
data := TablerPageData{ data := TablerPageData{

View file

@ -44,6 +44,45 @@ func SampleNavbarMenu() TablerMenu {
} }
} }
// SampleAdminUsers returns sample data for the admin users page.
func SampleAdminUsers() AdminUsersPage {
return AdminUsersPage{
AddLink: "/admin/users/add",
Users: []AdminUserRow{
{Name: "Paweł Kuna", Email: "pawel.kuna@example.com", Status: "Active", Roles: "Administrator, Editor", EditLink: "/admin/users/edit/1"},
{Name: "Jane Doe", Email: "jane.doe@example.com", Status: "Active", Roles: "Editor", EditLink: "/admin/users/edit/2"},
{Name: "Jeffie Lewzey", Email: "jlewzey@seesaa.net", Status: "Invited", Roles: "Viewer", EditLink: "/admin/users/edit/3"},
{Name: "Mallory Hulme", Email: "mhulme@domainmarket.com", Status: "Active", Roles: "Administrator", EditLink: "/admin/users/edit/4"},
{Name: "Dunn Slane", Email: "dslane@epa.gov", Status: "Inactive", Roles: "Editor, Viewer", EditLink: "/admin/users/edit/5"},
},
}
}
// SampleUserSettings returns sample data for the user settings page.
func SampleUserSettings() FormtablerUserSettingsPage {
return FormtablerUserSettingsPage{
ActiveTab: "My Account",
SidebarSections: []FormtablerUserSettingsSection{
{
Title: "Business settings",
SubItems: []FormtablerUserSettingsNavItem{
{Title: "My Account", Link: "/user/settings", Active: true},
{Title: "My Notifications", Link: "#"},
{Title: "Connected Apps", Link: "#"},
{Title: "Plans", Link: "#"},
{Title: "Billing & Invoices", Link: "#"},
},
},
{
Title: "Experience",
SubItems: []FormtablerUserSettingsNavItem{
{Title: "Give Feedback", Link: "#"},
},
},
},
}
}
// SampleComponents returns sample data for alerts, breadcrumbs, and toasts. // SampleComponents returns sample data for alerts, breadcrumbs, and toasts.
func SampleComponents() FormtablerComponentsPage { func SampleComponents() FormtablerComponentsPage {
return FormtablerComponentsPage{ return FormtablerComponentsPage{

View file

@ -481,6 +481,45 @@ type FormtablerComponentsPage struct {
Toasts []FormtablerToast Toasts []FormtablerToast
} }
// FormtablerUserSettingsSection represents a section in the settings sidebar.
type FormtablerUserSettingsSection struct {
Title string
SubItems []FormtablerUserSettingsNavItem
}
// FormtablerUserSettingsNavItem represents a single navigation item in the settings sidebar.
type FormtablerUserSettingsNavItem struct {
Title string
Link string
Active bool
}
// FormtablerUserSettingsPage holds the data for the user settings page.
type FormtablerUserSettingsPage struct {
SidebarSections []FormtablerUserSettingsSection
ActiveTab string
}
// AdminUserRow represents a single user in the admin users list.
type AdminUserRow struct {
Name string
Email string
Status string // "Active", "Inactive", "Invited"
Roles string // comma-separated role names
EditLink string
}
// AdminUsersPage holds the data for the admin users page.
type AdminUsersPage struct {
Users []AdminUserRow
AddLink string
}
// AdminCustomersPage holds the data for the admin customers listing page.
type AdminCustomersPage struct {
Customers []CustomerTableRow
}
// AuthLockPageData holds the data for the account lock page. // AuthLockPageData holds the data for the account lock page.
type AuthLockPageData struct { type AuthLockPageData struct {
PersonName string PersonName string

View file

@ -36,8 +36,8 @@ func registerRoutes() {
controller.Post("/reset-password/code/:code", controllers.SetNewPassword) controller.Post("/reset-password/code/:code", controllers.SetNewPassword)
// Uncomment the lines below to enable user administration // Uncomment the lines below to enable user administration
controller.Get("/admin/users", controllers.AdminUsersList) //controller.Get("/admin/users", controllers.AdminUsersList)
controller.Post("/admin/users", controllers.AdminUsersList) //controller.Post("/admin/users", controllers.AdminUsersList)
controller.Get("/admin/users/add", controllers.AdminUsersAdd) controller.Get("/admin/users/add", controllers.AdminUsersAdd)
controller.Post("/admin/users/add", controllers.AdminUsersAdd) controller.Post("/admin/users/add", controllers.AdminUsersAdd)
controller.Get("/admin/users/edit/:id", controllers.AdminUsersEdit) controller.Get("/admin/users/edit/:id", controllers.AdminUsersEdit)
@ -77,6 +77,13 @@ func registerRoutes() {
controller.Post("/user/forgot", controllers.UserForgot) controller.Post("/user/forgot", controllers.UserForgot)
controller.Get("/user/lock", controllers.UserLock) controller.Get("/user/lock", controllers.UserLock)
controller.Post("/user/lock", controllers.UserLock) controller.Post("/user/lock", controllers.UserLock)
controller.Get("/user/settings", controllers.UserSettings)
controller.Post("/user/settings", controllers.UserSettings)
controller.Get("/admin/users", controllers.AdminUsers)
controller.Post("/admin/users", controllers.AdminUsers)
controller.Get("/admin/customers", controllers.AdminCustomers)
controller.Post("/admin/customers", controllers.AdminCustomers)
controller.Get("/tablertable", controllers.TablerTables) controller.Get("/tablertable", controllers.TablerTables)
controller.Get("/tablerformelements", controllers.TablerFormElements) controller.Get("/tablerformelements", controllers.TablerFormElements)

View file

@ -0,0 +1,96 @@
{{template "base_header" .}}
{{$admin := .AdminUsers}}
<div class="page">
{{if .ShowTopbar}}
{{template "tabler_navbar" .}}
{{end}}
<div class="page-wrapper">
{{if .PageHeader}}
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
{{if .PagePretitle}}
<div class="page-pretitle">
{{.PagePretitle}}
</div>
{{end}}
<h1 class="page-title">
{{.PageHeader}}
</h1>
</div>
<div class="col-auto ms-auto d-print-none">
<div class="btn-list">
<a href="{{$admin.AddLink}}" class="btn btn-primary d-none d-sm-inline-block">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path d="M12 5l0 14"></path><path d="M5 12l14 0"></path></svg>
Create new user
</a>
</div>
</div>
</div>
</div>
</div>
{{end}}
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="table-responsive">
<table class="table table-vcenter card-table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Status</th>
<th>Roles</th>
<th class="w-1"></th>
</tr>
</thead>
<tbody>
{{range $admin.Users}}
<tr>
<td>
<div class="d-flex py-1 align-items-center">
<span class="avatar avatar-sm me-2" style="background-image: url(/static/avatars/{{.Name | truncate 3}}.jpg)"></span>
<div class="flex-fill">
<div class="font-weight-medium">{{.Name}}</div>
</div>
</div>
</td>
<td class="text-secondary">{{.Email}}</td>
<td>
{{if eq .Status "Active"}}
<span class="status-dot status-dot-animated bg-green"></span>
{{else if eq .Status "Inactive"}}
<span class="status-dot bg-muted"></span>
{{else if eq .Status "Invited"}}
<span class="status-dot bg-blue"></span>
{{end}}
{{.Status}}
</td>
<td>
<div class="row g-1">
{{range split ", " .Roles}}
<div class="col-auto">
<span class="badge bg-blue-lt text-uppercase">{{.}}</span>
</div>
{{end}}
</div>
</td>
<td>
<a href="{{.EditLink}}" class="btn btn-ghost btn-sm">Edit</a>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
</div>
{{template "tabler_footer" .}}
</div>
</div>
{{template "base_footer" .}}

View file

@ -0,0 +1,165 @@
{{template "base_header" .}}
{{$admin := .AdminCustomers}}
<div class="page">
{{if .ShowTopbar}}
{{template "tabler_navbar" .}}
{{end}}
<div class="page-wrapper">
{{if .PageHeader}}
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
{{if .PagePretitle}}
<div class="page-pretitle">
{{.PagePretitle}}
</div>
{{end}}
<h1 class="page-title">
{{.PageHeader}}
</h1>
</div>
<div class="col-auto ms-auto d-print-none">
<div class="btn-list">
<a href="#" class="btn btn-primary d-none d-sm-inline-block">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path d="M12 5l0 14"></path><path d="M5 12l14 0"></path></svg>
Add customer
</a>
</div>
</div>
</div>
</div>
</div>
{{end}}
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="card-header">
<div class="row w-full">
<div class="col">
<h3 class="card-title mb-0">Customers</h3>
<p class="text-secondary m-0">Manage your customer relationships.</p>
</div>
<div class="col-md-auto col-sm-12">
<div class="ms-auto d-flex flex-wrap btn-list">
<div class="input-group input-group-flat w-auto">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path d="M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0"></path><path d="M21 21l-6 -6"></path></svg>
</span>
<input type="text" class="form-control" placeholder="Search customers…">
</div>
<a href="#" class="btn btn-icon" aria-label="More options">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path d="M5 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M19 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg>
</a>
</div>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table table-vcenter card-table">
<thead>
<tr>
<th class="w-1"><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select all"></th>
<th>Name</th>
<th>Location</th>
<th>Status</th>
<th>Start date</th>
<th>Tags</th>
<th>Department</th>
<th class="w-1"></th>
</tr>
</thead>
<tbody>
{{range $i, $customer := $admin.Customers}}
<tr>
<td><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select customer {{$i}}"></td>
<td>
<div class="d-flex py-1 align-items-center">
<span class="avatar avatar-sm me-2" style="background-image: url(/static/avatars/{{.AvatarID}}.jpg)"></span>
<div class="flex-fill">
<div class="font-weight-medium">{{.FullName}}</div>
<div class="text-secondary"><a href="#" class="text-reset">{{.Email}}</a></div>
</div>
</div>
</td>
<td>
<div>{{.City}}</div>
<div class="text-secondary">{{.Country}}</div>
</td>
<td>
{{if eq .Status "VIP"}}
<span class="badge bg-blue-lt text-uppercase">{{.Status}}</span>
{{else if eq .Status "New"}}
<span class="badge bg-green-lt text-uppercase">{{.Status}}</span>
{{else}}
<span class="badge bg-muted-lt text-uppercase">{{.Status}}</span>
{{end}}
</td>
<td class="text-secondary">{{.Date}}</td>
<td>
<div class="row g-1">
{{range .Tags}}
<div class="col-auto">
<span class="badge bg-green-lt text-uppercase">{{.}}</span>
</div>
{{end}}
</div>
</td>
<td>
<span class="badge bg-muted-lt text-uppercase">{{.Department}}</span>
</td>
<td>
<div class="btn-list flex-nowrap">
<a href="#" class="btn btn-ghost btn-sm">Edit</a>
<div class="dropdown">
<button class="btn btn-ghost btn-icon btn-sm" data-bs-toggle="dropdown">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path d="M5 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M19 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Edit</a>
<a class="dropdown-item" href="#">Duplicate</a>
<a class="dropdown-item text-danger" href="#">Delete</a>
</div>
</div>
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="card-footer d-flex align-items-center">
<div class="dropdown">
<a class="btn dropdown-toggle" data-bs-toggle="dropdown">
<span class="me-1">20</span>
<span>records</span>
</a>
<div class="dropdown-menu">
<a class="dropdown-item">10 records</a>
<a class="dropdown-item active">20 records</a>
<a class="dropdown-item">50 records</a>
<a class="dropdown-item">100 records</a>
</div>
</div>
<ul class="pagination ms-auto mb-0">
<li class="page-item disabled"><a class="page-link"></a></li>
<li class="page-item active"><a class="page-link">1</a></li>
<li class="page-item"><a class="page-link">2</a></li>
<li class="page-item"><a class="page-link">3</a></li>
<li class="page-item"><a class="page-link">4</a></li>
<li class="page-item"><a class="page-link">5</a></li>
<li class="page-item"><a class="page-link"></a></li>
</ul>
</div>
</div>
</div>
</div>
{{template "tabler_footer" .}}
</div>
</div>
{{template "base_footer" .}}

View file

@ -0,0 +1,111 @@
{{template "base_header" .}}
{{$s := .UserSettings}}
<div class="page">
{{if .ShowTopbar}}
{{template "tabler_navbar" .}}
{{end}}
<div class="page-wrapper">
{{if .PageHeader}}
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
{{if .PagePretitle}}
<div class="page-pretitle">
{{.PagePretitle}}
</div>
{{end}}
<h1 class="page-title">
{{.PageHeader}}
</h1>
</div>
</div>
</div>
</div>
{{end}}
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="row g-0">
<div class="col-12 col-md-3 border-end">
<div class="card-body">
{{range $s.SidebarSections}}
<h4 class="subheader">{{.Title}}</h4>
<nav class="list-group list-group-transparent mb-4">
{{range .SubItems}}
<a href="{{.Link}}" class="list-group-item list-group-item-action d-flex align-items-center{{if .Active}} active{{end}}">{{.Title}}</a>
{{end}}
</nav>
{{end}}
</div>
</div>
<div class="col-12 col-md-9 d-flex flex-column">
<div class="card-body">
<h3 class="card-title">{{defaultVal "My Account" $s.ActiveTab}}</h3>
<div class="row mb-3">
<div class="col-auto">
<span class="avatar avatar-xl" style="background-image: url(/static/avatars/000m.jpg)"></span>
</div>
<div class="col align-self-center">
<div class="text-secondary mt-1">Paweł Kuna</div>
<a href="#" class="btn btn-sm btn-outline-primary mt-2">Change avatar</a>
</div>
</div>
<h4 class="subheader">Personal Information</h4>
<div class="row mb-3">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">First Name</label>
<input type="text" class="form-control" value="Paweł">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Last Name</label>
<input type="text" class="form-control" value="Kuna">
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Email address</label>
<input type="email" class="form-control" value="pawel.kuna@example.com">
</div>
<div class="mb-3">
<label class="form-label">Bio</label>
<textarea class="form-control" rows="3" placeholder="Write a short bio...">UI Designer at Tabler</textarea>
</div>
<h4 class="subheader">Password</h4>
<div class="row mb-3">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Current Password</label>
<input type="password" class="form-control" placeholder="Leave blank to keep unchanged">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">New Password</label>
<input type="password" class="form-control" placeholder="Leave blank to keep unchanged">
</div>
</div>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{template "tabler_footer" .}}
</div>
</div>
{{template "base_footer" .}}

View file

@ -21,7 +21,7 @@
<td> <td>
{{if eq .Type "avatar"}} {{if eq .Type "avatar"}}
<div class="d-flex py-1 align-items-center"> <div class="d-flex py-1 align-items-center">
<span class="avatar me-2" style="background-image: url(/static/avatars/{{.AvatarID}}.jpg)"></span> <span class="avatar me-2" style="background-image: url(/public/static/avatars/{{.AvatarID}}.jpg)"></span>
<div class="flex-fill"> <div class="flex-fill">
<div class="font-weight-medium">{{.Value}}</div> <div class="font-weight-medium">{{.Value}}</div>
{{if .Subtext}}<div class="text-secondary"><a href="#" class="text-reset">{{.Subtext}}</a></div>{{end}} {{if .Subtext}}<div class="text-secondary"><a href="#" class="text-reset">{{.Subtext}}</a></div>{{end}}