Sign in

A field sales app (React Native)

React Native: check in, tasks, leads and visits.

A React Native (Expo) app for people in the field: check in, see today's tasks and leads, log a visit.

  1. RegisterKind Mobile or desktop, callback com.acme.field:/callback, permissions hr.read hr.attendance crm.read crm.write projects.read projects.write.
  2. Sign in
    JAVASCRIPT
    import * as AuthSession from "expo-auth-session";
    
    const discovery = AuthSession.useAutoDiscovery("https://accounts.zilomail.in/oidc");
    const [request, response, promptAsync] = AuthSession.useAuthRequest(
      {
        clientId: "zo_app_…",
        redirectUri: "com.acme.field:/callback",
        scopes: ["openid", "profile", "hr.read", "hr.attendance", "crm.read", "crm.write", "projects.read", "projects.write"],
        usePKCE: true,
      },
      discovery,
    );
    
    useEffect(() => {
      if (response?.type !== "success") return;
      AuthSession.exchangeCodeAsync(
        { clientId: "zo_app_…", code: response.params.code, redirectUri: "com.acme.field:/callback", extraParams: { code_verifier: request.codeVerifier } },
        discovery,
      ).then((t) => SecureStore.setItemAsync("tokens", JSON.stringify(t)));
    }, [response]);
  3. Check in with location
    JAVASCRIPT
    const { coords } = await Location.getCurrentPositionAsync({});
    const res = await api("/v1/hr/attendance/check-in", { method: "POST", body: { lat: coords.latitude, lng: coords.longitude } });
    // 200 { status: "PRESENT", checkIn: "…" }   ·   409 "Already checked in today."
  4. Today's work
    JAVASCRIPT
    const tasks = await api("/v1/projects/tasks?mine=true&status=TODO");
    const leads = await api("/v1/crm/leads?stage=CONTACTED&limit=20");   // only their territory's
    
    await api(`/v1/crm/leads/${lead.id}/activities`, {
      method: "POST",
      body: { type: "VISIT", subject: "Showed the new range", done: true },
    });