base feature
This commit is contained in:
218
main.go
Normal file
218
main.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"mealprep/database"
|
||||
"mealprep/handlers"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Print startup banner
|
||||
printBanner()
|
||||
|
||||
// Initialize database
|
||||
if err := database.InitDB("mealprep.db"); err != nil {
|
||||
log.Fatalf("Failed to initialize database: %v", err)
|
||||
}
|
||||
defer database.DB.Close()
|
||||
|
||||
log.Println("✅ Database initialized successfully")
|
||||
|
||||
// Static files
|
||||
fs := http.FileServer(http.Dir("static"))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", fs))
|
||||
|
||||
// Routes
|
||||
http.HandleFunc("/", indexHandler)
|
||||
|
||||
// Ingredients
|
||||
http.HandleFunc("/ingredients", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
handlers.IngredientsHandler(w, r)
|
||||
case "POST":
|
||||
handlers.AddIngredientHandler(w, r)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/ingredients/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "DELETE" {
|
||||
handlers.DeleteIngredientHandler(w, r)
|
||||
} else {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
|
||||
// Meals
|
||||
http.HandleFunc("/meals", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
handlers.MealsHandler(w, r)
|
||||
case "POST":
|
||||
handlers.AddMealHandler(w, r)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/meals/", func(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Path
|
||||
if strings.Contains(path, "/ingredients") {
|
||||
// Meal ingredients routes
|
||||
if r.Method == "GET" {
|
||||
handlers.GetMealIngredientsHandler(w, r)
|
||||
} else if r.Method == "POST" {
|
||||
handlers.AddMealIngredientHandler(w, r)
|
||||
} else if r.Method == "DELETE" {
|
||||
handlers.DeleteMealIngredientHandler(w, r)
|
||||
} else {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
} else {
|
||||
// Meal delete route
|
||||
if r.Method == "DELETE" {
|
||||
handlers.DeleteMealHandler(w, r)
|
||||
} else {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Week Plan
|
||||
http.HandleFunc("/week-plan", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
handlers.WeekPlanHandler(w, r)
|
||||
case "POST":
|
||||
handlers.AddWeekPlanEntryHandler(w, r)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/week-plan/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "DELETE" {
|
||||
handlers.DeleteWeekPlanEntryHandler(w, r)
|
||||
} else {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
|
||||
// Grocery List
|
||||
http.HandleFunc("/grocery-list", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
handlers.GroceryListHandler(w, r)
|
||||
} else {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Start server
|
||||
port := "8080"
|
||||
fmt.Println()
|
||||
log.Printf("🚀 Server running on http://localhost:%s", port)
|
||||
log.Println("📝 Press Ctrl+C to stop the server")
|
||||
fmt.Println()
|
||||
if err := http.ListenAndServe(":"+port, nil); err != nil {
|
||||
log.Fatalf("❌ Failed to start server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func printBanner() {
|
||||
banner := `
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🍽️ MEAL PREP PLANNER 🍽️ ║
|
||||
║ ║
|
||||
║ Plan your meals • Generate grocery lists ║
|
||||
║ ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
`
|
||||
fmt.Println(banner)
|
||||
log.Println("🔧 Initializing application...")
|
||||
}
|
||||
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl := `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Meal Prep Planner</title>
|
||||
<link rel="stylesheet" href="/static/styles.css">
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<h1>🍽️ Meal Prep Planner</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<div class="tabs">
|
||||
<button class="tab active"
|
||||
hx-get="/ingredients"
|
||||
hx-target="#content"
|
||||
hx-swap="innerHTML"
|
||||
onclick="setActiveTab(this)">
|
||||
Ingredients
|
||||
</button>
|
||||
<button class="tab"
|
||||
hx-get="/meals"
|
||||
hx-target="#content"
|
||||
hx-swap="innerHTML"
|
||||
onclick="setActiveTab(this)">
|
||||
Meals
|
||||
</button>
|
||||
<button class="tab"
|
||||
hx-get="/week-plan"
|
||||
hx-target="#content"
|
||||
hx-swap="innerHTML"
|
||||
onclick="setActiveTab(this)">
|
||||
Week Plan
|
||||
</button>
|
||||
<button class="tab"
|
||||
hx-get="/grocery-list"
|
||||
hx-target="#content"
|
||||
hx-swap="innerHTML"
|
||||
onclick="setActiveTab(this)">
|
||||
Grocery List
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="content" class="content">
|
||||
<div hx-get="/ingredients" hx-trigger="load"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function setActiveTab(clickedTab) {
|
||||
// Remove active class from all tabs
|
||||
document.querySelectorAll('.tab').forEach(tab => {
|
||||
tab.classList.remove('active');
|
||||
});
|
||||
// Add active class to clicked tab
|
||||
clickedTab.classList.add('active');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
t := template.Must(template.New("index").Parse(tmpl))
|
||||
if err := t.Execute(w, nil); err != nil {
|
||||
log.Printf("Error rendering template: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user