index — walletdrain @ c4034a8e6b409b47ec5ee6f64bcb12c8dfa16304

Little app to track my spendings, for the time being only for music

can add and view, no edits yet
crispy-caesus 114518720+crispy-caesus@users.noreply.github.com
Thu, 01 May 2025 15:27:05 +0200
commit

c4034a8e6b409b47ec5ee6f64bcb12c8dfa16304

parent

53ad629d62fde3314998255f50bb7464d93cedf9

3 files changed, 220 insertions(+), 136 deletions(-)

jump to
M main.gomain.go

@@ -2,6 +2,7 @@ package main

import ( //"fmt" + "log" "strconv" "fyne.io/fyne/v2"

@@ -11,109 +12,152 @@ "fyne.io/fyne/v2/layout"

"fyne.io/fyne/v2/widget" ) - func tableView(w fyne.Window, category string) { - items := loadCategory(category) + items := loadCategory(category) - table := widget.NewTable( - func() (int, int) { - return len(items), 5 - }, - func() fyne.CanvasObject { - return widget.NewLabel("uhh, something went wrong") - }, - func(id widget.TableCellID, cell fyne.CanvasObject) { - label := cell.(*widget.Label) - label.Truncation = fyne.TextTruncateEllipsis - switch id.Col { - case 0: - label.SetText(items[id.Row].name.String) - case 1: - label.SetText(items[id.Row].artist.String) - case 2: - label.SetText(strconv.FormatFloat(items[id.Row].price, 'f', 2, 64) + " " + "€") - case 3: - label.SetText(items[id.Row].seller.String) - case 4: - label.SetText(items[id.Row].purchase_date.String) - } - }, - ) - table.SetColumnWidth(0, 100) - table.SetColumnWidth(1, 100) - table.SetColumnWidth(2, 100) - table.SetColumnWidth(3, 100) + table := widget.NewTable( + func() (int, int) { + items = loadCategory(category) + return len(items), 5 + }, + func() fyne.CanvasObject { + return widget.NewLabel("uhh, something went wrong") + }, + func(id widget.TableCellID, cell fyne.CanvasObject) { + label := cell.(*widget.Label) + label.Truncation = fyne.TextTruncateEllipsis + switch id.Col { + case 0: + label.SetText(items[id.Row].name.String) + case 1: + label.SetText(items[id.Row].artist.String) + case 2: + label.SetText(strconv.FormatFloat(items[id.Row].price, 'f', 2, 64) + " " + "€") + case 3: + label.SetText(items[id.Row].seller.String) + case 4: + label.SetText(items[id.Row].purchase_date.String) + } + }, + ) + table.SetColumnWidth(0, 100) + table.SetColumnWidth(1, 100) + table.SetColumnWidth(2, 100) + table.SetColumnWidth(3, 100) - /* - headers := []string{"Name", "Price", "Seller", "Purchase Date"} - for i, header := range headers { - fmt.Printf("i: %d\nheader: %s", i, header) - table.UpdateHeader(widget.TableCellID{Row: -1, Col: i}, - widget.NewLabel(header)) - } - */ + /* + headers := []string{"Name", "Price", "Seller", "Purchase Date"} + for i, header := range headers { + fmt.Printf("i: %d\nheader: %s", i, header) + table.UpdateHeader(widget.TableCellID{Row: -1, Col: i}, + widget.NewLabel(header)) + } + */ - editForm := widget.NewForm() + nameEntry := widget.NewEntry() + nameEntry.SetPlaceHolder("Sirens") - nameEntry := widget.NewEntry() - nameEntry.SetPlaceHolder("test") - editForm.Append("Name", nameEntry) + artistEntry := widget.NewEntry() + artistEntry.SetPlaceHolder("MatKat") - artistEntry := widget.NewEntry() - artistEntry.SetPlaceHolder("test") - editForm.Append("Artist", artistEntry) + priceEntry := widget.NewEntry() + priceEntry.SetPlaceHolder("5") - priceEntry := widget.NewEntry() - priceEntry.SetPlaceHolder("test") - editForm.Append("Price", priceEntry) + sellerEntry := widget.NewEntry() + sellerEntry.SetPlaceHolder("Bandcamp") - + dateEntry := widget.NewEntry() + dateEntry.SetPlaceHolder("2025-04-20") - split := container.NewHSplit(table, editForm) - /* - table.OnSelected = func(id widget.TableCellID) { - editForm := widget.NewForm() - for colIndex := 0; colIndex < 4; colIndex++ { - entry := widget.NewEntry() - entry.SetText(table.Cel) - } - } - */ + noteEntry := widget.NewEntry() + noteEntry.SetPlaceHolder("got this because... uhh I forgot") + + editForm := &widget.Form{ + Items: []*widget.FormItem{ + {Text: "Release Name", Widget: nameEntry}, + {Text: "Artist", Widget: artistEntry}, + {Text: "Price", Widget: priceEntry}, + {Text: "Seller", Widget: sellerEntry}, + {Text: "Date", Widget: dateEntry}, + {Text: "Note", Widget: noteEntry}, + }, + OnSubmit: func() { + log.Println("Form submitted") + + price, err := strconv.ParseFloat(priceEntry.Text, 32) + if err != nil { + log.Fatal("dum") + } + newMusicItem := musicItem{ + name: StringToNullString(nameEntry.Text), + artist: StringToNullString(artistEntry.Text), + price: price, + seller: StringToNullString(sellerEntry.Text), + purchase_date: StringToNullString(dateEntry.Text), + note: StringToNullString(noteEntry.Text), + } + insertMusicEntry(newMusicItem) + + table.Refresh() + log.Println("table should have refreshed") + + }, + OnCancel: func() { + nameEntry.SetText("") + artistEntry.SetText("") + priceEntry.SetText("") + sellerEntry.SetText("") + dateEntry.SetText("") + noteEntry.SetText("") + + log.Println("Form cancelled") + }, + } + + split := container.NewHSplit(table, editForm) + /* + table.OnSelected = func(id widget.TableCellID) { + editForm := widget.NewForm() + for colIndex := 0; colIndex < 4; colIndex++ { + entry := widget.NewEntry() + entry.SetText(table.Cel) + } + } + */ - w.SetContent(split) + w.SetContent(split) } func mainMenu(w fyne.Window) { - musicButton := widget.NewButton("Music", func() {tableView(w, "music")}) - groceriesButton := widget.NewButton("Groceries", func() {tableView(w, "groceries")}) - recurringButton := widget.NewButton("Recurring", func() {tableView(w, "recurring")}) - otherButton := widget.NewButton("Other", func() {tableView(w, "other")}) + musicButton := widget.NewButton("Music", func() { tableView(w, "music") }) + groceriesButton := widget.NewButton("Groceries", func() { tableView(w, "groceries") }) + recurringButton := widget.NewButton("Recurring", func() { tableView(w, "recurring") }) + otherButton := widget.NewButton("Other", func() { tableView(w, "other") }) - content := container.New( - layout.NewVBoxLayout(), - layout.NewSpacer(), - musicButton, - groceriesButton, - recurringButton, - otherButton, - layout.NewSpacer(), - ) + content := container.New( + layout.NewVBoxLayout(), + layout.NewSpacer(), + musicButton, + groceriesButton, + recurringButton, + otherButton, + layout.NewSpacer(), + ) - w.SetContent(container.New( - layout.NewHBoxLayout(), - layout.NewSpacer(), - content, - layout.NewSpacer(), - )) + w.SetContent(container.New( + layout.NewHBoxLayout(), + layout.NewSpacer(), + content, + layout.NewSpacer(), + )) } func main() { - a := app.New() - w := a.NewWindow("Hello World") + a := app.New() + w := a.NewWindow("Hello World") + + mainMenu(w) - mainMenu(w) - - - w.ShowAndRun() + w.ShowAndRun() }
M sql.gosql.go

