package fields
import (
"encoding/json"
"fmt"
"sort"
"github.com/acaloiaro/frm"
"github.com/acaloiaro/frm/ui/selector"
"github.com/acaloiaro/frm/types"
"github.com/google/uuid"
)
// RequiredFieldIndicator visually indicates that a field is required
templ RequiredFieldIndicator() {
*
}
// FieldLabel is a HTML label for a field
templ FieldLabel(field types.FormField) {
}
templ FieldTypeIcon(fieldType types.FormFieldType) {
switch int(fieldType) {
case int(types.FormFieldTypeTextSingle), int(types.FormFieldTypeTextMultiple):
case int(types.FormFieldTypeSingleSelect), int(types.FormFieldTypeMultiSelect):
case int(types.FormFieldTypeSingleChoice), int(types.FormFieldTypeSingleChoiceSpaced):
}
}
// View displays fields with the appropriate UI component
templ View(field types.FormField) {
switch field.Type {
case types.FormFieldTypeTextSingle:
@singleLineTextView(field)
case types.FormFieldTypeTextMultiple:
@multiLineTextView(field)
case types.FormFieldTypeSingleSelect, types.FormFieldTypeMultiSelect:
@selectView(field)
case types.FormFieldTypeSingleChoice:
@SingleChoice(field)
case types.FormFieldTypeSingleChoiceSpaced:
@SingleChoiceSpaced(field)
}
}
templ singleLineTextView(field types.FormField) {
@FieldLabel(field)
}
templ multiLineTextView(field types.FormField) {
@FieldLabel(field)
}
templ selectView(field types.FormField) {
@selector.Selector(selector.SelectArgs{
ID: field.ID.String(),
Name: field.ID.String(),
Label: field.Label,
LabelClass: "text-slate-700 text-xl py-1",
Required: field.Required,
Placeholder: field.Placeholder,
Multiple: field.Type == types.FormFieldTypeMultiSelect,
Options: ToSelectorOpts(field.Options, false),
SearchDisabled: true,
EditItems: false,
Hyperscript: fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()),
})
}
// FormFieldTypeLabel is the UI label for FormFieldTypes, e.g. 'text_single' -> "Single line text"
templ FormFieldTypeLabel(fieldType types.FormFieldType) {
@FieldTypeIcon(types.FormFieldType(fieldType))
}
// ToSelectorOpts converts a slices of types.Option to a slice of selector.Option
func ToSelectorOpts(opts []types.Option, selectAll bool) (sopts []selector.Option) {
for _, opt := range opts {
if selectAll {
opt.Selected = true
}
sopts = append(sopts, (selector.Option)(opt))
}
return
}
// ToSelectorOptsStr converts a slices of types.Option to a slice of selector.Option
func ToSelectorOptsStr(opts []string, selectAll bool) (sopts []selector.Option) {
// TODO: Fix -- adding an empty option because the first select