set up better ux for using categories

This commit is contained in:
2024-03-13 03:06:23 +00:00
parent 4fd0e72a86
commit 066e6d2a09
12 changed files with 107 additions and 33 deletions

View File

@@ -51,4 +51,6 @@ type BoxItemWithItemInfo struct {
Name string Name string
Stage PackingStage Stage PackingStage
Category Category Category Category
Description *string
Notes *string
} }

View File

@@ -156,7 +156,7 @@ func GetBoxItemsByBoxID(boxID int) ([]BoxItemWithItemInfo, error) {
// get all rows from box_items where boxid = boxID // get all rows from box_items where boxid = boxID
// also get the item info for each item // also get the item info for each item
rows, err := db.Query( rows, err := db.Query(
"SELECT id, items.name, items.stage, items.category FROM boxitems JOIN items ON itemid=items.id WHERE boxid = ?", "SELECT id, items.name, items.stage, items.category, items.description, items.notes FROM boxitems JOIN items ON itemid=items.id WHERE boxid = ?",
boxID) boxID)
if err != nil { if err != nil {
@@ -169,7 +169,7 @@ func GetBoxItemsByBoxID(boxID int) ([]BoxItemWithItemInfo, error) {
for rows.Next() { for rows.Next() {
boxItem := BoxItemWithItemInfo{} boxItem := BoxItemWithItemInfo{}
if err = rows.Scan(&boxItem.ID, &boxItem.Name, &boxItem.Stage, &boxItem.Category); err != nil { if err = rows.Scan(&boxItem.ID, &boxItem.Name, &boxItem.Stage, &boxItem.Category, &boxItem.Description, &boxItem.Notes); err != nil {
return nil, err return nil, err
} }

View File

@@ -47,6 +47,8 @@ func main() {
boxActions := routes.Boxes(html) boxActions := routes.Boxes(html)
boxItemActions := routes.BoxItems(html) boxItemActions := routes.BoxItems(html)
router.Handle("/items/edit", web.Action(itemActions.Edit)) router.Handle("/items/edit", web.Action(itemActions.Edit))
router.Handle("/items/delete", web.Action(itemActions.Delete)) router.Handle("/items/delete", web.Action(itemActions.Delete))
router.Handle("/items/save", web.Action(itemActions.Save)) router.Handle("/items/save", web.Action(itemActions.Save))

View File

@@ -107,11 +107,18 @@ func GetItemByID(r *http.Request) *web.Response {
func Put(r *http.Request) *web.Response { func Put(r *http.Request) *web.Response {
id, _ := web.PathLast(r) id, _ := web.PathLast(r)
err := r.ParseForm() if err := r.ParseForm(); err != nil {
if err != nil {
return web.Error(http.StatusBadRequest, err, nil) return web.Error(http.StatusBadRequest, err, nil)
} }
if r.Form.Get("category") == "" {
panic(r.Form.Get(""))
}
if r.Form.Get("stage") == "" {
panic(r.Form.Get(""))
}
name := r.Form.Get("name") name := r.Form.Get("name")
stage := r.Form.Get("stage") stage := r.Form.Get("stage")
category := r.Form.Get("category") category := r.Form.Get("category")
@@ -145,9 +152,7 @@ func Put(r *http.Request) *web.Response {
}(), }(),
} }
_, err = db.PutItem(item) if _, err := db.PutItem(item); err != nil {
if err != nil {
return web.Error(http.StatusInternalServerError, err, nil) return web.Error(http.StatusInternalServerError, err, nil)
} }

0
scripts/index.js Normal file
View File

View File

@@ -1,3 +1,23 @@
<tr id="box-item-list"> <tr class="box-item-list">
<td>Hooray!</td> <td>
<table>
<thead>
<tr>
<th scope="col" class="px-6 py-4"></th>
<th scope="col" class="px-6 py-4">#</th>
<th scope="col" class="px-6 py-4">Name</th>
<th scope="col" class="px-6 py-4">Stage</th>
<th scope="col" class="px-6 py-4">Category</th>
<th scope="col" class="px-6 py-4">Description</th>
<th scope="col" class="px-6 py-4">Notes</th>
<th scope="col" class="px-6 py-4"></th>
</tr>
</thead>
<tbody id="table-body">
{{range .}}
{{ template "box-items/box-item-row.html" . }}
{{end}}
</tbody>
</table>
</td>
</tr> </tr>

View File

@@ -0,0 +1,10 @@
<tr class="box-item-row border-b dark:border-neutral-500 hover:bg-slate-300 hover:bg-opacity-20">
<td class="whitespace-nowrap px-6 py-4">{{ .ID }}</td>
<td class="whitespace-nowrap px-6 py-4">{{ .Name }}</td>
{{ template "components/parsed-packing-stage.html" .Stage }}
{{ template "components/parsed-category.html" .Category }}
<td class="whitespace-nowrap px-6 py-4">{{ .Description }}</td>
<td class="whitespace-nowrap px-6 py-4">{{ .Notes }}</td>
</tr>

View File

@@ -3,6 +3,7 @@
<button <button
hx-get="/box-items?boxid={{ .ID }}" hx-get="/box-items?boxid={{ .ID }}"
hx-target="#boxrow-{{ .ID }}" hx-target="#boxrow-{{ .ID }}"
hx-swap="afterend"
class="inline-flex items-center h-8 px-4 m-2 text-sm text-stone-100 transition-colors duration-150 bg-stone-700 rounded-lg focus:shadow-outline hover:bg-stone-800" class="inline-flex items-center h-8 px-4 m-2 text-sm text-stone-100 transition-colors duration-150 bg-stone-700 rounded-lg focus:shadow-outline hover:bg-stone-800"
> >
&gt; &gt;
@@ -11,9 +12,9 @@
<td class="whitespace-nowrap px-6 py-4">{{.ID}}</td> <td class="whitespace-nowrap px-6 py-4">{{.ID}}</td>
<td class="whitespace-nowrap px-6 py-4">{{.Name}}</td> <td class="whitespace-nowrap px-6 py-4">{{.Name}}</td>
{{ template "components/parsed-packing-stage.html" .Stage }} {{ template "components/parsed-packing-stage.html" .ID }}
{{ template "components/parsed-category.html" .Category }} {{ template "components/parsed-category.html" .ID }}
{{ if .Description }} {{ if .Description }}
<td class="whitespace-nowrap px-6 py-4">{{.Description}}</td> <td class="whitespace-nowrap px-6 py-4">{{.Description}}</td>

View File

@@ -0,0 +1,8 @@
<select class="category-selector" data-include-edit="{{.ID}}" value="{{.Category}}" name="category">
<option value="0">Bedroom</option>
<option value="1">Bathroom</option>
<option value="2">Kitchen</option>
<option value="3">Office</option>
<option value="4">Living Room</option>
<option value="5">Other</option>
</select>

View File

@@ -0,0 +1,7 @@
<select class="packing-stage-selector" data-include-edit="{{.ID}}" value="{{.Stage}}" name="stage">
<option value="0">Essentials</option>
<option value="1">Stage One</option>
<option value="2">Stage Two</option>
<option value="3">Stage Three</option>
<option value="4">Determine Later</option>
</select>

View File

@@ -18,6 +18,7 @@
hx-get="/items" hx-get="/items"
hx-target="#home-page-container" hx-target="#home-page-container"
hx-swap="innerHTML" hx-swap="innerHTML"
onclick="handleLabelUpdate"
class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800" class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800"
> >
Items Items
@@ -26,6 +27,7 @@
hx-get="/boxes" hx-get="/boxes"
hx-target="#home-page-container" hx-target="#home-page-container"
hx-swap="innerHTML" hx-swap="innerHTML"
onclick="handleLabelUpdate"
class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800" class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800"
> >
Boxes Boxes
@@ -34,11 +36,18 @@
</nav> </nav>
<br/> <br/>
<span class="text-xl">Items</span> <span id="page-label" class="text-xl">Items</span>
<div id="home-page-container"> <div id="home-page-container">
{{ template "items/entity-list.html" . }} {{ template "items/entity-list.html" . }}
</div> </div>
</div> </div>
</main> </main>
<script>
function handleLabelUpdate() {
const prev = document.getElementById('page-label').innerText;
document.getElementById('page-label').innerText = prev === 'Items' ? 'Boxes' : 'Items';
}
</script>
</body> </body>
</html> </html>

View File

@@ -1,39 +1,40 @@
<tr id="datarow-{{.ID}}" class="datarow border-b dark:border-neutral-500"> <tr id="datarow-{{.ID}}" class="datarow border-b dark:border-neutral-500">
<td class="whitespace-nowrap px-6 py-4"> <td class="whitespace-nowrap px-6 py-4">
<input hidden disabled type="text" name="id" value="{{.ID}}" data-include-edit="{{.ID}}" /> <input class="data-input-{{.ID}}" hidden disabled type="text" name="id" value="{{.ID}}" data-include-edit="{{.ID}}" />
<span>{{.ID}}</span> <span>{{.ID}}</span>
</td> </td>
<td class="whitespace-nowrap px-6 py-4"> <td class="whitespace-nowrap px-6 py-4">
<input <input
type="text" type="text"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" class="data-input-{{.ID}} shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
data-include-edit="{{.ID}}" data-include-edit="{{.ID}}"
name="name" name="name"
value="{{.Name}}" value="{{.Name}}"
/> />
</td> </td>
<td class="whitespace-nowrap px-6 py-4"> <td class="whitespace-nowrap px-6 py-4">
<input <select class="data-input-{{.ID}}" id="packing-stage-selector-{{.ID}}" data-include-edit="{{.ID}}" value="{{.Stage}}" name="stage">
type="text" <option value="0">Essentials</option>
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" <option value="1">Stage One</option>
data-include-edit="{{.ID}}" <option value="2">Stage Two</option>
name="stage" <option value="3">Stage Three</option>
value="{{.Stage}}" <option value="4">Determine Later</option>
/> </select>
</td>
<td class="whitespace-nowrap px-6 py-4">
<select class="data-input-{{.ID}}" id="category-selector-{{.ID}}" data-include-edit="{{.ID}}" value="{{.Category}}" name="category">
<option value="0">Bedroom</option>
<option value="1">Bathroom</option>
<option value="2">Kitchen</option>
<option value="3">Office</option>
<option value="4">Living Room</option>
<option value="5">Other</option>
</select>
</td> </td>
<td class="whitespace-nowrap px-6 py-4"> <td class="whitespace-nowrap px-6 py-4">
<input <input
type="text" type="text"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" class="data-input-{{.ID}} shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
data-include-edit="{{.ID}}"
name="category"
value="{{.Category}}"
/>
</td>
<td class="whitespace-nowrap px-6 py-4">
<input
type="text"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
data-include-edit="{{.ID}}" data-include-edit="{{.ID}}"
name="description" name="description"
value="{{.Description}}" value="{{.Description}}"
@@ -42,7 +43,7 @@
<td class="whitespace-nowrap px-6 py-4"> <td class="whitespace-nowrap px-6 py-4">
<input <input
type="text" type="text"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" class="data-input-{{.ID}} shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
data-include-edit="{{.ID}}" data-include-edit="{{.ID}}"
name="notes" name="notes"
value="{{.Notes}}" value="{{.Notes}}"
@@ -54,7 +55,7 @@
hx-target="#datarow-{{.ID}}" hx-target="#datarow-{{.ID}}"
hx-swap="outerHTML" hx-swap="outerHTML"
hx-indicator="#processing" hx-indicator="#processing"
hx-include="input[data-include-edit='{{.ID}}']" hx-include=".data-input-{{.ID}}"
class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800" class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800"
href="" href=""
>Save</a >Save</a
@@ -71,4 +72,13 @@
>Cancel</a >Cancel</a
> >
</td> </td>
<script>
document.getElementById("category-selector-{{.ID}}").onchange = (e) => {
console.log(e.target.value);
}
document.getElementById("packing-stage-selector-{{.ID}}").onchange = (e) => {
console.log(e.target.value);
}
</script>
</tr> </tr>