# `PhoenixKit.Utils.Reorder`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.112/lib/phoenix_kit/utils/reorder.ex#L1)

Two-phase index rewrite for drag-to-reorder list views.

Given a list of UUIDs in their new display order and an Ecto schema,
rewrites a position field on the matching rows to `1..N` matching
the order of the input list. The write runs in two passes inside a
transaction — first to negative indices, then to positive — so a
unique index on the position column (should one ever be added)
wouldn't trip mid-update.

Consumers that need pre-write validation (scope checks, permission
guards) or post-write side effects (activity logging, PubSub
broadcasts) should wrap this helper rather than fold the logic in
here. `PhoenixKitProjects.reorder_projects/2` is the reference
consumer doing exactly that — this module owns only the index-rewrite
primitive.

Non-UUID entries in the payload are silently filtered (a stale or
malformed drop event can't poison the rewrite). Duplicates dedup
last-write-wins via `Enum.uniq/1`.

## Example

    defmodule MyApp.Endpoints do
      alias PhoenixKit.Utils.Reorder

      def reorder_endpoints(ordered_ids) do
        Reorder.reorder(MyApp.Endpoint, ordered_ids, :sort_order, repo: repo())
      end
    end

# `result`

```elixir
@type result() :: {:ok, non_neg_integer()} | {:error, :too_many_uuids}
```

# `reorder`

```elixir
@spec reorder(module(), [String.t()], atom(), keyword()) :: result()
```

Rewrites `field` on the rows whose `uuid` appears in `ordered_ids`,
setting it to each UUID's 1-based position in the list.

Returns `{:ok, count}` where `count` is the number of rows actually
updated in the positive-write phase (matches `Repo.update_all`'s
count semantics — UUIDs in the payload that don't resolve to real
rows aren't counted). Returns `{:error, :too_many_uuids}` when the
dedup'd payload exceeds the configured cap. An empty / fully-filtered
payload returns `{:ok, 0}`.

## Options

- `:repo` — the Ecto repo to use. Defaults to
  `PhoenixKit.RepoHelper.repo/0` so it picks up the host app's repo.
- `:max_uuids` — payload cap, checked after dedup. Default `500`.
  Guards against runaway drop events from a misbehaving client.

---

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