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

# Mobile SDK - React Native

**Github Repository:** [https://github.com/KlipFit/kleep-rn](https://github.com/KlipFit/kleep-rn)

Ein schlankes WebView-Wrapper um `drawer.kleep.ai`. Das SDK stellt eine Komponente + zwei Methoden bereit und spiegelt die iOS-Oberfläche wider.

## Installation

***

Jede Version wird als npm-Tarball auf `cdn.kleep.ai` veröffentlicht. Zwei URL-Formen sind verfügbar:

**Neueste stabile Version** (wird automatisch mit jeder neuen stabilen Version aktualisiert — Vorabversionen verschieben diesen Zeiger nie):

```bash theme={null}
npm install https://cdn.kleep.ai/react-native-sdk/latest.tgz \
  react-native-webview \
  @react-native-async-storage/async-storage
```

**Eine bestimmte Version festlegen** (empfohlen für die Produktion — vollständig unveränderlich):

```bash theme={null}
npm install https://cdn.kleep.ai/react-native-sdk/releases/v1.0.0/kleep-react-native-1.0.0.tgz \
  react-native-webview \
  @react-native-async-storage/async-storage
```

Ersetzen Sie `v1.0.0` und `1.0.0` durch das gewünschte Release-Tag. Die beiden aufgeführten Pakete sind Peer-Abhängigkeiten — das SDK benötigt sie, lässt Ihnen aber die Versionskontrolle.

Der veröffentlichte Tarball enthält eine SHA-256-Datei (`<tarball>.sha256` / `latest.tgz.sha256`), falls Sie die Integrität vor der Installation überprüfen möchten.

### Expo

Beide Peer-Abhängigkeiten sind in Expo Go (SDK 54+) vorgebündelt. Kein zusätzliches Setup in der Entwicklung erforderlich. Für Produktions-Builds werden sie automatisch durch `expo prebuild` erfasst.

### Bare React Native

```bash theme={null}
cd ios && pod install
```

## Berechtigungen

***

Für den Schuh-Flow (Kamera-Scan) fügen Sie zu `ios/<App>/Info.plist` hinzu:

```xml theme={null}
<key>NSCameraUsageDescription</key>
<string>Used to scan your shoe size</string>
```

Und zu `android/app/src/main/AndroidManifest.xml`:

```xml theme={null}
<uses-permission android:name="android.permission.CAMERA" />
```

## Einmalige Konfiguration beim App-Start

***

```tsx theme={null}
import { Kleep } from '@kleep/react-native';

Kleep.configure({
  publicId: 'YOUR_KLEEP_PUBLIC_ID',  // UUID provided by Kleep
  language: 'fr',                      // optional, default UI language
});
```

| Feld       | Erforderlich | Beschreibung                                                                                                           |
| ---------- | ------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `publicId` | ja           | UUID zur Identifikation Ihres Händlers (von Kleep bereitgestellt)                                                      |
| `language` | nein         | `'fr' \| 'en' \| 'de' \| 'it' \| 'es' \| 'nl' \| 'pt' \| 'ja' \| 'ko' \| 'pl' \| 'br' \| 'dk' \| 'fi' \| 'se' \| 'gb'` |

## Verwendung

***

### Methode 1: `Kleep.checkProduct`

Rufen Sie diese Methode beim Mounten des PDP auf. Das Ergebnis steuert den CTA „Meine Größe finden" — ob er gerendert wird und welche Beschriftung angezeigt werden soll.

| Parameter   | Priorität      | Beschreibung                 |
| ----------- | -------------- | ---------------------------- |
| `productId` | *erforderlich* | Ihre Produkt-ID beim Händler |

**Rückgabewert**

```ts theme={null}
{
  recommendable: boolean;
  productFound: boolean;
  category?: 'clothing' | 'lingerie' | 'footwear' | 'children';
  recommendedSize?: string;   // e.g. "M", "38"
}
```

**Logik-Schema**

| `recommendable` | `recommendedSize` | Was rendern                                           |
| --------------- | ----------------- | ----------------------------------------------------- |
| `false`         | —                 | **CTA ausblenden** (Produkt nicht für Kleep geeignet) |
| `true`          | nicht vorhanden   | CTA: **„Trouver ma taille"**                          |
| `true`          | `"M"`             | CTA: **„Taille recommandée: M"**                      |

Das SDK cached das Ergebnis 5 Minuten lang im Speicher, nach `(publicId, productId)` für das Gate und `(publicId, productId, mid)` für die empfohlene Größe. Das erneute Rendern des PDP oder das Zurücknavigieren ist kostenlos.

**Implementierungsbeispiel**

```tsx theme={null}
import { useEffect, useState } from 'react';
import { Pressable, Text } from 'react-native';
import { Kleep, KleepFindSizeView, type KleepCheckProductResult } from '@kleep/react-native';

function ProductPage({ product }) {
  const [check, setCheck] = useState<KleepCheckProductResult | null>(null);
  const [open, setOpen] = useState(false);

  useEffect(() => {
    Kleep.checkProduct({ productId: product.id }).then(setCheck);
  }, [product.id]);

  if (!check?.recommendable) return <ProductContent />;

  return (
    <>
      <ProductContent />
      <Pressable onPress={() => setOpen(true)}>
        <Text>
          {check.recommendedSize
            ? `Taille recommandée : ${check.recommendedSize}`
            : 'Trouver ma taille'}
        </Text>
      </Pressable>
      <KleepFindSizeView
        visible={open}
        productId={product.id}
        variantId={selectedVariant?.id}
        onAddToCart={(e) => cart.add(e.variantId)}
        onSelectSize={(e) => pdp.setSize(e.size)}
        onDismiss={() => setOpen(false)}
      />
    </>
  );
}
```

### Methode 2: `<KleepFindSizeView>`

Mounten Sie diese Komponente, um den Größenfinder-Drawer in einem Vollbild-Modal+WebView zu öffnen. Kontrolliertes Komponentenmuster: Sie besitzen den `visible`-Zustand, das SDK fordert das Schließen über `onDismiss` an.

| Prop           | Priorität      | Beschreibung                                                                                                                                               |
| -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `visible`      | *erforderlich* | Steuert die Modal-Sichtbarkeit                                                                                                                             |
| `productId`    | *erforderlich* | Wie in `checkProduct`                                                                                                                                      |
| `onDismiss`    | *erforderlich* | Wird ausgelöst, wenn der Nutzer den Drawer schließt (X / Swipe / Zurück). Der Host MUSS `visible` auf `false` setzen                                       |
| `variantId`    | *optional*     | Wählt eine Variante für die Empfehlung vor                                                                                                                 |
| `customerId`   | *optional*     | CRM-Identifikator für sitzungsübergreifende Verknüpfung                                                                                                    |
| `language`     | *optional*     | Überschreibt die SDK-Sprache für diesen Öffnungsvorgang                                                                                                    |
| `countryCode`  | *optional*     | z. B. `"FR"`, `"US"` — steuert Maßeinheitensystem + BH-Größen-Standards                                                                                    |
| `stocks`       | *optional*     | `{ [variantId]: number \| boolean }` — Drawer zeigt nicht verfügbare / teilweise Lager-UI                                                                  |
| `mock`         | *optional*     | `true` → Drawer überspringt echte Empfehlungs-API-Aufrufe (nur QA)                                                                                         |
| `forceState`   | *optional*     | `'outOfRange' \| 'unavailable' \| 'error' \| 'qrcode'` — QA-Türöffner, um einen Endzustand direkt zu rendern                                               |
| `warmRestore`  | *optional*     | `{ mid, uid }` — eine vorhandene Messung vorladen (Intro-Flow überspringen). Geräteinterne Wiederherstellung erfolgt bereits automatisch über AsyncStorage |
| `extraParams`  | *optional*     | Rohes `Record<string, string>`, das an die Drawer-URL angehängt wird (Notausstieg)                                                                         |
| `onAddToCart`  | *optional*     | `(event: { variantId, size? }) => void` — Nutzer hat den In-Drawer-CTA „In den Warenkorb" gedrückt. **Der Host fügt die Variante seinem Warenkorb hinzu**  |
| `onSelectSize` | *optional*     | `(event: { size }) => void` — Nutzer hat eine Größe auf dem Ergebnisbildschirm ausgewählt. **Der Host sollte seinen PDP-Größenwähler synchronisieren**     |
| `onMessage`    | *optional*     | Debug-Hook — wird für jede eingehende postMessage ausgelöst, die aus dem Drawer geparst wird                                                               |
| `style`        | *optional*     | `StyleProp<ViewStyle>` — Container-Stil-Überschreibung                                                                                                     |
| `webViewProps` | *optional*     | Wird an `react-native-webview` für erweiterte Anpassungen weitergeleitet                                                                                   |

**Automatisch vom SDK verdrahtet (Sie müssen nichts tun):**

* Verbindet das iFrame-ähnliche `window.parent.postMessage` des Drawers mit der React Native-Bridge
* Speichert `mid` / `uid` in AsyncStorage, wenn der Drawer sie pusht
* Antwortet auf `getMid` / `getUid` / `getSizes`-postMessages vom Drawer
* Ruft `Kleep.checkProduct` beim Öffnen auf, um den Flow aufzulösen (Bekleidung / Dessous / Schuhe / Kinder) — verwendet denselben 5-Minuten-Cache wie Ihr CTA-Aufruf, sodass es kostenlos ist, wenn Sie `checkProduct` bereits aufgerufen haben

### Methode 3: `Kleep.track`

Fire-and-Forget-Analytics. Wirft nie eine Exception.

| Parameter            | Priorität      | Beschreibung                                        |
| -------------------- | -------------- | --------------------------------------------------- |
| `eventName`          | *erforderlich* | Name des Ereignisses                                |
| `options.customerId` | *optional*     | CRM-Identifikator                                   |
| `options.parameters` | *optional*     | `Record<string, unknown>` — beliebige Ereignisdaten |

```tsx theme={null}
import { Kleep } from '@kleep/react-native';

await Kleep.track('product_viewed', {
  parameters: { productId: product.id },
});

await Kleep.track('product_added_to_cart', {
  customerId: user.id,
  parameters: {
    productId: product.id,
    variantId: selectedVariant.id,
    cart: cart.items,
  },
});

await Kleep.track('checkout_completed', {
  customerId: user.id,
  parameters: { orderId: order.id, cart: order.items },
});
```

Wir möchten 3 Ereignisse tracken:

| eventName               | Auslöser                                     |
| ----------------------- | -------------------------------------------- |
| `product_viewed`        | Beim Aufrufen des PDP                        |
| `product_added_to_cart` | Beim Hinzufügen eines Produkts zum Warenkorb |
| `checkout_completed`    | Bei der Bestellbestätigung nach der Zahlung  |

**`product_viewed`-Beispiel**

```jsx theme={null}
{
  productId: "123ABC456"
}
```

**`product_added_to_cart`-Beispiel**

```jsx theme={null}
{
  productId: "123ABC456",
  variantId: "123ABC456-00R",
  cart: [
    {
      productId: "123ABC456",
      variantId: "123ABC456-00R",
      sku: "XYZ",
      size: "S",
      quantity: 2,
      price: { amount: "50", currencyCode: "EUR" }
    }
  ]
}
```

**`checkout_completed`-Beispiel**

```jsx theme={null}
{
  orderId: "000001",
  cart: [
    {
      lineItemId: "000001#1",
      productId: "123ABC456",
      variantId: "123ABC456-00R",
      sku: "XYZ",
      size: "S",
      quantity: 2,
      price: { amount: "50", currencyCode: "EUR" }
    }
  ]
}
```

## Cache-Invalidierung

***

Das SDK hält zwei In-Memory-Caches (jeweils 5 Min. TTL):

* **Produkt-Gate** — `(publicId, productId) → { recommendable, category, productFound }`
* **Empfohlene Größe** — `(publicId, productId, mid) → Größenbeschriftung`

Beide werden automatisch invalidiert. Wenn Sie eine Aktualisierung erzwingen müssen (Nutzer hat sich abgemeldet, Händler gewechselt, manuelle Aktualisierungsschaltfläche):

```tsx theme={null}
Kleep.clearCheckProductCache();
```
