> ## 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.

# Mobiili-SDK - React Native

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

Ohut WebView-käärinen `drawer.kleep.ai`:n ympärillä. SDK tarjoaa yhden komponentin ja kaksi metodia, jotka vastaavat iOS-pintaa.

## Asennus

***

Jokainen julkaisu on saatavilla npm-tarbällina `cdn.kleep.ai`:ssa. Kaksi URL-muotoa on käytettävissä:

**Uusin vakaa** (päivittyy automaattisesti jokaisen uuden vakaan julkaisun myötä — esijulkaisut eivät koskaan siirrä tätä osoitinta):

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

**Kiinnitä tietty versio** (suositeltavaa tuotantoon — täysin muuttumaton):

```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
```

Korvaa `v1.0.0` ja `1.0.0` haluamallasi julkaisutunnisteella. Luetellut paketit ovat vertaisriippuvuuksia — SDK vaatii ne, mutta antaa sinun hallita versiota.

Julkaistu tarbälli sisältää SHA-256-tarkistussumman (`<tarball>.sha256` / `latest.tgz.sha256`), jos haluat varmistaa eheyden ennen asennusta.

### Expo

Molemmat vertaisriippuvuudet on esipaketoitu Expo Go:ssa (SDK 54+). Kehitysvaiheessa ei tarvita ylimääräistä asennusta. Tuotantojulkaisuissa `expo prebuild` ottaa ne automaattisesti käyttöön.

### Bare React Native

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

## Käyttöoikeudet

***

Jalkinevirtausta varten (kameraskannausta), lisää `ios/<App>/Info.plist`-tiedostoon:

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

Ja `android/app/src/main/AndroidManifest.xml`-tiedostoon:

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

## Määritä kerran sovelluksen käynnistyessä

***

```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
});
```

| Kenttä     | Pakollinen | Kuvaus                                                                                                                 |
| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| `publicId` | kyllä      | UUID, joka tunnistaa jälleenmyyjäsi (Kleepin toimittama)                                                               |
| `language` | ei         | `'fr' \| 'en' \| 'de' \| 'it' \| 'es' \| 'nl' \| 'pt' \| 'ja' \| 'ko' \| 'pl' \| 'br' \| 'dk' \| 'fi' \| 'se' \| 'gb'` |

## Käyttö

***

### Metodi 1: `Kleep.checkProduct`

Kutsu tätä PDP:n latautuessa. Tulos ohjaa "Löydä kokoni" CTA:ta — näytetäänkö se ja mitä etikettä käytetään.

| parametri   | prioriteetti | kuvaus                       |
| ----------- | ------------ | ---------------------------- |
| `productId` | *pakollinen* | Tuotteesi ID jälleenmyyjällä |

**Palauttaa**

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

**Logiikkakaavio**

| `recommendable` | `recommendedSize` | Mitä renderöidään                           |
| --------------- | ----------------- | ------------------------------------------- |
| `false`         | —                 | **Piilota CTA** (tuote ei kelpaa Kleepille) |
| `true`          | puuttuu           | CTA: **"Trouver ma taille"**                |
| `true`          | `"M"`             | CTA: **"Taille recommandée: M"**            |

SDK välimuistittaa tuloksen 5 minuutiksi muistiin, avaimella `(publicId, productId)` portille ja `(publicId, productId, mid)` suosituskoolle. PDP:n uudelleenrenderöinti tai taaksepäin navigointi on ilmaista.

**Toteutusesimerkki**

```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)}
      />
    </>
  );
}
```

### Metodi 2: `<KleepFindSizeView>`

Liitä tämä komponentti avaamaan kokohakuvetolaatikko koko näytön Modal+WebView-komponentissa. Ohjattu komponenttimalli: omistat `visible`-tilan, SDK pyytää sulkemista `onDismiss`-kutsulla.

