# Go Backend Tablo Edit And Color Design

**Date:** 2026-05-10

**Goal**

Add edit support to the Go backend `/tablos` page so each project card and list row exposes an edit action immediately to the left of delete, opening a modal that allows the owner to update the tablo `name` and `color`.

**Chosen Approach**

This change follows the minimal additive path:

- keep the existing `/tablos` page structure, HTMX flow, and delete behavior
- keep the current persisted `status` field and status-based filtering unchanged
- add a persisted `color` field
- extend the existing create modal to accept `color`
- add a dedicated edit modal and update route for `name` and `color`

This intentionally does not start the broader `status` deprecation effort. `status` remains in place as-is for this slice.

**Scope**

- Add a `color` field to Go backend tablo persistence.
- Render an edit action on project cards and list rows.
- Open a server-rendered edit modal for a specific tablo.
- Allow create and edit flows to submit `name` and `color`.
- Validate `color` as a full 6-digit hexadecimal value in `#RRGGBB` format.
- Re-render the `/tablos` content after successful create, update, or delete while preserving current page state.

**Out Of Scope**

- Removing or deprecating the existing `status` field
- Task-derived status inference
- Reworking the current search or filter model
- Introducing custom JavaScript beyond the existing HTMX-driven pattern
- Building a `/tablos/:id` detail edit page

**User Experience**

On the Go backend `Mes Projets` page:

- every grid card shows an edit icon button immediately left of the trash icon
- every list row shows the same edit icon button immediately left of the trash icon
- clicking edit opens a modal prefilled with the tablo's current `name` and `color`
- the modal lets the user update:
  - `name`
  - `color`
- the edit modal includes a color picker control bound to the same `color` value
- `status` is not editable in the create or edit modal for this slice

The stored color value remains a strict full hex string such as `#3B82F6`.

**Data Model**

Extend `public.tablos` with:

- `color text not null`

The Go domain model should add:

- `Color string` on `tablos.Record`

Create and update inputs should both include:

- `Name string`
- `Color string`

The current `status` field remains present and unchanged.

**Validation**

Validation rules:

- `name` is required after trimming whitespace
- `color` is required
- `color` must match `^#[0-9A-Fa-f]{6}$`

Validation happens in the handler layer for this slice. The handler should return inline modal errors with HTTP `422` when validation fails.

Examples:

- valid: `#3B82F6`
- valid: `#ff6600`
- invalid: `3B82F6`
- invalid: `#0af`
- invalid: `blue`

**Routes**

Add or extend the following routes:

- `GET /tablos`
  - unchanged page render entrypoint
  - supports existing query params:
    - `view=grid|list`
    - `q=<search text>`
    - `status=all|todo|in_progress|done`
    - `modal=create`
- `POST /tablos`
  - create a new tablo using `name` and `color`
  - continue assigning the existing default `status`
- `GET /tablos/{id}/edit`
  - render the edit modal for the owner
  - preserve current page state through query params
- `POST /tablos/{id}`
  - update `name` and `color` for the owner
- `DELETE /tablos/{id}`
  - unchanged behavior, aside from adjacent edit action in the UI

`POST /tablos/{id}` is preferred here over introducing `PATCH` because it keeps the modal form flow simple and consistent with the current server-rendered HTMX form handling.

**Repository Design**

Minimum repository behavior:

- create tablo with `name`, `color`, and current default `status`
- list tablos including `color`
- update `name`, `color`, and `updated_at` for an owned non-deleted tablo
- soft delete owned tablos as before

Minimum repository methods:

- `CreateTablo`
- `ListTablos`
- `UpdateTablo`
- `SoftDeleteTablo`

Update semantics:

- scope by `id`
- require `owner_id = current user`
- reject deleted rows
- update `name`, `color`, and `updated_at`
- treat missing, foreign-owned, or deleted rows as not found for this slice

**Rendering Contract**

The `/tablos` page should keep its current HTMX-rendered dashboard composition and add edit support without restructuring the page.

Grid cards:

- keep the existing status badge
- render an edit icon button immediately before the delete icon button
- continue using the current card structure and layout

List rows:

- keep the current trailing action cell
- render edit and delete as adjacent icon buttons with edit on the left

Modal behavior:

