# `Cardbox.Narabe`
[🔗](https://github.com/hattoriai/cardbox/blob/v0.1.0/lib/cardbox/narabe.ex#L2)

A collection as a Narabe board: a column for each group of the view's
field, its records as cards, which people move within a column and
across them.

    <Cardbox.Narabe.board id="board" collection={@collection} view={@view}
      records={@records} on_move="move">
      <:card :let={record}>{record.data["title"]}</:card>
    </Cardbox.Narabe.board>

    def handle_event("move", params, socket),
      do: Cardbox.Narabe.handle_move(socket, params, MyApp.Cardbox, socket.assigns.collection,
            socket.assigns.view, actor: socket.assigns.current_user.id)

The view is a saved `Cardbox.View` of type `board`, whose options say
what it shows:

  * `group_by` - the field of the columns: a select or a status (a
    column for each choice, in their order and their colours), a person
    (a column for each person of `people`, and each one a record
    names), or a checkbox (Yes and No);
  * `hidden_groups` - the ids of the columns not shown;
  * `card_fields` - the fields a card shows under its title, unless the
    `card` slot draws it.

Records with no value are in a last column ("No status") when there
are some. A card moved to another column takes that column's value, and
its place among the records (`move/3` of your module): a person who
may not change the record (`allow?/3`) sees the card go back, with the
reason. When the view sorts its records, a card keeps its place in that
order, and only its column changes.

The records are those of the view (`list/3`); the board reads no more.
Load them again on a `Cardbox.Event` of the collection, as for every
view: who moved the card sees it there already.

# `board`

A board of a view's records, in a column for each group of its field.
## Attributes

* `id` (`:string`) (required)
* `collection` (`Cardbox.Collection`) (required)
* `view` (`Cardbox.View`) (required) - a view of type `board`.
* `records` (`:list`) (required) - the records to show (`list/3` of the view).
* `people` (`:list`) - `%{id, name}`, for the columns of a person field. Defaults to `[]`.
* `on_move` (`:string`) - the event of a move; without it, nothing moves. Defaults to `nil`.
* Global attributes are accepted. Supports all globals plus: `["multiple", "handle", "readonly", "locale", "messages", "issho", "user", "class", "phx-target"]`.
## Slots

* `column` - a column's header, given the column (`%{id, name, color}`) as `:let`.
* `card` - a card, given the record as `:let`; its title and `card_fields` by default.
* `footer` - the end of each column, given the column as `:let`.

# `column_of`

```elixir
@spec column_of(Cardbox.Record.t(), Cardbox.Field.t()) :: String.t()
```

The id of the column of a record.

# `columns`

```elixir
@spec columns(Cardbox.Field.t(), [Cardbox.Record.t()], [map()]) :: [map()]
```

The columns of a board: `%{id, name, color}`, in their order, with the
last for the records with no value when there are some.

# `handle_move`

```elixir
@spec handle_move(
  Phoenix.LiveView.Socket.t(),
  map(),
  module(),
  Cardbox.Collection.t(),
  Cardbox.View.t(),
  keyword()
) :: {:reply, map(), Phoenix.LiveView.Socket.t()}
```

Answers the board's move event: `move/5`, and its reply for the board
(`Narabe.Live.reply/1`), which puts a refused card back.

# `move`

```elixir
@spec move(module(), Cardbox.Collection.t(), Cardbox.View.t(), map(), keyword()) ::
  :ok | {:error, String.t() | atom()}
```

Saves a move of the board: each card moved takes the value of its new
column, and its place after or before the card the move names. `opts`:
`:actor`.

---

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