probo/cmd/filter/filter.go
2024-03-25 15:53:20 +01:00

207 lines
3.9 KiB
Go

package filter
import (
"fmt"
"git.andreafazzi.eu/andrea/probo/pkg/store"
"git.andreafazzi.eu/andrea/probo/pkg/store/file"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/remogatto/sugarfoam/components/group"
"github.com/remogatto/sugarfoam/components/header"
"github.com/remogatto/sugarfoam/components/statusbar"
"github.com/remogatto/sugarfoam/components/table"
"github.com/remogatto/sugarfoam/components/textinput"
"github.com/remogatto/sugarfoam/components/viewport"
"github.com/remogatto/sugarfoam/layout"
"github.com/remogatto/sugarfoam/layout/tiled"
)
type Store interface {
}
type storeLoadedMsg struct {
store file.FileStorer[store.Storable]
}
type FilterModel struct {
// UI
group *group.Model
help help.Model
statusBar *statusbar.Model
// Layout
document *layout.Layout
// Key bindings
bindings *keyBindings
// Store
store file.FileStorer[store.Storable]
state int
}
type keyBindings struct {
group *group.Model
quit key.Binding
}
func (k *keyBindings) ShortHelp() []key.Binding {
keys := make([]key.Binding, 0)
current := k.group.Current()
switch item := current.(type) {
case *table.Model:
keys = append(
keys,
item.KeyMap.LineUp,
item.KeyMap.LineDown,
)
}
keys = append(
keys,
k.quit,
)
return keys
}
func (k keyBindings) FullHelp() [][]key.Binding {
return [][]key.Binding{
{
k.quit,
},
}
}
func newBindings(g *group.Model) *keyBindings {
return &keyBindings{
group: g,
quit: key.NewBinding(
key.WithKeys("esc"), key.WithHelp("esc", "Quit app"),
),
}
}
func New() *FilterModel {
textinput := textinput.New(
textinput.WithPlaceholder("Write your jq filter here..."),
)
table := table.New()
viewport := viewport.New()
help := help.New()
group := group.New(
group.WithItems(textinput, viewport, table),
group.WithLayout(
layout.New(
layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Padding(1, 0, 1, 0)}),
layout.WithItem(textinput),
layout.WithItem(tiled.New(viewport, table)),
),
),
)
bindings := newBindings(group)
statusBar := statusbar.New(bindings)
header := header.New(
header.WithContent(
lipgloss.NewStyle().
Bold(true).
Border(lipgloss.NormalBorder(), false, false, true, false).
Render("Participants filter 👫"),
),
)
document := layout.New(
layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Margin(1)}),
layout.WithItem(header),
layout.WithItem(group),
layout.WithItem(statusBar),
)
return &FilterModel{
group: group,
statusBar: statusBar,
document: document,
bindings: bindings,
help: help,
}
}
func (m *FilterModel) Init() tea.Cmd {
var cmds []tea.Cmd
cmds = append(cmds, m.group.Init(), loadParticipantStore())
m.group.Focus()
return tea.Batch(cmds...)
}
func (m *FilterModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.document.SetSize(msg.Width, msg.Height)
case tea.KeyMsg:
switch {
case key.Matches(msg, m.bindings.quit):
return m, tea.Quit
}
case storeLoadedMsg:
m.handleStoreLoaded(msg)
}
cmds = m.handleState(msg, cmds)
return m, tea.Batch(cmds...)
}
func (m *FilterModel) View() string {
return m.document.View()
}
func (m *FilterModel) handleStoreLoaded(msg tea.Msg) {
storeMsg := msg.(storeLoadedMsg)
m.store = storeMsg.store
m.state = FilterState
}
func (m *FilterModel) handleState(msg tea.Msg, cmds []tea.Cmd) []tea.Cmd {
_, cmd := m.group.Update(msg)
cmds = append(cmds, cmd)
m.statusBar.SetContent(
formats[FilterState][0],
fmt.Sprintf(formats[FilterState][1], len(m.store.ReadAll())),
formats[FilterState][2],
)
return cmds
}
func loadParticipantStore() tea.Cmd {
return func() tea.Msg {
pStore, err := file.NewDefaultParticipantFileStore()
if err != nil {
panic(err)
}
return storeLoadedMsg{pStore}
}
}