first commit

This commit is contained in:
2026-03-19 10:37:52 +00:00
commit d6b75cc25c
1790 changed files with 217457 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Notificações e Alarmes -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Cuida"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
</activity>
<activity android:name=".ui.auth.LoginActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.auth.RegisterActivity" />
<activity android:name=".DetalhePacienteActivity" />
<activity android:name=".ChatActivity" android:windowSoftInputMode="adjustResize" />
<activity android:name=".AgendaActivity" />
<activity android:name=".PerfilMedicoActivity" />
<activity android:name=".EditarPerfilActivity" />
</application>
</manifest>

View File

@@ -0,0 +1,121 @@
package com.example.medcuida.pro;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CalendarView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.example.medcuida.pro.models.Consulta;
import com.example.medcuida.pro.ui.adapters.ConsultaAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class AgendaActivity extends AppCompatActivity {
private ConsultaAdapter adapter;
private FirebaseFirestore db;
private String doctorId;
private TextView textAgendaVazia;
private RecyclerView recyclerAgenda;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_agenda);
CalendarView calendarView = findViewById(R.id.calendarView);
recyclerAgenda = findViewById(R.id.recycler_agenda);
textAgendaVazia = findViewById(R.id.text_agenda_vazia);
recyclerAgenda.setLayoutManager(new LinearLayoutManager(this));
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setSelectedItemId(R.id.nav_agenda);
bottomNav.setOnItemSelectedListener(item -> {
if (item.getItemId() == R.id.nav_agenda) {
return true;
} else if (item.getItemId() == R.id.nav_pacientes) {
startActivity(new Intent(this, MainActivity.class));
return false;
} else if (item.getItemId() == R.id.nav_perfil) {
startActivity(new Intent(this, PerfilMedicoActivity.class));
return false;
}
return false;
});
adapter = new ConsultaAdapter(null, consulta -> {
Intent intent = new Intent(AgendaActivity.this, DetalhePacienteActivity.class);
intent.putExtra("PACIENTE_ID", consulta.getPacienteId());
intent.putExtra("CONSULTA_ID", consulta.getId());
startActivity(intent);
});
recyclerAgenda.setAdapter(adapter);
db = FirebaseFirestore.getInstance();
if (FirebaseAuth.getInstance().getCurrentUser() != null) {
doctorId = FirebaseAuth.getInstance().getCurrentUser().getUid();
}
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
loadConsultasForDate(sdf.format(new Date()));
calendarView.setOnDateChangeListener((view, year, month, dayOfMonth) -> {
String selectedDate = String.format(Locale.getDefault(), "%02d/%02d/%d", dayOfMonth, month + 1, year);
loadConsultasForDate(selectedDate);
});
}
private void loadConsultasForDate(String dateStr) {
if (doctorId == null) return;
db.collection("consultas")
.whereEqualTo("medicoId", doctorId)
.addSnapshotListener((value, error) -> {
if (error != null || value == null) return;
List<Consulta> consultasList = new ArrayList<>();
for (QueryDocumentSnapshot doc : value) {
Consulta c = doc.toObject(Consulta.class);
if (c.getData() != null && (c.getData().equals(dateStr) || c.getData().equals(getAlternativeDate(dateStr)))) {
if ("confirmada".equalsIgnoreCase(c.getStatus())) {
c.setId(doc.getId());
consultasList.add(c);
}
}
}
adapter.setConsultas(consultasList);
if (consultasList.isEmpty()) {
textAgendaVazia.setVisibility(View.VISIBLE);
recyclerAgenda.setVisibility(View.GONE);
} else {
textAgendaVazia.setVisibility(View.GONE);
recyclerAgenda.setVisibility(View.VISIBLE);
}
});
}
private String getAlternativeDate(String paddedDate) {
try {
String[] parts = paddedDate.split("/");
return Integer.parseInt(parts[0]) + "/" + Integer.parseInt(parts[1]) + "/" + parts[2];
} catch (Exception e) {
return paddedDate;
}
}
}

View File

@@ -0,0 +1,119 @@
package com.example.medcuida.pro;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.medcuida.pro.models.Mensagem;
import com.example.medcuida.pro.ui.adapters.MensagemAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import java.util.ArrayList;
import java.util.List;
public class ChatActivity extends AppCompatActivity {
private static final String TAG = "ChatActivity";
private RecyclerView recyclerMensagens;
private EditText etMensagemInput;
private ImageButton btnEnviar;
private MensagemAdapter adapter;
private FirebaseFirestore db;
private FirebaseAuth mAuth;
private String currentUserId;
private String consultaId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
db = FirebaseFirestore.getInstance();
mAuth = FirebaseAuth.getInstance();
if (mAuth.getCurrentUser() == null) {
Toast.makeText(this, "Erro de autenticação", Toast.LENGTH_SHORT).show();
finish();
return;
}
currentUserId = mAuth.getCurrentUser().getUid();
consultaId = getIntent().getStringExtra("CONSULTA_ID");
if (consultaId == null || consultaId.isEmpty()) {
Toast.makeText(this, "Consulta inválida", Toast.LENGTH_SHORT).show();
finish();
return;
}
recyclerMensagens = findViewById(R.id.recycler_mensagens);
etMensagemInput = findViewById(R.id.et_mensagem_input);
btnEnviar = findViewById(R.id.btn_enviar);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setStackFromEnd(true); // Para as mensagens começarem do fundo
recyclerMensagens.setLayoutManager(layoutManager);
adapter = new MensagemAdapter(currentUserId);
recyclerMensagens.setAdapter(adapter);
btnEnviar.setOnClickListener(v -> enviarMensagem());
carregarMensagens();
}
private void carregarMensagens() {
db.collection("consultas").document(consultaId).collection("mensagens")
.orderBy("timestamp", Query.Direction.ASCENDING)
.addSnapshotListener((value, error) -> {
if (error != null) {
Log.e(TAG, "Erro ao carregar mensagens.", error);
return;
}
List<Mensagem> mensagens = new ArrayList<>();
if (value != null) {
for (DocumentSnapshot doc : value) {
Mensagem msg = doc.toObject(Mensagem.class);
if (msg != null) {
mensagens.add(msg);
}
}
}
adapter.setMensagens(mensagens);
if (!mensagens.isEmpty()) {
recyclerMensagens.scrollToPosition(mensagens.size() - 1);
}
});
}
private void enviarMensagem() {
String texto = etMensagemInput.getText().toString().trim();
if (TextUtils.isEmpty(texto)) {
return;
}
Mensagem novaMensagem = new Mensagem(texto, currentUserId, System.currentTimeMillis());
db.collection("consultas").document(consultaId).collection("mensagens")
.add(novaMensagem)
.addOnSuccessListener(documentReference -> etMensagemInput.setText(""))
.addOnFailureListener(e -> Toast.makeText(ChatActivity.this, "Erro ao enviar.", Toast.LENGTH_SHORT).show());
}
}

View File

