Ir para o conteúdo

Mobile - Contratos API

Endpoints Utilizados pelo Mobile

O mobile consome a mesma API REST do backend documentada em API - Documentação Completa. Este documento destaca os endpoints mais relevantes para o mobile.

Autenticação

Login

POST /api/auth/login

Uso no mobile:

const response = await api.post('/auth/login', {
  email,
  password
})

const { token, refresh_token } = response.data
await SecureStore.setItemAsync('token', token)
await SecureStore.setItemAsync('refresh_token', refresh_token)

Refresh Token

POST /api/auth/refresh

Uso no mobile:

const response = await api.post('/auth/refresh', {
  refresh_token: await SecureStore.getItemAsync('refresh_token')
})

const { token } = response.data
await SecureStore.setItemAsync('token', token)

Registro Diário

Criar Observação

POST /api/observations

Payload:

{
  "date": "2024-01-15",
  "symbol_id": 1,
  "sensation_id": 2,
  "appearance_id": 3,
  "had_intercourse": false,
  "is_first_day_of_menstruation": false
}

Uso no mobile:

await api.post('/observations', {
  date: formatDate(new Date()),
  symbol_id: selectedSymbolId,
  sensation_id: selectedSensationId,
  appearance_id: selectedAppearanceId,
  had_intercourse: false,
  is_first_day_of_menstruation: isFirstDay
})

Listar Observações

GET /api/observations?cycle_id=1&start_date=2024-01-01&end_date=2024-01-31

Status de Fertilidade

Obter Status

GET /api/client/fertility-status?date=2024-01-15

Resposta:

{
  "is_fertile": false,
  "intercourse_status": "allowed_no_risk",
  "days_after_peak": null,
  "has_bleeding": false,
  "peak_date": null
}

Uso no mobile:

const { data: fertilityStatus } = useQuery({
  queryKey: ['fertility-status', date],
  queryFn: () => api.get('/client/fertility-status', {
    params: { date: formatDate(date) }
  }).then(res => res.data)
})

Ciclos

Listar Ciclos

GET /api/cycles

Obter Ciclo Ativo

GET /api/cycles/active

Criar Ciclo

POST /api/cycles

Payload:

{
  "start_date": "2024-01-01"
}

Sincronização

Push (Enviar Dados)

POST /api/sync/push

Payload:

{
  "cycles": [
    {
      "sync_id": "uuid-local",
      "start_date": "2024-01-01",
      "is_active": true
    }
  ],
  "observations": [
    {
      "sync_id": "uuid-local",
      "date": "2024-01-15",
      "symbol_id": 1
    }
  ]
}

Uso no mobile:

// Coletar dados locais (offline)
const localCycles = await getLocalCycles()
const localObservations = await getLocalObservations()

// Enviar para servidor
await api.post('/sync/push', {
  cycles: localCycles,
  observations: localObservations
})

Pull (Buscar Atualizações)

GET /api/sync/pull?last_sync=2024-01-15T10:00:00Z

Resposta:

{
  "cycles": [...],
  "observations": [...],
  "last_sync": "2024-01-15T10:00:00Z"
}

Uso no mobile:

const lastSync = await getLastSyncTimestamp()

const { data } = await api.get('/sync/pull', {
  params: { last_sync: lastSync }
})

// Salvar dados localmente
await saveLocalCycles(data.cycles)
await saveLocalObservations(data.observations)
await saveLastSyncTimestamp(data.last_sync)

Símbolos Permitidos

Obter Símbolos Permitidos

GET /api/symbols/allowed

Resposta:

{
  "allowed_symbols": [1, 2, 3],
  "restricted_symbols": [4, 5],
  "cycle_day": 16
}

Uso no mobile:

const { data: allowedSymbols } = useQuery({
  queryKey: ['allowed-symbols'],
  queryFn: () => api.get('/symbols/allowed').then(res => res.data)
})

// Filtrar símbolos disponíveis para seleção
const availableSymbols = symbols.filter(s => 
  allowedSymbols?.allowed_symbols.includes(s.id)
)

Dados do Método Billings

Sensações

GET /api/billings/sensations

Aparências

GET /api/billings/appearances

Símbolos

GET /api/billings/symbols

Fluxos Críticos

1. Registro Diário Completo

// 1. Verificar ciclo ativo
const { data: activeCycle } = await api.get('/cycles/active')

if (!activeCycle) {
  // Criar novo ciclo
  await api.post('/cycles', { start_date: formatDate(new Date()) })
}

// 2. Obter símbolos permitidos
const { data: allowedSymbols } = await api.get('/symbols/allowed')

// 3. Criar observação
await api.post('/observations', {
  date: formatDate(new Date()),
  symbol_id: selectedSymbolId,
  sensation_id: selectedSensationId,
  appearance_id: selectedAppearanceId
})

// 4. Atualizar status de fertilidade
queryClient.invalidateQueries(['fertility-status'])

2. Sincronização Offline

// Quando voltar online
const syncData = async () => {
  try {
    // Push: enviar dados locais
    const localData = await getLocalPendingData()
    if (localData.cycles.length > 0 || localData.observations.length > 0) {
      await api.post('/sync/push', localData)
      await clearLocalPendingData()
    }

    // Pull: buscar atualizações
    const lastSync = await getLastSyncTimestamp()
    const { data } = await api.get('/sync/pull', {
      params: { last_sync: lastSync }
    })

    // Atualizar dados locais
    await mergeLocalData(data)
    await saveLastSyncTimestamp(data.last_sync)
  } catch (error) {
    console.error('Erro na sincronização:', error)
  }
}

3. Dashboard

// Buscar dados do dashboard
const { data: statistics } = useQuery({
  queryKey: ['client-statistics'],
  queryFn: () => api.get('/client/statistics').then(res => res.data)
})

// statistics contém:
// - active_cycle
// - fertility_status
// - total_cycles
// - average_cycle_length

Payloads Esperados

Criar Observação

Request:

{
  "date": "2024-01-15",
  "symbol_id": 1,
  "sensation_id": 2,
  "appearance_id": 3,
  "had_intercourse": false,
  "is_first_day_of_menstruation": false
}

Response (201):

{
  "id": 123,
  "user_id": 1,
  "cycle_id": 1,
  "date": "2024-01-15",
  "symbol_id": 1,
  "sensation_id": 2,
  "appearance_id": 3,
  "fertility_status": {
    "is_fertile": false,
    "intercourse_status": "allowed_no_risk"
  }
}

Sincronização Push

Request:

{
  "cycles": [
    {
      "sync_id": "local-uuid-1",
      "start_date": "2024-01-01",
      "is_active": true
    }
  ],
  "observations": [
    {
      "sync_id": "local-uuid-2",
      "date": "2024-01-15",
      "symbol_id": 1
    }
  ]
}

Response (200):

{
  "synced_count": 2,
  "conflicts": []
}

Dependência Direta da API

O mobile depende completamente da API documentada em API - Documentação Completa. Qualquer mudança na API deve ser refletida no mobile.

Referências