package builder
import (
"fmt"
"slices"
"github.com/acaloiaro/frm"
"github.com/acaloiaro/frm/types"
"github.com/acaloiaro/frm/ui"
"github.com/acaloiaro/frm/ui/collector"
"github.com/acaloiaro/frm/ui/fields"
"github.com/acaloiaro/frm/ui/selector"
"github.com/google/uuid"
)
// Application DOM events
const (
// FieldsFormEvent is the event triggered when any of a form's fields have been updated in the UI. When triggered,
// the fields form pushes updates from the UI to the draft form on the backend.
FieldsFormUpdateEvent = "fields-form-updated"
// FormSettingsEvent is the event triggered when any of a form's settings have been updated in the UI. When triggered,
// the fields form pushes updates from the UI to the draft form on the backend.
FormSettingsUpdateEvent = "form-settings-updated"
// LogicConfiguratorTargetFieldSelected is the event triggered when a form field is selected as a the target for field logic
LogicConfiguratorTargetFieldSelected = "logic-configurator-target-field-selected"
)
// Logic field group form field names
const (
// FieldLogicChosenFieldID is the name of a HTML form field. The value of the form field with this name represents the field that was chosen as the target for field-specific logic.
FieldLogicTargetFieldID = "target_field_id"
// FieldLogicComparator is the name of a HTML form field. The value of the form field represents the boolean comparator to be used to evaluate the chosen field against its field value.
FieldLogicComparator = "comparator"
// FieldLogicChosenFieldValue is the name of a HTML Form field. The value of the form field represents the value that the target field's value is compared against when deciding whether or not to display a field in the UI.
FieldLogicTargetFieldValue = "target_field_value"
// FieldLogicActions is the name of a HTML form field. The value of the form field represents the actions to be taken when the field's logic evaluates truthfully
FieldLogicActions = "actions"
)
// Field groups within the the form field configuration screen
const (
FieldGroupLogic = "logic"
)
// Builder is the primary form builder UI, surrounded by the app chrome
templ Builder(form frm.Form) {
@ui.App("Form builder") {
@FormBuilderNav(form)
@builderColumnLeft(form)
@collector.FormPreview(collector.ViewerArgs{Preview: true, Form: form})
@builderColumnRight(form)
}
}
// FormBuilderNavTitle renders the title of the form in the nav bar. This is a separate template so that the title can be updated when settings change, without updating, and losing the state of, the rest of the nav bar
templ FormBuilderNavTitle(form frm.Form) {
{ form.Name }
}
// FormBuilderNav is the top-of-the-page navigation bar
templ FormBuilderNav(form frm.Form) {
@ui.MutedButton(ui.ButtonArgs{Label: "Build", Classes: []string{"cursor-pointer tab-active [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{
"role": "tab",
"tabindex": 0,
"_": "on click take .tab-active from .tab-active then add .hidden to .active-section then take .active-section for #form-fields then remove .hidden from #form-fields",
})
@ui.MutedButton(ui.ButtonArgs{Label: "Settings", Classes: []string{"cursor-pointer [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{
"role": "tab",
"tabindex": 2,
"_": "on click take .tab-active from .tab-active then add .hidden to .active-section take .active-section for #settings-main then remove .hidden from #settings-main",
})
@FormBuilderNavTitle(form)
}
// FormSettings is the UI for configuring form-level settings.
templ FormSettings(form frm.Form) {
}
// builderColumnLeft is the left-hand panel of the form builder UI
templ builderColumnLeft(form frm.Form) {
@FormFields(form)
@FormSettings(form)
}
// FormFields lists a form's fields as a sortable list, that when re-sorted, updates the fields' sort order in the form
templ FormFields(form frm.Form) {
@FormFieldsForm(form)
}
// FormFieldsForm is the list of fields on the left-hand side of the screen that displays a sorted list of form fields
templ FormFieldsForm(form frm.Form) {
@ui.Button(ui.ButtonArgs{
Label: "Add field",
Classes: []string{"flex-grow", "justify-center", "uppercase"},
}, templ.Attributes{
"_": "on click toggle .hidden on .active-configurator then take .active-configurator from .active-configurator for #configure-add-field then remove .hidden from #configure-add-field",
}) {
@ui.HeroIcon("solid", "plus")
}
}
// builerColumnRight is the right-hand panel of the form build UI, used for adding and configuring fields
templ builderColumnRight(form frm.Form) {
Add field
for i, fieldType := range types.FormFieldTypeValues() {
@FormFieldConfigurator(form)
}
// FormFieldConfigurator is the view on the right-hand side of the screen for configuring individual fields
templ FormFieldConfigurator(form frm.Form) {
}
// fieldSettingsConfiguration configures the settings for a specific field
// FIELD_TYPES: field types may be added/modified/removed below
templ fieldSettingsConfiguration(form frm.Form, field types.FormField) {
@fields.RequiredFieldIndicator()
switch field.Type {
case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect, types.FormFieldTypeSingleChoice, types.FormFieldTypeSingleChoiceSpaced: