package pages import ( "log/slog" "tasksquire/common" "tasksquire/components/picker" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type TimespanPickerPage struct { common *common.Common picker *picker.Picker selectedTimespan string } func NewTimespanPickerPage(common *common.Common, currentTimespan string) *TimespanPickerPage { p := &TimespanPickerPage{ common: common, selectedTimespan: currentTimespan, } timespanOptions := []list.Item{ picker.NewItem(":day"), picker.NewItem(":yesterday"), picker.NewItem(":week"), picker.NewItem(":lastweek"), picker.NewItem(":month"), picker.NewItem(":lastmonth"), picker.NewItem(":year"), } itemProvider := func() []list.Item { return timespanOptions } onSelect := func(item list.Item) tea.Cmd { return func() tea.Msg { return timespanSelectedMsg{item: item} } } p.picker = picker.New(common, "Select Timespan", itemProvider, onSelect) // Select the current timespan in the picker p.picker.SelectItemByFilterValue(currentTimespan) p.SetSize(common.Width(), common.Height()) return p } func (p *TimespanPickerPage) SetSize(width, height int) { p.common.SetSize(width, height) // Set list size with some padding/limits to look like a picker listWidth := width - 4 if listWidth > 40 { listWidth = 40 } listHeight := height - 6 if listHeight > 20 { listHeight = 20 } p.picker.SetSize(listWidth, listHeight) } func (p *TimespanPickerPage) Init() tea.Cmd { return p.picker.Init() } type timespanSelectedMsg struct { item list.Item } func (p *TimespanPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: p.SetSize(msg.Width, msg.Height) case timespanSelectedMsg: timespan := msg.item.FilterValue() model, err := p.common.PopPage() if err != nil { slog.Error("page stack empty") return nil, tea.Quit } return model, func() tea.Msg { return UpdateTimespanMsg(timespan) } case tea.KeyMsg: if !p.picker.IsFiltering() { 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 } } } _, cmd = p.picker.Update(msg) return p, cmd } func (p *TimespanPickerPage) View() string { width := p.common.Width() - 4 if width > 40 { width = 40 } content := p.picker.View() styledContent := lipgloss.NewStyle().Width(width).Render(content) return lipgloss.Place( p.common.Width(), p.common.Height(), lipgloss.Center, lipgloss.Center, p.common.Styles.Base.Render(styledContent), ) } type UpdateTimespanMsg string