@@ -0,0 +1,100 @@
package com.example.medcuida.pro;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.button.MaterialButton;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
public class DetalhePacienteActivity extends AppCompatActivity {
private static final String TAG = "DetalhePaciente";
private TextView tvNome, tvIdade, tvNumeroUtente, tvMedicacao, tvSexo, tvEmail;
private MaterialButton btnChat;
private FirebaseFirestore db;
private String pacienteId;
private String consultaId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detalhe_paciente);
tvNome = findViewById(R.id.tv_nome_paciente);
tvIdade = findViewById(R.id.tv_idade_paciente);
tvNumeroUtente = findViewById(R.id.tv_numero_utente);
tvSexo = findViewById(R.id.tv_sexo_paciente);
tvEmail = findViewById(R.id.tv_email_paciente);
tvMedicacao = findViewById(R.id.tv_medicacao_paciente);
btnChat = findViewById(R.id.btn_chat_paciente);
db = FirebaseFirestore.getInstance();
pacienteId = getIntent().getStringExtra("PACIENTE_ID");
consultaId = getIntent().getStringExtra("CONSULTA_ID");
if (pacienteId == null || pacienteId.isEmpty()) {
Toast.makeText(this, "Erro ao carregar dados do paciente.", Toast.LENGTH_SHORT).show();
finish();
return;
}
btnChat.setOnClickListener(v -> {
Intent intent = new Intent(DetalhePacienteActivity.this, ChatActivity.class);
intent.putExtra("CONSULTA_ID", consultaId);
intent.putExtra("PACIENTE_ID", pacienteId);
startActivity(intent);
});
carregarDadosPaciente();
}
private void carregarDadosPaciente() {
db.collection("usuarios").document(pacienteId)
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null && document.exists()) {
String nome = document.getString("nome_completo");
String idade = document.getString("idade");
String numUtente = document.getString("numero_utente");
String sexo = document.getString("sexo");
String email = document.getString("email");
// Let's assume there is a medicacao field, if not, we use a default text
String medicacao = document.getString("medicacao");
if (medicacao == null || medicacao.isEmpty()) {
medicacao = "Nenhuma medicação registada no perfil atual.";
}
tvNome.setText("Nome: " + (nome != null ? nome : "N/D"));
tvIdade.setText("Idade: " + (idade != null ? idade : "N/D"));
tvNumeroUtente.setText("Nº Utente: " + (numUtente != null ? numUtente : "N/D"));
tvSexo.setText("Sexo: " + (sexo != null ? sexo : "N/D"));
tvEmail.setText("Email: " + (email != null ? email : "N/D"));
tvMedicacao.setText(medicacao);
} else {
Log.d(TAG, "No such document");
Toast.makeText(DetalhePacienteActivity.this, "Paciente não encontrado", Toast.LENGTH_SHORT).show();
}
} else {
Log.d(TAG, "get failed with ", task.getException());
Toast.makeText(DetalhePacienteActivity.this, "Erro ao buscar dados", Toast.LENGTH_SHORT).show();
}
});
}
}

View File

@@ -0,0 +1,120 @@
package com.example.medcuida.pro;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
import java.util.HashMap;
import java.util.Map;
public class EditarPerfilActivity extends AppCompatActivity {
private TextInputEditText nameEditText, specialtyEditText, emailEditText;
private AutoCompleteTextView genderAutoComplete;
private MaterialButton btnGuardar;
private ImageButton btnVoltar;
private FirebaseAuth mAuth;
private FirebaseFirestore db;
private String currentUserId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editar_perfil);
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
if (mAuth.getCurrentUser() == null) {
finish();
return;
}
currentUserId = mAuth.getCurrentUser().getUid();
nameEditText = findViewById(R.id.edit_name);
specialtyEditText = findViewById(R.id.edit_specialty);
genderAutoComplete = findViewById(R.id.edit_gender);
emailEditText = findViewById(R.id.edit_email);
btnGuardar = findViewById(R.id.btn_guardar_alteracoes);
btnVoltar = findViewById(R.id.btn_voltar);
setupGenderDropdown();
btnVoltar.setOnClickListener(v -> finish());
btnGuardar.setOnClickListener(v -> guardarAlteracoes());
carregarDados();
}
private void setupGenderDropdown() {
String[] genders = new String[]{"Masculino", "Feminino", "Outro"};
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_dropdown_item_1line,
genders
);
genderAutoComplete.setAdapter(adapter);
}
private void carregarDados() {
db.collection("medicos").document(currentUserId).get().addOnSuccessListener(doc -> {
if (doc.exists()) {
nameEditText.setText(doc.getString("nome"));
specialtyEditText.setText(doc.getString("especialidade"));
emailEditText.setText(doc.getString("email"));
String gender = doc.getString("gender");
if (gender != null) {
genderAutoComplete.setText(gender, false);
}
}
}).addOnFailureListener(e -> Toast.makeText(this, "Erro ao carregar dados.", Toast.LENGTH_SHORT).show());
}
private void guardarAlteracoes() {
String name = nameEditText.getText() != null ? nameEditText.getText().toString().trim() : "";
String specialty = specialtyEditText.getText() != null ? specialtyEditText.getText().toString().trim() : "";
String gender = genderAutoComplete.getText() != null ? genderAutoComplete.getText().toString().trim() : "";
if (TextUtils.isEmpty(name)) {
nameEditText.setError("O nome é obrigatório");
return;
}
if (TextUtils.isEmpty(specialty)) {
specialtyEditText.setError("A especialidade é obrigatória");
return;
}
btnGuardar.setEnabled(false);
Map<String, Object> updates = new HashMap<>();
updates.put("nome", name);
updates.put("especialidade", specialty);
updates.put("gender", gender);
db.collection("medicos").document(currentUserId)
.update(updates)
.addOnSuccessListener(aVoid -> {
Toast.makeText(EditarPerfilActivity.this, "Dados atualizados com sucesso!", Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
finish();
})
.addOnFailureListener(e -> {
Toast.makeText(EditarPerfilActivity.this, "Erro ao guardar alterações", Toast.LENGTH_SHORT).show();
btnGuardar.setEnabled(true);
});
}
}

View File

