jamtrack/views/locations.templ
Frédéric G. MARAND 6f3321371d bug(ux): fix various front end bugs.
- Fixed song add form (3 HTMX bugs: reset on typeahead, wrong query param, artist-only find-or-create)
- Added Played checkbox to add form; inline edit (✎/Save/Cancel) for setlist rows
- View fixes: date format, location name instead of ID in jam list, notes on location detail, song count column, location name links to detail
- Title typeahead + cross-filtering (artist↔title filter each other)
- Fixed datalist accumulation bug: HTMX 2.0 inherits hx-swap from parent; added explicit hx-swap="innerHTML" on both inputs
- Setlist sort by id (ULID = insertion order); created rejected by PocketBase
- Location delete guard: OnRecordDelete hook blocks if jams exist; FK enforcement is app-level not SQLite-level

Loose ends to pick up:
- Focus-after-add not user-confirmed yet (setTimeout approach)
- jams.participants and setlist.position still in DB schema but unused in UI (optional migration to clean up)
- Logout flow and dashboard ranking not browser-tested
2026-06-15 14:12:57 +02:00

104 lines
2.9 KiB
Text

package views
import (
"fmt"
"github.com/pocketbase/pocketbase/core"
"code.osinet.fr/fgm/jamtrack/internal/query"
)
// LocationList renders the locations management page with an inline add form.
templ LocationList(locations []*core.Record) {
@Layout("Locations") {
<div class="level">
<div class="level-left">
<h1 class="title">Locations</h1>
</div>
</div>
<div class="columns">
<div class="column is-half">
if len(locations) == 0 {
<p class="has-text-grey mb-4">No locations yet.</p>
} else {
<table class="table is-fullwidth is-striped mb-4">
<thead>
<tr><th>Name</th><th>Notes</th></tr>
</thead>
<tbody>
for _, loc := range locations {
<tr>
<td><a href={ templ.SafeURL("/locations/" + loc.Id) }>{ loc.GetString("name") }</a></td>
<td>{ loc.GetString("notes") }</td>
</tr>
}
</tbody>
</table>
}
<form method="POST" action="/locations">
<div class="field has-addons">
<div class="control is-expanded">
<input class="input" type="text" name="name" placeholder="Location name" required/>
</div>
<div class="control">
<button class="button is-primary" type="submit">Add</button>
</div>
</div>
<div class="field">
<div class="control">
<input class="input" type="text" name="notes" placeholder="Notes (optional)"/>
</div>
</div>
</form>
</div>
</div>
}
}
// LocationDetail renders a single location's jam history and per-location ranking.
templ LocationDetail(loc *core.Record, jams []*core.Record, ranks []query.SongRank) {
@Layout(loc.GetString("name")) {
<h1 class="title">{ loc.GetString("name") }</h1>
if loc.GetString("notes") != "" {
<p class="subtitle is-6 has-text-grey">{ loc.GetString("notes") }</p>
}
<div class="columns">
<div class="column">
<h2 class="subtitle">Jams at this location</h2>
if len(jams) == 0 {
<p class="has-text-grey">No jams logged here yet.</p>
} else {
<table class="table is-fullwidth is-striped">
<thead><tr><th>Date</th></tr></thead>
<tbody>
for _, j := range jams {
<tr>
<td><a href={ templ.SafeURL("/jams/" + j.Id) }>{ dateOnly(j.GetString("date")) }</a></td>
</tr>
}
</tbody>
</table>
}
</div>
<div class="column">
<h2 class="subtitle">Practice ranking</h2>
if len(ranks) == 0 {
<p class="has-text-grey">No songs played here yet.</p>
} else {
<table class="table is-fullwidth is-striped">
<thead>
<tr><th>Artist</th><th>Title</th><th class="has-text-right">Played</th></tr>
</thead>
<tbody>
for _, r := range ranks {
<tr>
<td>{ r.Artist }</td>
<td>{ r.Title }</td>
<td class="has-text-right">{ fmt.Sprint(r.PlayedCount) }</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
}
}