Problem
appModel in model.go:1–111 carries ~40 peer fields mixing two concerns:
- Domain state:
goals, config, selectedGoal, error info
- UI state: cursor position, search query + active flag, modal visibility, input focus index, input mode flag, loading/refreshing flags, per-field input buffers (datapoint value, datapoint comment, slug, title, goal type, gunits, goaldate, goalval, rate)
handlers.go:30–485 reaches directly into these fields to mutate them. There is no seam between "what the user is trying to do" (submit a datapoint for goal X with value Y) and "how the UI is tracking that in flight" (which textbox is focused, what's been typed so far, is the modal open).
The cost shows up in test coverage: handlers_test.go tests the helper validators (validateDatapointInput, validateCreateGoalInput) but does not test the interactive handlers, because constructing an appModel for a single interaction requires populating dozens of unrelated fields. Bugs in the interaction between character filters (isAlphanumericOrDash, isLetter, isNumericOrNull, isNumericWithDecimal) and form validation only surface in manual TUI use.
Proposed direction (subject to grilling)
Split appModel into:
- a domain state holding goals + config + selection
- one or more UI sub-states for modals (datapoint entry, goal creation, search), each owning its own input buffers and focus
Handlers then operate on a sub-state, not the world.
Caveat — lower confidence than the API/deadline/table issues
Bubble Tea idioms push toward big model structs. This refactor fights the framework somewhat. Worth grilling before committing.
Files involved
model.go:1–111
handlers.go:30–485
Problem
appModelinmodel.go:1–111carries ~40 peer fields mixing two concerns:goals,config,selectedGoal, error infohandlers.go:30–485reaches directly into these fields to mutate them. There is no seam between "what the user is trying to do" (submit a datapoint for goal X with value Y) and "how the UI is tracking that in flight" (which textbox is focused, what's been typed so far, is the modal open).The cost shows up in test coverage:
handlers_test.gotests the helper validators (validateDatapointInput,validateCreateGoalInput) but does not test the interactive handlers, because constructing anappModelfor a single interaction requires populating dozens of unrelated fields. Bugs in the interaction between character filters (isAlphanumericOrDash,isLetter,isNumericOrNull,isNumericWithDecimal) and form validation only surface in manual TUI use.Proposed direction (subject to grilling)
Split
appModelinto:Handlers then operate on a sub-state, not the world.
Caveat — lower confidence than the API/deadline/table issues
Bubble Tea idioms push toward big model structs. This refactor fights the framework somewhat. Worth grilling before committing.
Files involved
model.go:1–111handlers.go:30–485