# `PhoenixKitEcommerce.Web.OptionState`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ecommerce/blob/v0.1.8/lib/phoenix_kit_ecommerce/web/option_state.ex#L1)

Encapsulates option-related state for product form.

This module manages all option-related data in a single struct,
replacing the multiple assigns previously used in product_form.ex:
- `new_value_inputs` -> `state.new_inputs`
- `selected_option_values` -> `state.selected`
- `original_option_values` -> `state.available`
- `metadata["_price_modifiers"]` -> `state.modifiers`
- `option_schema` -> `state.schema`

## Usage

    # Initialize state from product and schema
    state = OptionState.new(product, option_schema)

    # Toggle a value selection
    state = OptionState.toggle_value(state, "size", "M", ["S", "M", "L"])

    # Add a new custom value
    state = OptionState.add_value(state, "size", "XL")

    # Remove a value
    state = OptionState.remove_value(state, "size", "XL")

    # Update a price modifier
    state = OptionState.update_modifier(state, "size", "M", "5.00")

    # Convert back to metadata for saving
    metadata = OptionState.to_metadata(state)

# `t`

```elixir
@type t() :: %PhoenixKitEcommerce.Web.OptionState{
  available: %{required(String.t()) =&gt; [String.t()]},
  modifiers: %{required(String.t()) =&gt; %{required(String.t()) =&gt; String.t()}},
  new_inputs: %{required(String.t()) =&gt; String.t()},
  schema: [map()],
  selected: %{required(String.t()) =&gt; [String.t()]}
}
```

# `add_new_option`

Adds a completely new option with an initial value.

Returns `{:ok, state}` or `{:error, reason}`.

## Examples

    {:ok, state} = OptionState.add_new_option(state, "material", "Wood")

# `add_value`

Adds a new value to an option.

The value is added to both `available` and `selected` maps.
Returns `{:ok, state}` or `{:error, reason}`.

## Examples

    {:ok, state} = OptionState.add_value(state, "size", "XL")
    {:error, "already exists"} = OptionState.add_value(state, "size", "M")

# `get_all_values`

Gets all values available for an option (schema + custom added).

## Examples

    OptionState.get_all_values(state, "size")
    # => ["S", "M", "L", "XL"]

# `get_modifier`

Gets the modifier value for an option/value pair.

## Examples

    OptionState.get_modifier(state, "size", "M")
    # => "5.00"

# `get_selected_values`

Gets selected values for an option (or all if not explicitly set).

## Examples

    OptionState.get_selected_values(state, "size", ["S", "M", "L"])
    # => ["M", "L"]

# `has_custom_selection?`

Checks if option has custom selection (not all values selected).

## Examples

    OptionState.has_custom_selection?(state, "size")
    # => true

# `new`

Creates a new OptionState from a product and option schema.

## Examples

    product = %Product{metadata: %{"_option_values" => %{"size" => ["M", "L"]}}}
    schema = [%{"key" => "size", "type" => "select", "options" => ["S", "M", "L"]}]

    state = OptionState.new(product, schema)
    # => %OptionState{
    #   schema: [...],
    #   available: %{"size" => ["S", "M", "L"]},
    #   selected: %{"size" => ["M", "L"]},
    #   modifiers: %{},
    #   new_inputs: %{}
    # }

# `remove_value`

Removes a value from an option.

Removes from `available`, `selected`, and any associated modifiers.

## Examples

    state = OptionState.remove_value(state, "size", "XL")

# `to_metadata`

Converts the state back to a metadata map for saving.

Returns a map with `_option_values` and `_price_modifiers` keys.
Empty maps are omitted.

## Examples

    state = %OptionState{
      selected: %{"size" => ["M", "L"]},
      modifiers: %{"size" => %{"M" => "5.00"}}
    }

    OptionState.to_metadata(state)
    # => %{
    #   "_option_values" => %{"size" => ["M", "L"]},
    #   "_price_modifiers" => %{"size" => %{"M" => "5.00"}}
    # }

# `toggle_value`

Toggles a value selection on/off.

If the value is selected, it will be deselected. If not selected, it will be selected.
The `all_values` parameter is used to determine when all values are selected
(in which case the key is removed from selected map).

## Examples

    state = OptionState.toggle_value(state, "size", "M", ["S", "M", "L"])

# `update_modifier`

Updates a price modifier for a specific option value.

## Examples

    state = OptionState.update_modifier(state, "size", "M", "5.00")

# `update_new_input`

Updates the new value input for an option key.

## Examples

    state = OptionState.update_new_input(state, "size", "XL")

# `value_selected?`

Checks if a value is currently selected for an option.

## Examples

    OptionState.value_selected?(state, "size", "M", ["S", "M", "L"])
    # => true

---

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