166 lines
5.2 KiB
Markdown
166 lines
5.2 KiB
Markdown
# 🏠 MainActivity.java — Ecrã Principal
|
||
|
||
> **Ficheiro:** `app/src/main/java/com/example/medcuida/pro/MainActivity.java`
|
||
> **Layout:** `activity_main.xml`
|
||
> **Linhas de código:** 404
|
||
|
||
---
|
||
|
||
## Descrição Geral
|
||
|
||
A `MainActivity` é o **ecrã central da aplicação**. Funciona como um painel de controlo do médico, com **3 secções** controladas por uma `BottomNavigationView`:
|
||
|
||
| Tab | Conteúdo |
|
||
|---|---|
|
||
| 📅 **Agenda** | Calendário + lista de consultas do dia selecionado |
|
||
| 👥 **Pacientes** | Lista de todos os pacientes registados |
|
||
| 👤 **Perfil** | Dados do médico (nome, email, especialidade, cédula) |
|
||
|
||
---
|
||
|
||
## Inicialização (`onCreate`) — Linhas 59–188
|
||
|
||
### 1. Configuração do Layout (Linhas 63–69)
|
||
```java
|
||
setContentView(R.layout.activity_main);
|
||
```
|
||
- Carrega o layout XML
|
||
- Envolto em `try-catch` para capturar erros de inflação da view
|
||
|
||
### 2. Verificação de Autenticação (Linhas 71–79)
|
||
```java
|
||
if (mAuth.getCurrentUser() == null) {
|
||
startActivity(new Intent(this, LoginActivity.class));
|
||
finish();
|
||
return;
|
||
}
|
||
```
|
||
- Se o utilizador **não está autenticado**, redireciona para o `LoginActivity`
|
||
- Obtém o `uid` do médico atual para filtrar dados
|
||
|
||
### 3. Carregamento do Nome em Cache (Linhas 91–95)
|
||
```java
|
||
String cachedName = getSharedPreferences("SessaoMedico", MODE_PRIVATE).getString("nome_medico", "");
|
||
```
|
||
- Lê o nome do médico das `SharedPreferences` para **exibição instantânea** (sem esperar pelo Firestore)
|
||
- Mostra "Olá, [Primeiro Nome]" no topo
|
||
|
||
### 4. Configuração dos Pacientes (Linhas 97–107)
|
||
- Cria um `RecyclerView` com `PacienteAdapter`
|
||
- Ao clicar num paciente → abre `DetalhePacienteActivity`
|
||
|
||
### 5. Configuração da Agenda (Linhas 109–120)
|
||
- Cria um `RecyclerView` com `ConsultaAdapter`
|
||
- Ao clicar numa consulta → abre `DetalhePacienteActivity` com ID da consulta
|
||
|
||
### 6. Configuração do Perfil (Linhas 122–139)
|
||
- Associa os `TextView` do perfil (nome, email, especialidade, cédula)
|
||
- **Botão "Editar Dados"** → abre `EditarPerfilActivity`
|
||
- **Botão "Logout"** → faz sign out e redireciona para login
|
||
|
||
### 7. Bottom Navigation (Linhas 141–162)
|
||
```java
|
||
bottomNav.setOnItemSelectedListener(item -> {
|
||
// Esconde todas as views
|
||
// Mostra apenas a view selecionada
|
||
});
|
||
```
|
||
- Controla a visibilidade das 3 secções (Agenda, Pacientes, Perfil)
|
||
- A tab **Agenda** é a selecionada por defeito
|
||
|
||
### 8. Carregamento de Dados (Linhas 164–183)
|
||
- Chama `loadUtilizadores()` para carregar pacientes
|
||
- Chama `loadPerfilMedico()` para carregar o perfil
|
||
- Configura o `CalendarView` para filtrar consultas por data
|
||
|
||
---
|
||
|
||
## Lógica dos Pacientes — Linhas 190–230
|
||
|
||
### `loadUtilizadores()`
|
||
```java
|
||
db.collection("utilizadores").addSnapshotListener(...)
|
||
```
|
||
|
||
**O que faz:**
|
||
1. Escuta **em tempo real** a coleção `utilizadores` no Firestore
|
||
2. Para cada documento:
|
||
- Converte para objeto `Paciente`
|
||
- Tenta o campo `nome_completo`, depois `nome` como fallback
|
||
- Filtra: apenas inclui se `tipo` for `"paciente"` ou não estiver definido
|
||
3. Atualiza o `RecyclerView` ou mostra mensagem "vazio"
|
||
|
||
---
|
||
|
||
## Ações nas Consultas — Linhas 232–260
|
||
|
||
### `onAceitarClick(Consulta)` — Linha 233
|
||
- Atualiza o campo `status` da consulta para `"aceite"` no Firestore
|
||
|
||
### `onEliminarClick(Consulta)` — Linha 238
|
||
- **Elimina** o documento da consulta do Firestore
|
||
|
||
### `onConsultaClick(Consulta)` — Linha 246
|
||
- Abre o `DetalhePacienteActivity` com os IDs do paciente e da consulta
|
||
|
||
### `updateConsultaStatus()` — Linha 253
|
||
- Método auxiliar que atualiza o campo `status` de uma consulta
|
||
|
||
---
|
||
|
||
## Lógica da Agenda — Linhas 262–342
|
||
|
||
### `loadConsultasAgendaForDate(String dateStr)`
|
||
|
||
**O que faz:**
|
||
1. Remove qualquer listener anterior (para evitar duplicados)
|
||
2. Escuta **todas** as consultas em tempo real
|
||
3. Para cada consulta:
|
||
- Verifica se **pertence ao médico atual** (campo `medicos` pode ser `String` ou `List`)
|
||
- Verifica se a **data corresponde** à data selecionada (suporta 3 formatos: `dd/MM/yyyy`, `d/M/yyyy`, `yyyy-MM-dd`)
|
||
- Exclui consultas com status `"cancelada"`
|
||
4. Atualiza a lista na UI
|
||
|
||
### `convertToISODate()` — Linha 324
|
||
- Converte `"22/04/2026"` → `"2026-04-22"`
|
||
|
||
### `getAlternativeDate()` — Linha 335
|
||
- Converte `"01/04/2026"` → `"1/4/2026"` (sem zeros à esquerda)
|
||
|
||
---
|
||
|
||
## Lógica do Perfil — Linhas 350–402
|
||
|
||
### `loadPerfilMedico()`
|
||
1. Escuta em tempo real na coleção `utilizadores`
|
||
2. Se o documento **não existe**, faz fallback para a coleção `medicos`
|
||
3. Chama `updateProfileUI()` com os dados encontrados
|
||
|
||
### `updateProfileUI(DocumentSnapshot doc)`
|
||
1. Lê `nome_completo` (ou `nome` como fallback)
|
||
2. Guarda o nome nas `SharedPreferences` para cache
|
||
3. Atualiza todos os campos da UI:
|
||
- Nome, Email, Especialidade, Cédula profissional
|
||
- Saudação "Olá, [Nome]" no topo
|
||
|
||
---
|
||
|
||
## Diagrama de Fluxo
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[onCreate] --> B{Utilizador autenticado?}
|
||
B -->|Não| C[Ir para Login]
|
||
B -->|Sim| D[Carregar UI]
|
||
D --> E[Carregar nome em cache]
|
||
D --> F[Configurar RecyclerViews]
|
||
D --> G[Configurar BottomNav]
|
||
D --> H[loadUtilizadores]
|
||
D --> I[loadPerfilMedico]
|
||
D --> J[loadConsultasAgendaForDate - hoje]
|
||
|
||
G -->|Tab Agenda| K[Mostrar Agenda]
|
||
G -->|Tab Pacientes| L[Mostrar Pacientes]
|
||
G -->|Tab Perfil| M[Mostrar Perfil]
|
||
```
|