Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion expo-app/@types/CreatingItinerary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import { VisaModelTypes } from "./VisaModelTypes";
* @property specialWish - Special wishes or requests for the trip.
* @property visitPreferences - Optional list of visit preferences.
* @property itinerary - Optional object representing the detailed itinerary.
* @property status - Status of the itinerary ("Planejado", "Rascunho", or "Passado").
* @property coverImage - Optional cover image URI for the itinerary.
* @property isNew - Optional flag to indicate if this is a newly created itinerary.
*/
export type CreatingItinerary = {
title: string,
Expand All @@ -48,5 +51,8 @@ export type CreatingItinerary = {
visitPreferences?: Array<string>,
itinerary?: Object,
pixabayTags?: string,
images?: Object
images?: Object,
status?: "Planejado" | "Rascunho" | "Passado",
coverImage?: string,
isNew?: boolean
}
36 changes: 36 additions & 0 deletions expo-app/@types/ExpenseControlTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export type ExpenseCategory =
| "Transporte"
| "Hospedagem"
| "Alimentação"
| "Atividades"
| "Compras"
| "Emergência"
| "Outros";

export type Expense = {
id: string;
title: string;
amount: number;
category: ExpenseCategory;
description?: string;
date: string;
itineraryTitle: string;
activityTitle?: string;
location?: string;
createdAt: string;
};

export type ExpensesByCategory = {
[key in ExpenseCategory]: number;
};

export type ExpenseControlContextType = {
expenses: Expense[];
addExpense: (expense: Expense) => Promise<void>;
removeExpense: (expenseId: string) => Promise<void>;
updateExpense: (expenseId: string, updatedExpense: Partial<Expense>) => Promise<void>;
getTotalExpenses: () => number;
getExpensesByCategory: () => ExpensesByCategory;
getExpensesByItinerary: (itineraryTitle: string) => Expense[];
clearAllExpenses: () => Promise<void>;
}
20 changes: 20 additions & 0 deletions expo-app/@types/FavoritePlacesTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type FavoritePlace = {
id: string;
title: string;
description: string;
coordinates: string;
category: string;
location: string;
date: string;
itineraryTitle: string;
favoritedAt: string;
images?: string[];
}

export type FavoritePlacesContextType = {
favoritePlaces: FavoritePlace[];
addFavoritePlace: (place: FavoritePlace) => Promise<void>;
removeFavoritePlace: (placeId: string) => Promise<void>;
isFavorite: (placeId: string) => boolean;
clearAllFavorites: () => Promise<void>;
}
93 changes: 80 additions & 13 deletions expo-app/docs/utils/gpt-requests.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,95 @@
# GPT Requests

Helpers para acessar endpoints do backend que intermediam chamadas à OpenAI.
Helpers para acessar os endpoints do backend que intermediam chamadas à OpenAI.

- Arquivo: `src/utils/gptRequests.ts`
- Endpoints: `http://SEU-IP-AQUI:3000/api/generateItinerary` e `http://SEU-IP-AQUI:3000/api/justchat`
Este arquivo documenta a API cliente localizada em `src/utils/gptRequests.ts` e traz exemplos, recomendações de uso e tratamento de erros.

## API
## API (assinaturas)

- `generateItinerary(prompt: string): Promise<string>`
- Envia `{ prompt }` e retorna `data.message` com o itinerário gerado.
- Envia `{ prompt }` para o endpoint e retorna `data.message` com o itinerário (texto).
- `generateChatAnswers(prompt: string): Promise<string>`
- Envia `{ prompt }` e retorna `data.message` com a resposta do chat.
- Envia `{ prompt }` e retorna `data.message` com a resposta do chat (texto).

## Exemplo
> Observação: a forma exata do `data` retornado depende do backend; adapte os parsers caso o formato seja diferente (ex.: `data.result` ou `data.choices[0].text`).

## Exemplo de implementação (TypeScript)

Arquivo sugerido: `src/utils/gptRequests.ts`

```ts
import { API_URL } from "@config"; // ou './config'

type ApiResponse = {
ok: boolean;
message?: string;
error?: string;
};

async function postJson(path: string, body: object, signal?: AbortSignal) {
const res = await fetch(`${API_URL}${path}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
signal,
});

const data: ApiResponse = await res.json().catch(() => ({ ok: false, error: "invalid_json" }));

if (!res.ok) {
const errMsg = data?.error || `HTTP ${res.status}`;
const error: any = new Error(errMsg);
error.status = res.status;
throw error;
}

return data;
}

export async function generateItinerary(prompt: string, signal?: AbortSignal): Promise<string> {
const data = await postJson("/api/generateItinerary", { prompt }, signal);
if (!data.message) throw new Error("Resposta inválida do servidor");
return data.message;
}

export async function generateChatAnswers(prompt: string, signal?: AbortSignal): Promise<string> {
const data = await postJson("/api/justchat", { prompt }, signal);
if (!data.message) throw new Error("Resposta inválida do servidor");
return data.message;
}
```

## Exemplo de uso

```ts
import { generateItinerary, generateChatAnswers } from "@utils/gptRequests";

const itinerary = await generateItinerary("3 dias em Salvador focando em cultura e gastronomia");
const answer = await generateChatAnswers("Quais os melhores meses para visitar Floripa?");
async function run() {
try {
const itinerary = await generateItinerary("3 dias em Salvador focando em cultura e gastronomia");
console.log(itinerary);

const answer = await generateChatAnswers("Quais os melhores meses para visitar Floripa?");
console.log(answer);
} catch (err) {
console.error("Erro na chamada GPT:", err);
}
}
```

## Dicas e erros comuns
## Boas práticas e dicas

- centralize a URL da API em `src/config.ts` (exportar `API_URL`) e use-a em `gptRequests.ts`.
- trate `response.ok` e `data` com validação — não confie apenas no `res.json()`.
- HTTP 429: indique ao usuário que a cota foi atingida e ofereça retry exponencial ou uma mensagem amigável.
- timeouts: use `AbortController` para cancelar requisições longas (ex.: timeout em 15s).
- retries: em erros transientes (timeout, 502, 503), implemente retry com backoff.
- logs: registre `status` e `body` em ambiente de desenvolvimento para debug.
- CORS: se o backend estiver em domínio diferente, verifique as configurações CORS do servidor.

## Erros comuns e how-to debug

- Substitua `SEU-IP-AQUI` pelo host da sua API (veja também `src/config.ts` onde há `API_URL` para outros módulos).
- HTTP 429: indica cota da OpenAI atingida; exponha mensagem ao usuário.
- Trate `response.ok` falso como erro de fluxo.
- URL inválida/hardcode: troque por `API_URL` — verifique `src/config.ts`.
- 429 (rate limit): exiba mensagem e desabilite ação temporariamente; registre para investigar.
- 500 / 502 / 503: retry com backoff e alertar manutenção.
- resposta sem `message`: confirme o contrato da API e ajuste o parser.
89 changes: 89 additions & 0 deletions expo-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions expo-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.4",
"react-native-calendars": "^1.1313.0",
"react-native-country-flag": "^2.0.2",
"react-native-dotenv": "^3.4.11",
"react-native-drawer-layout": "^4.2.0",
Expand Down
Loading