# `PhoenixKitCatalogue.Errors`
[🔗](https://github.com/BeamLabEU/phoenix_kit_catalogue/blob/0.1.14/lib/phoenix_kit_catalogue/errors.ex#L1)

Central mapping from error atoms (returned by `PhoenixKitCatalogue.Catalogue`
and the import pipeline) to translated, user-facing strings.

Keeping UI copy in one place means every "not found" / "delete failed" /
"cycle" flash reads the same wording, and translations live in core's
gettext backend rather than being scattered across LiveViews. Callers
pattern-match on atoms (or tagged tuples for atoms with parameters);
`message/1` wraps each mapping in `gettext/1` at the UI boundary.

## Supported reason shapes

  * plain atoms — `:would_create_cycle`, `:cross_catalogue`, etc.
  * tagged tuples — `{:referenced_by_smart_items, count}`,
    `{:duplicate_referenced_catalogue, uuid}`,
    `{:invalid_price, raw}`, `{:invalid_markup, raw}`,
    `{:sheet_empty, sheet}`, `{:sheet_read_failed, sheet, raw}`,
    `{:xlsx_open_failed, raw}`, `{:xlsx_read_failed, raw}`,
    `{:csv_parse_failed, raw}`
  * `Ecto.Changeset.t()` — passed through unchanged so callers can
    keep the changeset for `<.input>` rendering. UI flashes typically
    pull a summary via `Ecto.Changeset.traverse_errors/2`.
  * strings — passed through unchanged (legacy / interpolated messages)
  * anything else — rendered as `"Unexpected error: <inspect>"` so
    nothing silently surfaces a raw struct or tuple

## Example

    iex> PhoenixKitCatalogue.Errors.message(:would_create_cycle)
    "Cannot move a category under itself or one of its descendants."

    iex> PhoenixKitCatalogue.Errors.message({:referenced_by_smart_items, 3})
    "Cannot delete: 3 smart items still reference this catalogue."

# `error_atom`

```elixir
@type error_atom() ::
  :would_create_cycle
  | :cross_catalogue
  | :parent_not_found
  | :not_siblings
  | :category_not_found
  | :catalogue_not_found
  | :same_catalogue
  | :no_user
  | :unsupported
  | :not_found
  | :missing_item_name
  | :unsupported_file_format
  | :csv_empty
```

Atoms returned by the public `Catalogue` API and the import
pipeline. Tagged tuples extend this set when an atom needs a
parameter (`{:referenced_by_smart_items, count}`).

# `message`

```elixir
@spec message(term()) :: String.t()
```

Translates an error reason into a user-facing string via gettext.

Use this at the UI boundary — typically inside `put_flash(:error, ...)`
in a LiveView's `handle_event/3` clause. Context functions return
raw atoms; the LV decides whether to surface the specific reason
(via this helper) or a generic flash for unhandled shapes.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