@@ -0,0 +1,274 @@
package com.example.medcuida.pro;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CalendarView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.medcuida.pro.models.Consulta;
import com.example.medcuida.pro.ui.adapters.ConsultaAdapter;
import com.example.medcuida.pro.ui.auth.LoginActivity;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.button.MaterialButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements ConsultaAdapter.OnConsultaActionClickListener, ConsultaAdapter.OnConsultaClickListener {
private View viewAgenda, viewPacientes, viewPerfil;
// Pacientes
private RecyclerView recyclerConsultas;
private TextView textEmptyState;
private ConsultaAdapter adapterPacientes;
// Agenda
private RecyclerView recyclerAgenda;
private TextView textAgendaVazia;
private ConsultaAdapter adapterAgenda;
// Perfil
private TextView tvNome, tvEmail, tvEspecialidade, tvCedula;
private MaterialButton btnLogout, btnEditarDados;
// Header
private TextView tvGreetingMain;
private FirebaseAuth mAuth;
private FirebaseFirestore db;
private String currentMedicoId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.activity_main);
} catch (Exception e) {
Toast.makeText(this, "Erro View: " + e.getMessage(), Toast.LENGTH_LONG).show();
// Retorna precocemente em caso de falha severa na interface gráfica
return;
}
try {
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
if (mAuth.getCurrentUser() == null) {
startActivity(new Intent(this, LoginActivity.class));
finish();
return;
}
currentMedicoId = mAuth.getCurrentUser().getUid();
// Bind Views
viewAgenda = findViewById(R.id.view_agenda);
viewPacientes = findViewById(R.id.view_pacientes);
viewPerfil = findViewById(R.id.view_perfil);
tvGreetingMain = findViewById(R.id.tv_greeting_main);
// Bind Pacientes
recyclerConsultas = findViewById(R.id.recycler_consultas);
textEmptyState = findViewById(R.id.text_empty_state);
recyclerConsultas.setLayoutManager(new LinearLayoutManager(this));
adapterPacientes = new ConsultaAdapter(this, this);
recyclerConsultas.setAdapter(adapterPacientes);
// Bind Agenda
recyclerAgenda = findViewById(R.id.recycler_agenda);
textAgendaVazia = findViewById(R.id.text_agenda_vazia);
CalendarView calendarView = findViewById(R.id.calendarView);
recyclerAgenda.setLayoutManager(new LinearLayoutManager(this));
adapterAgenda = new ConsultaAdapter(null, consulta -> {
Intent intent = new Intent(MainActivity.this, DetalhePacienteActivity.class);
intent.putExtra("PACIENTE_ID", consulta.getPacienteId());
intent.putExtra("CONSULTA_ID", consulta.getId());
startActivity(intent);
});
recyclerAgenda.setAdapter(adapterAgenda);
// Bind Perfil
tvNome = findViewById(R.id.tv_nome_medico);
tvEmail = findViewById(R.id.tv_email_medico);
tvEspecialidade = findViewById(R.id.tv_especialidade);
tvCedula = findViewById(R.id.tv_cedula);
btnLogout = findViewById(R.id.btn_logout);
btnEditarDados = findViewById(R.id.btn_editar_dados);
btnEditarDados.setOnClickListener(v -> {
startActivity(new Intent(MainActivity.this, EditarPerfilActivity.class));
});
btnLogout.setOnClickListener(v -> {
mAuth.signOut();
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
});
// Setup BottomNavigation
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setSelectedItemId(R.id.nav_agenda);
bottomNav.setOnItemSelectedListener(item -> {
viewAgenda.setVisibility(View.GONE);
viewPacientes.setVisibility(View.GONE);
viewPerfil.setVisibility(View.GONE);
if (item.getItemId() == R.id.nav_agenda) {
viewAgenda.setVisibility(View.VISIBLE);
return true;
} else if (item.getItemId() == R.id.nav_pacientes) {
viewPacientes.setVisibility(View.VISIBLE);
return true;
} else if (item.getItemId() == R.id.nav_perfil) {
viewPerfil.setVisibility(View.VISIBLE);
return true;
}
return false;
});
// Load Initial Data
loadConsultasPacientes();
loadPerfilMedico();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
loadConsultasAgendaForDate(sdf.format(new Date()));
calendarView.setOnDateChangeListener((view, year, month, dayOfMonth) -> {
String selectedDate = String.format(Locale.getDefault(), "%02d/%02d/%d", dayOfMonth, month + 1, year);
loadConsultasAgendaForDate(selectedDate);
});
} catch(Exception e) {
Toast.makeText(this, "Erro Init: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
// PACIENTES LOGIC
private void loadConsultasPacientes() {
db.collection("consultas")
.whereEqualTo("medicoId", currentMedicoId)
.addSnapshotListener((value, error) -> {
if (error != null) return;
List<Consulta> consultas = new ArrayList<>();
if (value != null) {
for (DocumentSnapshot doc : value) {
Consulta consulta = doc.toObject(Consulta.class);
if (consulta != null) {
consulta.setId(doc.getId());
consultas.add(consulta);
}
}
}
if (consultas.isEmpty()) {
textEmptyState.setVisibility(View.VISIBLE);
recyclerConsultas.setVisibility(View.GONE);
} else {
textEmptyState.setVisibility(View.GONE);
recyclerConsultas.setVisibility(View.VISIBLE);
adapterPacientes.setConsultas(consultas);
}
});
}
@Override
public void onConfirmarClick(Consulta consulta) {
updateConsultaStatus(consulta.getId(), "Confirmada");
}
@Override
public void onCancelarClick(Consulta consulta) {
updateConsultaStatus(consulta.getId(), "Cancelada");
}
@Override
public void onConsultaClick(Consulta consulta) {
Intent intent = new Intent(this, DetalhePacienteActivity.class);
intent.putExtra("PACIENTE_ID", consulta.getPacienteId());
intent.putExtra("CONSULTA_ID", consulta.getId());
startActivity(intent);
}
private void updateConsultaStatus(String consultaId, String newStatus) {
db.collection("consultas").document(consultaId)
.update("status", newStatus)
.addOnSuccessListener(aVoid -> Toast.makeText(this, "Consulta " + newStatus.toLowerCase(), Toast.LENGTH_SHORT).show())
.addOnFailureListener(e -> Toast.makeText(this, "Erro ao atualizar consulta", Toast.LENGTH_SHORT).show());
}
// AGENDA LOGIC
private void loadConsultasAgendaForDate(String dateStr) {
if(currentMedicoId == null) return;
db.collection("consultas")
.whereEqualTo("medicoId", currentMedicoId)
.addSnapshotListener((value, error) -> {
if (error != null || value == null) return;
List<Consulta> consultasList = new ArrayList<>();
for (QueryDocumentSnapshot doc : value) {
Consulta c = doc.toObject(Consulta.class);
if (c.getData() != null && (c.getData().equals(dateStr) || c.getData().equals(getAlternativeDate(dateStr)))) {
if (c.getStatus() == null || !"cancelada".equalsIgnoreCase(c.getStatus())) {
c.setId(doc.getId());
consultasList.add(c);
}
}
}
adapterAgenda.setConsultas(consultasList);
if (consultasList.isEmpty()) {
textAgendaVazia.setVisibility(View.VISIBLE);
recyclerAgenda.setVisibility(View.GONE);
} else {
textAgendaVazia.setVisibility(View.GONE);
recyclerAgenda.setVisibility(View.VISIBLE);
}
});
}
private String getAlternativeDate(String paddedDate) {
try {
String[] parts = paddedDate.split("/");
return Integer.parseInt(parts[0]) + "/" + Integer.parseInt(parts[1]) + "/" + parts[2];
} catch (Exception e) {
return paddedDate;
}
}
@Override
protected void onResume() {
super.onResume();
loadPerfilMedico();
}
// PERFIL LOGIC
private void loadPerfilMedico() {
if(currentMedicoId == null) return;
db.collection("medicos").document(currentMedicoId).get().addOnSuccessListener(doc -> {
if (doc.exists()) {
String fetchedName = doc.getString("nome");
tvNome.setText(fetchedName);
if (tvGreetingMain != null && fetchedName != null) {
tvGreetingMain.setText("Olá, " + fetchedName.split(" ")[0]);
}
tvEmail.setText(doc.getString("email"));
tvEspecialidade.setText("Especialidade: " + doc.getString("especialidade"));
tvCedula.setText("Cédula: " + doc.getString("cedula_profissional"));
}
});
}
}

View File

@@ -0,0 +1,87 @@
package com.example.medcuida.pro;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.medcuida.pro.ui.auth.LoginActivity;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
public class PerfilMedicoActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private FirebaseFirestore db;
private TextView tvNome, tvEmail, tvEspecialidade, tvCedula;
private MaterialButton btnLogout, btnEditarDados;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perfil_medico);
tvNome = findViewById(R.id.tv_nome_medico);
tvEmail = findViewById(R.id.tv_email_medico);
tvEspecialidade = findViewById(R.id.tv_especialidade);
tvCedula = findViewById(R.id.tv_cedula);
btnLogout = findViewById(R.id.btn_logout);
btnEditarDados = findViewById(R.id.btn_editar_dados);
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
btnEditarDados.setOnClickListener(v -> {
startActivity(new Intent(PerfilMedicoActivity.this, EditarPerfilActivity.class));
});
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setSelectedItemId(R.id.nav_perfil);
bottomNav.setOnItemSelectedListener(item -> {
if (item.getItemId() == R.id.nav_perfil) {
return true;
} else if (item.getItemId() == R.id.nav_agenda) {
startActivity(new Intent(this, AgendaActivity.class));
return false;
} else if (item.getItemId() == R.id.nav_pacientes) {
startActivity(new Intent(this, MainActivity.class));
return false;
}
return false;
});
btnLogout.setOnClickListener(v -> {
mAuth.signOut();
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
});
}
@Override
protected void onResume() {
super.onResume();
carregarPerfil();
}
private void carregarPerfil() {
if (mAuth.getCurrentUser() != null) {
String uid = mAuth.getCurrentUser().getUid();
db.collection("medicos").document(uid).get().addOnSuccessListener(doc -> {
if (doc.exists()) {
tvNome.setText(doc.getString("nome"));
tvEmail.setText(doc.getString("email"));
tvEspecialidade.setText("Especialidade: " + doc.getString("especialidade"));
tvCedula.setText("Cédula: " + doc.getString("cedula_profissional"));
}
}).addOnFailureListener(e -> Toast.makeText(this, "Erro ao carregar perfil.", Toast.LENGTH_SHORT).show());
}
}
}

View File

