blocked dates page and warning for special-cake orders

Add blocked_date table (migration 5), model, and store CRUD methods.
Add management page at /blocked with add/delete functionality.
Add nav link 'Terminy zablokowane' with event_busy icon.
Pass blocked dates to order form as JSON data attribute.
On form submit, if the order has special cakes and the date is
blocked, show a confirm() dialog warning the user.
This commit is contained in:
bronkuu 2026-06-15 18:54:48 +02:00
parent 5a5372b831
commit 5f156ab6a0
13 changed files with 175 additions and 16 deletions

View file

@ -0,0 +1,44 @@
package templates
import (
"strconv"
"git.bronku.xyz/bronku/cake-order-tracker/models"
)
templ BlockedPage(blocked []models.BlockedDate) {
@Layout("Terminy zablokowane", templ.NopComponent, BlockedMain(blocked))
}
templ BlockedMain(blocked []models.BlockedDate) {
<section class="card" style="max-width:30rem">
<header>
<h2>
<span class="material-symbols-outlined">block</span>
Terminy zablokowane
</h2>
</header>
<div>
<form method="POST" action="/blocked" class="horizontal-group" style="gap:0.5rem;margin-bottom:1rem">
<input type="date" name="date" required class="form-input" style="width:auto"/>
<button type="submit" class="btn primary">Zablokuj</button>
</form>
if len(blocked) == 0 {
<p class="text-muted" style="text-align:center;padding:1rem 0">Brak zablokowanych terminów</p>
} else {
<ul class="breakdown-list">
for _, b := range blocked {
<li class="breakdown-item">
<span>{ b.Date }</span>
<form method="POST" action={ templ.URL("/blocked/" + strconv.Itoa(b.ID) + "/delete") } style="display:inline">
<button type="submit" class="action-btn" title="Usuń">
<span class="material-symbols-outlined">close</span>
</button>
</form>
</li>
}
</ul>
}
</div>
</section>
}

View file

@ -1,6 +1,7 @@
package templates
import (
"encoding/json"
"fmt"
"strconv"
"strings"
@ -73,6 +74,15 @@ func orderItemsDesc(order models.Order) string {
return desc
}
func blockedDatesJSON(dates []models.BlockedDate) string {
names := make([]string, len(dates))
for i, d := range dates {
names[i] = d.Date
}
b, _ := json.Marshal(names)
return string(b)
}
func orderScript(order models.Order) string {
var b strings.Builder
b.WriteString("<script>")

View file

@ -10,18 +10,22 @@ templ Nav() {
<p>Tracker</p>
</div>
</div>
<a href="/order" class="cta" hx-get="/order" hx-target="#main" hx-push-url="true">
<a href="/order" class="cta" hx-get="/order" hx-target="#main" hx-swap="outerHTML" hx-push-url="true">
<span class="material-symbols-outlined">add</span>
<span>Nowe zamówienie</span>
</a>
<nav>
<a href="/orders" class="link" hx-get="/orders" hx-target="#main" hx-push-url="true">
<a href="/orders" class="link" hx-get="/orders" hx-target="#main" hx-swap="outerHTML" hx-push-url="true">
<span class="material-symbols-outlined">dashboard</span>
<span>Panel główny</span>
</a>
<a href="/cakes" class="link" hx-get="/cakes" hx-target="#main" hx-push-url="true">
<a href="/cakes" class="link" hx-get="/cakes" hx-target="#main" hx-swap="outerHTML" hx-push-url="true">
<span class="material-symbols-outlined">inventory_2</span>
<span>Katalog</span>
</a>
<a href="/blocked" class="link" hx-get="/blocked" hx-target="#main" hx-swap="outerHTML" hx-push-url="true">
<span class="material-symbols-outlined">event_busy</span>
<span>Terminy zablokowane</span>
</a>
</nav>
}

View file

@ -6,12 +6,12 @@ import (
"git.bronku.xyz/bronku/cake-order-tracker/models"
)
templ OrderPage(order models.Order, catalogue []models.Cake, allTags []models.Tag) {
@Layout(OrderTitle(order), templ.NopComponent, OrderForm(order, catalogue, allTags))
templ OrderPage(order models.Order, catalogue []models.Cake, allTags []models.Tag, blockedDates []models.BlockedDate) {
@Layout(OrderTitle(order), templ.NopComponent, OrderForm(order, catalogue, allTags, blockedDates))
}
templ OrderForm(order models.Order, catalogue []models.Cake, allTags []models.Tag) {
<form method="post" class="split-pane">
templ OrderForm(order models.Order, catalogue []models.Cake, allTags []models.Tag, blockedDates []models.BlockedDate) {
<form method="post" class="split-pane" onsubmit="return confirmBlockedDate(this)" data-blocked-dates={ blockedDatesJSON(blockedDates) }>
<input type="hidden" name="id" value={ strconv.Itoa(order.ID) }/>
<div class="order-left">
<section class="card">