kettlebell-tracker/internal/ui/history.go

320 lines
10 KiB
Go

package ui
import (
"fmt"
"log"
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"git.patanix.de/git/kettlebell-app/internal/data"
"git.patanix.de/git/kettlebell-app/internal/ui/utils"
)
func MakeHistoryScreen(db *data.DatabaseService, parent fyne.Window) fyne.CanvasObject {
var history []data.TrainingSession
placeholder := widget.NewLabel("Noch keine Trainingsdaten vorhanden.")
var showDetailDialog func(session *data.TrainingSession, id int)
var refreshData func()
list := widget.NewList(
func() int { return len(history) },
func() fyne.CanvasObject {
return container.NewGridWithColumns(4,
widget.NewLabel(""),
widget.NewLabel(""),
widget.NewLabel(""),
widget.NewLabel(""),
)
},
func(i widget.ListItemID, o fyne.CanvasObject) {
session := history[i]
row := o.(*fyne.Container)
row.Objects[0].(*widget.Label).SetText(session.Date.Format("02.01.2006 15:04"))
row.Objects[1].(*widget.Label).SetText(fmt.Sprintf("%d", session.Sets))
row.Objects[2].(*widget.Label).SetText(utils.FormatDuration(session.Duration))
row.Objects[3].(*widget.Label).SetText(fmt.Sprintf("%d", session.RepsPerSet))
},
)
list.OnSelected = func(id widget.ListItemID) {
session := &history[id]
showDetailDialog(session, id)
list.Unselect(id)
}
showDetailDialog = func(session *data.TrainingSession, id int) {
setsEntry := widget.NewEntry()
setsEntry.SetText(fmt.Sprintf("%d", session.Sets))
durationEntry := widget.NewEntry()
durationEntry.SetText(fmt.Sprintf("%d", session.Duration))
repsEntry := widget.NewEntry()
repsEntry.SetText(fmt.Sprintf("%d", session.RepsPerSet))
weightLeftEntry := widget.NewEntry()
weightLeftEntry.SetText(fmt.Sprintf("%.1f", session.WeightLeft))
weightRightEntry := widget.NewEntry()
weightRightEntry.SetText(fmt.Sprintf("%.1f", session.WeightRight))
// Info-Header
info := container.NewVBox(
widget.NewLabel(fmt.Sprintf("Datum: %s", session.Date.Format("02.01.2006 15:04"))),
widget.NewLabel(fmt.Sprintf("Programm: %s", session.Program)),
widget.NewLabel(fmt.Sprintf("Block-Tag: %d", session.BlockDay)),
)
form := widget.NewForm(
&widget.FormItem{Text: "Sätze", Widget: setsEntry},
&widget.FormItem{Text: "Dauer (Sekunden)", Widget: durationEntry},
&widget.FormItem{Text: "Reps/Satz", Widget: repsEntry},
&widget.FormItem{Text: "Gewicht links (kg)", Widget: weightLeftEntry},
&widget.FormItem{Text: "Gewicht rechts (kg)", Widget: weightRightEntry},
)
// Lokale Dialog-Referenz deklarieren
var detailDialog dialog.Dialog
saveBtn := widget.NewButtonWithIcon("Speichern", theme.ConfirmIcon(), func() {
sets, err := strconv.Atoi(setsEntry.Text)
if err != nil {
dialog.ShowError(fmt.Errorf("Ungültige Sätze-Zahl"), parent)
return
}
duration, err := strconv.Atoi(durationEntry.Text)
if err != nil {
dialog.ShowError(fmt.Errorf("Ungültige Dauer"), parent)
return
}
reps, err := strconv.Atoi(repsEntry.Text)
if err != nil {
dialog.ShowError(fmt.Errorf("Ungültige Wiederholungszahl"), parent)
return
}
weightLeft, err := strconv.ParseFloat(weightLeftEntry.Text, 64)
if err != nil {
dialog.ShowError(fmt.Errorf("Ungültiges Gewicht links"), parent)
return
}
weightRight, err := strconv.ParseFloat(weightRightEntry.Text, 64)
if err != nil {
dialog.ShowError(fmt.Errorf("Ungültiges Gewicht rechts"), parent)
return
}
session.Sets = int64(sets)
session.Duration = int64(duration)
session.RepsPerSet = int64(reps)
session.WeightLeft = weightLeft
session.WeightRight = weightRight
if err := db.UpdateTraining(session); err != nil {
dialog.ShowError(err, parent)
return
}
dialog.ShowInformation("Erfolg", "Trainingseintrag aktualisiert.", parent)
refreshData()
detailDialog.Hide()
})
deleteBtn := widget.NewButtonWithIcon("Löschen", theme.DeleteIcon(), func() {
dialog.ShowConfirm("Eintrag löschen", "Möchtest du diesen Eintrag wirklich löschen?", func(ok bool) {
if ok {
err := db.DeleteTraining(session.ID)
if err != nil {
dialog.ShowError(err, parent)
return
}
refreshData()
detailDialog.Hide()
}
}, parent)
})
cancelBtn := widget.NewButton("Abbrechen", func() {
detailDialog.Hide()
})
btns := container.NewHBox(saveBtn, deleteBtn, cancelBtn)
content := container.NewVBox(
info,
form,
btns,
)
// Hier wird der Dialog erzeugt und die lokale Variable gesetzt
detailDialog = dialog.NewCustom("Training bearbeiten/löschen", "Schließen", content, parent)
detailDialog.Show()
}
// showDetailDialog = func(session *data.TrainingSession, id int) {
// details := container.NewVBox(
// widget.NewLabel(fmt.Sprintf("Datum: %s", session.Date.Format("02.01.2006 15:04"))),
// widget.NewLabel(fmt.Sprintf("Programm: %s", session.Program)),
// widget.NewLabel(fmt.Sprintf("Block-Tag: %d", session.BlockDay)),
// widget.NewLabel(fmt.Sprintf("Sätze: %d", session.Sets)),
// widget.NewLabel(fmt.Sprintf("Dauer: %s", utils.FormatDuration(session.Duration))),
// widget.NewLabel(fmt.Sprintf("Reps/Satz: %d", session.RepsPerSet)),
// widget.NewLabel(fmt.Sprintf("Gewicht links: %.1f kg", session.WeightLeft)),
// widget.NewLabel(fmt.Sprintf("Gewicht rechts: %.1f kg", session.WeightRight)),
// )
// deleteBtn := widget.NewButtonWithIcon("Löschen", theme.DeleteIcon(), func() {
// dialog.ShowConfirm("Eintrag löschen", "Möchtest du diesen Eintrag wirklich löschen?", func(ok bool) {
// if ok {
// err := db.DeleteTraining(session.ID)
// if err != nil {
// dialog.ShowError(err, parent)
// return
// }
// refreshData()
// }
// }, parent)
// })
// editBtn := widget.NewButtonWithIcon("Bearbeiten", theme.DocumentCreateIcon(), func() {
// setsEntry := widget.NewEntry()
// setsEntry.SetText(fmt.Sprintf("%d", session.Sets))
// durationEntry := widget.NewEntry()
// durationEntry.SetText(fmt.Sprintf("%d", session.Duration))
// repsEntry := widget.NewEntry()
// repsEntry.SetText(fmt.Sprintf("%d", session.RepsPerSet))
// weightLeftEntry := widget.NewEntry()
// weightLeftEntry.SetText(fmt.Sprintf("%.1f", session.WeightLeft))
// weightRightEntry := widget.NewEntry()
// weightRightEntry.SetText(fmt.Sprintf("%.1f", session.WeightRight))
// items := []*widget.FormItem{
// {Text: "Sätze", Widget: setsEntry},
// {Text: "Dauer (Sekunden)", Widget: durationEntry},
// {Text: "Reps/Satz", Widget: repsEntry},
// {Text: "Gewicht links (kg)", Widget: weightLeftEntry},
// {Text: "Gewicht rechts (kg)", Widget: weightRightEntry},
// }
// var editDialog dialog.Dialog
// editDialog = dialog.NewForm(
// "Training bearbeiten",
// "Speichern",
// "Abbrechen",
// items,
// func(ok bool) {
// if !ok {
// log.Printf("Bearbeiten abgebrochen für Session-ID %d", session.ID)
// return
// }
// // AB HIER: Das ist der Submit-Handler!
// log.Printf("Bearbeiten gespeichert für Session-ID %d", session.ID)
// sets, err := strconv.Atoi(setsEntry.Text)
// if err != nil {
// dialog.ShowError(fmt.Errorf("Ungültige Sätze-Zahl"), parent)
// return
// }
// duration, err := strconv.Atoi(durationEntry.Text)
// if err != nil {
// dialog.ShowError(fmt.Errorf("Ungültige Dauer"), parent)
// return
// }
// reps, err := strconv.Atoi(repsEntry.Text)
// if err != nil {
// dialog.ShowError(fmt.Errorf("Ungültige Wiederholungszahl"), parent)
// return
// }
// weightLeft, err := strconv.ParseFloat(weightLeftEntry.Text, 64)
// if err != nil {
// dialog.ShowError(fmt.Errorf("Ungültiges Gewicht links"), parent)
// return
// }
// weightRight, err := strconv.ParseFloat(weightRightEntry.Text, 64)
// if err != nil {
// dialog.ShowError(fmt.Errorf("Ungültiges Gewicht rechts"), parent)
// return
// }
// session.Sets = int64(sets)
// session.Duration = int64(duration)
// session.RepsPerSet = int64(reps)
// session.WeightLeft = weightLeft
// session.WeightRight = weightRight
// log.Printf("UpdateTraining wird aufgerufen für Session-ID %d", session.ID)
// if err := db.UpdateTraining(session); err != nil {
// dialog.ShowError(err, parent)
// return
// }
// log.Printf("UpdateTraining erfolgreich für Session-ID %d", session.ID)
// dialog.ShowInformation("Erfolg", "Trainingseintrag aktualisiert.", parent)
// refreshData()
// },
// parent,
// )
// editDialog.Show()
// })
// btns := container.NewHBox(editBtn, deleteBtn)
// dialog.ShowCustom("Training Details", "Schließen", container.NewVBox(details, btns), parent)
// }
refreshData = func() {
var err error
history, err = db.GetHistory()
if err != nil {
log.Printf("Fehler beim Laden der Historie: %v", err)
dialog.ShowError(err, parent)
return
}
if len(history) == 0 {
placeholder.Show()
list.Hide()
} else {
placeholder.Hide()
list.Show()
}
list.Refresh()
}
header := container.NewGridWithColumns(4,
widget.NewLabelWithStyle("Datum", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
widget.NewLabelWithStyle("Sätze", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
widget.NewLabelWithStyle("Dauer", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
widget.NewLabelWithStyle("Reps/Satz", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
)
toolbar := widget.NewToolbar(widget.NewToolbarAction(theme.ViewRefreshIcon(), refreshData))
// content := container.NewVBox(header, container.NewStack(list, container.NewCenter(placeholder)))
// layout := container.NewBorder(toolbar, nil, nil, nil, content)
content := container.NewBorder(
header,
nil,
nil,
nil,
container.NewVScroll(list),
)
layout := container.NewBorder(
toolbar,
nil,
nil,
nil,
content,
)
if layout.Visible() {
refreshData()
}
return layout
}