@@ -0,0 +1,28 @@
package com.example.medcuida.pro.models;
public class Consulta {
private String id;
private String data;
private String hora;
private String medicoId;
private String pacienteId;
private String pacienteNome;
private String status;
public Consulta() {}
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public String getHora() { return hora; }
public void setHora(String hora) { this.hora = hora; }
public String getMedicoId() { return medicoId; }
public void setMedicoId(String medicoId) { this.medicoId = medicoId; }
public String getPacienteId() { return pacienteId; }
public void setPacienteId(String pacienteId) { this.pacienteId = pacienteId; }
public String getPacienteNome() { return pacienteNome; }
public void setPacienteNome(String pacienteNome) { this.pacienteNome = pacienteNome; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}

View File

@@ -0,0 +1,60 @@
package com.example.medcuida.pro.models;
public class Medico {
private String id;
private String nome;
private String email;
private String especialidade;
private String genero;
public Medico() {
}
public Medico(String id, String nome, String email, String especialidade, String genero) {
this.id = id;
this.nome = nome;
this.email = email;
this.especialidade = especialidade;
this.genero = genero;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEspecialidade() {
return especialidade;
}
public void setEspecialidade(String especialidade) {
this.especialidade = especialidade;
}
public String getGenero() {
return genero;
}
public void setGenero(String genero) {
this.genero = genero;
}
}

View File

@@ -0,0 +1,41 @@
package com.example.medcuida.pro.models;
public class Mensagem {
private String texto;
private String senderId;
private long timestamp;
public Mensagem() {
// Firestore required
}
public Mensagem(String texto, String senderId, long timestamp) {
this.texto = texto;
this.senderId = senderId;
this.timestamp = timestamp;
}
public String getTexto() {
return texto;
}
public void setTexto(String texto) {
this.texto = texto;
}
public String getSenderId() {
return senderId;
}
public void setSenderId(String senderId) {
this.senderId = senderId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}

View File

@@ -0,0 +1,113 @@
package com.example.medcuida.pro.ui.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.medcuida.pro.R;
import com.example.medcuida.pro.models.Consulta;
import com.google.android.material.button.MaterialButton;
import java.util.ArrayList;
import java.util.List;
public class ConsultaAdapter extends RecyclerView.Adapter<ConsultaAdapter.ConsultaViewHolder> {
private List<Consulta> consultasList = new ArrayList<>();
private final OnConsultaActionClickListener actionClickListener;
private final OnConsultaClickListener clickListener;
public interface OnConsultaActionClickListener {
void onConfirmarClick(Consulta consulta);
void onCancelarClick(Consulta consulta);
}
public interface OnConsultaClickListener {
void onConsultaClick(Consulta consulta);
}
public ConsultaAdapter(OnConsultaActionClickListener actionClickListener, OnConsultaClickListener clickListener) {
this.actionClickListener = actionClickListener;
this.clickListener = clickListener;
}
public void setConsultas(List<Consulta> consultas) {
this.consultasList = consultas;
notifyDataSetChanged();
}
@NonNull
@Override
public ConsultaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_consulta_medico, parent, false);
return new ConsultaViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ConsultaViewHolder holder, int position) {
Consulta consulta = consultasList.get(position);
holder.bind(consulta, actionClickListener, clickListener);
}
@Override
public int getItemCount() {
return consultasList.size();
}
static class ConsultaViewHolder extends RecyclerView.ViewHolder {
TextView textPacienteNome, textDataHora, textStatus;
MaterialButton btnConfirmar, btnCancelar;
public ConsultaViewHolder(@NonNull View itemView) {
super(itemView);
textPacienteNome = itemView.findViewById(R.id.text_paciente_nome);
textDataHora = itemView.findViewById(R.id.text_consulta_data_hora);
textStatus = itemView.findViewById(R.id.text_consulta_status);
btnConfirmar = itemView.findViewById(R.id.btn_confirmar);
btnCancelar = itemView.findViewById(R.id.btn_cancelar);
}
public void bind(final Consulta consulta, final OnConsultaActionClickListener actionListener, final OnConsultaClickListener clickListener) {
textPacienteNome.setText(consulta.getPacienteNome() != null ? consulta.getPacienteNome() : "Desconhecido");
String dataHoraStr = (consulta.getData() != null ? consulta.getData() : "") + " às " +
(consulta.getHora() != null ? consulta.getHora() : "");
textDataHora.setText(dataHoraStr.trim().equals("às") ? "Data não definida" : dataHoraStr);
String status = consulta.getStatus() != null ? consulta.getStatus() : "Pendente";
textStatus.setText(status);
// Hide action buttons if the status isn't Pendente
if (!"Pendente".equalsIgnoreCase(status)) {
btnConfirmar.setVisibility(View.GONE);
btnCancelar.setVisibility(View.GONE);
} else {
btnConfirmar.setVisibility(View.VISIBLE);
btnCancelar.setVisibility(View.VISIBLE);
}
btnConfirmar.setOnClickListener(v -> {
if (actionListener != null) {
actionListener.onConfirmarClick(consulta);
}
});
btnCancelar.setOnClickListener(v -> {
if (actionListener != null) {
actionListener.onCancelarClick(consulta);
}
});
itemView.setOnClickListener(v -> {
if (clickListener != null){
clickListener.onConsultaClick(consulta);
}
});
}
}
}

View File

@@ -0,0 +1,73 @@
package com.example.medcuida.pro.ui.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.medcuida.pro.R;
import com.example.medcuida.pro.models.Mensagem;
import java.util.ArrayList;
import java.util.List;
public class MensagemAdapter extends RecyclerView.Adapter<MensagemAdapter.MensagemViewHolder> {
private List<Mensagem> mensagens = new ArrayList<>();
private String currentUserId;
public MensagemAdapter(String currentUserId) {
this.currentUserId = currentUserId;
}
public void setMensagens(List<Mensagem> mensagens) {
this.mensagens = mensagens;
notifyDataSetChanged();
}
@NonNull
@Override
public MensagemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_mensagem, parent, false);
return new MensagemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MensagemViewHolder holder, int position) {
Mensagem mensagem = mensagens.get(position);
if (mensagem.getSenderId() != null && mensagem.getSenderId().equals(currentUserId)) {
// Eu enviei
holder.layoutMsgEnviada.setVisibility(View.VISIBLE);
holder.layoutMsgRecebida.setVisibility(View.GONE);
holder.tvMsgEnviada.setText(mensagem.getTexto());
} else {
// Eu recebi
holder.layoutMsgEnviada.setVisibility(View.GONE);
holder.layoutMsgRecebida.setVisibility(View.VISIBLE);
holder.tvMsgRecebida.setText(mensagem.getTexto());
}
}
@Override
public int getItemCount() {
return mensagens.size();
}
static class MensagemViewHolder extends RecyclerView.ViewHolder {
LinearLayout layoutMsgRecebida, layoutMsgEnviada;
TextView tvMsgRecebida, tvMsgEnviada;
public MensagemViewHolder(@NonNull View itemView) {
super(itemView);
layoutMsgRecebida = itemView.findViewById(R.id.layout_msg_recebida);
layoutMsgEnviada = itemView.findViewById(R.id.layout_msg_enviada);
tvMsgRecebida = itemView.findViewById(R.id.tv_msg_recebida);
tvMsgEnviada = itemView.findViewById(R.id.tv_msg_enviada);
}
}
}

View File

