Add time page
This commit is contained in:
161
pages/timePage.go
Normal file
161
pages/timePage.go
Normal file
@ -0,0 +1,161 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"tasksquire/common"
|
||||
"tasksquire/components/timetable"
|
||||
"tasksquire/timewarrior"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type TimePage struct {
|
||||
common *common.Common
|
||||
|
||||
intervals timetable.Model
|
||||
data timewarrior.Intervals
|
||||
|
||||
shouldSelectActive bool
|
||||
}
|
||||
|
||||
func NewTimePage(com *common.Common) *TimePage {
|
||||
p := &TimePage{
|
||||
common: com,
|
||||
}
|
||||
|
||||
p.populateTable(timewarrior.Intervals{})
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *TimePage) Init() tea.Cmd {
|
||||
return tea.Batch(p.getIntervals(), doTick())
|
||||
}
|
||||
|
||||
func (p *TimePage) 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 intervalsMsg:
|
||||
p.data = timewarrior.Intervals(msg)
|
||||
p.populateTable(p.data)
|
||||
case tickMsg:
|
||||
cmds = append(cmds, p.getIntervals())
|
||||
cmds = append(cmds, doTick())
|
||||
case tea.KeyMsg:
|
||||
switch {
|
||||
case key.Matches(msg, p.common.Keymap.Quit):
|
||||
return p, tea.Quit
|
||||
case key.Matches(msg, p.common.Keymap.StartStop):
|
||||
row := p.intervals.SelectedRow()
|
||||
if row != nil {
|
||||
interval := (*timewarrior.Interval)(row)
|
||||
if interval.IsActive() {
|
||||
p.common.TimeW.StopTracking()
|
||||
} else {
|
||||
p.common.TimeW.ContinueInterval(interval.ID)
|
||||
p.shouldSelectActive = true
|
||||
}
|
||||
return p, tea.Batch(p.getIntervals(), doTick())
|
||||
}
|
||||
case key.Matches(msg, p.common.Keymap.Delete):
|
||||
row := p.intervals.SelectedRow()
|
||||
if row != nil {
|
||||
interval := (*timewarrior.Interval)(row)
|
||||
p.common.TimeW.DeleteInterval(interval.ID)
|
||||
return p, tea.Batch(p.getIntervals(), doTick())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
p.intervals, cmd = p.intervals.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
return p, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (p *TimePage) View() string {
|
||||
if len(p.data) == 0 {
|
||||
return p.common.Styles.Base.Render("No intervals found for today")
|
||||
}
|
||||
return p.intervals.View()
|
||||
}
|
||||
|
||||
func (p *TimePage) SetSize(width int, height int) {
|
||||
p.common.SetSize(width, height)
|
||||
p.intervals.SetWidth(width - p.common.Styles.Base.GetHorizontalFrameSize())
|
||||
p.intervals.SetHeight(height - p.common.Styles.Base.GetVerticalFrameSize())
|
||||
}
|
||||
|
||||
func (p *TimePage) populateTable(intervals timewarrior.Intervals) {
|
||||
var selectedStart string
|
||||
currentIdx := p.intervals.Cursor()
|
||||
if row := p.intervals.SelectedRow(); row != nil {
|
||||
selectedStart = row.Start
|
||||
}
|
||||
|
||||
columns := []timetable.Column{
|
||||
{Title: "ID", Name: "id", Width: 4},
|
||||
{Title: "Start", Name: "start", Width: 16},
|
||||
{Title: "End", Name: "end", Width: 16},
|
||||
{Title: "Duration", Name: "duration", Width: 10},
|
||||
{Title: "Tags", Name: "tags", Width: 0}, // flexible width
|
||||
}
|
||||
|
||||
p.intervals = timetable.New(
|
||||
p.common,
|
||||
timetable.WithColumns(columns),
|
||||
timetable.WithIntervals(intervals),
|
||||
timetable.WithFocused(true),
|
||||
timetable.WithWidth(p.common.Width()-p.common.Styles.Base.GetVerticalFrameSize()),
|
||||
timetable.WithHeight(p.common.Height()-p.common.Styles.Base.GetHorizontalFrameSize()),
|
||||
timetable.WithStyles(p.common.Styles.TableStyle),
|
||||
)
|
||||
|
||||
if len(intervals) > 0 {
|
||||
newIdx := -1
|
||||
|
||||
if p.shouldSelectActive {
|
||||
for i, interval := range intervals {
|
||||
if interval.IsActive() {
|
||||
newIdx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
p.shouldSelectActive = false
|
||||
}
|
||||
|
||||
if newIdx == -1 && selectedStart != "" {
|
||||
for i, interval := range intervals {
|
||||
if interval.Start == selectedStart {
|
||||
newIdx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newIdx == -1 {
|
||||
newIdx = currentIdx
|
||||
}
|
||||
|
||||
if newIdx >= len(intervals) {
|
||||
newIdx = len(intervals) - 1
|
||||
}
|
||||
if newIdx < 0 {
|
||||
newIdx = 0
|
||||
}
|
||||
|
||||
p.intervals.SetCursor(newIdx)
|
||||
}
|
||||
}
|
||||
|
||||
type intervalsMsg timewarrior.Intervals
|
||||
|
||||
func (p *TimePage) getIntervals() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
// ":day" is a timewarrior hint for "today"
|
||||
intervals := p.common.TimeW.GetIntervals(":day")
|
||||
return intervalsMsg(intervals)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user