- create modal collects `name` and `color`
- edit modal collects `name` and `color`
- edit modal includes a native color picker control, prefilled from the current tablo color
- the picker and color text input stay in sync so submissions always send one canonical `#RRGGBB` value
- both modals render inline validation errors
- cancel closes the modal and preserves current page state

**Color Rendering**

The page should use the stored hex value directly rather than only relying on predefined accent classes.

Expected usage:

- avatar or visual accent background
- progress or supporting color accent where appropriate
- any existing accent mapping should be replaced or bypassed only where needed for real color rendering

Implementation should keep style usage narrow and predictable, for example through inline `style` attributes generated from validated values. Since the input is strictly validated server-side, using the stored value in inline styles is acceptable for this slice.

**HTMX Flow**

Open create modal:

- `hx-get` to `/tablos?...&modal=create`
- swap the main content region as today

Open edit modal:

- `hx-get` to `/tablos/{id}/edit?...current state...`
- swap the main content region with the page content that includes the modal

Submit create:

- `hx-post` to `/tablos`
- on success:
  - return refreshed `/tablos` content
  - modal closes because returned state omits modal-open flag
- on failure:
  - return `422`
  - re-render create modal with entered values and inline errors

Submit edit:

- `hx-post` to `/tablos/{id}`
- on success:
  - return refreshed `/tablos` content
  - modal closes
- on failure:
  - return `422`
  - re-render edit modal with entered values and inline errors

Delete:

- keep existing HTMX delete flow
- preserve `view`, `q`, and `status`

**View Model Changes**

`TabloCardView` should add fields needed for edit and color support, for example:

- `Color string`
- `EditRequestURL string`

`TablosPageViewModel` should continue carrying current page state and modal form values. To support both create and edit cleanly, the modal state will likely need to expand beyond the current boolean-only create modal approach.

A pragmatic shape is:

- modal kind: none, create, edit
- form values:
  - name
  - color
- optional editing tablo id
- error message or field-level errors

The exact struct layout can be chosen during implementation, but it should support both modal variants without duplicating page-state plumbing.

For the edit modal specifically, the view model should provide the current validated hex color so both:

- the text input
- the native color picker

can render from the same source of truth.

**Error Handling**

Create or update validation failure:

- return HTTP `422`
- keep modal open
- show clear inline error message near the relevant field or top of form

Unknown or unauthorized tablo on edit open or update:

- return not found behavior
- do not leak whether the tablo exists for another owner

Repository or rendering failures:

- return the existing server error behavior

**Testing Strategy**

Repository coverage:

- create persists `color`
- list returns `color`
- update changes `name`, `color`, and `updated_at`
- update rejects different owner
- update rejects deleted tablo

Handler coverage:

- `GET /tablos` create modal includes `color` field
- `GET /tablos/{id}/edit` renders prefilled `name`, `color`, and color picker value
- `POST /tablos` rejects missing or invalid `color`
- `POST /tablos/{id}` rejects missing or invalid `color`
- `POST /tablos/{id}` updates visible name and color in returned HTML
- edit modal keeps color picker and submitted hex value aligned
- grid card markup contains edit action before delete
- list row markup contains edit action before delete

HTML assertions should verify:

- the edit trigger exists with the expected icon/button semantics
- the edit trigger appears before delete in the rendered action area
- the modal contains both `Nom du projet` and `Couleur`
- the edit modal contains a color picker control in addition to the hex color input
- invalid hex values return a `422` response with inline feedback mentioning `#RRGGBB`

**Implementation Notes**

- preserve the current page query state on create, edit open, edit submit, and delete
- avoid introducing unrelated refactors to status handling
- prefer reuse of the existing modal and shared UI primitives
- keep changes scoped to the Go backend vertical slice:
  - schema
  - queries
  - repository
  - handlers
  - `templ` views
  - tests

**Acceptance Criteria**

The feature is complete when:

- the Go backend `/tablos` page shows an edit action to the left of delete
- clicking edit opens a modal for the selected tablo
- the modal allows changing the tablo `name`
- the modal allows changing the tablo `color`
- the edit modal includes a color picker for choosing the tablo color
- create also accepts `color`
- `color` only accepts full 6-digit hex values like `#3B82F6`
- successful edits update the rendered project card or list row
- current search, filter, and view state are preserved throughout the HTMX flow