@@ -0,0 +1,138 @@
package com.example.medcuida.pro.ui.auth;
import com.example.medcuida.pro.AgendaActivity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.medcuida.pro.MainActivity;
import com.example.medcuida.pro.R;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.FirebaseFirestore;
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private TextInputEditText emailEditText, passwordEditText;
private MaterialButton loginButton;
private TextView registerLink, forgotPasswordLink;
private FirebaseAuth mAuth;
private FirebaseFirestore db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Firebase Init
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
// Check if user is already logged in
if (mAuth.getCurrentUser() != null) {
checkIfMedicoAndProceed(mAuth.getCurrentUser().getUid());
}
// UI References
emailEditText = findViewById(R.id.email_edit_text);
passwordEditText = findViewById(R.id.password_edit_text);
loginButton = findViewById(R.id.login_button);
registerLink = findViewById(R.id.register_link);
forgotPasswordLink = findViewById(R.id.forgot_password_link);
loginButton.setOnClickListener(v -> attemptLogin());
registerLink.setOnClickListener(v -> {
startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
});
forgotPasswordLink.setOnClickListener(v -> {
String email = emailEditText.getText() != null ? emailEditText.getText().toString().trim() : "";
if (TextUtils.isEmpty(email)) {
emailEditText.setError("Por favor, introduza o seu e-mail aqui para recuperar a sua palavra-passe.");
emailEditText.requestFocus();
return;
}
mAuth.sendPasswordResetEmail(email).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(LoginActivity.this, "Enviámos um link para redefinir a palavra-passe. Verifica também o Lixo/Spam.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(LoginActivity.this, "Erro ao enviar pedido de recuperação.", Toast.LENGTH_LONG).show();
}
});
});
}
private void attemptLogin() {
String email = emailEditText.getText() != null ? emailEditText.getText().toString().trim() : "";
String password = passwordEditText.getText() != null ? passwordEditText.getText().toString().trim() : "";
if (TextUtils.isEmpty(email)) {
emailEditText.setError("O Email é obrigatório");
emailEditText.requestFocus();
return;
}
if (TextUtils.isEmpty(password)) {
passwordEditText.setError("A palavra-passe é obrigatória");
passwordEditText.requestFocus();
return;
}
loginUser(email, password);
}
private void loginUser(String email, String password) {
loginButton.setEnabled(false);
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
Log.d(TAG, "signInWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
checkIfMedicoAndProceed(user.getUid());
}
} else {
Log.w(TAG, "signInWithEmail:failure", task.getException());
Toast.makeText(LoginActivity.this, "Falha na autenticação.",
Toast.LENGTH_SHORT).show();
loginButton.setEnabled(true);
}
});
}
private void checkIfMedicoAndProceed(String uid) {
db.collection("medicos").document(uid).get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
if (task.getResult() != null && task.getResult().exists()) {
// É médico
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
} else {
// Não existe na coleção "medicos"
Toast.makeText(LoginActivity.this, "Esta conta não tem acesso à app do Médico.", Toast.LENGTH_LONG).show();
mAuth.signOut();
loginButton.setEnabled(true);
}
} else {
Log.w(TAG, "checkIfMedico:failure", task.getException());
Toast.makeText(LoginActivity.this, "Erro ao validar conta de médico.", Toast.LENGTH_SHORT).show();
loginButton.setEnabled(true);
}
});
}
}

View File

