Add task completion toggle, custom task templates, and umlaut UI updates
This commit is contained in:
@@ -6,32 +6,14 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func buildTasksForDay(plans []Plan, stepMap map[int64][]CropStep, month, day int) []Task {
|
||||
var tasks []Task
|
||||
for _, p := range plans {
|
||||
tasks = append(tasks, expandPlanDayTasks(p, stepMap[p.CropID], month, day)...)
|
||||
}
|
||||
func buildTasksForDay(plans []Plan, stepMap map[int64][]CropStep, customTasks []CustomTask, doneMap map[string]bool, month, day int) []Task {
|
||||
tasks := collectTasksForDate(plans, stepMap, customTasks, month, day, 0)
|
||||
applyCompletion(tasks, doneMap)
|
||||
sortTasks(tasks)
|
||||
return tasks
|
||||
}
|
||||
|
||||
func buildCalendar(plans []Plan, stepMap map[int64][]CropStep, startMonth, startDay, daysPerMonth, spanMonths int) []CalendarMonth {
|
||||
tasksByKey := make(map[string][]Task)
|
||||
for _, p := range plans {
|
||||
for m := 1; m <= 12; m++ {
|
||||
for d := 1; d <= daysPerMonth; d++ {
|
||||
dayTasks := expandPlanDayTasks(p, stepMap[p.CropID], m, d)
|
||||
if len(dayTasks) > 0 {
|
||||
key := fmt.Sprintf("%d-%d", m, d)
|
||||
tasksByKey[key] = append(tasksByKey[key], dayTasks...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := range tasksByKey {
|
||||
sortTasks(tasksByKey[k])
|
||||
}
|
||||
|
||||
func buildCalendar(plans []Plan, stepMap map[int64][]CropStep, customTasks []CustomTask, doneMap map[string]bool, startMonth, startDay, daysPerMonth, spanMonths int) []CalendarMonth {
|
||||
var out []CalendarMonth
|
||||
for offset := 0; offset < spanMonths; offset++ {
|
||||
month := wrapMonth(startMonth + offset)
|
||||
@@ -45,10 +27,12 @@ func buildCalendar(plans []Plan, stepMap map[int64][]CropStep, startMonth, start
|
||||
if offset == 0 {
|
||||
fromDay = startDay
|
||||
}
|
||||
|
||||
var days []CalendarDay
|
||||
for d := fromDay; d <= daysPerMonth; d++ {
|
||||
key := fmt.Sprintf("%d-%d", month, d)
|
||||
items := append([]Task(nil), tasksByKey[key]...)
|
||||
items := collectTasksForDate(plans, stepMap, customTasks, month, d, yearOffset)
|
||||
applyCompletion(items, doneMap)
|
||||
sortTasks(items)
|
||||
days = append(days, CalendarDay{Day: d, Tasks: items})
|
||||
}
|
||||
out = append(out, CalendarMonth{
|
||||
@@ -62,20 +46,57 @@ func buildCalendar(plans []Plan, stepMap map[int64][]CropStep, startMonth, start
|
||||
return out
|
||||
}
|
||||
|
||||
func expandPlanDayTasks(p Plan, steps []CropStep, month, day int) []Task {
|
||||
func collectTasksForDate(plans []Plan, stepMap map[int64][]CropStep, customTasks []CustomTask, month, day, yearOffset int) []Task {
|
||||
var tasks []Task
|
||||
|
||||
for _, p := range plans {
|
||||
tasks = append(tasks, expandPlanDayTasks(p, stepMap[p.CropID], month, day, yearOffset)...)
|
||||
}
|
||||
for _, c := range customTasks {
|
||||
if c.Month == month && c.Day == day && c.YearOffset == yearOffset {
|
||||
field := c.TargetName
|
||||
if strings.TrimSpace(field) == "" {
|
||||
field = "Allgemein"
|
||||
}
|
||||
msg := c.Title
|
||||
if strings.TrimSpace(c.Notes) != "" {
|
||||
msg = fmt.Sprintf("%s (Notiz: %s)", msg, c.Notes)
|
||||
}
|
||||
tasks = append(tasks, Task{
|
||||
UID: fmt.Sprintf("custom:%d", c.ID),
|
||||
Type: "Aufgabe",
|
||||
Field: field,
|
||||
Message: msg,
|
||||
Month: month,
|
||||
Day: day,
|
||||
YearOffset: yearOffset,
|
||||
SortOrder: 40,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
func expandPlanDayTasks(p Plan, steps []CropStep, month, day, yearOffset int) []Task {
|
||||
field := p.TargetName
|
||||
if strings.TrimSpace(field) == "" {
|
||||
field = "Unbekanntes Feld"
|
||||
}
|
||||
|
||||
var out []Task
|
||||
baseHarvest := p.HarvestMonth
|
||||
|
||||
if p.StartMonth == month && p.StartDay == day {
|
||||
if p.StartMonth == month && p.StartDay == day && yearOffset == 0 {
|
||||
out = append(out, Task{
|
||||
Type: "Aussaat",
|
||||
Field: field,
|
||||
Message: withOptionalNote(fmt.Sprintf("Aussaat %s", p.CropName), p.Notes),
|
||||
SortOrder: 10,
|
||||
UID: fmt.Sprintf("plan:%d:sow:0", p.ID),
|
||||
Type: "Aussaat",
|
||||
Field: field,
|
||||
Message: withOptionalNote(fmt.Sprintf("Aussaat %s", p.CropName), p.Notes),
|
||||
Month: month,
|
||||
Day: day,
|
||||
YearOffset: yearOffset,
|
||||
SortOrder: 10,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -90,13 +111,19 @@ func expandPlanDayTasks(p Plan, steps []CropStep, month, day int) []Task {
|
||||
}
|
||||
}
|
||||
harvestMonths = uniqueMonths(harvestMonths)
|
||||
for _, hm := range harvestMonths {
|
||||
|
||||
for idx, hm := range harvestMonths {
|
||||
if hm == month && p.HarvestDay == day {
|
||||
uid := fmt.Sprintf("plan:%d:harvest:%d", p.ID, idx)
|
||||
out = append(out, Task{
|
||||
Type: "Ernte",
|
||||
Field: field,
|
||||
Message: withOptionalNote(fmt.Sprintf("Ernte %s", p.CropName), p.Notes),
|
||||
SortOrder: 20,
|
||||
UID: uid,
|
||||
Type: "Ernte",
|
||||
Field: field,
|
||||
Message: withOptionalNote(fmt.Sprintf("Ernte %s", p.CropName), p.Notes),
|
||||
Month: month,
|
||||
Day: day,
|
||||
YearOffset: yearOffset,
|
||||
SortOrder: 20,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -105,23 +132,31 @@ func expandPlanDayTasks(p Plan, steps []CropStep, month, day int) []Task {
|
||||
switch s.Phase {
|
||||
case "pre":
|
||||
taskMonth := wrapMonth(p.StartMonth - s.MonthOffset)
|
||||
if taskMonth == month && p.StartDay == day {
|
||||
if taskMonth == month && p.StartDay == day && yearOffset == 0 {
|
||||
out = append(out, Task{
|
||||
Type: "Vorbereitung",
|
||||
Field: field,
|
||||
Message: s.Title,
|
||||
SortOrder: 5,
|
||||
UID: fmt.Sprintf("plan:%d:pre:%d", p.ID, s.ID),
|
||||
Type: "Vorbereitung",
|
||||
Field: field,
|
||||
Message: s.Title,
|
||||
Month: month,
|
||||
Day: day,
|
||||
YearOffset: yearOffset,
|
||||
SortOrder: 5,
|
||||
})
|
||||
}
|
||||
case "post":
|
||||
for _, hm := range harvestMonths {
|
||||
for idx, hm := range harvestMonths {
|
||||
taskMonth := wrapMonth(hm + s.MonthOffset)
|
||||
if taskMonth == month && p.HarvestDay == day {
|
||||
out = append(out, Task{
|
||||
Type: "Nachbereitung",
|
||||
Field: field,
|
||||
Message: s.Title,
|
||||
SortOrder: 30,
|
||||
UID: fmt.Sprintf("plan:%d:post:%d:%d", p.ID, s.ID, idx),
|
||||
Type: "Nachbereitung",
|
||||
Field: field,
|
||||
Message: s.Title,
|
||||
Month: month,
|
||||
Day: day,
|
||||
YearOffset: yearOffset,
|
||||
SortOrder: 30,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -131,6 +166,13 @@ func expandPlanDayTasks(p Plan, steps []CropStep, month, day int) []Task {
|
||||
return out
|
||||
}
|
||||
|
||||
func applyCompletion(tasks []Task, doneMap map[string]bool) {
|
||||
for i := range tasks {
|
||||
k := completionKey(tasks[i].UID, tasks[i].Month, tasks[i].Day, tasks[i].YearOffset)
|
||||
tasks[i].Completed = doneMap[k]
|
||||
}
|
||||
}
|
||||
|
||||
func (p Plan) HarvestDistance() int {
|
||||
if p.GrowMonths <= 0 {
|
||||
return 1
|
||||
@@ -148,6 +190,9 @@ func withOptionalNote(base, note string) string {
|
||||
|
||||
func sortTasks(tasks []Task) {
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
if tasks[i].Completed != tasks[j].Completed {
|
||||
return !tasks[i].Completed
|
||||
}
|
||||
if tasks[i].SortOrder == tasks[j].SortOrder {
|
||||
if tasks[i].Field == tasks[j].Field {
|
||||
return tasks[i].Message < tasks[j].Message
|
||||
@@ -169,3 +214,7 @@ func uniqueMonths(values []int) []int {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func completionKey(uid string, month, day, yearOffset int) string {
|
||||
return fmt.Sprintf("%s|%d|%d|%d", uid, month, day, yearOffset)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user