birthay-reminderapp/main.go
Your Name 0159e5e49f yeet
2026-02-19 22:36:03 +01:00

143 lines
3.4 KiB
Go

package main
import (
"database/sql"
"html/template"
"log"
"net/http"
"time"
_ "github.com/mattn/go-sqlite3"
)
type Birthday struct {
ID int `db:"id"`
Name string `db:"name"`
Birthday time.Time `db:"birthday"`
GiftPurchased bool `db:"gift_purchased"`
DaysUntil int `db:"days_until"`
}
var db *sql.DB
func initDB() {
var err error
db, err = sql.Open("sqlite3", "./birthdays.db")
if err != nil {
log.Fatal(err)
}
// Create table if it doesn't exist
createTableSQL := `
CREATE TABLE IF NOT EXISTS birthdays (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
birthday DATE NOT NULL,
gift_purchased BOOLEAN DEFAULT FALSE
);`
_, err = db.Exec(createTableSQL)
if err != nil {
log.Fatal(err)
}
}
func getBirthdays() ([]Birthday, error) {
rows, err := db.Query("SELECT id, name, birthday, gift_purchased FROM birthdays ORDER BY birthday")
if err != nil {
return nil, err
}
defer rows.Close()
var birthdays []Birthday
for rows.Next() {
var b Birthday
err := rows.Scan(&b.ID, &b.Name, &b.Birthday, &b.GiftPurchased)
if err != nil {
return nil, err
}
birthdays = append(birthdays, b)
}
return birthdays, nil
}
func addBirthday(name string, birthday time.Time, giftPurchased bool) error {
_, err := db.Exec("INSERT INTO birthdays (name, birthday, gift_purchased) VALUES (?, ?, ?)", name, birthday, giftPurchased)
return err
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
name := r.FormValue("name")
birthdayStr := r.FormValue("birthday")
giftPurchased := r.FormValue("giftPurchased") == "on"
// Parse the birthday date
birthday, err := time.Parse("2006-01-02", birthdayStr)
if err != nil {
log.Printf("Error parsing birthday: %v", err)
http.Error(w, "Invalid birthday date", http.StatusBadRequest)
return
}
err = addBirthday(name, birthday, giftPurchased)
if err != nil {
log.Printf("Error adding birthday: %v", err)
http.Error(w, "Error adding birthday", http.StatusInternalServerError)
return
}
// Redirect to avoid resubmission
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
birthdays, err := getBirthdays()
if err != nil {
log.Printf("Error getting birthdays: %v", err)
http.Error(w, "Error getting birthdays", http.StatusInternalServerError)
return
}
// Calculate days until each birthday
for i, b := range birthdays {
nextBirthday := time.Date(time.Now().Year(), b.Birthday.Month(), b.Birthday.Day(), 0, 0, 0, 0, time.Now().Location())
if nextBirthday.Before(time.Now()) {
nextBirthday = nextBirthday.AddDate(1, 0, 0)
}
daysUntil := int(nextBirthday.Sub(time.Now()).Hours() / 24)
birthdays[i].DaysUntil = daysUntil
}
data := struct {
UpcomingBirthdays []Birthday
}{
UpcomingBirthdays: birthdays,
}
// Parse template from template directory
tmpl, err := template.ParseFiles("template/index.html")
if err != nil {
log.Printf("Error parsing template: %v", err)
http.Error(w, "Template error", http.StatusInternalServerError)
return
}
err = tmpl.Execute(w, data)
if err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Template execution error", http.StatusInternalServerError)
return
}
}
func main() {
initDB()
defer db.Close()
http.HandleFunc("/", homeHandler)
log.Println("Server starting on http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}