@@ -0,0 +1,161 @@
package com.example.medcuida.pro.ui.auth;
import com.example.medcuida.pro.AgendaActivity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.medcuida.pro.MainActivity;
import com.example.medcuida.pro.R;
import com.example.medcuida.pro.models.Medico;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.FirebaseFirestore;
public class RegisterActivity extends AppCompatActivity {
private static final String TAG = "RegisterActivity";
private TextInputEditText nameEditText, specialtyEditText, emailEditText, passwordEditText;
private AutoCompleteTextView genderAutoComplete;
private MaterialButton registerButton;
private TextView loginLink;
private FirebaseAuth mAuth;
private FirebaseFirestore db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_medico);
// Firebase Init
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
// UI References
nameEditText = findViewById(R.id.name_edit_text);
specialtyEditText = findViewById(R.id.specialty_edit_text);
genderAutoComplete = findViewById(R.id.gender_auto_complete);
emailEditText = findViewById(R.id.email_edit_text);
passwordEditText = findViewById(R.id.password_edit_text);
registerButton = findViewById(R.id.register_button);
loginLink = findViewById(R.id.login_link);
setupGenderDropdown();
registerButton.setOnClickListener(v -> attemptRegister());
loginLink.setOnClickListener(v -> {
startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
finish();
});
}
private void setupGenderDropdown() {
String[] genders = new String[]{"Masculino", "Feminino", "Outro"};
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_dropdown_item_1line,
genders
);
genderAutoComplete.setAdapter(adapter);
}
private void attemptRegister() {
String name = nameEditText.getText() != null ? nameEditText.getText().toString().trim() : "";
String specialty = specialtyEditText.getText() != null ? specialtyEditText.getText().toString().trim() : "";
String gender = genderAutoComplete.getText() != null ? genderAutoComplete.getText().toString().trim() : "";
String email = emailEditText.getText() != null ? emailEditText.getText().toString().trim() : "";
String password = passwordEditText.getText() != null ? passwordEditText.getText().toString().trim() : "";
if (TextUtils.isEmpty(name)) {
nameEditText.setError("O nome é obrigatório");
nameEditText.requestFocus();
return;
}
if (TextUtils.isEmpty(specialty)) {
specialtyEditText.setError("A especialidade é obrigatória");
specialtyEditText.requestFocus();
return;
}
if (TextUtils.isEmpty(gender)) {
genderAutoComplete.setError("O género é obrigatório");
genderAutoComplete.requestFocus();
return;
}
if (TextUtils.isEmpty(email)) {
emailEditText.setError("O Email é obrigatório");
emailEditText.requestFocus();
return;
}
if (TextUtils.isEmpty(password)) {
passwordEditText.setError("A palavra-passe é obrigatória");
passwordEditText.requestFocus();
return;
}
if (password.length() < 6) {
passwordEditText.setError("A palavra-passe deve ter pelo menos 6 caracteres");
passwordEditText.requestFocus();
return;
}
registerUser(name, specialty, gender, email, password);
}
private void registerUser(String name, String specialty, String gender, String email, String password) {
registerButton.setEnabled(false);
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
Log.d(TAG, "createUserWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
saveMedicoData(user.getUid(), name, specialty, gender, email);
}
} else {
Log.w(TAG, "createUserWithEmail:failure", task.getException());
Toast.makeText(RegisterActivity.this, "Falha no registo: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_LONG).show();
registerButton.setEnabled(true);
}
});
}
private void saveMedicoData(String uid, String name, String specialty, String gender, String email) {
Medico medico = new Medico(uid, name, email, specialty, gender);
db.collection("medicos")
.document(uid)
.set(medico)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Log.d(TAG, "saveMedicoData:success");
Toast.makeText(RegisterActivity.this, "Registo efetuado com sucesso!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(RegisterActivity.this, MainActivity.class));
finish();
} else {
Log.e(TAG, "saveMedicoData:failure", task.getException());
Toast.makeText(RegisterActivity.this, "Falha ao guardar dados do médico.", Toast.LENGTH_SHORT).show();
registerButton.setEnabled(true);
}
});
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@android:color/white" />
<foreground android:drawable="@drawable/ic_logo_scaled" />
</adaptive-icon>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#E0E0E0" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="16dp"
android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/colorPrimary" />
<corners
android:bottomLeftRadius="16dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F5F5F5" />
<corners android:radius="24dp" />
<stroke
android:width="1dp"
android:color="#E0E0E0" />
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#40B00020">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<stroke android:width="2dp" android:color="@color/error_color" />
<corners android:radius="8dp" />
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#400066CC">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<stroke android:width="2dp" android:color="@color/primary_color" />
<corners android:radius="8dp" />
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/primary_light_color"/>
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M20,2H4c-1.1,0 -2,0.9 -2,2v18l4,-4h14c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#005B96"
android:pathData="M0,0h108v108h-108z"/>
<path
android:fillColor="#FFFFFF"
android:pathData="M48,30h12v24h24v12h-24v24h-12v-24h-24v-12h24z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_logo" />
</layer-list>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#005B96"
android:pathData="M54,54m-54,0a54,54 0 1,1 108,0a54,54 0 1,1 -108,0"/>
<path
android:fillColor="#FFFFFF"
android:pathData="M48,30h12v24h24v12h-24v24h-12v-24h-24v-12h24z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-35dp"
android:bottom="-35dp"
android:left="-35dp"
android:right="-35dp">
<bitmap
android:src="@drawable/ic_logo"
android:gravity="center" />
</item>
</layer-list>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M19,3h-1L18,1h-2v2L8,3L8,1L6,1v2L5,3c-1.11,0 -1.99,0.9 -1.99,2L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,9h14v10zM7,11h2v2L7,13zM11,11h6v2L11,13zM7,15h2v2L7,17zM11,15h6v2L11,17z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1L21,20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M19,3h-1L18,1h-2v2L8,3L8,1L6,1v2L5,3c-1.11,0 -1.99,0.9 -1.99,2L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,8h14v11zM7,10h5v5L7,15z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#FF000000" android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1c-1.3,0 -2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM12,6c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19c-2.33,0 -4.31,-1.46 -5.11,-3.5 0,-1.66 3.33,-2.5 5.11,-2.5s5.11,0.84 5.11,2.5c-0.8,2.04 -2.78,3.5 -5.11,3.5z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#F5F5F5">
<CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:elevation="4dp"/>
<TextView
android:id="@+id/text_agenda_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Consultas agendadas:"
android:textStyle="bold"
android:padding="16dp"
android:textColor="?attr/colorPrimary"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_agenda"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:paddingHorizontal="8dp"/>
<TextView
android:id="@+id/text_agenda_vazia"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Não tens consultas neste dia."
android:gravity="center"
android:visibility="gone"
android:textColor="#9E9E9E"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="@menu/menu_bottom"
app:labelVisibilityMode="labeled" />
</LinearLayout>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5"
tools:context=".ChatActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_mensagens"
android:layout_width="match_parent"
android:layout_height="0dp"
android:padding="8dp"
android:clipToPadding="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/layout_input" />
<LinearLayout
android:id="@+id/layout_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/white"
android:padding="8dp"
android:elevation="8dp"
android:gravity="center_vertical"
app:layout_constraintBottom_toBottomOf="parent">
<EditText
android:id="@+id/et_mensagem_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Escrever mensagem..."
android:background="@drawable/bg_chat_input"
android:padding="12dp"
android:maxLines="4"
android:inputType="textMultiLine"
android:textSize="16sp" />
<ImageButton
android:id="@+id/btn_enviar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_send"
android:contentDescription="Enviar mensagem"
app:tint="?attr/colorPrimary" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".DetalhePacienteActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/btn_chat_paciente">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<!-- Card Pessoal -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Informação Pessoal"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="?attr/colorPrimary"
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/tv_nome_paciente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome: A carregar..."
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_idade_paciente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Idade: A carregar..."
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_numero_utente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nº Utente: A carregar..."
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_sexo_paciente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sexo: A carregar..."
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_email_paciente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email: A carregar..."
android:textSize="16sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Card Clínica -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medicação Atual"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="?attr/colorPrimary"
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/tv_medicacao_paciente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A carregar medicação..."
android:textSize="16sp"
android:lineSpacingExtra="4dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_chat_paciente"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_margin="24dp"
android:text="Conversar com Paciente"
android:textSize="16sp"
app:icon="@drawable/ic_chat"
app:iconGravity="textStart"
app:cornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="#FAFAFA">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<ImageButton
android:id="@+id/btn_voltar"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_arrow_back"
android:background="?attr/selectableItemBackgroundBorderless"
app:tint="?attr/colorPrimary"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Editar Dados Pessoais"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_specialty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Especialidade"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Sexo">
<AutoCompleteTextView
android:id="@+id/edit_gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="Email (Não editável)"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_guardar_alteracoes"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="GUARDAR ALTERAÇÕES"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="28dp"
app:backgroundTint="#000000"
android:textColor="@color/white"/>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp"
android:background="@color/background_color">
<ImageView
android:layout_width="187dp"
android:layout_height="177dp"
android:layout_marginBottom="24dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_logo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/forgot_password"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Insira o seu email para recuperar a palavra-passe."
android:gravity="center"
android:textSize="16sp"
android:layout_marginBottom="32dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/email_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email_hint"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/reset_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Recuperar Palavra-passe"
android:textSize="16sp"
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/back_to_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Voltar ao Login"
android:textColor="@color/primary_color"
android:textStyle="bold"/>
</LinearLayout>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@color/background_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp">
<ImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginBottom="24dp"
android:contentDescription="@string/app_name"
android:src="@drawable/logo_app" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/surface_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login_title"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/email_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email_hint"
android:autofillHints="emailAddress"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password_hint"
android:autofillHints="password"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkbox_remember_me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Lembrar-me"
android:layout_gravity="start"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="@string/login_button"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/forgot_password_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/forgot_password"
android:textColor="@color/secondary_color"
android:layout_gravity="center_horizontal"
android:padding="8dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_account"
android:textColor="@color/text_secondary"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/register_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/register_title"
android:textStyle="bold"
android:textColor="@color/secondary_color"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,224 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5">
<LinearLayout
android:id="@+id/lay_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:paddingTop="24dp"
android:paddingBottom="16dp"
android:paddingHorizontal="24dp"
android:background="#F5F5F5"
android:elevation="0dp">
<TextView
android:id="@+id/tv_greeting_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Olá, Médico"
android:textSize="26sp"
android:textStyle="bold"
android:textColor="?attr/colorPrimary"/>
</LinearLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/lay_top"
android:layout_above="@id/bottom_navigation">
<!-- AGENDA VIEW -->
<LinearLayout
android:id="@+id/view_agenda"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/surface_color"
android:elevation="2dp" />
<TextView
android:id="@+id/text_agenda_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="As tuas consultas planeadas:"
android:textStyle="bold"
android:textSize="18sp"
android:padding="16dp"
android:textColor="@color/primary_color"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_agenda"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:paddingBottom="16dp" />
<TextView
android:id="@+id/text_agenda_vazia"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="A tua agenda está livre."
android:gravity="center"
android:visibility="gone"
android:textSize="16sp"
android:textColor="@color/text_secondary"/>
</LinearLayout>
<!-- PACIENTES VIEW -->
<LinearLayout
android:id="@+id/view_pacientes"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/text_empty_state"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Nenhuma consulta marcada."
android:gravity="center"
android:visibility="gone"
android:textSize="18sp"
android:textColor="#9E9E9E" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_consultas"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:paddingTop="8dp"
android:paddingBottom="16dp" />
</LinearLayout>
<!-- PERFIL VIEW -->
<LinearLayout
android:id="@+id/view_perfil"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center_horizontal"
android:background="#FAFAFA"
android:visibility="gone">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_user"
android:layout_marginBottom="16dp"
app:tint="#616161"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardElevation="8dp"
app:strokeWidth="0dp"
app:cardCornerRadius="16dp"
app:cardBackgroundColor="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="24dp"
android:paddingBottom="24dp"
android:paddingHorizontal="16dp"
android:gravity="center_horizontal">
<TextView
android:id="@+id/tv_nome_medico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome do Utilizador"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@+id/tv_email_medico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="email@exemplo.com"
android:textColor="#757575"
android:textSize="14sp"
android:layout_marginBottom="16dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E0E0E0"
android:layout_marginBottom="16dp"
android:layout_marginHorizontal="8dp"/>
<TextView
android:id="@+id/tv_especialidade"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Especialidade: --"
android:textColor="#616161"
android:textSize="15sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_cedula"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cédula: --"
android:textColor="#616161"
android:textSize="15sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_editar_dados"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="EDITAR DADOS"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="28dp"
app:backgroundTint="#000000"
android:textColor="@color/white"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="TERMINAR SESSÃO"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="28dp"
app:strokeColor="#D32F2F"
app:strokeWidth="1dp"
app:backgroundTint="@color/white"
android:textColor="#D32F2F"/>
</LinearLayout>
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:menu="@menu/menu_bottom"
app:labelVisibilityMode="labeled" />
</RelativeLayout>

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center_horizontal"
android:background="#FAFAFA">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_user"
android:layout_marginBottom="16dp"
app:tint="#616161"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardElevation="8dp"
app:strokeWidth="0dp"
app:cardCornerRadius="16dp"
app:cardBackgroundColor="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="24dp"
android:paddingBottom="24dp"
android:paddingHorizontal="16dp"
android:gravity="center_horizontal">
<TextView
android:id="@+id/tv_nome_medico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome do Utilizador"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@+id/tv_email_medico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="email@exemplo.com"
android:textColor="#757575"
android:textSize="14sp"
android:layout_marginBottom="16dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E0E0E0"
android:layout_marginBottom="16dp"
android:layout_marginHorizontal="8dp"/>
<TextView
android:id="@+id/tv_especialidade"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Especialidade: --"
android:textColor="#616161"
android:textSize="15sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tv_cedula"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cédula: --"
android:textColor="#616161"
android:textSize="15sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_editar_dados"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="EDITAR DADOS"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="28dp"
app:backgroundTint="#000000"
android:textColor="@color/white"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="TERMINAR SESSÃO"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="28dp"
app:strokeColor="#D32F2F"
app:strokeWidth="1dp"
app:backgroundTint="@color/white"
android:textColor="#D32F2F"/>
</LinearLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="@menu/menu_bottom"
app:labelVisibilityMode="labeled" />
</LinearLayout>

