feat(budget): fix design and editing
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
This commit is contained in:
@@ -35,7 +35,7 @@ func (h HandlerImpl) Handle(r *http.ServeMux) {
|
|||||||
r.Handle("GET /budget/new", h.handleNew())
|
r.Handle("GET /budget/new", h.handleNew())
|
||||||
r.Handle("GET /budget/{id}", h.handleEdit())
|
r.Handle("GET /budget/{id}", h.handleEdit())
|
||||||
r.Handle("POST /budget/{id}", h.handlePost())
|
r.Handle("POST /budget/{id}", h.handlePost())
|
||||||
// r.Handle("DELETE /budget/{id}", h.handleDelete())
|
r.Handle("DELETE /budget/{id}", h.handleDelete())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HandlerImpl) handlePage() http.HandlerFunc {
|
func (h HandlerImpl) handlePage() http.HandlerFunc {
|
||||||
@@ -112,18 +112,18 @@ func (h HandlerImpl) handlePost() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// id uuid.UUID
|
id uuid.UUID
|
||||||
// err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
// if idStr != "new" {
|
if idStr != "new" {
|
||||||
// id, err = uuid.Parse(idStr)
|
id, err = uuid.Parse(idStr)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest))
|
core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest))
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
valueF, err := strconv.ParseFloat(r.FormValue("value"), 64)
|
valueF, err := strconv.ParseFloat(r.FormValue("value"), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -133,25 +133,52 @@ func (h HandlerImpl) handlePost() http.HandlerFunc {
|
|||||||
value := int64(math.Round(valueF * DECIMALS_MULTIPLIER))
|
value := int64(math.Round(valueF * DECIMALS_MULTIPLIER))
|
||||||
|
|
||||||
input := Budget{
|
input := Budget{
|
||||||
Value: value,
|
Id: id,
|
||||||
Description: r.FormValue("name"),
|
Description: r.FormValue("name"),
|
||||||
|
Value: value,
|
||||||
}
|
}
|
||||||
|
|
||||||
var budget *Budget
|
|
||||||
if idStr == "new" {
|
if idStr == "new" {
|
||||||
budget, err = h.s.Add(r.Context(), user, input)
|
_, err = h.s.Add(r.Context(), user, input)
|
||||||
|
if err != nil {
|
||||||
|
core.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err = h.s.Update(r.Context(), user, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
core.HandleError(w, r, err)
|
core.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// } else {
|
|
||||||
// budget, err = h.s.Update(r.Context(), user, input)
|
|
||||||
// if err != nil {
|
|
||||||
// core.HandleError(w, r, err)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
core.DoRedirect(w, r, "/budget/"+budget.Id.String())
|
core.DoRedirect(w, r, "/budget")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h HandlerImpl) handleDelete() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
core.UpdateSpan(r)
|
||||||
|
|
||||||
|
user := core.GetUser(r)
|
||||||
|
if user == nil {
|
||||||
|
core.DoRedirect(w, r, "/auth/signin")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idStr := r.PathValue("id")
|
||||||
|
id, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.s.Delete(r.Context(), user, id)
|
||||||
|
if err != nil {
|
||||||
|
core.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
core.DoRedirect(w, r, "/budget")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,15 +53,24 @@ func (s ServiceImpl) Add(ctx context.Context, user *auth_types.User, budget Budg
|
|||||||
return s.db.Insert(ctx, budget)
|
return s.db.Insert(ctx, budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ServiceImpl) Update(ctx context.Context, user *auth_types.User, budget Budget) (*Budget, error) {
|
func (s ServiceImpl) Update(ctx context.Context, user *auth_types.User, input Budget) (*Budget, error) {
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return nil, core.ErrUnauthorized
|
return nil, core.ErrUnauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
budget, err := s.Get(ctx, user, input.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
budget.Description = input.Description
|
||||||
|
budget.Value = input.Value
|
||||||
|
|
||||||
if user.Id != budget.UserId {
|
if user.Id != budget.UserId {
|
||||||
return nil, core.ErrBadRequest
|
return nil, core.ErrBadRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid := s.isBudgetValid(budget)
|
isValid := s.isBudgetValid(*budget)
|
||||||
if !isValid {
|
if !isValid {
|
||||||
return nil, core.ErrBadRequest
|
return nil, core.ErrBadRequest
|
||||||
}
|
}
|
||||||
@@ -70,7 +79,7 @@ func (s ServiceImpl) Update(ctx context.Context, user *auth_types.User, budget B
|
|||||||
now := s.clock.Now()
|
now := s.clock.Now()
|
||||||
budget.UpdatedAt = &now
|
budget.UpdatedAt = &now
|
||||||
|
|
||||||
return s.db.Update(ctx, budget)
|
return s.db.Update(ctx, *budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ServiceImpl) Delete(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) error {
|
func (s ServiceImpl) Delete(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) error {
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ templ page(budgets []Budget) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
templ editNew() {
|
templ editNew() {
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col h-full">
|
||||||
@core.Breadcrumb([]string{"Home", "Budget", "New"}, []string{"/", "/budget", "/budget/new"})
|
@core.Breadcrumb([]string{"Home", "Budget", "New"}, []string{"/", "/budget", "/budget/new"})
|
||||||
<div class="flex justify-center items-center flex-1">
|
<div class="flex justify-center items-center flex-1">
|
||||||
<form
|
<form
|
||||||
hx-post={ "/budget/new" }
|
hx-post={ "/budget/new" }
|
||||||
class="grid grid-cols-4 items-center gap-4 mr-auto max-w-2xl h-full"
|
class="grid grid-cols-4 items-center gap-4 max-w-2xl"
|
||||||
>
|
>
|
||||||
<label for="timestamp" class="text-sm text-gray-500">Name</label>
|
<label for="timestamp" class="text-sm text-gray-500">Name</label>
|
||||||
<input
|
<input
|
||||||
@@ -58,12 +58,12 @@ templ editNew() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
templ edit(budget Budget) {
|
templ edit(budget Budget) {
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col h-full">
|
||||||
@core.Breadcrumb([]string{"Home", "Budget", budget.Description}, []string{"/", "/budget", "/budget/" + budget.Id.String()})
|
@core.Breadcrumb([]string{"Home", "Budget", budget.Description}, []string{"/", "/budget", "/budget/" + budget.Id.String()})
|
||||||
<div class="flex justify-center items-center flex-1">
|
<div class="flex justify-center items-center flex-1">
|
||||||
<form
|
<form
|
||||||
hx-post={ "/budget/new" }
|
hx-post={ "/budget/" + budget.Id.String() }
|
||||||
class="grid grid-cols-4 items-center gap-4 mr-auto max-w-2xl h-full"
|
class="grid grid-cols-4 items-center gap-4 max-w-2xl"
|
||||||
>
|
>
|
||||||
<label for="timestamp" class="text-sm text-gray-500">Name</label>
|
<label for="timestamp" class="text-sm text-gray-500">Name</label>
|
||||||
<input
|
<input
|
||||||
@@ -81,6 +81,16 @@ templ edit(budget Budget) {
|
|||||||
class="bg-white input col-span-3"
|
class="bg-white input col-span-3"
|
||||||
/>
|
/>
|
||||||
<div class="flex gap-6 justify-end col-span-4">
|
<div class="flex gap-6 justify-end col-span-4">
|
||||||
|
<button
|
||||||
|
hx-delete={ "/budget/" + budget.Id.String() }
|
||||||
|
hx-confirm={ "Do you really want to delete '" + budget.Description + "'" }
|
||||||
|
class="col-start-4 p-2 px-4 decoration-yellow-400 decoration-[0.25rem] hover:bg-red-50 rounded-lg hover:underline flex items-center gap-2 justify-center"
|
||||||
|
>
|
||||||
|
@svg.Delete()
|
||||||
|
<span>
|
||||||
|
Delete
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
<a href="/budget" class="col-start-3 p-2 px-4 decoration-yellow-400 decoration-[0.25rem] hover:bg-gray-200 rounded-lg hover:underline flex items-center gap-2 justify-center">
|
<a href="/budget" class="col-start-3 p-2 px-4 decoration-yellow-400 decoration-[0.25rem] hover:bg-gray-200 rounded-lg hover:underline flex items-center gap-2 justify-center">
|
||||||
<span class="h-4 w-4">
|
<span class="h-4 w-4">
|
||||||
@svg.Cancel()
|
@svg.Cancel()
|
||||||
@@ -114,12 +124,12 @@ templ newItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
templ item(budget Budget) {
|
templ item(budget Budget) {
|
||||||
<a href={ "/budget/" + budget.Id.String() } class="flex flex-col w-64 h-64 p-5 rounded-lg bg-gray-50 border-1 border-gray-300 ">
|
<a href={ "/budget/" + budget.Id.String() } class="p-5 w-64 h-64 flex gap-10 active:bg-gray-200 flex-col justify-center items-center hover:bg-gray-100 transition-all cursor-pointer rounded-lg bg-gray-50 border-1 border-gray-300">
|
||||||
<span>
|
<span>
|
||||||
{ budget.Description }
|
{ budget.Description }
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{ 200 }€
|
{ core.FormatEuros(budget.Value) }
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user