package pages import ( "log/slog" "tasksquire/common" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" ) type ProjectPickerPage struct { common *common.Common form *huh.Form } func NewProjectPickerPage(common *common.Common, activeProject string) *ProjectPickerPage { p := &ProjectPickerPage{ common: common, } var selected string if activeProject == "" { selected = "(none)" } else { selected = activeProject } projects := common.TW.GetProjects() options := []string{"(none)"} options = append(options, projects...) p.form = huh.NewForm( huh.NewGroup( huh.NewSelect[string](). Key("project"). Options(huh.NewOptions(options...)...). Title("Projects"). Description("Choose a project"). Value(&selected). WithTheme(common.Styles.Form), ), ). WithShowHelp(false). WithShowErrors(false) p.SetSize(common.Width(), common.Height()) return p } func (p *ProjectPickerPage) SetSize(width, height int) { p.common.SetSize(width, height) if width >= 20 { p.form = p.form.WithWidth(20) } else { p.form = p.form.WithWidth(width) } if height >= 30 { p.form = p.form.WithHeight(30) } else { p.form = p.form.WithHeight(height) } } func (p *ProjectPickerPage) Init() tea.Cmd { return p.form.Init() } func (p *ProjectPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: p.SetSize(msg.Width, msg.Height) case tea.KeyMsg: switch { case key.Matches(msg, p.common.Keymap.Back): model, err := p.common.PopPage() if err != nil { slog.Error("page stack empty") return nil, tea.Quit } return model, BackCmd } } f, cmd := p.form.Update(msg) if f, ok := f.(*huh.Form); ok { p.form = f cmds = append(cmds, cmd) } if p.form.State == huh.StateCompleted { cmds = append(cmds, p.updateProjectCmd) model, err := p.common.PopPage() if err != nil { slog.Error("page stack empty") return nil, tea.Quit } return model, tea.Batch(cmds...) } return p, tea.Batch(cmds...) } func (p *ProjectPickerPage) View() string { return lipgloss.Place( p.common.Width(), p.common.Height(), lipgloss.Center, lipgloss.Center, p.common.Styles.Base.Render(p.form.View()), ) } func (p *ProjectPickerPage) updateProjectCmd() tea.Msg { project := p.form.GetString("project") if project == "(none)" { project = "" } return UpdateProjectMsg(project) } type UpdateProjectMsg string