View File

@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@color/background_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginBottom="24dp"
android:contentDescription="@string/app_name"
android:src="@drawable/logo_app" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="4dp"
app:cardBackgroundColor="@color/surface_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/register_title"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/name_hint"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="8dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/age_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/age_hint"
android:maxLength="3"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/utente_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nº Utente"
android:maxLength="9"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Sexo">
<AutoCompleteTextView
android:id="@+id/gender_auto_complete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/email_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email_hint"
android:autofillHints="emailAddress"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password_hint"
android:autofillHints="password"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/register_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="@string/register_button"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/already_account"
android:textColor="@color/text_secondary"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/login_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login_title"
android:textStyle="bold"
android:textColor="@color/secondary_color"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@color/background_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginBottom="24dp"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_logo" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="4dp"
app:cardBackgroundColor="@color/surface_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/register_title"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/name_hint"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/specialty_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Especialidade"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Sexo">
<AutoCompleteTextView
android:id="@+id/gender_auto_complete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/email_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email_hint"
android:autofillHints="emailAddress"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password_hint"
android:autofillHints="password"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/register_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="@string/register_button"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/already_account"
android:textColor="@color/text_secondary"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/login_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login_title"
android:textStyle="bold"
android:textColor="@color/secondary_color"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome do Medicamento"
android:layout_marginBottom="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_med_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapWords" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:text="Horário"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@+id/text_med_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="08:00"
android:textSize="18sp"
android:padding="12dp"
android:background="#E0E0E0"
android:gravity="center"
android:layout_marginBottom="16dp"/>
<TextView
android:text="Via de Administração"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginBottom="4dp"/>
<RadioGroup
android:id="@+id/radio_group_route"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<RadioButton
android:id="@+id/radio_oral"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Via Oral (Pela boca)" />
<RadioButton
android:id="@+id/radio_topical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Via Tópica (Na pele)" />
<RadioButton
android:id="@+id/radio_inhalatory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Via Inalatória (Pelo nariz/boca)" />
</RadioGroup>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Notas (Opcional)"
android:layout_marginBottom="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_med_notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:minLines="2"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alterar Palavra-passe"
android:textSize="20sp"
android:textStyle="bold"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/new_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nova Palavra-passe"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_cancel_password"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancelar"
android:layout_marginEnd="8dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_save_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Salvar" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/edit_profile_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_placeholder"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
android:clickable="true"
android:focusable="true"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_change_photo"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Mudar Foto"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Editar Dados"
android:textSize="20sp"
android:textStyle="bold"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Idade"
android:maxLength="3"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_utente"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nº Utente"
android:maxLength="9"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_change_password"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Alterar Palavra-passe"
android:layout_marginBottom="24dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_cancel"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancelar"
android:layout_marginEnd="8dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Salvar" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_appointments"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="16dp"/>
<!-- Placeholder for RecyclerView -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Futuras"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_appointments_future"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Passadas"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_appointments_past"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:id="@+id/text_greeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Olá, utilizador!"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_next_medication"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/text_greeting">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Próxima Medicação"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/primary_color"/>
<TextView
android:id="@+id/next_med_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Paracetamol 500mg"
android:textSize="16sp"
android:layout_marginTop="8dp"/>
<TextView
android:id="@+id/next_med_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hoje, 14:00"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="4dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_book_appointment"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Marcar Consulta"
android:textSize="16sp"
android:layout_marginTop="24dp"
app:icon="@android:drawable/ic_menu_my_calendar"
app:iconGravity="textStart"
app:layout_constraintTop_toBottomOf="@id/card_next_medication"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_medication"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="16dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_medication"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/text_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/text_empty_medications"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Ainda não tem medicamentos guardados."
android:textSize="16sp"
android:textColor="@color/text_secondary"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/text_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_add_medication"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@android:drawable/ic_input_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:contentDescription="Adicionar Medicamento"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center_horizontal"
android:background="@color/background_color">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/profile_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_placeholder"
android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
android:layout_marginBottom="24dp"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="8dp"
app:cardCornerRadius="24dp"
app:cardBackgroundColor="@color/surface_color"
android:layout_marginBottom="32dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center">
<TextView
android:id="@+id/profile_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome do Utilizador"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/profile_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="email@exemplo.com"
android:textSize="14sp"
android:textColor="@color/text_secondary"
android:layout_marginBottom="24dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E0E0E0"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginBottom="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Idade: "
android:textSize="16sp"
android:textColor="@color/text_secondary"/>
<TextView
android:id="@+id/profile_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/text_primary"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nº Utente: "
android:textSize="16sp"
android:textColor="@color/text_secondary"/>
<TextView
android:id="@+id/profile_utente"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/text_primary"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_edit_profile"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Editar Dados"
android:layout_marginBottom="16dp"
android:backgroundTint="@color/secondary_color"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_logout"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Terminar Sessão"
app:strokeColor="@color/error_color"
android:textColor="@color/error_color"/>
</LinearLayout>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Agendar Consulta"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginBottom="24dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selecionar Data"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selecionar Horário"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_time_slots"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selecionar Médico/Especialidade"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Escolha o médico">
<AutoCompleteTextView
android:id="@+id/spinner_doctor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_reason"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Motivo da Consulta"
android:inputType="textMultiLine"
android:minLines="2"
android:maxLines="4"/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btn_confirm_appointment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Confirmar Agendamento"/>
</LinearLayout>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_sns24"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="32dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_call_sns"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="Ligar SNS 24 (808 24 24 24)"
android:textSize="18sp"
android:backgroundTint="@color/teal_700"
app:icon="@android:drawable/ic_menu_call"
app:iconGravity="textStart"
android:layout_marginBottom="32dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#CCCCCC"
android:layout_marginBottom="24dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Triagem com Inteligência Artificial"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="16dp"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Descreva o que está a sentir..."
android:layout_marginBottom="16dp"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/input_symptoms"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences|textMultiLine"
android:minLines="3"
android:gravity="top|start"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_ai_triage"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Analisar Sintomas"
android:textSize="16sp"
app:cornerRadius="8dp"
android:layout_marginBottom="24dp"/>
<TextView
android:id="@+id/text_ai_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@android:color/black"
android:padding="16dp"
android:background="#F5F5F5"
android:visibility="gone"
android:layout_marginBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_find_hospital"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Hospital mais próximo"
android:textSize="16sp"
android:backgroundTint="@android:color/holo_red_dark"
app:icon="@android:drawable/ic_menu_mapmode"
app:cornerRadius="8dp"
android:visibility="gone"/>
</LinearLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="16dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/text_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tipo de Consulta"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/primary_color"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp">
<TextView
android:id="@+id/text_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dd/MM/yyyy"
android:layout_marginEnd="16dp"/>
<TextView
android:id="@+id/text_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HH:mm"
android:textStyle="italic"/>
</LinearLayout>
<TextView
android:id="@+id/text_reason"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Motivo: --"
android:textSize="14sp"
android:textColor="@color/text_secondary"
android:layout_marginTop="8dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E5E7EB"
app:cardBackgroundColor="@color/surface_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="56dp"
android:layout_height="56dp"
android:padding="12dp"
android:background="@drawable/circle_bg"
android:src="@drawable/ic_user"
app:tint="@color/primary_color"
android:contentDescription="Foto do utente"
android:layout_marginEnd="16dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text_paciente_nome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Nome do Paciente"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/text_primary" />
<TextView
android:id="@+id/text_consulta_data_hora"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Data e Hora"
android:textSize="14sp"
android:layout_marginTop="2dp"
android:textColor="@color/text_secondary" />
<TextView
android:id="@+id/text_consulta_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Pendente"
android:textSize="13sp"
android:layout_marginTop="4dp"
android:textColor="@color/primary_color"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp"
android:weightSum="2">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_cancelar"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:textColor="@color/error_color"
app:strokeColor="@color/error_color"
android:text="Cancelar" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_confirmar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="Confirmar" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="16dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@android:drawable/ic_menu_agenda"
app:tint="@color/secondary_color"
android:layout_marginEnd="16dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/text_med_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome Medicamento"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/primary_color"/>
<TextView
android:id="@+id/text_med_dosage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dosagem"
android:layout_marginTop="4dp"/>
<TextView
android:id="@+id/text_med_notes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Observações"
android:textStyle="italic"
android:textSize="12sp"
android:layout_marginTop="2dp"/>
</LinearLayout>
<TextView
android:id="@+id/text_med_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HH:mm"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginEnd="16dp"/>
<CheckBox
android:id="@+id/checkbox_taken"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="@color/primary_color"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dp">
<!-- Mensagem Recebida (Paciente) -->
<LinearLayout
android:id="@+id/layout_msg_recebida"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:visibility="gone">
<TextView
android:id="@+id/tv_msg_recebida"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_bubble_receive"
android:textColor="@color/black"
android:padding="12dp"
android:textSize="16sp"
android:maxWidth="280dp"
android:text="Mensagem que recebi do paciente" />
</LinearLayout>
<!-- Mensagem Enviada (Médico) -->
<LinearLayout
android:id="@+id/layout_msg_enviada"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:visibility="visible">
<TextView
android:id="@+id/tv_msg_enviada"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_bubble_send"
android:textColor="@color/white"
android:padding="12dp"
android:textSize="16sp"
android:maxWidth="280dp"
android:text="Mensagem que eu enviei" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.button.MaterialButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_time_slot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="09:00"
android:checkable="true"
android:layout_margin="4dp"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@android:drawable/ic_menu_today"
android:title="@string/title_home" />
<item
android:id="@+id/navigation_appointments"
android:icon="@android:drawable/ic_menu_my_calendar"
android:title="@string/title_appointments" />
<item
android:id="@+id/navigation_medication"
android:icon="@android:drawable/ic_menu_agenda"
android:title="@string/title_medication" />
<item
android:id="@+id/navigation_sns24"
android:icon="@android:drawable/ic_menu_call"
android:title="@string/title_sns24" />
<item
android:id="@+id/navigation_profile"
android:icon="@android:drawable/ic_menu_myplaces"
android:title="@string/title_profile" />
</menu>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/nav_pacientes"
android:icon="@drawable/ic_nav_pacientes"
android:title="Pacientes" />
<item
android:id="@+id/nav_agenda"
android:icon="@drawable/ic_nav_agenda"
android:title="Agenda" />
<item
android:id="@+id/nav_perfil"
android:icon="@drawable/ic_user"
android:title="Perfil" />
</menu>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_home">
<fragment
android:id="@+id/navigation_home"
android:name="com.example.medcuida.pro.ui.home.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_home_to_schedule_appointment"
app:destination="@id/navigation_schedule_appointment" />
</fragment>
<fragment
android:id="@+id/navigation_appointments"
android:name="com.example.medcuida.pro.ui.appointments.AppointmentsFragment"
android:label="@string/title_appointments"
tools:layout="@layout/fragment_appointments">
<action
android:id="@+id/action_appointments_to_schedule"
app:destination="@id/navigation_schedule_appointment" />
</fragment>
<fragment
android:id="@+id/navigation_medication"
android:name="com.example.medcuida.pro.ui.medication.MedicationFragment"
android:label="@string/title_medication"
tools:layout="@layout/fragment_medication" />
<fragment
android:id="@+id/navigation_sns24"
android:name="com.example.medcuida.pro.ui.sns24.Sns24Fragment"
android:label="@string/title_sns24"
tools:layout="@layout/fragment_sns24" />
<fragment
android:id="@+id/navigation_profile"
android:name="com.example.medcuida.pro.ui.profile.ProfileFragment"
android:label="@string/title_profile"
tools:layout="@layout/fragment_profile" />
<fragment
android:id="@+id/navigation_schedule_appointment"
android:name="com.example.medcuida.pro.ui.schedule.ScheduleAppointmentFragment"
android:label="Agendar Consulta"
tools:layout="@layout/fragment_schedule_appointment" />
</navigation>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App Brand Colors -->
<color name="primary_color">#0275D8</color> <!-- Modern Clean Blue -->
<color name="primary_light_color">#E5F2FC</color>
<color name="primary_dark_color">#01579B</color>
<color name="secondary_color">#0056B3</color> <!-- Deep Bright Blue -->
<color name="secondary_dark_color">#004085</color>
<color name="background_color">#F4F6F8</color> <!-- Clean Light Grey/Off-White -->
<color name="surface_color">#FFFFFF</color>
<color name="text_primary">#1F2937</color> <!-- Deep Slate -->
<color name="text_secondary">#6B7280</color> <!-- Soft Slate -->
<color name="error_color">#EF4444</color> <!-- Modern Red -->
<!-- Standard overrides -->
<color name="purple_200">#90CAF9</color>
<color name="purple_500">#0275D8</color>
<color name="purple_700">#01579B</color>
<color name="teal_200">#03A9F4</color>
<color name="teal_700">#0056B3</color>
<color name="black">#000000</color>
<color name="white">#FFFFFF</color>
</resources>

