feat: initial commit
This commit is contained in:
178
internal/http/handler/webui/common/component/field.templ
Normal file
178
internal/http/handler/webui/common/component/field.templ
Normal file
@ -0,0 +1,178 @@
|
||||
package component
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"forge.cadoles.com/wpetit/kouiz/internal/http/form"
|
||||
)
|
||||
|
||||
templ FormField(form *form.Form, id string, name string, label string) {
|
||||
{{ field := form.Field(name) }}
|
||||
if field != nil {
|
||||
<div class="field">
|
||||
{{ err, hasErr := form.Error(name) }}
|
||||
<label class={ "label", templ.KV("has-text-danger", hasErr) } for={ id }>{ label }</label>
|
||||
<div class="control">
|
||||
<input class={ "input", templ.KV("is-danger", hasErr) } id={ id } name={ field.Name() } { field.Attrs()... }/>
|
||||
if hasErr {
|
||||
<p class="help is-danger">{ err.Message() }</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
type FormTextareaOptions struct {
|
||||
Attrs map[string]any
|
||||
}
|
||||
|
||||
type FormTextareaOptionFunc func(opts *FormTextareaOptions)
|
||||
|
||||
func WithTextareaAttrs(kvAttrs ...any) FormTextareaOptionFunc {
|
||||
return func(opts *FormTextareaOptions) {
|
||||
opts.Attrs = keyValuesToAttrs(kvAttrs)
|
||||
}
|
||||
}
|
||||
|
||||
func newFormTextareaOptions(funcs ...FormTextareaOptionFunc) *FormTextareaOptions {
|
||||
opts := &FormTextareaOptions{}
|
||||
for _, fn := range funcs {
|
||||
fn(opts)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
templ FormTextarea(form *form.Form, id string, name string, label string, funcs ...FormTextareaOptionFunc) {
|
||||
{{ opts := newFormTextareaOptions(funcs...) }}
|
||||
{{ field := form.Field(name) }}
|
||||
if field != nil {
|
||||
<div class="field">
|
||||
<label class="label" for={ id }>{ label }</label>
|
||||
<div class="control">
|
||||
{{ err, hasErr := form.Error(name) }}
|
||||
{{ value, hasValue := field.Get("value") }}
|
||||
<textarea class={ "textarea", templ.KV("is-danger", hasErr) } id={ id } name={ field.Name() } { mergeAttrs(field.Attrs(), opts.Attrs)... }>
|
||||
if hasValue {
|
||||
{ value.(string) }
|
||||
}
|
||||
</textarea>
|
||||
if hasErr {
|
||||
<p class="help is-danger">{ err.Message() }</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
type FormSelectOptions struct {
|
||||
Options []formSelectOption
|
||||
Attrs map[string]any
|
||||
}
|
||||
|
||||
type FormSelectOptionFunc func(opts *FormSelectOptions)
|
||||
|
||||
func WithOptions(kvOptions ...string) FormSelectOptionFunc {
|
||||
return func(opts *FormSelectOptions) {
|
||||
opts.Options = keyValuesToOptions(kvOptions)
|
||||
}
|
||||
}
|
||||
|
||||
func WithAttrs(kvAttrs ...any) FormSelectOptionFunc {
|
||||
return func(opts *FormSelectOptions) {
|
||||
opts.Attrs = keyValuesToAttrs(kvAttrs)
|
||||
}
|
||||
}
|
||||
|
||||
func keyValuesToAttrs(kv []any) map[string]any {
|
||||
if len(kv)%2 != 0 {
|
||||
panic(errors.New("expected pair number of key/values"))
|
||||
}
|
||||
|
||||
attrs := make(map[string]any, 0)
|
||||
|
||||
var key string
|
||||
for idx := range kv {
|
||||
if idx%2 == 0 {
|
||||
key = kv[idx].(string)
|
||||
continue
|
||||
}
|
||||
|
||||
attrs[key] = kv[idx]
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
type formSelectOption struct {
|
||||
Value string
|
||||
Label string
|
||||
}
|
||||
|
||||
func keyValuesToOptions(kv []string) []formSelectOption {
|
||||
if len(kv)%2 != 0 {
|
||||
panic(errors.New("expected pair number of key/values"))
|
||||
}
|
||||
|
||||
options := make([]formSelectOption, 0)
|
||||
|
||||
var key string
|
||||
for idx := range kv {
|
||||
if idx%2 == 0 {
|
||||
key = kv[idx]
|
||||
continue
|
||||
}
|
||||
|
||||
options = append(options, formSelectOption{
|
||||
Value: kv[idx],
|
||||
Label: key,
|
||||
})
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
func newFormSelectOptions(funcs ...FormSelectOptionFunc) *FormSelectOptions {
|
||||
opts := &FormSelectOptions{}
|
||||
for _, fn := range funcs {
|
||||
fn(opts)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
templ FormSelect(form *form.Form, id string, name string, label string, funcs ...FormSelectOptionFunc) {
|
||||
{{ opts := newFormSelectOptions(funcs...) }}
|
||||
{{ field := form.Field(name) }}
|
||||
if field != nil {
|
||||
<div class="field">
|
||||
<label class="label" for={ id }>{ label }</label>
|
||||
<div class="control">
|
||||
{{ err, hasErr := form.Error(name) }}
|
||||
{{ value, hasValue := field.Get("value") }}
|
||||
<div class="select is-fullwidth">
|
||||
<select id={ id } name={ field.Name() } { mergeAttrs(field.Attrs(), opts.Attrs)... }>
|
||||
for _, o := range opts.Options {
|
||||
<option
|
||||
if hasValue && value == o.Value {
|
||||
selected
|
||||
}
|
||||
value={ o.Value }
|
||||
>{ o.Label }</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
if hasErr {
|
||||
<p class="help is-danger">{ err.Message() }</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
func mergeAttrs(attrs ...map[string]any) map[string]any {
|
||||
merged := make(form.Attrs)
|
||||
for _, a := range attrs {
|
||||
for k, v := range a {
|
||||
merged[k] = v
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
Reference in New Issue
Block a user