# `MishkaGervaz.Form.Web.UploadHelpers`
[🔗](https://github.com/mishka-group/mishka_gervaz/blob/v0.0.1-alpha.3/lib/mishka_gervaz/form/web/upload_helpers.ex#L1)

Shared utility functions for file upload wiring in MishkaGervaz forms.

Provides helpers to:
- Build `allow_upload/3` options from DSL config
- Generate namespaced upload names to avoid collisions
- Parse accept strings
- Check if a form config has uploads

See `MishkaGervaz.Form.Web.Live` (calls `build_allow_upload_opts/2` +
`namespaced_upload_name/2` at mount), `MishkaGervaz.Form.Web.Events.UploadHandler`
(uses `namespaced_upload_name/2` for `consume_uploaded_entries`),
`MishkaGervaz.Form.Templates.Standard` (uses `find_upload_for_field/2` +
`upload_error_to_string/1`), and `MishkaGervaz.Form.Entities.Upload`.

# `build_allow_upload_opts`

```elixir
@spec build_allow_upload_opts(map(), String.t()) :: keyword()
```

Build keyword options for `Phoenix.LiveView.allow_upload/3` from a DSL upload config map.

## Examples

    iex> build_allow_upload_opts(%{accept: "image/*", max_entries: 3, max_file_size: 10_000_000, auto_upload: true}, "my-form")
    [accept: ~w(image/*), max_entries: 3, max_file_size: 10_000_000, auto_upload: true]

# `find_upload_for_field`

```elixir
@spec find_upload_for_field(map(), atom()) :: map() | nil
```

Find the upload config for a given field name.

Matches by `field` first, then by `name`.

# `has_uploads?`

```elixir
@spec has_uploads?(map()) :: boolean()
```

Check if a Static config struct has any uploads configured.

# `namespaced_upload_name`

```elixir
@spec namespaced_upload_name(atom(), String.t()) :: atom()
```

Generate a namespaced upload name unique per component instance.

This avoids collisions when multiple form components are on the same page.

## Examples

    iex> namespaced_upload_name(:avatar, "post-form")
    :avatar_post_form

# `parse_accept`

```elixir
@spec parse_accept(String.t() | [String.t()] | nil) :: :any | [String.t()]
```

Parse an accept string into a list of MIME types / extensions.

Returns `:any` if nil, or a list of trimmed parts.

## Examples

    iex> parse_accept(nil)
    :any

    iex> parse_accept("image/*,.pdf")
    ["image/*", ".pdf"]

# `upload_error_to_string`

```elixir
@spec upload_error_to_string(atom()) :: String.t()
```

Convert an upload error atom to a human-readable string.

---

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