| prop           | prioriteetti  | kuvaus                                                                                                                                                          |
| -------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `visible`      | *pakollinen*  | Hallitsee Modal-näkyvyyttä                                                                                                                                      |
| `productId`    | *pakollinen*  | Sama kuin `checkProduct`:ssa                                                                                                                                    |
| `onDismiss`    | *pakollinen*  | Laukeaa, kun käyttäjä sulkee vetolaatikon (X / pyyhkäisy / takaisin). Isäntäsovelluksen TÄYTYY kääntää `visible` arvoon `false`                                 |
| `variantId`    | *valinnainen* | Esivalitsee variantin suositusta varten                                                                                                                         |
| `customerId`   | *valinnainen* | CRM-tunniste istuntojen väliseen linkitykseen                                                                                                                   |
| `language`     | *valinnainen* | Korvaa SDK-tason kielen tämän avauksen ajaksi                                                                                                                   |
| `countryCode`  | *valinnainen* | esim. `"FR"`, `"US"` — ohjaa mittayksikköjärjestelmää ja rintaliivikokooletuksia                                                                                |
| `stocks`       | *valinnainen* | `{ [variantId]: number \| boolean }` — vetolaatikko näyttää ei-saatavilla / osittainen varasto -käyttöliittymän                                                 |
| `mock`         | *valinnainen* | `true` → vetolaatikko ohittaa oikeat suosituksen API-kutsut (vain QA)                                                                                           |
| `forceState`   | *valinnainen* | `'outOfRange' \| 'unavailable' \| 'error' \| 'qrcode'` — QA-luukku lopputilan suoraan renderöimiseksi                                                           |
| `warmRestore`  | *valinnainen* | `{ mid, uid }` — lataa olemassa oleva mittaus etukäteen (ohittaa johdanto-virtauksen). Samalaitteinen palautus on jo automaattinen AsyncStoragen kautta         |
| `extraParams`  | *valinnainen* | Raw `Record<string, string>` liitetään vetolaatikon URL:iin (pakoreitti)                                                                                        |
| `onAddToCart`  | *valinnainen* | `(event: { variantId, size? }) => void` — käyttäjä napauttoi vetolaatikon sisäistä "Lisää ostoskoriin" CTA:ta. **Isäntäsovellus lisää variantin ostoskoriinsa** |
| `onSelectSize` | *valinnainen* | `(event: { size }) => void` — käyttäjä valitsi koon Tulos-näytöllä. **Isäntäsovelluksen tulisi synkronoida PDP:n kokoValitsin**                                 |
| `onMessage`    | *valinnainen* | Debug-koukku — laukeaa jokaisesta vetolaatikosta jäsennetystä saapuvasta postMessage-viestistä                                                                  |
| `style`        | *valinnainen* | `StyleProp<ViewStyle>` — konttityylin ohitus                                                                                                                    |
| `webViewProps` | *valinnainen* | Välitetään `react-native-webview`:lle lisämukauttamista varten                                                                                                  |

**SDK:n automaattisesti kytkemät toiminnot (sinun ei tarvitse tehdä mitään):**

* Siltaa vetolaatikon iframe-tyylisen `window.parent.postMessage`:n React Native -sillalle
* Säilyttää `mid` / `uid`:n AsyncStorageen, kun vetolaatikko lähettää ne
* Vastaa `getMid` / `getUid` / `getSizes` postMessage-viesteihin vetolaatikosta
* Kutsuu `Kleep.checkProduct`:ia avauksen yhteydessä virtauksen ratkaisemiseksi (vaatteet / alusvaatteet / jalkineet / lapset) — käyttää samaa 5 minuutin välimuistia kuin CTA-kutsu, joten se on ilmainen jos olet jo kutsunut `checkProduct`:ia

### Metodi 3: `Kleep.track`

Lähetä-ja-unohda-analytiikka. Ei koskaan heitä poikkeuksia.

| parametri            | prioriteetti  | kuvaus                                                   |
| -------------------- | ------------- | -------------------------------------------------------- |
| `eventName`          | *pakollinen*  | Tapahtuman nimi                                          |
| `options.customerId` | *valinnainen* | CRM-tunniste                                             |
| `options.parameters` | *valinnainen* | `Record<string, unknown>` — mielivaltainen tapahtumaData |

```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 },
});
```

Haluamme seurata 3 tapahtumaa:

| eventName               | Laukaisija                                       |
| ----------------------- | ------------------------------------------------ |
| `product_viewed`        | PDP:n katselun yhteydessä                        |
| `product_added_to_cart` | Tuotteen lisäämisen yhteydessä ostoskoriin       |
| `checkout_completed`    | Tilauksen vahvistuksen yhteydessä maksun jälkeen |

**`product_viewed` esimerkki**

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

**`product_added_to_cart` esimerkki**

```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` esimerkki**

```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" }
    }
  ]
}
```

## Välimuistin tyhjentäminen

***

SDK pitää kahta muistivälimuistia (5 min TTL kumpikin):

* **Tuoteportti** — `(publicId, productId) → { recommendable, category, productFound }`
* **Suosituskoko** — `(publicId, productId, mid) → size label`

Molemmat tyhjenevät automaattisesti. Jos sinun täytyy pakottaa päivitys (käyttäjä kirjautui ulos, jälleenmyyjä vaihtui, manuaalinen päivityspainike):

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