@@ -9,18 +9,18 @@ _ "github.com/mattn/go-sqlite3"

) func openDB(DBName string) (*sql.DB, error) { - db, err := sql.Open("sqlite3", DBName + ".db") - if err != nil { - panic("couldn't open db") - } + db, err := sql.Open("sqlite3", DBName+".db") + if err != nil { + panic("couldn't open db") + } - return db, nil + return db, nil } func createTables(db *sql.DB, tableName string) (err error) { - switch tableName { - case "music": - _, err = db.Exec(`CREATE TABLE IF NOT EXISTS music ( + switch tableName { + case "music": + _, err = db.Exec(`CREATE TABLE IF NOT EXISTS music ( id INTEGER PRIMARY KEY AUTOINCREMENT, external_ids TEXT, name TEXT NOT NULL,

@@ -29,50 +29,71 @@ price FLOAT,

seller TEXT, note TEXT, purchase_date TEXT);`) - if err != nil { - panic(err) - return err - } - return nil - default: - panic("wrong table name") - } + if err != nil { + panic(err) + return err + } + return nil + default: + panic("wrong table name") + } +} + +func loadCategory(category string) []musicItem { + db, err := openDB("walletdrain") + if err != nil { + panic("couldn't open db") + } + defer db.Close() + + createTables(db, "music") + + query := fmt.Sprintf("SELECT * FROM %s", category) + + rows, err := db.Query(query) + if err != nil { + panic(err) + } + defer rows.Close() + + var results []musicItem + for rows.Next() { + var result musicItem + err := rows.Scan( + &result.id, + &result.external_ids, + &result.name, + &result.artist, + &result.price, + &result.seller, + &result.note, + &result.purchase_date) + if err != nil { + log.Print(err) + } + results = append(results, result) + } + return results } +func insertMusicEntry(entry musicItem) int { + db, err := openDB("walletdrain") + result, err := db.Exec(`INSERT INTO music + (name, artist, price, seller, purchase_date, note) + VALUES (?, ?, ?, ?, ?, ?);`, + entry.name, entry.artist, entry.price, entry.seller, entry.purchase_date, entry.note) -func loadCategory(category string) []musicItem { - db, err := openDB("walletdrain") - if err != nil { - panic("couldn't open db") - } - defer db.Close() - - createTables(db, "music") + if err != nil { + log.Fatal(err) + } + + lastID, err := result.LastInsertId() + + if err != nil { + log.Fatal(err) + } + + log.Printf("Inserted music item with id: %d", lastID) - query := fmt.Sprintf("SELECT * FROM %s", category) - - rows, err := db.Query(query) - if err != nil { - panic(err) - } - defer rows.Close() - - var results []musicItem - for rows.Next() { - var result musicItem - err := rows.Scan( - &result.id, - &result.external_ids, - &result.name, - &result.artist, - &result.price, - &result.seller, - &result.note, - &result.purchase_date) - if err != nil { - log.Print(err) - } - results = append(results, result) - } - return results -} + return 0 +}
A utils.go

@@ -0,0 +1,19 @@

+package main + +import "database/sql" + +// StringToNullString converts a string to sql.NullString +// Empty strings will be converted to NULL (Valid = false) +// Non-empty strings will be valid with the string value +func StringToNullString(s string) sql.NullString { + if s == "" { + return sql.NullString{ + String: "", + Valid: false, + } + } + return sql.NullString{ + String: s, + Valid: true, + } +}