- 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
104 lines
2.9 KiB
Text
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>
|
|
}
|
|
}
|