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

# Chargement du Catalogue de Produits

> Récupérer et mettre en cache les produits de cartes-cadeaux organisés par catégorie

## Vue d'ensemble

L'endpoint du catalogue retourne toutes les cartes-cadeaux et produits numériques disponibles, organisés par catégories telles que les cartes gaming, les services de streaming, etc. Les produits doivent être mis en cache pour minimiser les appels API, car le catalogue change rarement.

<Info>
  Mettez en cache les données du catalogue pendant **au moins 24 heures**. Les produits sont ajoutés/supprimés rarement.
</Info>

## Référence API

<Card title="GET /v3/gift-cards/catalog" icon="list" href="/fr/api-reference/gift-cards/get-catalog">
  Documentation complète de l'endpoint
</Card>

## Chargement de base du catalogue

<CodeGroup>
  ```javascript Node.js theme={null}
  async function loadCatalog() {
    const response = await fetch(
      "https://api.oneclickdz.com/v3/gift-cards/catalog",
      {
        headers: {
          "X-Access-Token": process.env.API_KEY,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`Failed to load catalog: ${response.status}`);
    }

    const result = await response.json();
    return result.data;
  }

  // Usage
  const catalog = await loadCatalog();
  console.log(`Total categories: ${catalog.categories.length}`);
  console.log(
    `Total products: ${catalog.categories.reduce(
      (sum, cat) => sum + cat.products.length,
      0
    )}`
  );
  ```

  ```python Python theme={null}
  import requests
  import os

  def load_catalog():
      response = requests.get(
          'https://api.oneclickdz.com/v3/gift-cards/catalog',
          headers={'X-Access-Token': os.getenv('API_KEY')}
      )

      response.raise_for_status()
      return response.json()['data']

  # Usage
  catalog = load_catalog()
  total_products = sum(len(cat['products']) for cat in catalog['categories'])
  print(f"Loaded {len(catalog['categories'])} categories with {total_products} products")
  ```

  ```php PHP theme={null}
  <?php

  function loadCatalog($apiKey) {
      $ch = curl_init('https://api.oneclickdz.com/v3/gift-cards/catalog');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'X-Access-Token: ' . $apiKey
      ]);

      $response = curl_exec($ch);
      $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);

      if ($httpCode !== 200) {
          throw new Exception("Failed to load catalog: " . $httpCode);
      }

      $result = json_decode($response, true);
      return $result['data'];
  }

  // Usage
  $catalog = loadCatalog(getenv('API_KEY'));
  echo "Total categories: " . count($catalog['categories']) . "\n";
  ?>
  ```

  ```bash cURL theme={null}
  curl https://api.oneclickdz.com/v3/gift-cards/catalog \
    -H "X-Access-Token: YOUR_API_KEY"
  ```
</CodeGroup>

## Structure de la réponse

```json theme={null}
{
  "success": true,
  "data": {
    "categories": [
      {
        "name": "Gaming Cards",
        "products": [
          {
            "id": "507f1f77bcf86cd799439011",
            "title": "PlayStation Network",
            "enabled": true,
            "region": "dz"
          },
          {
            "id": "507f1f77bcf86cd799439012",
            "title": "Google Play Gift Card",
            "enabled": true
          }
        ]
      },
      {
        "name": "Streaming Services",
        "products": [
          {
            "id": "507f1f77bcf86cd799439014",
            "title": "Netflix Gift Card",
            "enabled": true
          }
        ]
      }
    ]
  },
  "meta": {
    "totalCategories": 8,
    "totalProducts": 127
  }
}
```

## Implémentation du cache

<CodeGroup>
  ```javascript Node.js theme={null}
  class CatalogCache {
    constructor(ttlMinutes = 10) {
      this.data = null;
      this.timestamp = 0;
      this.ttl = ttlMinutes * 60 * 1000;
    }

    async get() {
      const now = Date.now();

      // Return cached if still valid
      if (this.data && now - this.timestamp < this.ttl) {
        console.log("Returning cached catalog");
        return this.data;
      }

      // Fetch fresh data
      console.log("Fetching fresh catalog");
      const response = await fetch(
        "https://api.oneclickdz.com/v3/gift-cards/catalog",
        {
          headers: { "X-Access-Token": process.env.API_KEY },
        }
      );

      this.data = await response.json();
      this.timestamp = now;

      return this.data;
    }

    invalidate() {
      this.data = null;
      this.timestamp = 0;
    }
  }

  // Usage
  const cache = new CatalogCache(10); // TTL 24 heures

  // First call - fetches from API
  const catalog1 = await cache.get();

  // Second call within 24 hours - returns cached
  const catalog2 = await cache.get();

  // Force refresh
  cache.invalidate();
  const catalog3 = await cache.get(); // Récupère de nouvelles données
  ```

  ```python Python theme={null}
  from datetime import datetime, timedelta
  import requests
  import os

  class CatalogCache:
      def __init__(self, ttl_minutes=10):
          self.data = None
          self.timestamp = None
          self.ttl = timedelta(minutes=ttl_minutes)

      def get(self):
          now = datetime.now()

          # Return cached if still valid
          if self.data and self.timestamp and (now - self.timestamp) < self.ttl:
              print('Returning cached catalog')
              return self.data

          # Fetch fresh data
          print('Fetching fresh catalog')
          response = requests.get(
              'https://api.oneclickdz.com/v3/gift-cards/catalog',
              headers={'X-Access-Token': os.getenv('API_KEY')}
          )
          response.raise_for_status()

          self.data = response.json()
          self.timestamp = now

          return self.data

      def invalidate(self):
          self.data = None
          self.timestamp = None

  # Usage
  cache = CatalogCache(ttl_minutes=10)

  # First call - fetches from API
  catalog1 = cache.get()

  # Second call within 24 hours - returns cached
  catalog2 = cache.get()

  # Force refresh
  cache.invalidate()
  catalog3 = cache.get()
  ```

  ```php PHP theme={null}
  <?php

  class CatalogCache {
      private $data = null;
      private $timestamp = 0;
      private $ttl;
      private $apiKey;

      public function __construct($apiKey, $ttlMinutes = 10) {
          $this->apiKey = $apiKey;
          $this->ttl = $ttlMinutes * 60;
      }

      public function get() {
          $now = time();

          // Return cached if still valid
          if ($this->data !== null && ($now - $this->timestamp) < $this->ttl) {
              error_log('Returning cached catalog');
              return $this->data;
          }

          // Fetch fresh data
          error_log('Fetching fresh catalog');
          $ch = curl_init('https://api.oneclickdz.com/v3/gift-cards/catalog');
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, [
              'X-Access-Token: ' . $this->apiKey
          ]);

          $response = curl_exec($ch);
          curl_close($ch);

          $this->data = json_decode($response, true);
          $this->timestamp = $now;

          return $this->data;
      }

      public function invalidate() {
          $this->data = null;
          $this->timestamp = 0;
      }
  }

  // Usage
  $cache = new CatalogCache(getenv('API_KEY'), 10);

  // First call - fetches from API
  $catalog1 = $cache->get();

  // Second call within 24 hours - returns cached
  $catalog2 = $cache->get();

  // Force refresh
  $cache->invalidate();
  $catalog3 = $cache->get();
  ?>
  ```
