feat: extract into remaining packages
All checks were successful
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 1m19s
All checks were successful
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 1m19s
There has been a cyclic dependency. transaction -> treasure_chest -> transaction_recurring -> transaction This has been temporarily solved by moving the GenerateTransactions function into the transaction package. In the future, this function has to be rewritten to use a proper Service insteas of direct DB access or replaced with a different system entirely.
This commit is contained in:
193
internal/treasure_chest/template.templ
Normal file
193
internal/treasure_chest/template.templ
Normal file
@@ -0,0 +1,193 @@
|
||||
package treasure_chest
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"spend-sparrow/internal/core"
|
||||
"spend-sparrow/internal/template/svg"
|
||||
"spend-sparrow/internal/treasure_chest_types"
|
||||
)
|
||||
|
||||
templ TreasureChestComp(treasureChests []*treasure_chest_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 *treasure_chest_types.TreasureChest, parents []*treasure_chest_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 *treasure_chest_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 {
|
||||
+ { core.FormatEuros(monthlySums[treasureChest.Id]) } <span class="text-gray-500 text-sm"> per month</span>
|
||||
}
|
||||
</p>
|
||||
if treasureChest.ParentId != nil {
|
||||
if treasureChest.CurrentBalance < 0 {
|
||||
<p class="mr-20 min-w-20 text-right text-red-700">{ core.FormatEuros(treasureChest.CurrentBalance) }</p>
|
||||
} else {
|
||||
<p class="mr-20 min-w-20 text-right text-green-700">{ core.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 []*treasure_chest_types.TreasureChest, selfId string) []*treasure_chest_types.TreasureChest {
|
||||
var result []*treasure_chest_types.TreasureChest
|
||||
|
||||
for _, node := range nodes {
|
||||
if node.ParentId == nil && node.Id.String() != selfId {
|
||||
result = append(result, node)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user