Add timestamp editor
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"tasksquire/components/input"
|
||||
"tasksquire/components/timestampeditor"
|
||||
"tasksquire/taskwarrior"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
@ -676,45 +677,56 @@ func (t tagEdit) View() string {
|
||||
|
||||
type timeEdit struct {
|
||||
common *common.Common
|
||||
fields []huh.Field
|
||||
fields []*timestampeditor.TimestampEditor
|
||||
|
||||
cursor int
|
||||
|
||||
// Store task field pointers to update them
|
||||
due *string
|
||||
scheduled *string
|
||||
wait *string
|
||||
until *string
|
||||
}
|
||||
|
||||
func NewTimeEdit(common *common.Common, due *string, scheduled *string, wait *string, until *string) *timeEdit {
|
||||
// defaultKeymap := huh.NewDefaultKeyMap()
|
||||
// Create timestamp editors for each date field
|
||||
dueEditor := timestampeditor.New(common).
|
||||
Title("Due").
|
||||
Description("When the task is due").
|
||||
ValueFromString(*due)
|
||||
|
||||
scheduledEditor := timestampeditor.New(common).
|
||||
Title("Scheduled").
|
||||
Description("When to start working on the task").
|
||||
ValueFromString(*scheduled)
|
||||
|
||||
waitEditor := timestampeditor.New(common).
|
||||
Title("Wait").
|
||||
Description("Hide task until this date").
|
||||
ValueFromString(*wait)
|
||||
|
||||
untilEditor := timestampeditor.New(common).
|
||||
Title("Until").
|
||||
Description("Task expires after this date").
|
||||
ValueFromString(*until)
|
||||
|
||||
t := timeEdit{
|
||||
common: common,
|
||||
fields: []huh.Field{
|
||||
huh.NewInput().
|
||||
Title("Due").
|
||||
Value(due).
|
||||
Validate(taskwarrior.ValidateDate).
|
||||
Inline(true).
|
||||
Prompt(": ").
|
||||
WithTheme(common.Styles.Form),
|
||||
huh.NewInput().
|
||||
Title("Scheduled").
|
||||
Value(scheduled).
|
||||
Validate(taskwarrior.ValidateDate).
|
||||
Inline(true).
|
||||
Prompt(": ").
|
||||
WithTheme(common.Styles.Form),
|
||||
huh.NewInput().
|
||||
Title("Wait").
|
||||
Value(wait).
|
||||
Validate(taskwarrior.ValidateDate).
|
||||
Inline(true).
|
||||
Prompt(": ").
|
||||
WithTheme(common.Styles.Form),
|
||||
huh.NewInput().
|
||||
Title("Until").
|
||||
Value(until).
|
||||
Validate(taskwarrior.ValidateDate).
|
||||
Inline(true).
|
||||
Prompt(": ").
|
||||
WithTheme(common.Styles.Form),
|
||||
fields: []*timestampeditor.TimestampEditor{
|
||||
dueEditor,
|
||||
scheduledEditor,
|
||||
waitEditor,
|
||||
untilEditor,
|
||||
},
|
||||
due: due,
|
||||
scheduled: scheduled,
|
||||
wait: wait,
|
||||
until: until,
|
||||
}
|
||||
|
||||
// Focus the first field
|
||||
if len(t.fields) > 0 {
|
||||
t.fields[0].Focus()
|
||||
}
|
||||
|
||||
return &t
|
||||
@ -725,12 +737,21 @@ func (t *timeEdit) GetName() string {
|
||||
}
|
||||
|
||||
func (t *timeEdit) SetCursor(c int) {
|
||||
if len(t.fields) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Blur the current field
|
||||
t.fields[t.cursor].Blur()
|
||||
|
||||
// Set new cursor position
|
||||
if c < 0 {
|
||||
t.cursor = len(t.fields) - 1
|
||||
} else {
|
||||
t.cursor = c
|
||||
}
|
||||
|
||||
// Focus the new field
|
||||
t.fields[t.cursor].Focus()
|
||||
}
|
||||
|
||||
@ -739,42 +760,71 @@ func (t *timeEdit) Init() tea.Cmd {
|
||||
}
|
||||
|
||||
func (t *timeEdit) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg.(type) {
|
||||
switch msg := msg.(type) {
|
||||
case nextFieldMsg:
|
||||
if t.cursor == len(t.fields)-1 {
|
||||
// Update task field before moving to next area
|
||||
t.syncToTaskFields()
|
||||
t.fields[t.cursor].Blur()
|
||||
return t, nextArea()
|
||||
}
|
||||
t.fields[t.cursor].Blur()
|
||||
t.cursor++
|
||||
t.fields[t.cursor].Focus()
|
||||
return t, nil
|
||||
case prevFieldMsg:
|
||||
if t.cursor == 0 {
|
||||
// Update task field before moving to previous area
|
||||
t.syncToTaskFields()
|
||||
t.fields[t.cursor].Blur()
|
||||
return t, prevArea()
|
||||
}
|
||||
t.fields[t.cursor].Blur()
|
||||
t.cursor--
|
||||
t.fields[t.cursor].Focus()
|
||||
return t, nil
|
||||
default:
|
||||
field, cmd := t.fields[t.cursor].Update(msg)
|
||||
t.fields[t.cursor] = field.(huh.Field)
|
||||
// Update the current timestamp editor
|
||||
model, cmd := t.fields[t.cursor].Update(msg)
|
||||
t.fields[t.cursor] = model.(*timestampeditor.TimestampEditor)
|
||||
return t, cmd
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (t *timeEdit) View() string {
|
||||
views := make([]string, len(t.fields))
|
||||
|
||||
for i, field := range t.fields {
|
||||
views[i] = field.View()
|
||||
if i < len(t.fields)-1 {
|
||||
views[i] += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return lipgloss.JoinVertical(
|
||||
lipgloss.Left,
|
||||
views...,
|
||||
)
|
||||
}
|
||||
|
||||
// syncToTaskFields converts the timestamp editor values back to task field strings
|
||||
func (t *timeEdit) syncToTaskFields() {
|
||||
// Update the task fields with values from the timestamp editors
|
||||
// GetValueString() returns empty string for unset timestamps
|
||||
if len(t.fields) > 0 {
|
||||
*t.due = t.fields[0].GetValueString()
|
||||
}
|
||||
if len(t.fields) > 1 {
|
||||
*t.scheduled = t.fields[1].GetValueString()
|
||||
}
|
||||
if len(t.fields) > 2 {
|
||||
*t.wait = t.fields[2].GetValueString()
|
||||
}
|
||||
if len(t.fields) > 3 {
|
||||
*t.until = t.fields[3].GetValueString()
|
||||
}
|
||||
}
|
||||
|
||||
type detailsEdit struct {
|
||||
com *common.Common
|
||||
vp viewport.Model
|
||||
@ -1009,6 +1059,9 @@ func (p *TaskEditorPage) updateTasksCmd() tea.Msg {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync timestamp fields from the timeEdit area (area 2)
|
||||
p.areas[2].(*timeEdit).syncToTaskFields()
|
||||
|
||||
if *(p.areas[0].(*taskEdit).newAnnotation) != "" {
|
||||
p.task.Annotations = append(p.task.Annotations, taskwarrior.Annotation{
|
||||
Entry: time.Now().Format("20060102T150405Z"),
|
||||
|
||||
Reference in New Issue
Block a user