@@ -6,6 +6,8 @@ package scaffold
6
6
7
7
import (
8
8
" fmt"
9
+ " time"
10
+
9
11
icons " github.com/iota-uz/icons/phosphor"
10
12
" github.com/iota-uz/iota-sdk/components/base"
11
13
" github.com/iota-uz/iota-sdk/components/base/button"
@@ -14,9 +16,9 @@ import (
14
16
" github.com/iota-uz/iota-sdk/components/loaders"
15
17
" github.com/iota-uz/iota-sdk/modules/core/presentation/templates/layouts"
16
18
" github.com/iota-uz/iota-sdk/pkg/composables"
17
- " time"
18
19
)
19
20
21
+ // DateTime renders a timestamp with Alpine-based relative formatting
20
22
templ DateTime (ts time.Time ) {
21
23
<div x-data =" relativeformat" >
22
24
<span x-text ={ fmt.Sprintf (` format('%s')` , ts.Format (time.RFC3339 )) }>
@@ -30,17 +32,13 @@ templ Rows(config *TableConfig) {
30
32
<tr class =" hidden" >
31
33
<td colspan ={ fmt.Sprintf (" %d " , len (config.Columns )) }>
32
34
@ 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" ),
36
36
})
37
37
</td >
38
38
</tr >
39
39
for _ , item := range config.Rows {
40
40
@ base.TableRow (base.TableRowProps {
41
- Attrs : templ.Attributes {
42
- " class" : " hide-on-load" ,
43
- },
41
+ Attrs : templ.Attributes {" class" : " hide-on-load" },
44
42
}) {
45
43
for _ , cell := range item.Cells () {
46
44
@ base.TableCell (base.TableCellProps {}) {
@@ -71,40 +69,54 @@ templ Table(config *TableConfig) {
71
69
}
72
70
}
73
71
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) {
76
74
{{ 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 >
99
92
</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)
104
117
</div >
105
- </form >
106
- @ Table (config)
107
- </div >
118
+ </div >
119
+ </form >
108
120
}
109
121
110
122
// Content renders the complete scaffold page content with filters and table
@@ -135,35 +147,9 @@ templ Content(config *TableConfig) {
135
147
})
136
148
</div >
137
149
</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 >
167
153
</div >
168
154
}
169
155
@@ -176,6 +162,7 @@ templ Page(config *TableConfig) {
176
162
}
177
163
}
178
164
165
+ // Helper to convert scaffold columns to base table columns
179
166
func toBaseTableColumns (columns []TableColumn ) []*base .TableColumn {
180
167
result := make ([]*base.TableColumn , len (columns))
181
168
for i , col := range columns {
0 commit comments