> ## Documentation Index
> Fetch the complete documentation index at: https://docs.everybite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Preferences

> Get SmartMenu filter options for a chain

Return the filter options configured for your chain's SmartMenu widget: enabled diets, allergens, and nutrient sliders. Use this to build the dietary preference UI in your app.

## Query

```graphql theme={null}
query GetSmartMenuFilterOptions {
  filterOptions {
    diets {
      type
      displayName
      description
      isEnabled
      ordinal
    }
    allergens {
      type
      displayName
      description
      isEnabled
      ordinal
      icon
    }
    nutrients {
      type
      displayName
      unit
      defaultMin
      defaultMax
    }
  }
}
```

<Info>
  This query requires an API key scoped to your chain in the `Authorization` header. You do not pass chain, widget, or session in the GraphQL query itself.
</Info>

## Parameters

This query takes no arguments. Chain and widget context come from your `Authorization` header.

## Response Types

### WidgetDietaryPreference

```graphql theme={null}
type WidgetDietaryPreference {
  type: DietType!
  displayName: String!
  description: String
  isEnabled: Boolean!
  ordinal: Int
}

enum DietType {
  VEGAN
  VEGETARIAN
  PESCATARIAN
}
```

### WidgetAllergen

```graphql theme={null}
type WidgetAllergen {
  type: AllergenType!
  displayName: String!
  description: String
  isEnabled: Boolean!
  ordinal: Int
  icon: String          # Icon or emoji identifier for UI
}

enum AllergenType {
  DAIRY
  EGG
  FISH
  SHELLFISH
  TREE_NUT
  PEANUT
  WHEAT
  SOY
  SESAME
}
```

### SmartMenuNutrientPreference

```graphql theme={null}
type SmartMenuNutrientPreference {
  type: NutrientType!
  displayName: String!
  unit: String!
  defaultMin: Float
  defaultMax: Float
}

enum NutrientType {
  CALORIES
  PROTEIN
  CARBOHYDRATES
  FAT_TOTAL
  SODIUM
  DIETARY_FIBER
  SUGAR
}
```

## Example

<CodeGroup>
  ```graphql Query theme={null}
  query {
    filterOptions {
      diets {
        type
        displayName
        description
      }
      allergens {
        type
        displayName
        icon
      }
      nutrients {
        type
        displayName
        unit
        defaultMax
      }
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "filterOptions": {
        "diets": [
          {
            "type": "VEGAN",
            "displayName": "Vegan",
            "description": "No animal products"
          },
          {
            "type": "VEGETARIAN",
            "displayName": "Vegetarian",
            "description": "No meat or fish"
          },
          {
            "type": "PESCATARIAN",
            "displayName": "Pescatarian",
            "description": "Fish but no meat"
          }
        ],
        "allergens": [
          { "type": "DAIRY", "displayName": "Dairy", "icon": "milk" },
          { "type": "EGG", "displayName": "Egg", "icon": "egg" },
          { "type": "FISH", "displayName": "Fish", "icon": "fish" },
          { "type": "SHELLFISH", "displayName": "Shellfish", "icon": "shrimp" },
          { "type": "TREE_NUT", "displayName": "Tree Nut", "icon": "nut" },
          { "type": "PEANUT", "displayName": "Peanut", "icon": "peanut" },
          { "type": "WHEAT", "displayName": "Wheat", "icon": "wheat" },
          { "type": "SOY", "displayName": "Soy", "icon": "soybean" },
          { "type": "SESAME", "displayName": "Sesame", "icon": "sesame" }
        ],
        "nutrients": [
          {
            "type": "CALORIES",
            "displayName": "Calories",
            "unit": "kcal",
            "defaultMax": 2000
          },
          {
            "type": "PROTEIN",
            "displayName": "Protein",
            "unit": "g",
            "defaultMax": null
          },
          {
            "type": "CARBOHYDRATES",
            "displayName": "Carbohydrates",
            "unit": "g",
            "defaultMax": null
          },
          {
            "type": "SODIUM",
            "displayName": "Sodium",
            "unit": "mg",
            "defaultMax": 2300
          }
        ]
      }
    }
  }
  ```
</CodeGroup>

## Using Preferences in Search

Pass user-selected preferences to the search query:

```graphql theme={null}
query SearchWithPreferences {
  search(
    preferences: {
      diets: [VEGETARIAN]
      excludeAllergens: [DAIRY, PEANUT]
      calorieRange: { max: 600 }
      nutrientRanges: {
        protein: { min: 20 }
      }
    }
  ) {
    matches {
      dish { id, name }
    }
    counts { matches, almostMatches }
  }
}
```

## UI Recommendations

### Diet Selector

```jsx theme={null}
// Example React component
function DietSelector({ options, selected, onChange }) {
  return (
    <div className="diet-options">
      {options.map(diet => (
        <button
          key={diet.type}
          className={selected.includes(diet.type) ? 'active' : ''}
          onClick={() => onChange(diet.type)}
          title={diet.description}
        >
          {diet.displayName}
        </button>
      ))}
    </div>
  );
}
```

### Allergen Exclusion

<Warning>
  Display allergen exclusions prominently. This is a health and safety feature - make it easy for guests to exclude allergens.
</Warning>

```jsx theme={null}
function AllergenExcluder({ options, excluded, onChange }) {
  return (
    <div className="allergen-options">
      <h3>Exclude Allergens</h3>
      {options.map(allergen => (
        <label key={allergen.type}>
          <input
            type="checkbox"
            checked={excluded.includes(allergen.type)}
            onChange={() => onChange(allergen.type)}
          />
          <span className="icon">{allergen.icon}</span>
          {allergen.displayName}
        </label>
      ))}
    </div>
  );
}
```

### Nutrient Range Sliders

```jsx theme={null}
function CalorieSlider({ max, value, onChange }) {
  return (
    <div className="calorie-slider">
      <label>Max Calories: {value} kcal</label>
      <input
        type="range"
        min={0}
        max={max}
        value={value}
        onChange={e => onChange(parseInt(e.target.value))}
      />
    </div>
  );
}
```

## Caching Filter Options

Unlike search results, filter options change infrequently. You may cache this response for a short period (e.g., 5 minutes) to reduce API calls during a session.

```javascript theme={null}
// Cache filter options per chain
const filterOptionsCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getFilterOptions(chainId) {
  const cached = filterOptionsCache.get(chainId);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const data = await fetchFilterOptions(chainId);
  filterOptionsCache.set(chainId, { data, timestamp: Date.now() });
  return data;
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Load Early" icon="bolt">
    Fetch filter options when the user opens the menu, not when they click "Filter".
  </Card>

  <Card title="Remember Preferences" icon="heart">
    Store user's preferred filters locally and pre-populate on return visits.
  </Card>

  <Card title="Show Counts" icon="hashtag">
    After filtering, show how many dishes match (e.g., "12 Vegetarian dishes").
  </Card>

  <Card title="Clear All Button" icon="xmark">
    Provide an easy way to reset all filters.
  </Card>
</CardGroup>
