@@ -6,6 +6,8 @@ package scaffold
66
77import (
88 " fmt"
9+ " time"
10+
911 icons " github.com/iota-uz/icons/phosphor"
1012 " github.com/iota-uz/iota-sdk/components/base"
1113 " github.com/iota-uz/iota-sdk/components/base/button"
@@ -14,9 +16,9 @@ import (
1416 " github.com/iota-uz/iota-sdk/components/loaders"
1517 " github.com/iota-uz/iota-sdk/modules/core/presentation/templates/layouts"
1618 " github.com/iota-uz/iota-sdk/pkg/composables"
17- " time"
1819)
1920
21+ // DateTime renders a timestamp with Alpine-based relative formatting
2022templ DateTime (ts time.Time ) {
2123 <div x-data =" relativeformat" >
2224 <span x-text ={ fmt.Sprintf (` format('%s')` , ts.Format (time.RFC3339 )) }>
@@ -30,17 +32,13 @@ templ Rows(config *TableConfig) {
3032 <tr class =" hidden" >
3133 <td colspan ={ fmt.Sprintf (" %d " , len (config.Columns )) }>
3234 @ loaders.Spinner (loaders.SpinnerProps {
33- ContainerClass : templ.Classes (
34- " flex justify-center items-center py-4" ,
35- ),
35+ ContainerClass : templ.Classes (" flex justify-center items-center py-4" ),
3636 })
3737 </td >
3838 </tr >
3939 for _ , item := range config.Rows {
4040 @ base.TableRow (base.TableRowProps {
41- Attrs : templ.Attributes {
42- " class" : " hide-on-load" ,
43- },
41+ Attrs : templ.Attributes {" class" : " hide-on-load" },
4442 }) {
4543 for _ , cell := range item.Cells () {
4644 @ base.TableCell (base.TableCellProps {}) {
@@ -71,40 +69,54 @@ templ Table(config *TableConfig) {
7169 }
7270}
7371
74- // TableContent renders the table with search and filters
75- templ TableContent (config *TableConfig) {
72+ // TableSection combines filters and table into one form to enable unified HTMX update
73+ templ TableSection (config *TableConfig) {
7674 {{ pageCtx := composables.UsePageCtx (ctx) }}
77- <div class =" bg-surface-600 border border-primary rounded-lg" >
78- <form
79- class =" p-4 flex items-center gap-3"
80- hx-get ={ config.DataURL }
81- hx-push-url =" true"
82- hx-trigger =" keyup changed delay:300ms from:(form input), change changed from:(form select), change from:(form input[type='checkbox'])"
83- hx-target =" #table-body"
84- hx-swap =" innerHTML"
85- hx-indicator =" #table-body"
86- >
87- <input type =" hidden" name =" page" value =" 1" />
88- <div class =" flex-1" >
89- @ input.Text (&input.Props {
90- AddonLeft : &input.Addon {
91- Component: icons.MagnifyingGlass (icons.Props {Size: " 20" }),
92- },
93- Placeholder : pageCtx.T (" Search" ),
94- Attrs : templ.Attributes {
95- " name" : " search" ,
96- " value" : " " ,
97- },
98- })
75+ <form
76+ hx-get ={ config.DataURL }
77+ hx-push-url =" true"
78+ hx-trigger =" keyup changed delay:300ms from:(form input), change from:(form select), change from:(form input[type='checkbox'])"
79+ hx-target =" #table-body"
80+ hx-swap =" innerHTML"
81+ hx-indicator =" #table-body"
82+ class =" flex flex-col md:flex-row gap-5"
83+ x-data =" checkboxes"
84+ x-init =" init"
85+ >
86+ <!-- Left sidebar with filters -->
87+ if config.SideFilter != nil {
88+ <div class =" hidden md:block w-64 flex-shrink-0" >
89+ <div class =" bg-surface-600 border border-primary rounded-lg p-4 mb-4" >
90+ @ config.SideFilter
91+ </div >
9992 </div >
100- <div class =" hidden md:flex gap-3 h-full" >
101- for _ , filter := range config.Filters {
102- @ filter
103- }
93+ }
94+ <!-- Main content area with search, filters, and table -->
95+ <div class =" flex-1" >
96+ <div class =" bg-surface-600 border border-primary rounded-lg" >
97+ <div class =" p-4 flex flex-col md:flex-row md:items-center gap-3" >
98+ <div class =" flex-1" >
99+ @ input.Text (&input.Props {
100+ AddonLeft : &input.Addon {
101+ Component: icons.MagnifyingGlass (icons.Props {Size: " 20" }),
102+ },
103+ Placeholder : pageCtx.T (" Search" ),
104+ Attrs : templ.Attributes {
105+ " name" : " search" ,
106+ " value" : " " ,
107+ },
108+ })
109+ </div >
110+ <div class =" hidden md:flex gap-3 h-full" >
111+ for _ , filter := range config.Filters {
112+ @ filter
113+ }
114+ </div >
115+ </div >
116+ @ Table (config)
104117 </div >
105- </form >
106- @ Table (config)
107- </div >
118+ </div >
119+ </form >
108120}
109121
110122// Content renders the complete scaffold page content with filters and table
@@ -135,35 +147,9 @@ templ Content(config *TableConfig) {
135147 })
136148 </div >
137149 </div >
138- if config.SideFilter != nil {
139- <div class =" mt-5 flex gap-5" >
140- <!-- Left sidebar with filters -->
141- <div class =" hidden md:block w-64 flex-shrink-0" >
142- <div class =" bg-surface-600 border border-primary rounded-lg p-4 mb-4" >
143- <form
144- hx-get ={ config.DataURL }
145- hx-target =" #table-body"
146- hx-swap =" innerHTML"
147- hx-push-url =" true"
148- hx-indicator =" #table-body"
149- hx-trigger =" change"
150- x-data =" checkboxes"
151- x-init =" init"
152- >
153- @ config.SideFilter
154- </form >
155- </div >
156- </div >
157- <!-- Main content area with table -->
158- <div class =" flex-1" >
159- @ TableContent (config)
160- </div >
161- </div >
162- } else {
163- <div class =" mt-5" >
164- @ TableContent (config)
165- </div >
166- }
150+ <div class =" mt-5" >
151+ @ TableSection (config)
152+ </div >
167153 </div >
168154}
169155
@@ -176,6 +162,7 @@ templ Page(config *TableConfig) {
176162 }
177163}
178164
165+ // Helper to convert scaffold columns to base table columns
179166func toBaseTableColumns (columns []TableColumn ) []*base .TableColumn {
180167 result := make ([]*base.TableColumn , len (columns))
181168 for i , col := range columns {
0 commit comments