# Expo / React Native

The Expo SDK (`@fivexer/expo`) is the worker-facing mobile layer. The base `@fivexer/sdk` already works in Expo because it is zero-dependency and only needs `fetch`; this package adds SecureStore session persistence, a live WebSocket queue, React hooks, push notifications, and location updates.

## Install

```
bashnpx expo install @fivexer/expo @fivexer/sdk expo-secure-store expo-notifications expo-location expo-constants react
```

## Scope

This package is **worker-portal only**. It logs in with a worker id + PIN and uses a scoped `wt_...` token. Never embed a workspace `sk_...` API key in a mobile app.

## Quickstart

```
tsximport { FivexerWorkerProvider, ExpoFivexerWorker, useWorkerSession, useQueue } from '@fivexer/expo';

const worker = new ExpoFivexerWorker({ baseUrl: 'https://api.fivexer.com' });

function App() {
    return (
        <FivexerWorkerProvider worker={worker}>
            <WorkerScreen />
        </FivexerWorkerProvider>
    );
}

function WorkerScreen() {
    const { session, login, logout, loading } = useWorkerSession();
    const { taskIds } = useQueue();

    if (loading) return <Text>Resuming…</Text>;
    if (!session) {
        return <Button title="Log in" onPress={() => login({ workspaceId: 'ws_...', workerId: 'w_...', pin: '1234' })} />;
    }

    return (
        <View>
            <Text>Hello, {session.workerId}</Text>
            <Text>Queue: {taskIds.length} tasks</Text>
            <Button title="Log out" onPress={logout} />
        </View>
    );
}
```

## Hooks

- `useWorkerSession()` — session, realtime connection status, `login`, `logout`, `refreshSession`.
- `useQueue()` — live task queue; refreshes automatically on `task.matched` and other lifecycle events.
- `useShift()` — the worker's shift state and the switch that changes it. Workers are created **off shift**, so an app that never calls `setAvailable(true)` correctly receives no work; surface this control prominently.
- `useTaskDetail(taskId)` — rich task detail for a task assigned to the worker.
- `useBreaks()` — today's breaks and completed-task count.
- `useTeamPresence()` — read-only view of who is working vs on break.
- `useMetricsToday()` — completed tasks, break time, working time.

## Push notifications

```
tsximport { registerForPushNotificationsAsync } from '@fivexer/expo';

async function enablePush(worker: ExpoFivexerWorker) {
    const registration = await registerForPushNotificationsAsync(worker);
    if (!registration) return; // permission denied
    // call registration.unregister() on logout
}
```

The platform sends a push when a task is matched to this worker. Tapping the notification is handled by your app's `expo-notifications` response listener.

## Location updates

```
tsximport { startLocationUpdatesAsync } from '@fivexer/expo';

async function enableLocation(worker: ExpoFivexerWorker) {
    const { remove } = await startLocationUpdatesAsync(worker, { intervalMs: 30_000 });
    // call remove() when the shift ends
}
```

Updates are throttled client-side and the server rate-limits them to avoid churn on the matching data plane.

## Realtime connection

The provider opens a WebSocket to `/realtime?token=wt_...` when the app is in the foreground and a session exists. It reconnects with backoff after network errors and pauses while the app is backgrounded to save battery.

## Custom storage

For tests or non-standard environments you can pass a `SecureStoreBackend`:

```
tsconst worker = new ExpoFivexerWorker({
    baseUrl: 'https://api.fivexer.com',
    storage: myAsyncKeyValueStore,
});
```
