läuft
This commit is contained in:
22
templates/alerts.gohtml
Normal file
22
templates/alerts.gohtml
Normal file
@@ -0,0 +1,22 @@
|
||||
{{define "title"}}Warnungen – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<h2>Produkte unter Mindestbestand</h2>
|
||||
{{if .Below}}
|
||||
<table class="table">
|
||||
<thead><tr><th>Produkt</th><th>Aktuell</th><th>Min</th><th>Händler</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Below}}
|
||||
<tr>
|
||||
<td><a href="/products/{{.ID}}">{{.Name}}</a></td>
|
||||
<td>{{.CurrentStock}}</td>
|
||||
<td>{{.MinStock}}</td>
|
||||
<td>{{.PreferredVendor}}</td>
|
||||
<td><a class="btn sm" href="/shopping-list">Zur Einkaufsliste</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="muted">Alles gut, keine Unterschreitungen.</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
29
templates/base.gohtml
Normal file
29
templates/base.gohtml
Normal file
@@ -0,0 +1,29 @@
|
||||
{{define "base"}}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>{{block "title" .}}Kücheninventar{{end}}</title>
|
||||
<link rel="stylesheet" href="/assets/style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<header class="container">
|
||||
<h1>🍳 Kücheninventar</h1>
|
||||
<nav>
|
||||
<a href="/">Dashboard</a>
|
||||
<a href="/products">Produkte</a>
|
||||
<a href="/alerts">Warnungen{{if .Alerts}} ({{.Alerts}}){{end}}</a>
|
||||
<a href="/shopping-list">Einkaufsliste</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="container">
|
||||
{{template "flash" .}}
|
||||
{{block "content" .}}{{end}}
|
||||
</main>
|
||||
<footer class="container muted">
|
||||
<p>© {{now | printf "%d"}} – Lokale Demo-App (Go + SQLite). Bilder bleiben lokal.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
39
templates/dashboard.gohtml
Normal file
39
templates/dashboard.gohtml
Normal file
@@ -0,0 +1,39 @@
|
||||
{{define "title"}}Dashboard – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<section class="card">
|
||||
<h2>Nächste ablaufende Einheit</h2>
|
||||
{{if .Next}}
|
||||
<div class="flex-between">
|
||||
<div>
|
||||
<strong>{{.Next.Product.Name}}</strong>
|
||||
{{if .Next.Product.Manufacturer}}<span class="muted">– {{.Next.Product.Manufacturer}}</span>{{end}}<br/>
|
||||
<span>Ablaufdatum: {{dateHuman .Next.ExpiryDate}}</span>
|
||||
</div>
|
||||
<form method="post" action="/units/{{.Next.ID}}/checkout?from=/">
|
||||
<button class="btn danger">Ausbuchen</button>
|
||||
</form>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="muted">Keine Einheiten auf Lager.</p>
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
|
||||
<section class="card">
|
||||
<h2>Produkte</h2>
|
||||
<div class="grid">
|
||||
{{range .Products}}
|
||||
<a class="product" href="/products/{{.ID}}">
|
||||
{{if .ImagePath}}<img src="{{.ImagePath}}" alt="{{.Name}}"/>
|
||||
{{else}}<div class="placeholder">Kein Bild</div>{{end}}
|
||||
<div class="meta">
|
||||
<div class="name">{{.Name}}</div>
|
||||
{{if .Manufacturer}}<div class="muted">{{.Manufacturer}}</div>{{end}}
|
||||
<div class="stock {{if and (gt .MinStock 0) (lt .CurrentStock .MinStock)}}warn{{end}}">Bestand: {{.CurrentStock}}{{if gt .MinStock 0}} / Min {{.MinStock}}{{end}}</div>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="actions"><a class="btn" href="/products/create">+ Produkt anlegen</a></div>
|
||||
</section>
|
||||
{{end}}
|
||||
3
templates/partials.gohtml
Normal file
3
templates/partials.gohtml
Normal file
@@ -0,0 +1,3 @@
|
||||
{{define "flash"}}
|
||||
{{/* Platzhalter für Nachrichten */}}
|
||||
{{end}}
|
||||
18
templates/product_create.gohtml
Normal file
18
templates/product_create.gohtml
Normal file
@@ -0,0 +1,18 @@
|
||||
{{define "title"}}Produkt anlegen – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<section class="card">
|
||||
<h2>Neues Produkt</h2>
|
||||
<form method="post" enctype="multipart/form-data" action="/products/create">
|
||||
<div class="form-grid">
|
||||
<label>Name*<input required name="name"/></label>
|
||||
<label>Hersteller<input name="manufacturer"/></label>
|
||||
<label>Größe / Inhalt<input name="size" placeholder="z. B. 500 g"/></label>
|
||||
<label>Bevorzugter Händler<input name="preferred_vendor" placeholder="z. B. REWE"/></label>
|
||||
<label>Mindestbestand<input type="number" min="0" name="min_stock" value="0"/></label>
|
||||
<label>Bild (Datei)<input type="file" name="image_file" accept="image/*"/></label>
|
||||
<label>Oder Bild-URL<input type="url" name="image_url" placeholder="https://…"/></label>
|
||||
</div>
|
||||
<button class="btn">Anlegen</button>
|
||||
</form>
|
||||
</section>
|
||||
{{end}}
|
||||
79
templates/product_detail.gohtml
Normal file
79
templates/product_detail.gohtml
Normal file
@@ -0,0 +1,79 @@
|
||||
{{define "title"}}Produkt – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<section class="card">
|
||||
<div class="flex-between">
|
||||
<div class="flex">
|
||||
{{if .Product.ImagePath}}<img class="cover" src="{{.Product.ImagePath}}" alt="{{.Product.Name}}"/>
|
||||
{{else}}<div class="cover placeholder">Kein Bild</div>{{end}}
|
||||
<div>
|
||||
<h2>{{.Product.Name}}</h2>
|
||||
{{if .Product.Manufacturer}}<div class="muted">{{.Product.Manufacturer}}</div>{{end}}
|
||||
{{if .Product.Size}}<div>Größe: {{.Product.Size}}</div>{{end}}
|
||||
<div>Bevorzugter Händler: {{if .Product.PreferredVendor}}{{.Product.PreferredVendor}}{{else}}–{{end}}</div>
|
||||
<div>Bestand: <strong>{{.Product.CurrentStock}}</strong>{{if gt .Product.MinStock 0}} / Min {{.Product.MinStock}}{{end}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" action="/products/{{.Product.ID}}">
|
||||
<div class="form-inline">
|
||||
<label>Min:<input type="number" min="0" name="min_stock" value="{{.Product.MinStock}}"/></label>
|
||||
<label>Händler:<input name="preferred_vendor" value="{{.Product.PreferredVendor}}"/></label>
|
||||
<label>Größe:<input name="size" value="{{.Product.Size}}"/></label>
|
||||
<label>Hersteller:<input name="manufacturer" value="{{.Product.Manufacturer}}"/></label>
|
||||
<button class="btn">Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="card">
|
||||
<h3>Nächste ablaufende Einheit</h3>
|
||||
{{if .Next}}
|
||||
<div class="flex-between">
|
||||
<div><span>Ablaufdatum: {{dateHuman .Next.ExpiryDate}}</span></div>
|
||||
<form method="post" action="/units/{{.Next.ID}}/checkout?from=/products/{{.Product.ID}}">
|
||||
<button class="btn danger">Ausbuchen</button>
|
||||
</form>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="muted">Keine Einheiten vorhanden.</p>
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
|
||||
<section class="card">
|
||||
<h3>Einheiten</h3>
|
||||
{{if .Units}}
|
||||
<table class="table">
|
||||
<thead><tr><th>#</th><th>Ablaufdatum</th><th>Aktion</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Units}}
|
||||
<tr>
|
||||
<td>{{.ID}}</td>
|
||||
<td>{{dateHuman .ExpiryDate}}</td>
|
||||
<td>
|
||||
<form method="post" action="/units/{{.ID}}/checkout?from=/products/{{$.Product.ID}}">
|
||||
<button class="btn sm">Ausbuchen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="muted">Noch keine Einheiten angelegt.</p>
|
||||
{{end}}
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Einheiten hinzufügen</summary>
|
||||
<form method="post" action="/products/{{.Product.ID}}/add-units">
|
||||
<div class="form-inline">
|
||||
<label>Menge:<input type="number" min="1" value="1" name="quantity"/></label>
|
||||
<label>Ablaufdatum:<input type="date" name="expiry_date" required/></label>
|
||||
<button class="btn">Hinzufügen</button>
|
||||
</div>
|
||||
</form>
|
||||
</details>
|
||||
</section>
|
||||
{{end}}
|
||||
20
templates/products.gohtml
Normal file
20
templates/products.gohtml
Normal file
@@ -0,0 +1,20 @@
|
||||
{{define "title"}}Produkte – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<div class="actions"><a class="btn" href="/products/create">+ Produkt anlegen</a></div>
|
||||
<table class="table">
|
||||
<thead><tr><th>Bild</th><th>Produkt</th><th>Hersteller</th><th>Größe</th><th>Händler</th><th>Bestand</th><th>Min</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Products}}
|
||||
<tr>
|
||||
<td class="tinyimg">{{if .ImagePath}}<img src="{{.ImagePath}}" alt="{{.Name}}"/>{{end}}</td>
|
||||
<td><a href="/products/{{.ID}}">{{.Name}}</a></td>
|
||||
<td>{{.Manufacturer}}</td>
|
||||
<td>{{.Size}}</td>
|
||||
<td>{{.PreferredVendor}}</td>
|
||||
<td>{{.CurrentStock}}</td>
|
||||
<td>{{.MinStock}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
26
templates/shopping_list.gohtml
Normal file
26
templates/shopping_list.gohtml
Normal file
@@ -0,0 +1,26 @@
|
||||
{{define "title"}}Einkaufsliste – Kücheninventar{{end}}
|
||||
{{define "content"}}
|
||||
<h2>Einkaufsliste nach Händler</h2>
|
||||
{{if .Vendors}}
|
||||
{{range .Vendors}}
|
||||
<section class="card">
|
||||
<h3>{{.}}</h3>
|
||||
<table class="table">
|
||||
<thead><tr><th>Produkt</th><th>Hersteller</th><th>Größe</th><th>Benötigt</th></tr></thead>
|
||||
<tbody>
|
||||
{{range (index $.Groups .)}}
|
||||
<tr>
|
||||
<td><a href="/products/{{.Product.ID}}">{{.Product.Name}}</a></td>
|
||||
<td>{{.Product.Manufacturer}}</td>
|
||||
<td>{{.Product.Size}}</td>
|
||||
<td><strong>{{.Needed}}</strong></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="muted">Keine offenen Bedarfe – alle Mindestbestände sind erfüllt.</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user