</CodeGroup>

## Filtrage des produits

N'afficher que les produits activés aux clients :

<CodeGroup>
  ```javascript Node.js theme={null}
  function getEnabledProducts(catalog) {
    const enabled = [];

    for (const category of catalog.categories) {
      const enabledInCategory = category.products.filter((p) => p.enabled);

      if (enabledInCategory.length > 0) {
        enabled.push({
          categoryName: category.name,
          products: enabledInCategory,
        });
      }
    }

    return enabled;
  }

  // Usage
  const catalog = await cache.get();
  const enabledProducts = getEnabledProducts(catalog.data);
  console.log("Enabled products:", JSON.stringify(enabledProducts, null, 2));
  ```

  ```python Python theme={null}
  def get_enabled_products(catalog):
      enabled = []

      for category in catalog['categories']:
          enabled_in_category = [p for p in category['products'] if p['enabled']]

          if enabled_in_category:
              enabled.append({
                  'categoryName': category['name'],
                  'products': enabled_in_category
              })

      return enabled

  # Usage
  catalog = cache.get()
  enabled_products = get_enabled_products(catalog['data'])
  print(f"Found {len(enabled_products)} categories with enabled products")
  ```

  ```php PHP theme={null}
  <?php

  function getEnabledProducts($catalog) {
      $enabled = [];

      foreach ($catalog['categories'] as $category) {
          $enabledInCategory = array_filter(
              $category['products'],
              function($p) { return $p['enabled']; }
          );

          if (!empty($enabledInCategory)) {
              $enabled[] = [
                  'categoryName' => $category['name'],
                  'products' => array_values($enabledInCategory)
              ];
          }
      }

      return $enabled;
  }

  // Usage
  $catalog = $cache->get();
  $enabledProducts = getEnabledProducts($catalog['data']);
  echo "Enabled categories: " . count($enabledProducts) . "\n";
  ?>
  ```
</CodeGroup>

## Filtrage par région

Filtrer les produits par région pour cibler des marchés spécifiques :

```javascript theme={null}
function filterByRegion(catalog, region = "dz") {
  return catalog.categories
    .map((category) => ({
      ...category,
      products: category.products.filter(
        (p) => p.enabled && (!p.region || p.region === region)
      ),
    }))
    .filter((cat) => cat.products.length > 0);
}

// Usage
const algerianProducts = filterByRegion(catalog.data, "dz");
```

## Bonnes pratiques

<CardGroup cols={2}>
  <Card title="Gérer les erreurs gracieusement" icon="triangle-exclamation">
    Revenez aux données en cache si l'API est temporairement indisponible
  </Card>

  <Card title="Organiser par catégorie" icon="folder-tree">
    Utilisez la structure par catégories pour une meilleure expérience utilisateur
  </Card>
</CardGroup>

## Étapes suivantes

<CardGroup cols={3}>
  <Card title="Vérifier les produits" icon="magnifying-glass" href="/fr/gift-card-guides/2-checking-products">
    Obtenir les prix et le stock pour les produits sélectionnés
  </Card>

  <Card title="Passer des commandes" icon="cart-shopping" href="/fr/gift-card-guides/3-placing-orders">
    Soumettre des commandes avec validation
  </Card>

  <Card title="Référence API" icon="book" href="/fr/api-reference/gift-cards/get-catalog">
    Documentation complète de l'endpoint
  </Card>

  <Card title="Vue d'ensemble" icon="book-open" href="/fr/gift-card-guides/overview">
    Retour à la vue d'ensemble de l'intégration
  </Card>

  <Card title="Suivre le statut" icon="chart-line" href="/fr/gift-card-guides/4-status-tracking">
    Surveiller l'exécution des commandes
  </Card>

  <Card title="Livraison sécurisée" icon="lock" href="/fr/gift-card-guides/5-secure-delivery">
    Chiffrer et livrer les cartes
  </Card>
</CardGroup>
