ui overhaul
Some checks failed
Build and deploy Havenllo / Verify Go and frontend (push) Failing after 29s
Build and deploy Havenllo / Build and push image (push) Has been skipped
Build and deploy Havenllo / Apply and restart Havenllo (push) Has been skipped

This commit is contained in:
Hermes
2026-07-14 11:09:54 -03:00
parent 240f73b229
commit afd23ca751
19 changed files with 603 additions and 382 deletions

View File

@@ -177,7 +177,7 @@ func (h *Handler) updateCard(w http.ResponseWriter, r *http.Request) {
return
}
card, err := h.service.UpdateCard(r.Context(), id, app.CardPatch{
Title: request.Title, Description: request.Description, Done: request.Done, ListID: request.ListID, Position: request.Position,
Title: request.Title, Description: request.Description, ListID: request.ListID, Position: request.Position,
})
if err != nil {
writeDomainError(w, err)

View File

@@ -84,3 +84,42 @@ func TestJSONValidationAndLastListConflict(t *testing.T) {
t.Fatalf("last list status = %d", got.Code)
}
}
func TestCardDoneFieldIsNotPartOfTheAPI(t *testing.T) {
t.Parallel()
handler := newHandler(t)
var board struct {
Lists []struct {
ID int64 `json:"id"`
} `json:"lists"`
}
if err := json.Unmarshal(request(t, handler, http.MethodGet, "/api/board", "", false).Body.Bytes(), &board); err != nil {
t.Fatal(err)
}
if len(board.Lists) == 0 {
t.Fatal("board has no lists")
}
created := request(t, handler, http.MethodPost, "/api/lists/"+strconv.FormatInt(board.Lists[0].ID, 10)+"/cards", `{"title":"status comes from the list"}`, true)
if created.Code != http.StatusCreated {
t.Fatalf("create card status = %d, body %s", created.Code, created.Body)
}
var payload struct {
Card map[string]json.RawMessage `json:"card"`
}
if err := json.Unmarshal(created.Body.Bytes(), &payload); err != nil {
t.Fatal(err)
}
if _, exists := payload.Card["done"]; exists {
t.Fatalf("card response unexpectedly contains done: %s", created.Body)
}
cardID := payload.Card["id"]
var id int64
if err := json.Unmarshal(cardID, &id); err != nil {
t.Fatal(err)
}
if got := request(t, handler, http.MethodPatch, "/api/cards/"+strconv.FormatInt(id, 10), `{"done":true}`, true); got.Code != http.StatusBadRequest {
t.Fatalf("done patch status = %d, body %s", got.Code, got.Body)
}
}

View File

@@ -21,7 +21,6 @@ type createCardRequest struct {
type updateCardRequest struct {
Title *string `json:"title,omitempty"`
Description *string `json:"description,omitempty"`
Done *bool `json:"done,omitempty"`
ListID *int64 `json:"list_id,omitempty"`
Position *float64 `json:"position,omitempty"`
}

View File

@@ -135,8 +135,8 @@ func (s *Service) CreateCard(ctx context.Context, listID int64, title, descripti
return domain.Card{}, err
}
now := timestamp()
result, err := tx.ExecContext(ctx, `INSERT INTO cards (list_id, title, description, position, done, created_at, updated_at)
VALUES (?, ?, ?, ?, 0, ?, ?)`, listID, title, description, pos, now, now)
result, err := tx.ExecContext(ctx, `INSERT INTO cards (list_id, title, description, position, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)`, listID, title, description, pos, now, now)
if err != nil {
return domain.Card{}, err
}
@@ -154,7 +154,6 @@ func (s *Service) CreateCard(ctx context.Context, listID int64, title, descripti
type CardPatch struct {
Title *string
Description *string
Done *bool
ListID *int64
Position *float64
}
@@ -189,9 +188,6 @@ func (s *Service) UpdateCard(ctx context.Context, id int64, patch CardPatch) (do
if patch.Description != nil {
card.Description = *patch.Description
}
if patch.Done != nil {
card.Done = *patch.Done
}
if patch.ListID != nil {
if _, err := store.List(ctx, tx, *patch.ListID); err != nil {
return domain.Card{}, err
@@ -207,12 +203,8 @@ func (s *Service) UpdateCard(ctx context.Context, id int64, patch CardPatch) (do
}
card.Position = pos + positionStep
}
done := 0
if card.Done {
done = 1
}
if _, err := tx.ExecContext(ctx, `UPDATE cards SET list_id = ?, title = ?, description = ?, position = ?, done = ?, updated_at = ? WHERE id = ?`,
card.ListID, card.Title, card.Description, card.Position, done, timestamp(), id); err != nil {
if _, err := tx.ExecContext(ctx, `UPDATE cards SET list_id = ?, title = ?, description = ?, position = ?, updated_at = ? WHERE id = ?`,
card.ListID, card.Title, card.Description, card.Position, timestamp(), id); err != nil {
return domain.Card{}, err
}
if err := normalizeCards(ctx, tx, sourceListID); err != nil {

View File

@@ -25,7 +25,6 @@ type Card struct {
Title string `json:"title"`
Description string `json:"description"`
Position float64 `json:"position"`
Done bool `json:"done"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}

View File

@@ -53,7 +53,7 @@ func List(ctx context.Context, q DBTX, id int64) (domain.List, error) {
}
func Cards(ctx context.Context, q DBTX, listID int64) ([]domain.Card, error) {
rows, err := q.QueryContext(ctx, `SELECT id, list_id, title, description, position, done, created_at, updated_at
rows, err := q.QueryContext(ctx, `SELECT id, list_id, title, description, position, created_at, updated_at
FROM cards WHERE list_id = ? ORDER BY position, id`, listID)
if err != nil {
return nil, err
@@ -71,7 +71,7 @@ func Cards(ctx context.Context, q DBTX, listID int64) ([]domain.Card, error) {
}
func Card(ctx context.Context, q DBTX, id int64) (domain.Card, error) {
row := q.QueryRowContext(ctx, `SELECT id, list_id, title, description, position, done, created_at, updated_at
row := q.QueryRowContext(ctx, `SELECT id, list_id, title, description, position, created_at, updated_at
FROM cards WHERE id = ?`, id)
card, err := scanCard(row)
if err == sql.ErrNoRows {
@@ -84,10 +84,7 @@ type scanner interface{ Scan(...any) error }
func scanCard(row scanner) (domain.Card, error) {
var card domain.Card
var done int
err := row.Scan(&card.ID, &card.ListID, &card.Title, &card.Description, &card.Position, &done, &card.CreatedAt, &card.UpdatedAt)
card.Done = done != 0
return card, err
return card, row.Scan(&card.ID, &card.ListID, &card.Title, &card.Description, &card.Position, &card.CreatedAt, &card.UpdatedAt)
}
func Snapshot(ctx context.Context, q DBTX) (domain.Snapshot, error) {