← back to Costa Rica App

src/api.ts

55 lines

// API client for the costa-rica backend. Token persisted in SecureStore.
import Constants from 'expo-constants';
import * as SecureStore from 'expo-secure-store';

const BASE = (Constants.expoConfig?.extra as any)?.apiBase || 'https://costarica.agentabrams.com';
let _token: string | null = null;

export async function loadToken() {
  _token = await SecureStore.getItemAsync('cr_token');
  return _token;
}
export async function setToken(t: string | null) {
  _token = t;
  if (t) await SecureStore.setItemAsync('cr_token', t);
  else await SecureStore.deleteItemAsync('cr_token');
}
export function isAuthed() { return !!_token; }

async function req(path: string, opts: RequestInit = {}) {
  const headers: any = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
  if (_token) headers.Authorization = `Bearer ${_token}`;
  const res = await fetch(`${BASE}/api/app${path}`, { ...opts, headers });
  const j = await res.json().catch(() => ({}));
  if (!res.ok || j.ok === false) throw new Error(j.error || `HTTP ${res.status}`);
  return j;
}

export const api = {
  register: (b: any) => req('/auth/register', { method: 'POST', body: JSON.stringify(b) }),
  login: (email: string, password: string) => req('/auth/login', { method: 'POST', body: JSON.stringify({ email, password }) }),
  apple: (identity_token: string, full_name?: string) => req('/auth/apple', { method: 'POST', body: JSON.stringify({ identity_token, full_name }) }),
  me: () => req('/me'),
  listings: (q: Record<string, string> = {}) => req('/listings?' + new URLSearchParams(q).toString()),
  listing: (slug: string) => req(`/listings/${slug}`),
  contact: (slug: string) => req(`/listings/${slug}/contact`),
  message: (slug: string, body: string) => req(`/listings/${slug}/message`, { method: 'POST', body: JSON.stringify({ body }) }),
  threads: () => req('/threads'),
  thread: (id: number) => req(`/threads/${id}`),
  availability: (slug: string, from?: string, to?: string) =>
    req(`/listings/${slug}/availability?` + new URLSearchParams({ ...(from && { from }), ...(to && { to }) } as any)),
  createBooking: (b: any) => req('/bookings', { method: 'POST', body: JSON.stringify(b) }),
  myBookings: () => req('/bookings'),
  booking: (code: string) => req(`/bookings/${code}`),
  pay: (code: string, method: string) => req(`/bookings/${code}/pay`, { method: 'POST', body: JSON.stringify({ method }) }),
  payment: (id: string) => req(`/payments/${id}`),
  // host
  hostApply: (b: any) => req('/host/apply', { method: 'POST', body: JSON.stringify(b) }),
  hostListing: (b: any) => req('/host/listings', { method: 'POST', body: JSON.stringify(b) }),
  addPayoutMethod: (b: any) => req('/host/payout-methods', { method: 'POST', body: JSON.stringify(b) }),
  plaidLinkToken: () => req('/host/plaid/link-token', { method: 'POST', body: '{}' }),
  plaidExchange: (public_token: string) => req('/host/plaid/exchange', { method: 'POST', body: JSON.stringify({ public_token }) }),
};

export const money = (minor: number, cur: string) => `${cur} ${(minor / 100).toFixed(2)}`;