View File

@@ -0,0 +1,21 @@
<resources>
<string name="app_name">Cuida</string>
<string name="title_home">Início</string>
<string name="title_appointments">Consultas</string>
<string name="title_medication">Medicação</string>
<string name="title_sns24">SNS 24</string>
<string name="title_profile">Perfil</string>
<!-- Auth -->
<string name="login_title">Iniciar Sessão</string>
<string name="register_title">Criar Conta</string>
<string name="forgot_password">Esqueci-me da Palavra-passe</string>
<string name="email_hint">Email</string>
<string name="password_hint">Palavra-passe</string>
<string name="name_hint">Nome Completo</string>
<string name="age_hint">Idade</string>
<string name="login_button">Entrar</string>
<string name="register_button">Registar</string>
<string name="no_account">Não tem conta?</string>
<string name="already_account">Já tem conta?</string>
</resources>

View File

@@ -0,0 +1,40 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Cuida" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryVariant">@color/primary_dark_color</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/secondary_color</item>
<item name="colorSecondaryVariant">@color/secondary_dark_color</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<item name="android:windowLightStatusBar">false</item>
<!-- Button Style -->
<item name="materialButtonStyle">@style/Widget.Cuida.Button</item>
<!-- Card Style -->
<item name="materialCardViewStyle">@style/Widget.Cuida.CardView</item>
</style>
<style name="Widget.Cuida.Button" parent="Widget.MaterialComponents.Button">
<item name="cornerRadius">100dp</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingBottom">12dp</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="Widget.Cuida.CardView" parent="Widget.MaterialComponents.CardView">
<item name="cardCornerRadius">24dp</item>
<item name="cardElevation">0dp</item>
<item name="strokeWidth">1dp</item>
<item name="strokeColor">#E0E0E0</item>
<item name="cardBackgroundColor">@color/surface_color</item>
</style>
<style name="ShapeAppearanceOverlay.App.CornerSize50Percent" parent="">
<item name="cornerSize">50%</item>
</style>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include domain="sharedpref" path="."/>
<include domain="database" path="."/>
</full-backup-content>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<include domain="sharedpref" path="."/>
<include domain="database" path="."/>
</cloud-backup>
<device-transfer>
<include domain="sharedpref" path="."/>
<include domain="database" path="."/>
</device-transfer>
</data-extraction-rules>