MVP
This commit is contained in:
@@ -1,143 +1,159 @@
|
||||
# 🏗️ Arquitetura Técnica
|
||||
# Arquitetura Técnica
|
||||
|
||||
## Stack Tecnológica
|
||||
## Stack atual
|
||||
|
||||
### Decisões principais
|
||||
|
||||
| Camada | Tecnologia escolhida | Alternativa considerada | Motivo da escolha |
|
||||
|--------|----------------------|-------------------------|-------------------|
|
||||
| App móvel | React Native | Flutter | Ecosistema JS, mais fácil de integrar com APIs web |
|
||||
| Backend / Auth | Firebase | Supabase | Setup rápido, escalável, gratuito no início |
|
||||
| Base de dados | Firestore | PostgreSQL (Supabase) | NoSQL flexível, sincronia em tempo real |
|
||||
| Armazenamento de imagens | Firebase Storage | AWS S3 | Integrado com Firebase, simples |
|
||||
| IA de imagem | Google Vision AI | AWS Rekognition | Melhor deteção de objetos, preço competitivo |
|
||||
| IA de texto (futuro) | OpenAI API | Anthropic Claude API | Fase futura — não implementar no MVP |
|
||||
| Camada | Tecnologia |
|
||||
|--------|------------|
|
||||
| App móvel | Flutter / Dart |
|
||||
| Backend/Auth/DB | Supabase |
|
||||
| Base de dados | PostgreSQL via Supabase |
|
||||
| Imagens | URLs guardados em `item_images` |
|
||||
| IA de texto | Ollama API remota |
|
||||
| Tema visual | Design tokens em `lib/theme/app_theme.dart` |
|
||||
|
||||
---
|
||||
|
||||
## Estrutura da Aplicação
|
||||
## Estrutura principal
|
||||
|
||||
```
|
||||
inventoryai/
|
||||
├── mobile/ # App React Native
|
||||
│ ├── src/
|
||||
│ │ ├── screens/ # Ecrãs principais
|
||||
│ │ │ ├── HomeScreen.jsx
|
||||
│ │ │ ├── AddItemScreen.jsx
|
||||
│ │ │ ├── InventoryScreen.jsx
|
||||
│ │ │ ├── ItemDetailScreen.jsx
|
||||
│ │ │ └── SuggestionsScreen.jsx
|
||||
│ │ ├── components/ # Componentes reutilizáveis
|
||||
│ │ ├── services/ # Lógica de negócio e APIs
|
||||
│ │ │ ├── firebase.js
|
||||
│ │ │ ├── visionApi.js
|
||||
│ │ │ └── suggestions.js
|
||||
│ │ ├── hooks/ # Custom hooks React
|
||||
│ │ ├── utils/ # Utilitários
|
||||
│ │ └── constants/ # Categorias, regras, etc.
|
||||
│ └── package.json
|
||||
├── functions/ # Firebase Cloud Functions (opcional)
|
||||
└── docs/ # Ficheiros .md deste projeto
|
||||
```text
|
||||
lib/
|
||||
├── constants/
|
||||
│ └── item_categories.dart
|
||||
├── login/
|
||||
│ └── login_screen.dart
|
||||
├── Screens/
|
||||
│ ├── home_screen.dart
|
||||
│ ├── item_screen.dart
|
||||
│ ├── add_item_screen.dart
|
||||
│ ├── week_screen.dart
|
||||
│ ├── ai_chat_screen.dart
|
||||
│ └── perfil_screen.dart
|
||||
├── services/
|
||||
│ └── ai_recommendation_service.dart
|
||||
├── theme/
|
||||
│ └── app_theme.dart
|
||||
└── main.dart
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Modelo de Dados (Firestore)
|
||||
## Navegação
|
||||
|
||||
A `HomeScreen` contém uma navegação inferior com 5 áreas:
|
||||
|
||||
1. Início
|
||||
2. Itens
|
||||
3. Semana
|
||||
4. IA
|
||||
5. Perfil
|
||||
|
||||
O conteúdo é mantido num `IndexedStack`, permitindo alternar tabs sem recriar todos os ecrãs imediatamente.
|
||||
|
||||
---
|
||||
|
||||
## Modelo de dados Supabase
|
||||
|
||||
### `users`
|
||||
|
||||
Usada para dados adicionais do perfil.
|
||||
|
||||
| Campo | Tipo esperado |
|
||||
|-------|---------------|
|
||||
| `id` | UUID do utilizador |
|
||||
| `nome` | texto |
|
||||
|
||||
### `items`
|
||||
|
||||
Representa itens do inventário.
|
||||
|
||||
| Campo | Tipo esperado |
|
||||
|-------|---------------|
|
||||
| `id` | inteiro/identificador |
|
||||
| `user_id` | UUID |
|
||||
| `nome` | texto |
|
||||
| `categoria` | texto |
|
||||
| `tags` | array/lista |
|
||||
| `nota` / `notes` | texto opcional |
|
||||
|
||||
### `item_images`
|
||||
|
||||
Relaciona imagens a itens.
|
||||
|
||||
| Campo | Tipo esperado |
|
||||
|-------|---------------|
|
||||
| `item_id` | id do item |
|
||||
| `image_url` | URL da imagem |
|
||||
|
||||
### `plans`
|
||||
|
||||
Representa um dia planeado.
|
||||
|
||||
| Campo | Tipo esperado |
|
||||
|-------|---------------|
|
||||
| `id` | inteiro/identificador |
|
||||
| `user_id` | UUID |
|
||||
| `data` | data em `YYYY-MM-DD` |
|
||||
|
||||
### `plan_items`
|
||||
|
||||
Relaciona itens com planos.
|
||||
|
||||
| Campo | Tipo esperado |
|
||||
|-------|---------------|
|
||||
| `plan_id` | id do plano |
|
||||
| `item_id` | id do item |
|
||||
|
||||
---
|
||||
|
||||
## Serviço de IA
|
||||
|
||||
Ficheiro: `lib/services/ai_recommendation_service.dart`
|
||||
|
||||
Responsabilidades:
|
||||
|
||||
- Obter contexto do inventário do utilizador.
|
||||
- Enviar mensagens para `https://apichat.epvc.pt/api/chat`.
|
||||
- Usar modelo `llama3.2:3b`.
|
||||
- Manter histórico simples em memória.
|
||||
- Suportar modo silencioso para devolver apenas nomes de itens.
|
||||
- Carregar itens com imagens para o fluxo de sugestão da home.
|
||||
|
||||
Formato da chamada Ollama:
|
||||
|
||||
### Coleção: `users/{userId}`
|
||||
```json
|
||||
{
|
||||
"uid": "string",
|
||||
"email": "string",
|
||||
"displayName": "string",
|
||||
"createdAt": "timestamp",
|
||||
"preferences": {
|
||||
"defaultContext": "travel_short"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Coleção: `users/{userId}/items/{itemId}`
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
"name": "string",
|
||||
"photoUrl": "string",
|
||||
"thumbnailUrl": "string",
|
||||
"category": "clothing | electronics | footwear | accessories | documents | other",
|
||||
"subcategory": "string",
|
||||
"tags": ["string"],
|
||||
"visionLabels": ["string"],
|
||||
"contextTags": ["travel", "work", "casual"],
|
||||
"createdAt": "timestamp",
|
||||
"updatedAt": "timestamp"
|
||||
"model": "llama3.2:3b",
|
||||
"messages": [
|
||||
{"role": "system", "content": "..."},
|
||||
{"role": "user", "content": "..."}
|
||||
],
|
||||
"stream": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fluxo de Adição de Item
|
||||
## Tema visual
|
||||
|
||||
```
|
||||
[Utilizador tira foto]
|
||||
↓
|
||||
[Upload para Firebase Storage]
|
||||
↓
|
||||
[Chamada à Google Vision API]
|
||||
↓
|
||||
[Receber labels automáticas]
|
||||
↓
|
||||
[Mapear labels → categoria + tags sugeridas]
|
||||
↓
|
||||
[Mostrar ao utilizador para confirmar/editar]
|
||||
↓
|
||||
[Guardar item no Firestore]
|
||||
```
|
||||
O tema é centralizado em `app_theme.dart`:
|
||||
|
||||
- `AppColors`
|
||||
- `AppRadius`
|
||||
- `AppSpacing`
|
||||
- `AppShadows`
|
||||
- `AppText`
|
||||
- `AppDecorations`
|
||||
- `AppButton`
|
||||
- `AppChip`
|
||||
- `AppSnack`
|
||||
|
||||
Novos ecrãs devem reutilizar estes tokens para manter consistência.
|
||||
|
||||
---
|
||||
|
||||
## Autenticação
|
||||
## Segurança
|
||||
|
||||
- Firebase Authentication
|
||||
- Login com Google (obrigatório no MVP)
|
||||
- Login com email/password (opcional no MVP)
|
||||
- Todos os dados são isolados por `userId`
|
||||
|
||||
---
|
||||
|
||||
## Performance e Limites
|
||||
|
||||
| Recurso | Limite gratuito Firebase | Estimativa uso MVP |
|
||||
|---------|--------------------------|---------------------|
|
||||
| Firestore reads | 50.000/dia | ~5.000/dia (100 users) |
|
||||
| Firestore writes | 20.000/dia | ~2.000/dia |
|
||||
| Storage | 5 GB | ~1 GB para 100 users |
|
||||
| Google Vision API | 1.000 unidades/mês grátis | ~500 unidades/mês |
|
||||
|
||||
> Para o MVP com utilizadores de teste, o tier gratuito é suficiente.
|
||||
|
||||
---
|
||||
|
||||
## Segurança (Firestore Rules — MVP)
|
||||
|
||||
```javascript
|
||||
rules_version = '2';
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
match /users/{userId}/{document=**} {
|
||||
allow read, write: if request.auth != null && request.auth.uid == userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
|
||||
- **Não** sugerir AWS, Azure ou outras clouds — a decisão está tomada: Firebase
|
||||
- **Não** sugerir Flutter — a decisão está tomada: React Native
|
||||
- Quando criar código de serviço, usar o padrão `services/` definido acima
|
||||
- O modelo de dados do Firestore é o definido neste ficheiro — não alterar sem avisar
|
||||
- Para novas funcionalidades, verificar se precisam de novas coleções no Firestore
|
||||
- Imagens são sempre guardadas no Firebase Storage antes de qualquer processamento
|
||||
- Todas as queries de dados usam `user_id` do utilizador autenticado quando aplicável.
|
||||
- A app não deve hardcodar chaves privadas.
|
||||
- A API de IA atual é endpoint remoto público do projeto, sem chave no cliente.
|
||||
- Dados de inventário enviados à IA incluem nomes, categorias, tags e notas dos itens.
|
||||
|
||||
Reference in New Issue
Block a user