Files
spend-sparrow/internal/template/treasurechest/treasure_chest.templ
Tim Wundenberg 307f0d25b8
Some checks failed
Build Docker Image / Build-Docker-Image (push) Has been cancelled
feat(layout): #211 optimize the overall layout for mobile
move navigation to aside
proper mobile handling
update logo.svg
remove pirata-one/only use it for the logo
2025-08-01 22:22:57 +02:00

191 lines
5.3 KiB
Plaintext

package treasurechest
import "spend-sparrow/internal/template/svg"
import "spend-sparrow/internal/types"
import "github.com/google/uuid"
templ TreasureChest(treasureChests []*types.TreasureChest, monthlySums map[uuid.UUID]int64) {
<div class="max-w-6xl mt-10 mx-auto">
<button
hx-get="/treasurechest/new"
hx-target="#treasurechest-items"
hx-swap="afterbegin"
class="ml-auto text-center button button-primary px-2 flex items-center gap-2"
>
@svg.Plus()
New Treasure Chest
</button>
<div id="treasurechest-items" class="my-6 flex flex-col">
for _, treasureChest := range treasureChests {
@TreasureChestItem(treasureChest, monthlySums)
}
</div>
</div>
}
templ EditTreasureChest(treasureChest *types.TreasureChest, parents []*types.TreasureChest, transactionsRecurring templ.Component) {
{{
var (
id string
name string
parentId uuid.UUID
cancelUrl string
)
indentation := " mt-10"
if treasureChest == nil {
id = "new"
name = ""
parentId = uuid.Nil
cancelUrl = "/empty"
} else {
id = treasureChest.Id.String()
name = treasureChest.Name
if treasureChest.ParentId != nil {
parentId = *treasureChest.ParentId
indentation = " mt-2 ml-14"
}
cancelUrl = "/treasurechest/" + id
}
}}
<div id={ "treasurechest-" + id } class={ "border-1 border-gray-300 p-4 bg-gray-50 rounded-lg" + indentation }>
<form
hx-post={ "/treasurechest/" + id }
hx-target={ "#treasurechest-" + id }
hx-swap="outerHTML"
class="text-xl flex justify-end gap-4 items-center"
>
<div class="grow grid grid-cols-[auto_1fr] items-center gap-4">
<label for="name" class="text-sm text-gray-500">Name</label>
<input
autofocus
name="name"
type="text"
value={ name }
placeholder="Treasure Chest Name"
class="bg-white input max-w-96"
/>
<label for="parent-id" class="text-sm text-gray-500">Parent</label>
<select name="parent-id" class="mr-auto bg-white input">
<option value="" class="text-gray-500">-</option>
for _, parent := range filterNoChildNoSelf(parents, id) {
<option
selected?={ parentId == parent.Id }
value={ parent.Id.String() }
>{ parent.Name }</option>
}
</select>
</div>
<button type="submit" class="button button-neglect px-1 flex items-center gap-2">
@svg.Save()
<span>
Save
</span>
</button>
<button
hx-get={ cancelUrl }
hx-target={ "#treasurechest-" + id }
hx-swap="outerHTML"
class="button button-neglect px-1 flex items-center gap-2"
>
<span class="h-4 w-4">
@svg.Cancel()
</span>
<span>
Cancel
</span>
</button>
</form>
if id != "new" {
<div class="m-10 border-b-gray-400 border-b-1"></div>
<div class="flex">
<h3 class="text-sm text-gray-500">Monthly Transactions</h3>
<button
hx-get={ "/transaction-recurring?id=new&treasure-chest-id=" + id }
hx-target="next #transaction-recurring"
hx-swap="outerHTML"
class="button button-primary ml-auto px-2 flex items-center gap-2"
>
@svg.Plus()
<p>New Monthly Transaction</p>
</button>
</div>
@transactionsRecurring
}
</div>
}
templ TreasureChestItem(treasureChest *types.TreasureChest, monthlySums map[uuid.UUID]int64) {
{{
var indentation string
viewTransactions := ""
if treasureChest.ParentId != nil {
indentation = " mt-2 ml-14"
} else {
indentation = " mt-10"
viewTransactions = "hidden"
}
}}
<div id={ "treasurechest-" + treasureChest.Id.String() } class={ "border-1 border-gray-300 p-4 bg-gray-50 rounded-lg" + indentation }>
<div class="text-xl flex justify-end items-center gap-4">
<p class="mr-auto">{ treasureChest.Name }</p>
<p class="mr-20 text-gray-600">
if treasureChest.ParentId != nil {
+ { types.FormatEuros(monthlySums[treasureChest.Id]) } <span class="text-gray-500 text-sm">&nbsp;per month</span>
}
</p>
if treasureChest.ParentId != nil {
if treasureChest.CurrentBalance < 0 {
<p class="mr-20 min-w-20 text-right text-red-700">{ types.FormatEuros(treasureChest.CurrentBalance) }</p>
} else {
<p class="mr-20 min-w-20 text-right text-green-700">{ types.FormatEuros(treasureChest.CurrentBalance) }</p>
}
}
<a
href={ templ.URL("/transaction?treasure-chest-id=" + treasureChest.Id.String()) }
class={ "button button-neglect px-1 flex items-center gap-2 " + viewTransactions }
title="View transactions"
>
@svg.Eye()
<span>
View
</span>
</a>
<button
hx-get={ "/treasurechest/" + treasureChest.Id.String() + "?edit=true" }
hx-target={ "#treasurechest-" + treasureChest.Id.String() }
hx-swap="outerHTML"
class="button button-neglect px-1 flex items-center gap-2"
>
@svg.Edit()
<span>
Edit
</span>
</button>
<button
hx-delete={ "/treasurechest/" + treasureChest.Id.String() }
hx-target={ "#treasurechest-" + treasureChest.Id.String() }
hx-swap="outerHTML"
class="button button-neglect px-1 flex items-center gap-2"
>
@svg.Delete()
<span>
Delete
</span>
</button>
</div>
</div>
}
func filterNoChildNoSelf(nodes []*types.TreasureChest, selfId string) []*types.TreasureChest {
var result []*types.TreasureChest
for _, node := range nodes {
if node.ParentId == nil && node.Id.String() != selfId {
result = append(result, node)
}
}
return result
}