MVP
This commit is contained in:
@@ -1,64 +1,79 @@
|
||||
# 📦 InventoryAI — Project Overview
|
||||
# DayMaker — Project Overview
|
||||
|
||||
## Visão Geral
|
||||
## Visão geral
|
||||
|
||||
**InventoryAI** é uma aplicação móvel de gestão de inventário pessoal inteligente.
|
||||
O utilizador fotografa os seus pertences, a app organiza-os automaticamente por categoria, e sugere o que levar consoante o contexto (viagem, clima, ocasião).
|
||||
**DayMaker** é uma aplicação móvel Flutter para organizar itens pessoais, planear o que usar/levar durante a semana e pedir sugestões a uma IA com base no inventário real do utilizador.
|
||||
|
||||
A app permite guardar roupas, eletrónica, calçado, acessórios, documentos e outros itens com categoria, tags e imagem. Depois, esses itens podem ser usados no planeamento semanal ou em sugestões geradas pela IA.
|
||||
|
||||
---
|
||||
|
||||
## Problema que resolve
|
||||
|
||||
As pessoas não sabem o que têm em casa. Perdem tempo a procurar itens, esquecem-se do que possuem, e não conseguem planear eficientemente o que levar para viagens ou eventos.
|
||||
Muitas pessoas esquecem o que têm, perdem tempo a escolher outfits ou não sabem o que levar para viagens, trabalho, praia, piqueniques e outros planos do dia.
|
||||
|
||||
O DayMaker centraliza o inventário pessoal e ajuda o utilizador a decidir rapidamente o que precisa.
|
||||
|
||||
---
|
||||
|
||||
## Proposta de Valor
|
||||
## Proposta de valor
|
||||
|
||||
> "Fotografa uma vez. A app lembra-se para sempre. Diz-te o que levar quando precisas."
|
||||
> "Guarda os teus itens uma vez. Planeia a semana e pede à IA sugestões com o que já tens."
|
||||
|
||||
---
|
||||
|
||||
## Funcionalidades atuais
|
||||
|
||||
- Autenticação com Supabase.
|
||||
- Home com saudação, resumo do dia, contagem de itens e itens recentes.
|
||||
- Inventário com pesquisa, filtros por categoria, vista em grid/lista e detalhe do item.
|
||||
- Adição e edição de itens com categorias e tags.
|
||||
- Imagens associadas aos itens via `item_images`.
|
||||
- Planeamento semanal com tabela `plans` e relação `plan_items`.
|
||||
- Chat com IA usando endpoint Ollama em `https://apichat.epvc.pt/api/chat`.
|
||||
- Botão "Pedir sugestão à IA" na home, com input de ocasião e sugestões rápidas.
|
||||
- Sugestões da IA limitadas aos itens existentes no inventário.
|
||||
- Exibição dos itens sugeridos com imagem, nome e categoria.
|
||||
- Exportação das sugestões para um dia da semana.
|
||||
|
||||
---
|
||||
|
||||
## Utilizador-alvo
|
||||
|
||||
- Pessoas que viajam frequentemente
|
||||
- Quem tem muita roupa e não consegue gerir outfits
|
||||
- Utilizadores organizados que querem controlo total dos seus bens pessoais
|
||||
- Nómadas digitais e viajantes de longa duração
|
||||
|
||||
---
|
||||
|
||||
## Princípios de Design
|
||||
|
||||
1. **Simplicidade primeiro** — o MVP não tem IA avançada. Regras simples parecem inteligentes.
|
||||
2. **Foto como input principal** — tirar foto é mais rápido do que escrever.
|
||||
3. **Categorização automática** — o utilizador não quer trabalho manual.
|
||||
4. **Sugestões contextuais** — a app responde a perguntas reais do utilizador.
|
||||
5. **Evolução progressiva** — começar simples, adicionar IA com dados reais.
|
||||
- Pessoas que querem organizar roupa, acessórios e objetos do dia a dia.
|
||||
- Utilizadores que planeiam outfits semanais.
|
||||
- Pessoas que viajam ou preparam atividades com frequência.
|
||||
- Estudantes e profissionais que querem saber rapidamente o que levar.
|
||||
|
||||
---
|
||||
|
||||
## Estado atual do projeto
|
||||
|
||||
| Fase | Estado |
|
||||
| Área | Estado |
|
||||
|------|--------|
|
||||
| Definição do MVP | ✅ Concluído |
|
||||
| Arquitetura técnica | ✅ Definida |
|
||||
| Implementação | 🔲 Por iniciar |
|
||||
| Testes com utilizadores | 🔲 Por iniciar |
|
||||
| IA avançada | 🔲 Fase futura |
|
||||
| App Flutter | Implementada |
|
||||
| Autenticação Supabase | Implementada |
|
||||
| Inventário | Implementado |
|
||||
| Imagens dos itens | Implementado |
|
||||
| Planeamento semanal | Implementado |
|
||||
| Chat IA | Implementado |
|
||||
| Sugestão IA com itens reais | Implementada |
|
||||
| Exportar sugestão para dia | Implementado |
|
||||
| Testes automatizados | Pendente |
|
||||
|
||||
---
|
||||
|
||||
## Ficheiros de contexto deste projeto
|
||||
## Documentos do projeto
|
||||
|
||||
| Ficheiro | Conteúdo |
|
||||
|----------|----------|
|
||||
| `00_PROJECT_OVERVIEW.md` | Este ficheiro — visão geral |
|
||||
| `01_MVP_DEFINITION.md` | Funcionalidades mínimas viáveis |
|
||||
| `02_ARCHITECTURE.md` | Stack técnica e estrutura da app |
|
||||
| `03_AI_VISION_LAYER.md` | Integração de IA para imagens |
|
||||
| `04_CATEGORIES_AND_TAGS.md` | Sistema de organização de itens |
|
||||
| `05_RECOMMENDATION_ENGINE.md` | Lógica de sugestões (regras + IA futura) |
|
||||
| `06_FUTURE_FEATURES.md` | Roadmap e funcionalidades avançadas |
|
||||
| `07_AGENT_BEHAVIOR.md` | Como o agente IA deve comportar-se |
|
||||
| `00_PROJECT_OVERVIEW.md` | Visão geral do projeto |
|
||||
| `01_MVP_DEFINITION.md` | Definição do produto atual |
|
||||
| `02_ARCHITECTURE.md` | Arquitetura técnica e dados |
|
||||
| `03_AI_VISION_LAYER.md` | Estado da camada de imagem/visão |
|
||||
| `04_CATEGORIES_AND_TAGS.md` | Categorias e tags usadas |
|
||||
| `05_RECOMMENDATION_ENGINE.md` | Funcionamento das sugestões da IA |
|
||||
| `06_FUTURE_FEATURES.md` | Roadmap futuro |
|
||||
| `07_AGENT_BEHAVIOR.md` | Regras para agentes de código |
|
||||
| `AI_AGENTS_LOG.md` | Histórico técnico das decisões de IA |
|
||||
| `RULE_ENGINE.md` | Regras atuais do sistema de sugestão |
|
||||
|
||||
@@ -1,101 +1,101 @@
|
||||
# 🎯 MVP — Definição do Produto Mínimo Viável
|
||||
# MVP — Produto Atual
|
||||
|
||||
## Objetivo do MVP
|
||||
## Objetivo
|
||||
|
||||
Criar a versão mais simples possível da app que já seja útil para um utilizador real.
|
||||
**Sem IA avançada. Sem funcionalidades complexas. Sem over-engineering.**
|
||||
O produto atual do **DayMaker** é uma app móvel funcional para guardar itens pessoais, consultar o inventário, planear dias da semana e pedir sugestões à IA com base nos itens existentes.
|
||||
|
||||
O MVP deve validar a hipótese central:
|
||||
> "Os utilizadores estão dispostos a fotografar os seus itens para depois receber sugestões contextuais."
|
||||
O foco é oferecer uma experiência simples e útil, sem obrigar o utilizador a configurar regras complexas.
|
||||
|
||||
---
|
||||
|
||||
## Funcionalidades obrigatórias (must-have)
|
||||
## Funcionalidades implementadas
|
||||
|
||||
### 1. 📸 Upload / Captura de Foto
|
||||
- O utilizador tira foto a um item com a câmara do telemóvel
|
||||
- Alternativa: selecionar foto da galeria
|
||||
- A foto é guardada no perfil do item
|
||||
- **Requisito mínimo:** uma foto por item
|
||||
### 1. Autenticação
|
||||
|
||||
### 2. 📦 Guardar Item
|
||||
- Cada item tem:
|
||||
- `nome` (texto livre ou sugerido pela IA de imagem)
|
||||
- `foto` (obrigatória)
|
||||
- `categoria` (selecionada pelo utilizador ou auto-detetada)
|
||||
- `tags` (opcional, atribuídas manualmente ou automaticamente)
|
||||
- `data de adição`
|
||||
- O item é guardado na base de dados do utilizador
|
||||
- Login e registo com Supabase Auth.
|
||||
- Dados associados ao utilizador autenticado.
|
||||
- Perfil com nome/email do utilizador.
|
||||
|
||||
### 3. 🏷️ Categorização
|
||||
- O utilizador escolhe a categoria principal do item
|
||||
- Categorias base disponíveis no MVP:
|
||||
- Roupa
|
||||
- Eletrónica
|
||||
- Calçado
|
||||
- Acessórios
|
||||
- Documentos
|
||||
- Outros
|
||||
- Subcategorias simples dentro de cada categoria (ver `04_CATEGORIES_AND_TAGS.md`)
|
||||
### 2. Home
|
||||
|
||||
### 4. 🔍 Pesquisa e Visualização do Inventário
|
||||
- Lista de todos os itens (grid de fotos ou lista)
|
||||
- Filtrar por categoria
|
||||
- Pesquisa por nome ou tag
|
||||
- Detalhe do item ao clicar
|
||||
- Saudação personalizada.
|
||||
- Card com dia atual.
|
||||
- Contagem de itens no inventário.
|
||||
- Lista de itens planeados para hoje.
|
||||
- Lista de itens recentes.
|
||||
- Botão de adicionar item.
|
||||
- Botão "Pedir sugestão à IA".
|
||||
|
||||
### 5. 🎯 Sugestões Simples por Contexto (sem IA)
|
||||
- O utilizador seleciona um contexto pré-definido:
|
||||
- "Vou viajar (curta duração)"
|
||||
- "Vou viajar (longa duração)"
|
||||
- "Vou ao trabalho"
|
||||
- "Fim de semana casual"
|
||||
- A app filtra e mostra os itens relevantes para esse contexto
|
||||
- As regras são estáticas e definidas manualmente (ver `05_RECOMMENDATION_ENGINE.md`)
|
||||
### 3. Inventário
|
||||
|
||||
Cada item contém, conforme disponibilidade da base de dados:
|
||||
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `nome`
|
||||
- `categoria`
|
||||
- `tags`
|
||||
- `nota` ou `notes`
|
||||
- imagens relacionadas em `item_images(image_url)`
|
||||
|
||||
Funcionalidades:
|
||||
|
||||
- Vista em grid.
|
||||
- Vista em lista.
|
||||
- Pesquisa por nome ou tag.
|
||||
- Filtro por categoria.
|
||||
- Detalhe do item.
|
||||
- Edição de nome, categoria e tags.
|
||||
- Remoção de itens.
|
||||
|
||||
### 4. Planeamento semanal
|
||||
|
||||
- Separação por dias da semana.
|
||||
- Tabela `plans` para representar um plano diário.
|
||||
- Tabela `plan_items` para associar itens ao plano.
|
||||
- Adição manual de itens a um dia.
|
||||
- Remoção de itens de um dia.
|
||||
- Home mostra os itens do dia atual.
|
||||
|
||||
### 5. Chat com IA
|
||||
|
||||
- Ecrã `AiChatScreen` acessível pela barra inferior.
|
||||
- Histórico de conversa em memória durante a sessão do serviço.
|
||||
- Sugestões rápidas no topo do chat.
|
||||
- Mensagens com design consistente com o tema da app.
|
||||
- Integração com Ollama via endpoint remoto.
|
||||
|
||||
### 6. Sugestão IA na Home
|
||||
|
||||
Fluxo atual:
|
||||
|
||||
1. Utilizador toca em "Pedir sugestão à IA".
|
||||
2. App pede a ocasião, por exemplo: `piquenique no parque`.
|
||||
3. IA recebe o inventário do utilizador como contexto.
|
||||
4. IA responde apenas com nomes de itens do inventário.
|
||||
5. App cruza a resposta com os itens reais.
|
||||
6. App mostra os itens sugeridos com imagem e categoria.
|
||||
7. Utilizador pode exportar esses itens para um dia da semana.
|
||||
|
||||
---
|
||||
|
||||
## Funcionalidades excluídas do MVP
|
||||
## Funcionalidades fora do escopo atual
|
||||
|
||||
> Estas funcionalidades são importantes mas ficam para iterações futuras.
|
||||
|
||||
- ❌ Sugestões baseadas em clima
|
||||
- ❌ Montagem automática de outfits
|
||||
- ❌ Integração com calendário
|
||||
- ❌ Assistente conversacional ("O que devo levar amanhã?")
|
||||
- ❌ Sistema de preferências pessoais aprendidas
|
||||
- ❌ Multi-utilizador / partilha
|
||||
- ❌ Exportação de listas
|
||||
- ❌ Notificações inteligentes
|
||||
- Reconhecimento automático de imagem por IA.
|
||||
- Previsão meteorológica.
|
||||
- Notificações push.
|
||||
- Sincronização com calendário externo.
|
||||
- Partilha de inventário entre utilizadores.
|
||||
- Recomendação visual por cor/compatibilidade.
|
||||
- Testes automatizados completos.
|
||||
|
||||
---
|
||||
|
||||
## Fluxo principal do utilizador (MVP)
|
||||
## Critérios de sucesso atuais
|
||||
|
||||
```
|
||||
1. Utilizador abre a app
|
||||
2. Tira foto de um item
|
||||
3. App sugere nome e categoria (via Google Vision)
|
||||
4. Utilizador confirma ou edita
|
||||
5. Item guardado no inventário
|
||||
6. Utilizador acede ao inventário → pesquisa / filtra
|
||||
7. Utilizador seleciona contexto → app mostra lista filtrada
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critérios de sucesso do MVP
|
||||
|
||||
- [ ] Utilizador consegue adicionar 10 itens em menos de 5 minutos
|
||||
- [ ] Pesquisa devolve resultados corretos em menos de 1 segundo
|
||||
- [ ] Sugestão por contexto é considerada "útil" por 70%+ dos utilizadores testados
|
||||
- [ ] Taxa de retenção ao fim de 7 dias > 40%
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
|
||||
- Quando o utilizador pedir para construir uma funcionalidade, verificar primeiro se está no MVP ou no roadmap futuro
|
||||
- Se estiver fora do MVP, avisar e perguntar se deve ser priorizada ou adiada
|
||||
- Nunca adicionar complexidade desnecessária ao MVP
|
||||
- Preferir sempre a solução mais simples que funcione
|
||||
- O utilizador consegue criar conta e entrar.
|
||||
- O utilizador consegue adicionar e consultar itens.
|
||||
- A pesquisa e filtros devolvem itens corretos.
|
||||
- O utilizador consegue planear itens para qualquer dia da semana.
|
||||
- A IA responde usando o inventário do utilizador.
|
||||
- A sugestão da IA pode ser exportada para a semana.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,204 +1,80 @@
|
||||
# 👁️ Camada de Visão por IA
|
||||
# Camada de Imagem e Visão
|
||||
|
||||
## Objetivo
|
||||
## Estado atual
|
||||
|
||||
Usar IA de visão computacional para **identificar automaticamente** o que está na foto tirada pelo utilizador, sugerindo:
|
||||
- Nome do item
|
||||
- Categoria
|
||||
- Tags relevantes
|
||||
O DayMaker guarda imagens dos itens, mas **não faz reconhecimento automático de imagem** no produto atual.
|
||||
|
||||
Isto reduz o esforço do utilizador ao mínimo.
|
||||
A imagem de cada item é tratada como dado visual associado ao inventário. A app espera receber ou guardar URLs em `item_images(image_url)` e usa essas imagens para:
|
||||
|
||||
- Mostrar cards no inventário.
|
||||
- Mostrar detalhes do item.
|
||||
- Mostrar itens planeados na semana.
|
||||
- Mostrar sugestões da IA com imagem quando há correspondência com itens reais.
|
||||
|
||||
---
|
||||
|
||||
## Serviço escolhido: Google Vision API
|
||||
## Fluxo atual de imagem
|
||||
|
||||
### Porquê Google Vision?
|
||||
- Fácil integração com Firebase (mesmo ecosistema Google)
|
||||
- Excelente deteção de objetos do quotidiano
|
||||
- Labels em múltiplos idiomas
|
||||
- Tier gratuito generoso (1.000 unidades/mês)
|
||||
- Documentação extensa
|
||||
|
||||
### Funcionalidades usadas no MVP
|
||||
|
||||
| Feature | Uso |
|
||||
|---------|-----|
|
||||
| `LABEL_DETECTION` | Identificar o objeto (ex: "T-shirt", "Laptop") |
|
||||
| `OBJECT_LOCALIZATION` | Confirmar que existe um objeto na foto |
|
||||
|
||||
> No MVP **não** usamos OCR, Safe Search ou outras features avançadas.
|
||||
|
||||
---
|
||||
|
||||
## Integração técnica
|
||||
|
||||
### Chamada à API (exemplo React Native)
|
||||
|
||||
```javascript
|
||||
// services/visionApi.js
|
||||
|
||||
const VISION_API_KEY = process.env.GOOGLE_VISION_API_KEY;
|
||||
const VISION_API_URL = `https://vision.googleapis.com/v1/images:annotate?key=${VISION_API_KEY}`;
|
||||
|
||||
export async function analyzeImage(base64Image) {
|
||||
const requestBody = {
|
||||
requests: [
|
||||
{
|
||||
image: { content: base64Image },
|
||||
features: [
|
||||
{ type: 'LABEL_DETECTION', maxResults: 10 },
|
||||
{ type: 'OBJECT_LOCALIZATION', maxResults: 5 }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const response = await fetch(VISION_API_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return parseVisionResponse(data);
|
||||
}
|
||||
```
|
||||
|
||||
### Parsing da resposta
|
||||
|
||||
```javascript
|
||||
// services/visionApi.js (continuação)
|
||||
|
||||
export function parseVisionResponse(data) {
|
||||
const labels = data.responses[0]?.labelAnnotations || [];
|
||||
const objects = data.responses[0]?.localizedObjectAnnotations || [];
|
||||
|
||||
// Extrair labels com score > 0.7
|
||||
const highConfidenceLabels = labels
|
||||
.filter(l => l.score > 0.7)
|
||||
.map(l => l.description.toLowerCase());
|
||||
|
||||
// Mapear para categoria da app
|
||||
const category = mapLabelsToCategory(highConfidenceLabels);
|
||||
|
||||
// Sugerir nome baseado no objeto mais confiante
|
||||
const suggestedName = objects[0]?.name || labels[0]?.description || 'Item';
|
||||
|
||||
return {
|
||||
suggestedName,
|
||||
category,
|
||||
tags: highConfidenceLabels.slice(0, 5),
|
||||
rawLabels: highConfidenceLabels
|
||||
};
|
||||
}
|
||||
```text
|
||||
Item criado/editado
|
||||
↓
|
||||
Imagem associada ao item
|
||||
↓
|
||||
URL guardado em item_images.image_url
|
||||
↓
|
||||
Ecrãs carregam items com item_images(image_url)
|
||||
↓
|
||||
Image.network mostra a imagem ou fallback por categoria
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mapeamento de Labels → Categorias
|
||||
## Ficheiros relevantes
|
||||
|
||||
```javascript
|
||||
// constants/categoryMapping.js
|
||||
|
||||
export const LABEL_TO_CATEGORY = {
|
||||
// Roupa
|
||||
't-shirt': 'clothing',
|
||||
'shirt': 'clothing',
|
||||
'dress': 'clothing',
|
||||
'jacket': 'clothing',
|
||||
'coat': 'clothing',
|
||||
'jeans': 'clothing',
|
||||
'trousers': 'clothing',
|
||||
'sweater': 'clothing',
|
||||
'clothing': 'clothing',
|
||||
'fashion': 'clothing',
|
||||
|
||||
// Eletrónica
|
||||
'laptop': 'electronics',
|
||||
'computer': 'electronics',
|
||||
'smartphone': 'electronics',
|
||||
'tablet': 'electronics',
|
||||
'headphones': 'electronics',
|
||||
'camera': 'electronics',
|
||||
'charger': 'electronics',
|
||||
'cable': 'electronics',
|
||||
'electronics': 'electronics',
|
||||
|
||||
// Calçado
|
||||
'shoe': 'footwear',
|
||||
'boot': 'footwear',
|
||||
'sneaker': 'footwear',
|
||||
'sandal': 'footwear',
|
||||
'footwear': 'footwear',
|
||||
|
||||
// Acessórios
|
||||
'bag': 'accessories',
|
||||
'backpack': 'accessories',
|
||||
'watch': 'accessories',
|
||||
'sunglasses': 'accessories',
|
||||
'hat': 'accessories',
|
||||
'belt': 'accessories',
|
||||
|
||||
// Documentos
|
||||
'passport': 'documents',
|
||||
'document': 'documents',
|
||||
'book': 'documents',
|
||||
'notebook': 'documents',
|
||||
};
|
||||
|
||||
export function mapLabelsToCategory(labels) {
|
||||
for (const label of labels) {
|
||||
if (LABEL_TO_CATEGORY[label]) {
|
||||
return LABEL_TO_CATEGORY[label];
|
||||
}
|
||||
}
|
||||
return 'other'; // fallback
|
||||
}
|
||||
```
|
||||
| Ficheiro | Responsabilidade |
|
||||
|----------|------------------|
|
||||
| `lib/Screens/add_item_screen.dart` | Criação de itens e associação de dados |
|
||||
| `lib/Screens/item_screen.dart` | Inventário, detalhe, edição e imagem do item |
|
||||
| `lib/Screens/week_screen.dart` | Mostra imagens dos itens planeados |
|
||||
| `lib/Screens/home_screen.dart` | Mostra itens recentes, hoje e sugestões IA |
|
||||
|
||||
---
|
||||
|
||||
## Fluxo de UX ao adicionar item
|
||||
## Fallback visual
|
||||
|
||||
```
|
||||
1. Utilizador tira foto
|
||||
2. App mostra loading ("A analisar item...")
|
||||
3. Google Vision responde com labels
|
||||
4. App mostra:
|
||||
- Nome sugerido (editável)
|
||||
- Categoria sugerida (editável)
|
||||
- Tags sugeridas (checkboxes, editáveis)
|
||||
5. Utilizador confirma ou ajusta
|
||||
6. Item guardado
|
||||
```
|
||||
Quando um item não tem imagem ou a imagem falha ao carregar:
|
||||
|
||||
> O utilizador tem **sempre** controlo final. A IA apenas sugere.
|
||||
- A UI mostra um fundo com a cor da categoria.
|
||||
- A UI mostra o ícone da categoria.
|
||||
|
||||
Isto evita cards vazios e mantém consistência visual.
|
||||
|
||||
---
|
||||
|
||||
## Tratamento de erros
|
||||
## Reconhecimento automático por IA
|
||||
|
||||
| Erro | Comportamento |
|
||||
|------|---------------|
|
||||
| API indisponível | Mostrar formulário manual, sem sugestões |
|
||||
| Foto sem objeto reconhecível | Mostrar sugestão "Outro" e pedir nome manual |
|
||||
| Score muito baixo (< 0.5) | Ignorar label, não sugerir |
|
||||
| Timeout | Retry 1x, depois formulário manual |
|
||||
Reconhecimento automático por imagem **não está implementado**.
|
||||
|
||||
Pode ser uma funcionalidade futura para sugerir:
|
||||
|
||||
- Nome do item.
|
||||
- Categoria.
|
||||
- Tags.
|
||||
- Cor dominante.
|
||||
- Tipo de peça ou objeto.
|
||||
|
||||
Possíveis serviços futuros:
|
||||
|
||||
- Google Vision API.
|
||||
- Modelos multimodais via API externa.
|
||||
- Modelo local/servidor próprio.
|
||||
|
||||
---
|
||||
|
||||
## Evolução futura desta camada
|
||||
## Regras para futuras implementações
|
||||
|
||||
- Fase 2: Treinar modelo custom com os dados dos utilizadores
|
||||
- Fase 3: Identificar marcas e modelos específicos
|
||||
- Fase 3: Reconhecimento de cor dominante para filtros de outfit
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
|
||||
- A chave da API (`GOOGLE_VISION_API_KEY`) nunca deve aparecer em código client-side em produção — usar Firebase Cloud Functions como proxy
|
||||
- No MVP, a chamada pode ser feita diretamente do cliente para simplicidade
|
||||
- Nunca guardar `rawLabels` como `name` sem confirmação do utilizador
|
||||
- O mapeamento de labels é iterativo — quando encontrar labels não mapeadas, adicionar ao ficheiro `categoryMapping.js`
|
||||
- Não guardar API keys privadas no cliente Flutter.
|
||||
- O utilizador deve poder confirmar/editar qualquer sugestão automática.
|
||||
- Nunca substituir nome, categoria ou tags sem confirmação.
|
||||
- Manter fallback manual caso a análise de imagem falhe.
|
||||
- Atualizar este documento antes de implementar visão computacional.
|
||||
|
||||
@@ -1,146 +1,102 @@
|
||||
# 🏷️ Sistema de Categorias e Tags
|
||||
# Sistema de Categorias e Tags
|
||||
|
||||
## Filosofia
|
||||
|
||||
O sistema de organização deve ser:
|
||||
- **Simples o suficiente** para não sobrecarregar o utilizador
|
||||
- **Flexível o suficiente** para cobrir a maioria dos casos reais
|
||||
- **Extensível** para futuras funcionalidades (outfits, clima, etc.)
|
||||
O sistema de organização deve ser simples, visual e útil para recomendações.
|
||||
|
||||
Categorias identificam o tipo principal do item. Tags descrevem contexto de uso, como `casual`, `work`, `travel` ou `gaming`.
|
||||
|
||||
---
|
||||
|
||||
## Categorias Principais (MVP)
|
||||
## Implementação atual
|
||||
|
||||
| ID | Nome | Ícone | Descrição |
|
||||
|----|------|-------|-----------|
|
||||
| `clothing` | Roupa | 👕 | Peças de vestuário |
|
||||
| `electronics` | Eletrónica | 💻 | Dispositivos e acessórios tecnológicos |
|
||||
| `footwear` | Calçado | 👟 | Sapatos, botas, sandálias |
|
||||
| `accessories` | Acessórios | 🎒 | Bolsas, relógios, óculos, bijuteria |
|
||||
| `documents` | Documentos | 📄 | Passaporte, cartões, papéis importantes |
|
||||
| `other` | Outros | 📦 | Tudo o resto |
|
||||
As categorias e tags vivem em:
|
||||
|
||||
```text
|
||||
lib/constants/item_categories.dart
|
||||
```
|
||||
|
||||
A UI usa estas constantes para:
|
||||
|
||||
- Mostrar filtros horizontais no inventário.
|
||||
- Mostrar ícones e cores por categoria.
|
||||
- Permitir seleção de categoria ao adicionar/editar item.
|
||||
- Permitir seleção de tags de contexto.
|
||||
- Enviar contexto útil à IA.
|
||||
|
||||
---
|
||||
|
||||
## Subcategorias por Categoria
|
||||
## Categorias principais
|
||||
|
||||
### 👕 Roupa (`clothing`)
|
||||
```
|
||||
casual → t-shirts, calças de ganga, hoodies
|
||||
formal → fatos, camisas, vestidos de cerimónia
|
||||
sportswear → leggings, tops de treino, shorts
|
||||
outerwear → casacos, impermeáveis, parkas
|
||||
underwear → roupa interior, meias
|
||||
sleepwear → pijamas, roupões
|
||||
```
|
||||
| ID esperado | Nome | Uso |
|
||||
|-------------|------|-----|
|
||||
| `roupa` / equivalente | Roupa | Peças de vestuário |
|
||||
| `eletronica` / equivalente | Eletrónica | Consolas, portáteis, carregadores, gadgets |
|
||||
| `calcado` / equivalente | Calçado | Botas, sapatilhas, sapatos |
|
||||
| `acessorios` / equivalente | Acessórios | Mochilas, bolsas, relógios, óculos |
|
||||
| `documentos` / equivalente | Documentos | Cartões, papéis, bilhetes, identificação |
|
||||
| `outros` / equivalente | Outros | Itens fora das categorias principais |
|
||||
|
||||
### 💻 Eletrónica (`electronics`)
|
||||
```
|
||||
computers → portáteis, tablets
|
||||
phones → smartphones, earphones
|
||||
cameras → máquinas fotográficas, action cams
|
||||
cables → carregadores, cabos USB, adaptadores
|
||||
gaming → consolas, comandos, jogos
|
||||
audio → headphones, colunas bluetooth
|
||||
```
|
||||
|
||||
### 👟 Calçado (`footwear`)
|
||||
```
|
||||
casual → sapatilhas, loafers
|
||||
formal → sapatos de salto, mocassins
|
||||
sport → ténis de corrida, chuteiras
|
||||
outdoor → botas de caminhada, sandálias
|
||||
```
|
||||
|
||||
### 🎒 Acessórios (`accessories`)
|
||||
```
|
||||
bags → mochilas, malas, bolsas
|
||||
watches → relógios analógicos e digitais
|
||||
eyewear → óculos de sol, óculos de grau
|
||||
jewelry → colares, pulseiras, brincos
|
||||
hats → bonés, chapéus, gorros
|
||||
belts → cintos
|
||||
```
|
||||
|
||||
### 📄 Documentos (`documents`)
|
||||
```
|
||||
identity → passaporte, BI, carta de condução
|
||||
health → cartão de saúde, receitas
|
||||
travel → bilhetes, reservas, seguros
|
||||
financial → cartões de crédito/débito
|
||||
```
|
||||
A nomenclatura exata deve seguir `item_categories.dart`, porque a UI usa esses IDs diretamente.
|
||||
|
||||
---
|
||||
|
||||
## Tags de Contexto
|
||||
## Tags de contexto
|
||||
|
||||
Estas tags determinam em que situações o item é relevante para sugestões:
|
||||
As tags são livres dentro das opções fornecidas pela app. Exemplos úteis:
|
||||
|
||||
| Tag | Descrição | Exemplos de itens |
|
||||
|-----|-----------|-------------------|
|
||||
| `travel` | Qualquer tipo de viagem | Mala, passaporte, adaptador de tomadas |
|
||||
| `work` | Ambiente de trabalho | Portátil, fato, sapatos formais |
|
||||
| `casual` | Dia-a-dia informal | Jeans, t-shirt, sapatilhas |
|
||||
| `sport` | Atividade física | Leggings, ténis de corrida, garrafa de água |
|
||||
| `formal` | Eventos formais | Fato, vestido, sapatos de salto |
|
||||
| `outdoor` | Exterior e natureza | Blusão, botas, impermeável |
|
||||
| `beach` | Praia ou piscina | Biquíni, chinelos, protetor solar |
|
||||
| `cold` | Clima frio | Casaco, cachecol, luvas |
|
||||
| `hot` | Clima quente | Roupa leve, t-shirts, sandálias |
|
||||
| Tag | Contexto |
|
||||
|-----|----------|
|
||||
| `casual` | Uso diário e informal |
|
||||
| `formal` | Reuniões, eventos e ocasiões formais |
|
||||
| `work` | Trabalho ou estudo |
|
||||
| `travel` | Viagens e deslocações |
|
||||
| `sport` | Treino/desporto |
|
||||
| `outdoor` | Atividades exteriores |
|
||||
| `beach` | Praia/piscina |
|
||||
| `cold` | Tempo frio |
|
||||
| `hot` | Tempo quente |
|
||||
| `gaming` | Consolas e entretenimento |
|
||||
|
||||
---
|
||||
|
||||
## Atribuição Automática de Tags de Contexto
|
||||
## Como as tags são usadas pela IA
|
||||
|
||||
Baseado na categoria e subcategoria, a app atribui context tags automaticamente:
|
||||
O serviço `AiRecommendationService` envia à IA um contexto com:
|
||||
|
||||
```javascript
|
||||
// constants/contextTagRules.js
|
||||
|
||||
export const AUTO_CONTEXT_TAGS = {
|
||||
// Por categoria
|
||||
'clothing.formal': ['work', 'formal'],
|
||||
'clothing.casual': ['casual', 'travel'],
|
||||
'clothing.sportswear':['sport'],
|
||||
'clothing.outerwear': ['travel', 'cold', 'outdoor'],
|
||||
|
||||
'electronics.computers': ['work', 'travel'],
|
||||
'electronics.phones': ['travel', 'work', 'casual'],
|
||||
'electronics.cables': ['travel'],
|
||||
'electronics.gaming': ['casual', 'travel'],
|
||||
|
||||
'footwear.formal': ['work', 'formal'],
|
||||
'footwear.casual': ['casual', 'travel'],
|
||||
'footwear.sport': ['sport'],
|
||||
'footwear.outdoor': ['outdoor', 'travel'],
|
||||
|
||||
'accessories.bags': ['travel', 'work', 'casual'],
|
||||
'documents.identity':['travel'],
|
||||
'documents.travel': ['travel'],
|
||||
};
|
||||
```text
|
||||
- nome do item
|
||||
- categoria
|
||||
- tags
|
||||
- nota/notes, quando existe
|
||||
```
|
||||
|
||||
---
|
||||
Exemplo:
|
||||
|
||||
## Interface de Tags (UX)
|
||||
```text
|
||||
- Switch (categoria: Eletrónica) [tags: gaming, casual]
|
||||
- Camisa verde (categoria: Roupa) [tags: formal, work]
|
||||
```
|
||||
|
||||
### Ao adicionar um item:
|
||||
1. Categoria é sugerida automaticamente (Google Vision)
|
||||
2. Subcategoria é apresentada como lista (scroll horizontal)
|
||||
3. Tags de contexto são pré-selecionadas automaticamente
|
||||
4. Utilizador pode adicionar/remover tags livremente
|
||||
5. Máximo de **10 tags por item** no MVP
|
||||
|
||||
### Pesquisa por tags:
|
||||
- Filtro por categoria (dropdown ou tabs)
|
||||
- Filtro por context tag (chips selecionáveis)
|
||||
- Pesquisa textual (nome ou qualquer tag)
|
||||
Quando o utilizador pede uma sugestão, por exemplo `piquenique no parque`, a IA deve escolher apenas itens compatíveis com o pedido e existentes no inventário.
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
## Pesquisa e filtros
|
||||
|
||||
- As categorias e subcategorias definidas aqui são **fixas** no MVP — não criar novas sem validar
|
||||
- As context tags são a base do sistema de sugestões em `05_RECOMMENDATION_ENGINE.md`
|
||||
- Quando o utilizador edita manualmente as tags, essas preferências devem ser guardadas e têm prioridade sobre as automáticas
|
||||
- O sistema de tags deve ser simples de perceber sem documentação — usar labels em português na UI
|
||||
No inventário, o utilizador pode:
|
||||
|
||||
- Pesquisar por nome.
|
||||
- Pesquisar por tag.
|
||||
- Filtrar por categoria.
|
||||
- Alternar entre vista em grid e lista.
|
||||
|
||||
---
|
||||
|
||||
## Regras para manutenção
|
||||
|
||||
- Não criar novas categorias diretamente na UI sem atualizar `item_categories.dart`.
|
||||
- Tags devem ser claras e curtas.
|
||||
- Preferir tags em minúsculas e sem espaços.
|
||||
- Se uma categoria nova for adicionada, garantir ícone, cor e nome visível.
|
||||
- A IA depende da qualidade das tags e notas; manter esses campos simples e úteis.
|
||||
|
||||
@@ -1,187 +1,133 @@
|
||||
# 🎯 Motor de Recomendações
|
||||
# Motor de Recomendações e IA
|
||||
|
||||
## Filosofia
|
||||
## Estado atual
|
||||
|
||||
> "Não precisas de IA para parecer inteligente. Precisas de regras bem pensadas."
|
||||
O DayMaker usa uma abordagem baseada em **IA de linguagem com contexto do inventário**.
|
||||
|
||||
O motor de recomendações evolui em 3 fases:
|
||||
|
||||
| Fase | Tecnologia | Estado |
|
||||
|------|-----------|--------|
|
||||
| 1 — Regras estáticas | Lógica JS simples | ✅ MVP |
|
||||
| 2 — IA de linguagem | OpenAI API | 🔲 Fase 2 |
|
||||
| 3 — Recomendação personalizada | Histórico + ML | 🔲 Fase 3 |
|
||||
Não existe atualmente um motor de regras local como fonte principal das recomendações. A recomendação é gerada pelo serviço `AiRecommendationService`, que chama uma API Ollama remota.
|
||||
|
||||
---
|
||||
|
||||
## FASE 1 — Regras Estáticas (MVP)
|
||||
## Serviço principal
|
||||
|
||||
### Contextos disponíveis
|
||||
Ficheiro:
|
||||
|
||||
O utilizador escolhe um dos seguintes contextos:
|
||||
|
||||
```javascript
|
||||
// constants/contexts.js
|
||||
|
||||
export const CONTEXTS = [
|
||||
{
|
||||
id: 'travel_short',
|
||||
label: 'Viagem curta (1-3 dias)',
|
||||
icon: '✈️',
|
||||
tags: ['travel'],
|
||||
priorityCategories: ['documents', 'clothing', 'electronics', 'footwear'],
|
||||
maxItems: 20,
|
||||
},
|
||||
{
|
||||
id: 'travel_long',
|
||||
label: 'Viagem longa (4+ dias)',
|
||||
icon: '🧳',
|
||||
tags: ['travel'],
|
||||
priorityCategories: ['documents', 'clothing', 'electronics', 'footwear', 'accessories'],
|
||||
maxItems: 40,
|
||||
},
|
||||
{
|
||||
id: 'work',
|
||||
label: 'Dia de trabalho',
|
||||
icon: '💼',
|
||||
tags: ['work'],
|
||||
priorityCategories: ['electronics', 'clothing', 'footwear', 'accessories'],
|
||||
maxItems: 15,
|
||||
},
|
||||
{
|
||||
id: 'casual',
|
||||
label: 'Fim de semana casual',
|
||||
icon: '😎',
|
||||
tags: ['casual'],
|
||||
priorityCategories: ['clothing', 'footwear', 'accessories'],
|
||||
maxItems: 10,
|
||||
},
|
||||
{
|
||||
id: 'sport',
|
||||
label: 'Treino / Desporto',
|
||||
icon: '🏃',
|
||||
tags: ['sport'],
|
||||
priorityCategories: ['clothing', 'footwear'],
|
||||
maxItems: 8,
|
||||
},
|
||||
{
|
||||
id: 'outdoor',
|
||||
label: 'Saída para o exterior',
|
||||
icon: '🌲',
|
||||
tags: ['outdoor', 'travel'],
|
||||
priorityCategories: ['clothing', 'footwear', 'accessories'],
|
||||
maxItems: 12,
|
||||
},
|
||||
];
|
||||
```text
|
||||
lib/services/ai_recommendation_service.dart
|
||||
```
|
||||
|
||||
### Lógica de filtragem
|
||||
Responsabilidades:
|
||||
|
||||
```javascript
|
||||
// services/suggestions.js
|
||||
|
||||
export function getSuggestionsForContext(items, contextId) {
|
||||
const context = CONTEXTS.find(c => c.id === contextId);
|
||||
if (!context) return [];
|
||||
|
||||
// 1. Filtrar itens com pelo menos uma tag do contexto
|
||||
const relevantItems = items.filter(item =>
|
||||
item.contextTags.some(tag => context.tags.includes(tag))
|
||||
);
|
||||
|
||||
// 2. Ordenar por prioridade de categoria
|
||||
const sorted = relevantItems.sort((a, b) => {
|
||||
const aIndex = context.priorityCategories.indexOf(a.category);
|
||||
const bIndex = context.priorityCategories.indexOf(b.category);
|
||||
const aPriority = aIndex === -1 ? 999 : aIndex;
|
||||
const bPriority = bIndex === -1 ? 999 : bIndex;
|
||||
return aPriority - bPriority;
|
||||
});
|
||||
|
||||
// 3. Limitar ao máximo de itens
|
||||
return sorted.slice(0, context.maxItems);
|
||||
}
|
||||
```
|
||||
|
||||
### Exemplos de output
|
||||
|
||||
**Contexto: "Viagem curta"**
|
||||
```
|
||||
✅ Passaporte (documents.identity → travel)
|
||||
✅ Portátil (electronics.computers → travel, work)
|
||||
✅ Carregador USB-C (electronics.cables → travel)
|
||||
✅ T-shirt preta (clothing.casual → casual, travel)
|
||||
✅ Jeans azul (clothing.casual → casual, travel)
|
||||
✅ Sapatilhas brancas (footwear.casual → casual, travel)
|
||||
❌ Fato de treino (clothing.sportswear → sport) ← não aparece
|
||||
❌ Consola PS5 (electronics.gaming → casual) ← não aparece
|
||||
```
|
||||
- Buscar itens do utilizador no Supabase.
|
||||
- Construir contexto textual do inventário.
|
||||
- Enviar mensagens para a API Ollama.
|
||||
- Manter histórico simples de conversa.
|
||||
- Suportar `silent: true` para sugestões estruturadas.
|
||||
- Buscar itens com imagens para a home.
|
||||
|
||||
---
|
||||
|
||||
## FASE 2 — IA de Linguagem (OpenAI API)
|
||||
## Endpoint e modelo
|
||||
|
||||
> **Não implementar no MVP. Esta secção é referência para a Fase 2.**
|
||||
| Campo | Valor |
|
||||
|-------|-------|
|
||||
| Endpoint | `https://apichat.epvc.pt/api/chat` |
|
||||
| Modelo | `llama3.2:3b` |
|
||||
| Stream | `false` |
|
||||
| Formato | Ollama `/api/chat` |
|
||||
|
||||
### Objetivo
|
||||
Payload base:
|
||||
|
||||
Permitir ao utilizador escrever em linguagem natural:
|
||||
- "Vou viajar 4 horas de comboio"
|
||||
- "Tenho uma reunião importante amanhã de manhã"
|
||||
- "Fim de semana na praia"
|
||||
|
||||
### Arquitetura proposta
|
||||
|
||||
```
|
||||
Utilizador escreve frase
|
||||
↓
|
||||
OpenAI API (classificação de contexto)
|
||||
↓
|
||||
Retorna JSON estruturado:
|
||||
```json
|
||||
{
|
||||
"context": "travel",
|
||||
"duration": "short",
|
||||
"environment": "transit",
|
||||
"weather": "unknown",
|
||||
"formality": "casual"
|
||||
"model": "llama3.2:3b",
|
||||
"messages": [
|
||||
{"role": "system", "content": "..."},
|
||||
{"role": "user", "content": "..."}
|
||||
],
|
||||
"stream": false
|
||||
}
|
||||
↓
|
||||
Motor de regras Fase 1 (com parâmetros enriquecidos)
|
||||
↓
|
||||
Lista de itens sugeridos
|
||||
```
|
||||
|
||||
### Prompt base para OpenAI
|
||||
|
||||
```
|
||||
System: És um assistente de inventário pessoal.
|
||||
Analisa a frase do utilizador e devolve APENAS um JSON com:
|
||||
- context: "travel" | "work" | "casual" | "sport" | "outdoor" | "formal"
|
||||
- duration: "short" | "medium" | "long" | null
|
||||
- environment: "indoor" | "outdoor" | "transit" | null
|
||||
- weather: "cold" | "hot" | "rainy" | null
|
||||
- formality: "casual" | "formal" | null
|
||||
|
||||
User: {frase do utilizador}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FASE 3 — Recomendação Personalizada
|
||||
## Prompt de sistema
|
||||
|
||||
> **Fase muito futura. Apenas visão.**
|
||||
A IA é instruída a:
|
||||
|
||||
- Sistema aprende quais itens o utilizador seleciona/ignora das sugestões
|
||||
- Pontuação de relevância por item por contexto
|
||||
- Integração com API de clima para filtros automáticos
|
||||
- Histórico de viagens para sugestões baseadas em padrões
|
||||
- Ajudar a montar outfits e escolher o que levar.
|
||||
- Usar linguagem simples e curta.
|
||||
- Não usar emojis.
|
||||
- Basear-se nas tags e notas dos itens.
|
||||
- Responder sempre em português.
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
## Contexto enviado à IA
|
||||
|
||||
- **No MVP, usar APENAS a Fase 1.** Não implementar OpenAI no MVP.
|
||||
- A lógica de `getSuggestionsForContext` deve ser pura (sem side effects)
|
||||
- Os contextos são fixos no MVP — não adicionar sem validar com o utilizador
|
||||
- A ordenação por `priorityCategories` é intencional e importante — respeitá-la
|
||||
- Quando a Fase 2 for implementada, o output do OpenAI deve mapear para os IDs de contexto da Fase 1
|
||||
O contexto inclui os itens do utilizador:
|
||||
|
||||
```text
|
||||
Itens disponiveis no inventario do utilizador:
|
||||
- Bota verde (categoria: Roupa) [tags: casual, outdoor]
|
||||
- Switch (categoria: Eletrónica) [tags: gaming, casual]
|
||||
```
|
||||
|
||||
Esse contexto é anexado à mensagem de sistema.
|
||||
|
||||
---
|
||||
|
||||
## Chat IA
|
||||
|
||||
No ecrã `AiChatScreen`:
|
||||
|
||||
- O utilizador escreve livremente.
|
||||
- Existem sugestões rápidas no topo.
|
||||
- A resposta é apresentada como conversa.
|
||||
- O histórico fica em memória no serviço enquanto a instância existir.
|
||||
|
||||
---
|
||||
|
||||
## Sugestão IA na Home
|
||||
|
||||
Fluxo:
|
||||
|
||||
1. Utilizador toca em `Pedir sugestão à IA`.
|
||||
2. App abre um diálogo e pede a ocasião.
|
||||
3. O utilizador pode escrever algo como `piquenique no parque` ou escolher chip rápido.
|
||||
4. A app envia a ocasião em modo `silent`.
|
||||
5. A IA deve devolver apenas nomes exatos dos itens, um por linha.
|
||||
6. A app cruza esses nomes com os itens reais do Supabase.
|
||||
7. A app mostra cards com imagem, nome e categoria.
|
||||
8. O utilizador pode exportar os itens para um dia da semana.
|
||||
|
||||
---
|
||||
|
||||
## Modo silencioso
|
||||
|
||||
Quando `silent: true`, a instrução acrescentada ao pedido é:
|
||||
|
||||
```text
|
||||
responde APENAS com os nomes exatos dos itens do meu inventario que sugeres, um por linha, sem numeracao, sem explicacao, sem comentarios.
|
||||
```
|
||||
|
||||
Isto permite transformar a resposta da IA numa lista de itens reais.
|
||||
|
||||
---
|
||||
|
||||
## Limitações conhecidas
|
||||
|
||||
- A correspondência depende da IA devolver nomes próximos aos nomes reais.
|
||||
- Se a IA devolver texto extra, a app tenta limpar linhas, mas pode falhar correspondência.
|
||||
- A IA não vê imagens, apenas nomes, categorias, tags e notas.
|
||||
- Não há ranking local por clima, cor ou histórico de uso.
|
||||
|
||||
---
|
||||
|
||||
## Melhorias futuras
|
||||
|
||||
- Resposta em JSON em vez de texto simples.
|
||||
- Validação local mais robusta por ID de item.
|
||||
- Sugestões com clima e duração.
|
||||
- Preferências aprendidas por histórico.
|
||||
- Integração com calendário.
|
||||
|
||||
@@ -1,119 +1,90 @@
|
||||
# 🚀 Roadmap e Funcionalidades Futuras
|
||||
# Roadmap e Funcionalidades Futuras
|
||||
|
||||
## Visão a longo prazo
|
||||
|
||||
> "Uma app que conhece tudo o que possuis e te diz exatamente o que precisas, quando precisas."
|
||||
> "Uma app que conhece o teu inventário e te ajuda a preparar qualquer dia, viagem ou ocasião."
|
||||
|
||||
---
|
||||
|
||||
## Fases de desenvolvimento
|
||||
## Estado atual concluído
|
||||
|
||||
```
|
||||
FASE 1 — MVP (agora)
|
||||
├── Upload de fotos
|
||||
├── Guardar itens
|
||||
├── Categorização manual + auto (Google Vision)
|
||||
├── Pesquisa / filtro
|
||||
└── Sugestões simples por regras
|
||||
O produto atual já inclui:
|
||||
|
||||
FASE 2 — IA de Linguagem
|
||||
├── Input em linguagem natural
|
||||
├── Integração OpenAI API
|
||||
└── Contextos dinâmicos
|
||||
|
||||
FASE 3 — Personalização
|
||||
├── Aprendizagem por histórico
|
||||
├── Integração com clima
|
||||
└── Sugestões proativas
|
||||
|
||||
FASE 4 — Social e Avançado
|
||||
├── Outfits automáticos
|
||||
├── Pack automático para viagens
|
||||
├── Integração com calendário
|
||||
└── Assistente conversacional
|
||||
```
|
||||
- Autenticação Supabase.
|
||||
- Inventário com imagens, categorias e tags.
|
||||
- Pesquisa e filtros.
|
||||
- Planeamento semanal.
|
||||
- Chat IA.
|
||||
- Sugestões IA com base nos itens reais.
|
||||
- Exportação de sugestões para dias da semana.
|
||||
|
||||
---
|
||||
|
||||
## Funcionalidades por fase
|
||||
## Próximas melhorias recomendadas
|
||||
|
||||
### 🔵 Fase 2 — IA de Linguagem
|
||||
### 1. Melhorar robustez das sugestões IA
|
||||
|
||||
**Input em linguagem natural**
|
||||
- Utilizador escreve ou fala: "Vou a uma conferência em Londres por 3 dias"
|
||||
- App interpreta e gera lista personalizada
|
||||
- Implementado via OpenAI API (ver `05_RECOMMENDATION_ENGINE.md`)
|
||||
- Fazer a IA devolver JSON com IDs ou nomes estruturados.
|
||||
- Validar itens sugeridos localmente antes de mostrar.
|
||||
- Mostrar mensagem clara quando nenhum item corresponde.
|
||||
- Permitir editar a lista antes de exportar.
|
||||
|
||||
**Contextos dinâmicos**
|
||||
- Em vez de escolher de uma lista, o utilizador descreve a situação
|
||||
- App infere contexto, duração, clima esperado, formalidade
|
||||
### 2. Checklist por plano
|
||||
|
||||
- Marcar item como preparado/levado.
|
||||
- Separar itens planeados de itens concluídos.
|
||||
- Mostrar progresso por dia.
|
||||
|
||||
### 3. Notificações
|
||||
|
||||
- Lembrete de itens planeados para amanhã.
|
||||
- Lembrete na manhã do dia.
|
||||
- Notificação quando uma viagem/plano tem poucos itens.
|
||||
|
||||
### 4. Clima e localização
|
||||
|
||||
- Utilizador informa destino/data.
|
||||
- App consulta previsão meteorológica.
|
||||
- IA recebe clima como contexto adicional.
|
||||
- Sugestões ajustadas para frio, calor ou chuva.
|
||||
|
||||
### 5. Reconhecimento por imagem
|
||||
|
||||
- Sugerir categoria e tags a partir da foto.
|
||||
- Detetar cor dominante.
|
||||
- Melhorar recomendações de outfit.
|
||||
|
||||
### 6. Preferências e histórico
|
||||
|
||||
- Guardar sugestões aceites/ignoradas.
|
||||
- Priorizar itens usados com frequência.
|
||||
- Evitar sugerir itens que o utilizador remove sempre.
|
||||
|
||||
### 7. Calendário externo
|
||||
|
||||
- Integração com Google Calendar / Apple Calendar.
|
||||
- Sugestões proativas baseadas em eventos.
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Fase 3 — Personalização
|
||||
## Funcionalidades fora do escopo atual
|
||||
|
||||
**Aprendizagem por histórico**
|
||||
- App regista quais itens o utilizador aceitou/ignorou nas sugestões
|
||||
- Com 10+ interações, começa a ajustar pesos de relevância
|
||||
- Exemplo: utilizador nunca leva sapatos formais em viagens curtas → app para de sugerir
|
||||
|
||||
**Integração com API de clima**
|
||||
- Utilizador indica destino e datas
|
||||
- App consulta previsão meteorológica
|
||||
- Filtra roupa por temperatura e condições
|
||||
- APIs candidatas: OpenWeatherMap, WeatherAPI
|
||||
|
||||
**Sugestões proativas (push notifications)**
|
||||
- "Tens uma reunião amanhã — lembra-te do teu fato"
|
||||
- "Viagem na sexta — queres ver a tua lista?"
|
||||
| Funcionalidade | Estado |
|
||||
|----------------|--------|
|
||||
| Clima automático | Futuro |
|
||||
| Notificações push | Futuro |
|
||||
| Reconhecimento de imagem | Futuro |
|
||||
| Calendário externo | Futuro |
|
||||
| Partilha/social | Futuro |
|
||||
| Recomendação visual por cor | Futuro |
|
||||
| Testes automatizados completos | Pendente |
|
||||
|
||||
---
|
||||
|
||||
### 🔴 Fase 4 — Funcionalidades Avançadas
|
||||
## Prioridade sugerida
|
||||
|
||||
**Montagem automática de outfits**
|
||||
- App combina peças de roupa compatíveis visualmente
|
||||
- Usa cor dominante extraída das fotos
|
||||
- Sugere conjuntos completos (peça cima + baixo + calçado + acessório)
|
||||
|
||||
**Pack automático para viagens**
|
||||
- Utilizador diz: "Vou 5 dias ao Porto, clima ameno, reuniões + lazer"
|
||||
- App gera lista completa, organizada por tipo de item
|
||||
- Permite marcar o que já está na mala (checklist)
|
||||
|
||||
**Integração com Google Calendar / Apple Calendar**
|
||||
- App lê eventos do calendário
|
||||
- Antecipa necessidades: "Reunião importante na 5ª feira → fato?"
|
||||
- Notificações contextuais automáticas
|
||||
|
||||
**Assistente conversacional**
|
||||
- Chat dentro da app
|
||||
- Perguntas como: "O que devo levar amanhã?"
|
||||
- Resposta baseada em calendário + clima + inventário
|
||||
- Implementado via OpenAI Assistants API ou similar
|
||||
|
||||
**Funcionalidades sociais (opcional)**
|
||||
- Partilhar listas com parceiro de viagem
|
||||
- "O que ele/ela já vai levar?" para evitar duplicações
|
||||
- Listas de viagem colaborativas
|
||||
|
||||
---
|
||||
|
||||
## Integrações externas planeadas
|
||||
|
||||
| Serviço | Fase | Objetivo |
|
||||
|---------|------|----------|
|
||||
| Google Vision AI | 1 (MVP) | Identificar objetos nas fotos |
|
||||
| OpenAI API | 2 | Processar linguagem natural |
|
||||
| OpenWeatherMap | 3 | Dados de clima por destino |
|
||||
| Google Calendar | 4 | Antecipação de necessidades |
|
||||
| Apple Calendar | 4 | Antecipação de necessidades (iOS) |
|
||||
|
||||
---
|
||||
|
||||
## Notas para o agente IA
|
||||
|
||||
- Quando o utilizador pedir uma funcionalidade das Fases 2-4, não recusar — mas clarificar que está fora do MVP e perguntar se deve ser planeada para uma fase futura
|
||||
- Não implementar funcionalidades de fases futuras sem confirmação explícita do utilizador
|
||||
- Ao planear uma funcionalidade futura, criar um documento de especificação separado antes de implementar
|
||||
- A ordem das fases é intencional — não saltar fases sem validação com utilizadores reais
|
||||
1. Resposta IA estruturada em JSON.
|
||||
2. Checklist por plano.
|
||||
3. Notificações simples.
|
||||
4. Clima.
|
||||
5. Visão por imagem.
|
||||
|
||||
@@ -1,184 +1,104 @@
|
||||
# 🤖 Comportamento do Agente IA
|
||||
# Comportamento do Agente IA
|
||||
|
||||
## Propósito deste ficheiro
|
||||
|
||||
Este ficheiro define como um agente IA (assistente de código, Cursor, Copilot, Claude, etc.) deve comportar-se quando trabalha neste projeto.
|
||||
**Lê este ficheiro primeiro antes de qualquer tarefa.**
|
||||
Este ficheiro define como um agente IA de código deve comportar-se quando trabalha no projeto **DayMaker**.
|
||||
|
||||
---
|
||||
|
||||
## Contexto do projeto
|
||||
|
||||
Estás a trabalhar num projeto chamado **InventoryAI** — uma app móvel de gestão de inventário pessoal com sugestões contextuais.
|
||||
DayMaker é uma app Flutter com Supabase para inventário pessoal, planeamento semanal e sugestões por IA usando Ollama.
|
||||
|
||||
Lê os seguintes ficheiros para entender o projeto completo:
|
||||
1. `00_PROJECT_OVERVIEW.md` — visão geral e princípios
|
||||
2. `01_MVP_DEFINITION.md` — o que está incluído no MVP
|
||||
3. `02_ARCHITECTURE.md` — stack técnica e modelo de dados
|
||||
4. `03_AI_VISION_LAYER.md` — integração com Google Vision
|
||||
5. `04_CATEGORIES_AND_TAGS.md` — sistema de organização
|
||||
6. `05_RECOMMENDATION_ENGINE.md` — lógica de sugestões
|
||||
7. `06_FUTURE_FEATURES.md` — roadmap futuro
|
||||
Antes de alterações grandes, consultar:
|
||||
|
||||
1. `00_PROJECT_OVERVIEW.md`
|
||||
2. `01_MVP_DEFINITION.md`
|
||||
3. `02_ARCHITECTURE.md`
|
||||
4. `05_RECOMMENDATION_ENGINE.md`
|
||||
|
||||
---
|
||||
|
||||
## Regras de comportamento
|
||||
|
||||
### ✅ SEMPRE fazer
|
||||
### Sempre fazer
|
||||
|
||||
- **Verificar o ficheiro MVP** antes de implementar qualquer funcionalidade — só implementar o que está em `01_MVP_DEFINITION.md`
|
||||
- **Respeitar a stack definida** em `02_ARCHITECTURE.md` — Firebase, React Native, Google Vision
|
||||
- **Usar o modelo de dados** exatamente como definido (campos, tipos, nomes)
|
||||
- **Manter o código simples** — se há duas formas, escolher a mais simples
|
||||
- **Comentar decisões de arquitetura** no código quando relevante
|
||||
- **Avisar** quando uma funcionalidade pedida está fora do MVP
|
||||
- **Perguntar** antes de alterar o modelo de dados ou a arquitetura
|
||||
- **Criar ficheiros de serviço** em `src/services/` para lógica de negócio
|
||||
- **Usar constantes** de `src/constants/` para valores fixos (categorias, contextos, etc.)
|
||||
- Respeitar a stack atual: Flutter, Dart, Supabase e Ollama API.
|
||||
- Usar os componentes e tokens de `lib/theme/app_theme.dart`.
|
||||
- Manter queries Supabase filtradas por `user_id` quando os dados forem do utilizador.
|
||||
- Verificar o modelo de dados antes de alterar tabelas ou campos.
|
||||
- Manter a UI consistente com a navegação atual: Início, Itens, Semana, IA e Perfil.
|
||||
- Usar `flutter analyze --no-pub` depois de alterações relevantes.
|
||||
- Explicar ao utilizador quando uma funcionalidade exige alteração de base de dados.
|
||||
|
||||
### ❌ NUNCA fazer
|
||||
### Nunca fazer
|
||||
|
||||
- Adicionar funcionalidades que não estão no MVP sem confirmação explícita
|
||||
- Mudar a stack tecnológica (ex: sugerir Flutter, Supabase, AWS)
|
||||
- Implementar OpenAI no MVP — fica para a Fase 2
|
||||
- Guardar a API key do Google Vision em código client-side em produção
|
||||
- Criar lógica de base de dados fora dos ficheiros `services/`
|
||||
- Usar `console.log` em produção para dados sensíveis do utilizador
|
||||
- Alterar os nomes dos campos do modelo de dados sem avisar
|
||||
- Reintroduzir Firebase, Firestore ou React Native.
|
||||
- Assumir que Google Vision está implementado.
|
||||
- Trocar o endpoint/modelo da IA sem testar ou explicar.
|
||||
- Hardcodar API keys privadas.
|
||||
- Enviar dados sensíveis desnecessários à IA.
|
||||
- Criar categorias fora de `item_categories.dart` sem atualizar a documentação.
|
||||
|
||||
---
|
||||
|
||||
## Linguagem e comunicação
|
||||
## Padrões de código
|
||||
|
||||
- Comunicar em **português** (de Portugal, não do Brasil)
|
||||
- Explicações técnicas devem ser **claras e objetivas**
|
||||
- Quando há uma decisão de arquitetura, **explicar o porquê**
|
||||
- Usar **exemplos de código** sempre que possível
|
||||
- Avisos sobre o MVP devem ser **visíveis** (usar emoji ⚠️ ou bloco de nota)
|
||||
### Flutter/Dart
|
||||
|
||||
- Widgets em `PascalCase`.
|
||||
- Métodos privados com `_camelCase`.
|
||||
- Serviços em `lib/services/`.
|
||||
- Telas em `lib/Screens/` ou pasta equivalente já existente.
|
||||
- Imports no topo do ficheiro.
|
||||
|
||||
### UI
|
||||
|
||||
Usar preferencialmente:
|
||||
|
||||
- `AppColors`
|
||||
- `AppText`
|
||||
- `AppRadius`
|
||||
- `AppShadows`
|
||||
- `AppDecorations`
|
||||
- `AppButton`
|
||||
- `AppChip`
|
||||
- `AppSnack`
|
||||
|
||||
### Supabase
|
||||
|
||||
- Ler utilizador com `Supabase.instance.client.auth.currentUser`.
|
||||
- Não executar operações de dados se `user == null`.
|
||||
- Usar `.eq('user_id', user.id)` em tabelas por utilizador.
|
||||
|
||||
---
|
||||
|
||||
## Ordem de construção obrigatória
|
||||
## IA e sugestões
|
||||
|
||||
Seguir esta ordem ao implementar. Não avançar para o próximo passo sem o anterior estar funcional:
|
||||
O fluxo atual usa `AiRecommendationService`.
|
||||
|
||||
```
|
||||
PASSO 1: 📸 Upload de fotos
|
||||
└── Câmara + seleção de galeria
|
||||
└── Upload para Firebase Storage
|
||||
└── URL guardado no estado
|
||||
- Chat livre: `sendMessage(text)`.
|
||||
- Sugestão estruturada: `sendMessage(text, silent: true)`.
|
||||
- Itens com imagem: `getItemsWithImages()`.
|
||||
|
||||
PASSO 2: 📦 Guardar itens
|
||||
└── Formulário básico (nome, categoria)
|
||||
└── Gravar no Firestore
|
||||
└── Autenticação Firebase
|
||||
|
||||
PASSO 3: 🏷️ Categorização
|
||||
└── Integração Google Vision API
|
||||
└── Mapeamento labels → categorias
|
||||
└── UI de confirmação/edição
|
||||
|
||||
PASSO 4: 🔍 Pesquisa e visualização
|
||||
└── Lista de itens (grid)
|
||||
└── Filtro por categoria
|
||||
└── Pesquisa por nome
|
||||
|
||||
PASSO 5: 🎯 Sugestões simples
|
||||
└── Seleção de contexto
|
||||
└── Lógica de filtragem por tags
|
||||
└── Apresentação da lista sugerida
|
||||
```
|
||||
A IA deve receber contexto de inventário e responder em português.
|
||||
|
||||
---
|
||||
|
||||
## Como responder a pedidos fora do MVP
|
||||
## Pedidos fora do produto atual
|
||||
|
||||
Quando o utilizador pede uma funcionalidade que está fora do MVP:
|
||||
Se o utilizador pedir clima, notificações, visão por imagem ou calendário externo:
|
||||
|
||||
```
|
||||
⚠️ MVP: Esta funcionalidade não está incluída no MVP atual.
|
||||
|
||||
Está documentada como [Fase X] em 06_FUTURE_FEATURES.md.
|
||||
|
||||
Opções:
|
||||
1. Adiar para a Fase X (recomendado — manter foco no MVP)
|
||||
2. Priorizar agora (implica atrasar outras funcionalidades do MVP)
|
||||
|
||||
O que preferes?
|
||||
```
|
||||
1. Explicar que é funcionalidade futura.
|
||||
2. Perguntar se deve implementar agora.
|
||||
3. Avisar se exigir nova dependência, API key ou alteração de base de dados.
|
||||
|
||||
---
|
||||
|
||||
## Padrões de código obrigatórios
|
||||
## Checklist antes de terminar uma tarefa
|
||||
|
||||
### Nomenclatura
|
||||
```javascript
|
||||
// Componentes React: PascalCase
|
||||
ItemCard.jsx
|
||||
AddItemScreen.jsx
|
||||
|
||||
// Serviços e utilitários: camelCase
|
||||
visionApi.js
|
||||
suggestions.js
|
||||
|
||||
// Constantes: camelCase (ficheiros), UPPER_SNAKE_CASE (valores)
|
||||
categoryMapping.js → export const LABEL_TO_CATEGORY = { ... }
|
||||
contexts.js → export const CONTEXTS = [ ... ]
|
||||
```
|
||||
|
||||
### Estrutura de um serviço
|
||||
```javascript
|
||||
// services/exemplo.js
|
||||
|
||||
// 1. Imports
|
||||
import { db } from './firebase';
|
||||
|
||||
// 2. Funções puras (sem side effects)
|
||||
export function processarDados(input) { ... }
|
||||
|
||||
// 3. Funções de base de dados
|
||||
export async function guardarItem(userId, item) { ... }
|
||||
export async function obterItens(userId) { ... }
|
||||
```
|
||||
|
||||
### Tratamento de erros
|
||||
```javascript
|
||||
// Sempre usar try/catch em chamadas assíncronas
|
||||
try {
|
||||
const resultado = await guardarItem(userId, novoItem);
|
||||
// sucesso
|
||||
} catch (erro) {
|
||||
console.error('Erro ao guardar item:', erro.message);
|
||||
// mostrar mensagem ao utilizador (não o erro técnico)
|
||||
Alert.alert('Erro', 'Não foi possível guardar o item. Tenta novamente.');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Perguntas frequentes
|
||||
|
||||
**P: O utilizador pediu uma funcionalidade — implemento já?**
|
||||
R: Verificar `01_MVP_DEFINITION.md`. Se estiver no MVP, implementar. Se não, avisar e perguntar.
|
||||
|
||||
**P: Posso usar uma biblioteca nova?**
|
||||
R: Só se resolver um problema que não tem solução simples sem ela. Avisar antes de instalar.
|
||||
|
||||
**P: O modelo de dados precisa de um campo novo — adiciono?**
|
||||
R: Avisar o utilizador, explicar o impacto, aguardar confirmação.
|
||||
|
||||
**P: A API do Google Vision não está a funcionar nos testes — o que fazer?**
|
||||
R: Criar um mock local (`services/visionApiMock.js`) que retorna dados fixos para desenvolvimento.
|
||||
|
||||
---
|
||||
|
||||
## Ficheiros de referência rápida
|
||||
|
||||
| Quero saber... | Ficheiro |
|
||||
|----------------|----------|
|
||||
| O que está no MVP? | `01_MVP_DEFINITION.md` |
|
||||
| Que tecnologias usar? | `02_ARCHITECTURE.md` |
|
||||
| Como a IA de imagem funciona? | `03_AI_VISION_LAYER.md` |
|
||||
| Que categorias existem? | `04_CATEGORIES_AND_TAGS.md` |
|
||||
| Como funcionam as sugestões? | `05_RECOMMENDATION_ENGINE.md` |
|
||||
| O que vem a seguir? | `06_FUTURE_FEATURES.md` |
|
||||
- Código compila com `flutter analyze --no-pub`.
|
||||
- Não há imports não usados.
|
||||
- UI segue tema atual.
|
||||
- Documentação atualizada quando a funcionalidade muda comportamento.
|
||||
- Resumo final indica ficheiros alterados.
|
||||
|
||||
@@ -1,70 +1,81 @@
|
||||
# 📝 AI Agents Log
|
||||
# AI Agents Log
|
||||
|
||||
## Propósito
|
||||
|
||||
Este ficheiro regista toda a atividade do agente de recomendação.
|
||||
Cada execução gera uma entrada neste log.
|
||||
Este ficheiro regista decisões e alterações relevantes relacionadas com a IA e recomendações do DayMaker.
|
||||
|
||||
---
|
||||
|
||||
## Formato de Entrada
|
||||
## Formato recomendado
|
||||
|
||||
### Data:
|
||||
```text
|
||||
### Data
|
||||
YYYY-MM-DD
|
||||
|
||||
### Agente:
|
||||
Recommender-MVP
|
||||
### Área
|
||||
Chat IA / Sugestão IA / Inventário / Planeamento / Documentação
|
||||
|
||||
### Tipo:
|
||||
- recomendacao
|
||||
- erro
|
||||
- melhoria
|
||||
### Descrição
|
||||
Resumo do que mudou.
|
||||
|
||||
### Descrição:
|
||||
O que foi feito
|
||||
|
||||
### Itens afetados:
|
||||
Lista de itens usados
|
||||
|
||||
### Ação tomada:
|
||||
O que se decidiu
|
||||
|
||||
### Notas:
|
||||
Observações úteis
|
||||
|
||||
---
|
||||
|
||||
## Regras de Logging
|
||||
|
||||
1. **SEMPRE** registar após cada execução
|
||||
2. Tipo `recomendacao` → quando sugestões são geradas com sucesso
|
||||
3. Tipo `erro` → quando lista vazia, pedido ambíguo ou dados incompletos
|
||||
4. Tipo `melhoria` → quando se detetam problemas no sistema
|
||||
5. Nunca omitir entradas de erro — são tão importantes como sucessos
|
||||
### Impacto
|
||||
Como afeta o utilizador ou o código.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Histórico
|
||||
|
||||
### Data:
|
||||
### Data
|
||||
2026-04-24
|
||||
|
||||
### Agente:
|
||||
Recommender-MVP
|
||||
### Área
|
||||
Recomendação inicial
|
||||
|
||||
### Tipo:
|
||||
recomendacao
|
||||
### Descrição
|
||||
Primeiras ideias de motor de recomendações baseado em regras estáticas e contextos.
|
||||
|
||||
### Descrição:
|
||||
Implementação inicial do motor de recomendações MVP. Sistema de regras estáticas com 6 contextos, parser por palavras-chave, logging e deteção de melhorias.
|
||||
### Impacto
|
||||
Serviu como base conceptual, mas não representa a implementação final.
|
||||
|
||||
### Itens afetados:
|
||||
T-shirt preta, Portátil, Nintendo Switch, Fones de ouvido, Passaporte, Carregador USB-C, Jeans azul, Sapatilhas brancas, Mochila, Fato de treino
|
||||
---
|
||||
|
||||
### Ação tomada:
|
||||
Criado APPprojetoLP.dart com modelo de dados alinhado com 02_ARCHITECTURE.md, contextos de 05_RECOMMENDATION_ENGINE.md, e tags de 04_CATEGORIES_AND_TAGS.md
|
||||
### Data
|
||||
2026-05-21
|
||||
|
||||
### Notas:
|
||||
- Parser de pedidos é básico (palavras-chave). Fase 2 usará OpenAI API.
|
||||
- Clima e formalidade são detetados mas não filtram itens no MVP.
|
||||
- Duração "medium" (ex: 4 horas) não tem regras específicas ainda.
|
||||
### Área
|
||||
Chat IA
|
||||
|
||||
### Descrição
|
||||
Integração do chat com endpoint Ollama remoto `https://apichat.epvc.pt/api/chat` usando o modelo `llama3.2:3b`.
|
||||
|
||||
### Impacto
|
||||
A app passou a ter ecrã de conversa com IA acessível pela barra inferior.
|
||||
|
||||
---
|
||||
|
||||
### Data
|
||||
2026-05-22
|
||||
|
||||
### Área
|
||||
Sugestão IA na Home
|
||||
|
||||
### Descrição
|
||||
Criado fluxo de sugestão por ocasião. O utilizador escreve algo como `piquenique no parque`; a IA responde com nomes de itens do inventário; a app cruza com itens reais, mostra imagens e permite exportar para a semana.
|
||||
|
||||
### Impacto
|
||||
A sugestão deixou de ser texto solto e passou a produzir itens acionáveis.
|
||||
|
||||
---
|
||||
|
||||
### Data
|
||||
2026-05-28
|
||||
|
||||
### Área
|
||||
Documentação
|
||||
|
||||
### Descrição
|
||||
Documentação reescrita para refletir o projeto final: Flutter, Supabase, inventário, planeamento semanal, chat IA e sugestões Ollama.
|
||||
|
||||
### Impacto
|
||||
Removidas referências antigas a React Native/Firebase/OpenAI como stack atual.
|
||||
|
||||
@@ -1,115 +1,93 @@
|
||||
# ⚙️ Rule Engine — Regras de Recomendação (MVP)
|
||||
# Regras do Sistema de Sugestão
|
||||
|
||||
## Propósito
|
||||
## Estado atual
|
||||
|
||||
Define as regras estáticas que o motor de recomendações segue para sugerir itens ao utilizador.
|
||||
O DayMaker não usa atualmente um motor de regras local como fonte principal de recomendações.
|
||||
|
||||
A sugestão é gerada pela IA através de `AiRecommendationService`, usando o inventário real do utilizador como contexto.
|
||||
|
||||
---
|
||||
|
||||
## Regras Ativas (MVP)
|
||||
## Regras ativas
|
||||
|
||||
### R1 — Filtragem por Context Tags
|
||||
```
|
||||
IF item.contextTags contém pelo menos uma tag do contexto
|
||||
THEN item é relevante
|
||||
### R1 — Usar apenas inventário do utilizador
|
||||
|
||||
A IA recebe apenas itens do utilizador autenticado.
|
||||
|
||||
```text
|
||||
items.user_id == currentUser.id
|
||||
```
|
||||
|
||||
### R2 — Ordenação por Prioridade de Categoria
|
||||
```
|
||||
Ordenar itens pela posição da categoria em context.priorityCategories
|
||||
Categorias fora da lista → prioridade baixa (999)
|
||||
```
|
||||
### R2 — Contexto textual dos itens
|
||||
|
||||
### R3 — Limite de Itens
|
||||
```
|
||||
Retornar no máximo context.maxItems itens
|
||||
```
|
||||
Cada item é enviado com:
|
||||
|
||||
| Contexto | maxItems |
|
||||
|----------|----------|
|
||||
| travel_short | 20 |
|
||||
| travel_long | 40 |
|
||||
| work | 15 |
|
||||
| casual | 10 |
|
||||
| sport | 8 |
|
||||
| outdoor | 12 |
|
||||
- nome
|
||||
- categoria
|
||||
- tags
|
||||
- nota/notes, quando disponível
|
||||
|
||||
### R4 — Interpretação de Pedido (Parser)
|
||||
```
|
||||
Palavras-chave → contexto + duração + clima + formalidade
|
||||
### R3 — Modo silencioso para sugestões
|
||||
|
||||
viagem/comboio/voo → travel_short + transit
|
||||
trabalho/reunião → work + indoor
|
||||
fim de semana/casual/lazer → casual
|
||||
treino/desporto/gym → sport
|
||||
exterior/caminhada → outdoor + outdoor
|
||||
Quando a sugestão vem da Home, o serviço usa `silent: true` e instrui a IA a responder apenas com nomes exatos dos itens.
|
||||
|
||||
4+ dias/semana/longa → duration:long + upgrade para travel_long
|
||||
4 horas/média → duration:medium
|
||||
1-2 horas/curta → duration:short
|
||||
### R4 — Correspondência com itens reais
|
||||
|
||||
frio/inverno → weather:cold
|
||||
calor/verão/praia → weather:hot
|
||||
chuva → weather:rainy
|
||||
A app cruza as linhas devolvidas pela IA com os nomes dos itens carregados do Supabase.
|
||||
|
||||
formal/cerimónia → formality:formal
|
||||
casual/informal → formality:casual
|
||||
```
|
||||
Apenas itens correspondidos são mostrados com imagem e podem ser exportados.
|
||||
|
||||
### R5 — Exportação para semana
|
||||
|
||||
Ao exportar:
|
||||
|
||||
1. A app cria ou encontra um registo em `plans` para o dia escolhido.
|
||||
2. Insere relações em `plan_items`.
|
||||
3. Evita duplicados já existentes no plano.
|
||||
|
||||
---
|
||||
|
||||
## Regras Pendentes (a implementar)
|
||||
## Limitações atuais
|
||||
|
||||
### R5 — Filtro por Duração
|
||||
```
|
||||
IF duration == short → apenas essenciais (documents, cables, 1x clothing)
|
||||
IF duration == medium → essenciais + entretenimento
|
||||
IF duration == long → essenciais + entretenimento + conforto extra
|
||||
```
|
||||
**Estado:** Não implementado no MVP atual. Duração é detetada mas não filtra.
|
||||
|
||||
### R6 — Filtro por Clima
|
||||
```
|
||||
IF weather == cold → priorizar outerwear, remover beach/hot items
|
||||
IF weather == hot → priorizar roupa leve, remover cold items
|
||||
IF weather == rainy → priorizar outerwear + accessories.impermeável
|
||||
```
|
||||
**Estado:** Clima é detetado mas não filtra itens no MVP.
|
||||
|
||||
### R7 — Filtro por Formalidade
|
||||
```
|
||||
IF formality == formal → priorizar clothing.formal, footwear.formal
|
||||
IF formality == casual → excluir clothing.formal
|
||||
```
|
||||
**Estado:** Formalidade é detetada mas não filtra itens no MVP.
|
||||
- A IA pode devolver nomes com pequenas diferenças.
|
||||
- O matching é textual e pode falhar se o nome não coincidir.
|
||||
- Não existe ranking local por categoria, clima ou duração.
|
||||
- Não existe checklist de itens preparados.
|
||||
|
||||
---
|
||||
|
||||
## Mapeamento de Context Tags (04_CATEGORIES_AND_TAGS.md)
|
||||
## Regras futuras recomendadas
|
||||
|
||||
| Categoria.Subcategoria | Context Tags |
|
||||
|------------------------|-------------|
|
||||
| clothing.formal | work, formal |
|
||||
| clothing.casual | casual, travel |
|
||||
| clothing.sportswear | sport |
|
||||
| clothing.outerwear | travel, cold, outdoor |
|
||||
| electronics.computers | work, travel |
|
||||
| electronics.phones | travel, work, casual |
|
||||
| electronics.cables | travel |
|
||||
| electronics.gaming | casual, travel |
|
||||
| footwear.formal | work, formal |
|
||||
| footwear.casual | casual, travel |
|
||||
| footwear.sport | sport |
|
||||
| footwear.outdoor | outdoor, travel |
|
||||
| accessories.bags | travel, work, casual |
|
||||
| documents.identity | travel |
|
||||
| documents.travel | travel |
|
||||
### RF1 — Resposta estruturada
|
||||
|
||||
Pedir à IA JSON com identificadores ou nomes normalizados.
|
||||
|
||||
### RF2 — Score local
|
||||
|
||||
Calcular pontuação por:
|
||||
|
||||
- categoria
|
||||
- tags
|
||||
- ocasião
|
||||
- histórico do utilizador
|
||||
- clima
|
||||
|
||||
### RF3 — Checklist
|
||||
|
||||
Guardar estado de cada item planeado:
|
||||
|
||||
- planeado
|
||||
- preparado
|
||||
- levado
|
||||
|
||||
### RF4 — Clima
|
||||
|
||||
Ajustar sugestões quando houver dados meteorológicos.
|
||||
|
||||
---
|
||||
|
||||
## Notas para o Agente
|
||||
## Notas para manutenção
|
||||
|
||||
- **NÃO** adicionar regras novas sem validar com o utilizador
|
||||
- As regras R5-R7 estão identificadas como pendentes — implementar quando o MVP base estiver estável
|
||||
- O parser de palavras-chave (R4) é temporário — Fase 2 substitui por OpenAI
|
||||
- Sempre que uma regra pendente for implementada, atualizar este ficheiro e o AI_AGENTS_LOG.md
|
||||
- Não mudar o comportamento do modo `silent` sem atualizar `05_RECOMMENDATION_ENGINE.md`.
|
||||
- Se a app passar a usar IDs na resposta da IA, atualizar este ficheiro e o serviço.
|
||||
- Manter a exportação compatível com `plans` e `plan_items`.
|
||||
|
||||
Reference in New Issue
Block a user