diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4b0d8f9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/GuilhermesApp/bin
+/GuilhermesApp/obj
diff --git a/GuilhermesApp/App.xaml b/GuilhermesApp/App.xaml
new file mode 100644
index 0000000..199fa79
--- /dev/null
+++ b/GuilhermesApp/App.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GuilhermesApp/App.xaml.cs b/GuilhermesApp/App.xaml.cs
new file mode 100644
index 0000000..9659b0a
--- /dev/null
+++ b/GuilhermesApp/App.xaml.cs
@@ -0,0 +1,14 @@
+namespace GuilhermesApp;
+
+public partial class App : Application
+{
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override Window CreateWindow(IActivationState? activationState)
+ {
+ return new Window(new AppShell());
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/AppShell.xaml b/GuilhermesApp/AppShell.xaml
new file mode 100644
index 0000000..4497d1e
--- /dev/null
+++ b/GuilhermesApp/AppShell.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/AppShell.xaml.cs b/GuilhermesApp/AppShell.xaml.cs
new file mode 100644
index 0000000..da6bf6e
--- /dev/null
+++ b/GuilhermesApp/AppShell.xaml.cs
@@ -0,0 +1,18 @@
+using GuilhermesApp.Pages;
+
+namespace GuilhermesApp;
+
+public partial class AppShell : Shell
+{
+ public AppShell()
+ {
+ InitializeComponent();
+
+ // Registar rotas para navegação
+ Routing.RegisterRoute(nameof(RegisterPage), typeof(RegisterPage));
+ Routing.RegisterRoute(nameof(ProfilePage), typeof(ProfilePage));
+ Routing.RegisterRoute(nameof(FormsHistoryPage), typeof(FormsHistoryPage));
+ Routing.RegisterRoute(nameof(NewFormPage), typeof(NewFormPage));
+ Routing.RegisterRoute(nameof(FormsMenuPage), typeof(FormsMenuPage));
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/GuilhermesApp.csproj b/GuilhermesApp/GuilhermesApp.csproj
new file mode 100644
index 0000000..964aedb
--- /dev/null
+++ b/GuilhermesApp/GuilhermesApp.csproj
@@ -0,0 +1,72 @@
+
+
+
+ true
+
+ net9.0-android;net9.0-ios;net9.0-maccatalyst
+ $(TargetFrameworks);net9.0-windows10.0.19041.0
+
+
+
+
+
+
+ Exe
+ GuilhermesApp
+ true
+ true
+ enable
+ enable
+
+
+ GuilhermesApp
+
+
+ com.companyname.guilhermesapp
+
+
+ 1.0
+ 1
+
+
+ None
+
+ 15.0
+ 15.0
+ 21.0
+ 10.0.17763.0
+ 10.0.17763.0
+ 6.5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GuilhermesApp/GuilhermesApp.csproj.user b/GuilhermesApp/GuilhermesApp.csproj.user
new file mode 100644
index 0000000..09e70e1
--- /dev/null
+++ b/GuilhermesApp/GuilhermesApp.csproj.user
@@ -0,0 +1,6 @@
+
+
+
+ net9.0-windows10.0.19041.0
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/GuilhermesApp.sln b/GuilhermesApp/GuilhermesApp.sln
new file mode 100644
index 0000000..d0d3ba0
--- /dev/null
+++ b/GuilhermesApp/GuilhermesApp.sln
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuilhermesApp", "GuilhermesApp.csproj", "{375AEA15-E9B8-87B0-1ED4-3F429D79CEA1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {375AEA15-E9B8-87B0-1ED4-3F429D79CEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {375AEA15-E9B8-87B0-1ED4-3F429D79CEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {375AEA15-E9B8-87B0-1ED4-3F429D79CEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {375AEA15-E9B8-87B0-1ED4-3F429D79CEA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {478009F4-C3B4-4F0D-AD10-73A3DE68D439}
+ EndGlobalSection
+EndGlobal
diff --git a/GuilhermesApp/Helpers/FirebaseService.cs b/GuilhermesApp/Helpers/FirebaseService.cs
new file mode 100644
index 0000000..5603f92
--- /dev/null
+++ b/GuilhermesApp/Helpers/FirebaseService.cs
@@ -0,0 +1,27 @@
+using Firebase.Auth;
+using Firebase.Auth.Providers;
+using Firebase.Database;
+
+namespace GuilhermesApp.Helpers;
+
+public class FirebaseService
+{
+ private const string WebApiKey = "AIzaSyBU367GLutI5FiXf5JvrwIMWu0jJoDGl9k";
+ private const string DatabaseUrl = "https://guilhermesapp-default-rtdb.europe-west1.firebasedatabase.app/";
+
+ public FirebaseAuthClient AuthClient { get; private set; }
+ public FirebaseClient DbClient { get; private set; }
+
+ public FirebaseService()
+ {
+ var config = new FirebaseAuthConfig
+ {
+ ApiKey = WebApiKey,
+ AuthDomain = "guilhermesapp.firebaseapp.com",
+ Providers = new FirebaseAuthProvider[] { new EmailProvider() }
+ };
+
+ AuthClient = new FirebaseAuthClient(config);
+ DbClient = new FirebaseClient(DatabaseUrl);
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/MainPage.xaml b/GuilhermesApp/MainPage.xaml
new file mode 100644
index 0000000..52244cd
--- /dev/null
+++ b/GuilhermesApp/MainPage.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GuilhermesApp/MainPage.xaml.cs b/GuilhermesApp/MainPage.xaml.cs
new file mode 100644
index 0000000..9c36910
--- /dev/null
+++ b/GuilhermesApp/MainPage.xaml.cs
@@ -0,0 +1,23 @@
+namespace GuilhermesApp;
+
+public partial class MainPage : ContentPage
+{
+ int count = 0;
+
+ public MainPage()
+ {
+ InitializeComponent();
+ }
+
+ private void OnCounterClicked(object? sender, EventArgs e)
+ {
+ count++;
+
+ if (count == 1)
+ CounterBtn.Text = $"Clicked {count} time";
+ else
+ CounterBtn.Text = $"Clicked {count} times";
+
+ SemanticScreenReader.Announce(CounterBtn.Text);
+ }
+}
diff --git a/GuilhermesApp/MauiProgram.cs b/GuilhermesApp/MauiProgram.cs
new file mode 100644
index 0000000..18dc9ba
--- /dev/null
+++ b/GuilhermesApp/MauiProgram.cs
@@ -0,0 +1,24 @@
+using Microsoft.Extensions.Logging;
+
+namespace GuilhermesApp;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+}
diff --git a/GuilhermesApp/Pages/ChatPage.xaml b/GuilhermesApp/Pages/ChatPage.xaml
new file mode 100644
index 0000000..b920074
--- /dev/null
+++ b/GuilhermesApp/Pages/ChatPage.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/ChatPage.xaml.cs b/GuilhermesApp/Pages/ChatPage.xaml.cs
new file mode 100644
index 0000000..2224dd2
--- /dev/null
+++ b/GuilhermesApp/Pages/ChatPage.xaml.cs
@@ -0,0 +1,94 @@
+using System.Text;
+using System.Text.Json;
+using Microsoft.Maui.Controls.Shapes;
+
+namespace GuilhermesApp.Pages;
+
+public partial class ChatPage : ContentPage
+{
+ private const string ApiKey = "AIzaSyBfQIHWK57GDhk4N-xYg_bEVWyQ6X1EmwA";
+ private const string Url = $"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={ApiKey}";
+ private HttpClient _httpClient = new HttpClient();
+
+ public ChatPage()
+ {
+ InitializeComponent();
+ AdicionarBalao("Olá! Sou o assistente da GuilhermesApp. Como te posso ajudar hoje?", false);
+ }
+
+ private async void OnEnviarClicked(object sender, EventArgs e)
+ {
+ if (string.IsNullOrWhiteSpace(MensagemEntry.Text)) return;
+
+ string textoUser = MensagemEntry.Text;
+ MensagemEntry.Text = "";
+ AdicionarBalao(textoUser, true);
+
+ EnviarBtn.IsEnabled = false;
+
+ try
+ {
+ var requestBody = new { contents = new[] { new { parts = new[] { new { text = textoUser } } } } };
+ var content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json");
+
+ var response = await _httpClient.PostAsync(Url, content);
+ var json = await response.Content.ReadAsStringAsync();
+
+ using var doc = JsonDocument.Parse(json);
+
+ // Verifica se o pedido teve sucesso
+ if (response.IsSuccessStatusCode)
+ {
+ var respostaBot = doc.RootElement
+ .GetProperty("candidates")[0]
+ .GetProperty("content")
+ .GetProperty("parts")[0]
+ .GetProperty("text").GetString();
+
+ AdicionarBalao(respostaBot, false);
+ }
+ else
+ {
+ // Lê a mensagem de erro real da Google
+ string erroGoogle = "Erro desconhecido.";
+ if (doc.RootElement.TryGetProperty("error", out var errorElement) &&
+ errorElement.TryGetProperty("message", out var msgElement))
+ {
+ erroGoogle = msgElement.GetString() ?? "Erro desconhecido";
+ }
+ AdicionarBalao($"A API recusou: {erroGoogle}", false);
+ }
+ }
+ catch (Exception ex)
+ {
+ AdicionarBalao($"Erro interno: {ex.Message}", false);
+ }
+
+ EnviarBtn.IsEnabled = true;
+ }
+ // Cria os balões visuais
+ private void AdicionarBalao(string? texto, bool isUser)
+ {
+ var label = new Label
+ {
+ Text = texto,
+ TextColor = Colors.Black,
+ Padding = 15
+ };
+
+ var border = new Border
+ {
+ StrokeShape = new RoundRectangle { CornerRadius = new CornerRadius(15) },
+ BackgroundColor = isUser ? Color.FromArgb("#D1E8FF") : Color.FromArgb("#F3F4F6"),
+ Stroke = Colors.Transparent,
+ Margin = new Thickness(isUser ? 50 : 0, 5, isUser ? 0 : 50, 5),
+ HorizontalOptions = isUser ? LayoutOptions.End : LayoutOptions.Start,
+ Content = label
+ };
+
+ ChatStack.Children.Add(border);
+
+ // Faz scroll automático para o fundo
+ ChatScroll.ScrollToAsync(ChatStack, ScrollToPosition.End, true);
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/FormsHistoryPage.xaml b/GuilhermesApp/Pages/FormsHistoryPage.xaml
new file mode 100644
index 0000000..7ffcd7d
--- /dev/null
+++ b/GuilhermesApp/Pages/FormsHistoryPage.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/FormsHistoryPage.xaml.cs b/GuilhermesApp/Pages/FormsHistoryPage.xaml.cs
new file mode 100644
index 0000000..396c76d
--- /dev/null
+++ b/GuilhermesApp/Pages/FormsHistoryPage.xaml.cs
@@ -0,0 +1,83 @@
+using GuilhermesApp.Helpers;
+using Firebase.Database.Query;
+
+namespace GuilhermesApp.Pages;
+
+public partial class FormsHistoryPage : ContentPage
+{
+ private FirebaseService _firebaseService = new FirebaseService();
+
+ public FormsHistoryPage()
+ {
+ InitializeComponent();
+ }
+
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+ await CarregarHistorico();
+ }
+
+ private async Task CarregarHistorico()
+ {
+ try
+ {
+ var user = _firebaseService.AuthClient.User;
+ if (user == null) return;
+
+ // Vai buscar todos os registos na pasta Forms do utilizador
+ var forms = await _firebaseService.DbClient
+ .Child("Forms")
+ .Child(user.Uid)
+ .OnceAsync();
+
+ LoadingIndicator.IsRunning = false;
+ LoadingIndicator.IsVisible = false;
+
+ if (forms.Count == 0)
+ {
+ EmptyLabel.IsVisible = true;
+ }
+ else
+ {
+ // Converte os dados, inverte a ordem (para o mais recente ficar no topo) e mostra na lista
+ var listaOrdenada = forms.Select(f => f.Object).Reverse().ToList();
+ FormsCollection.ItemsSource = listaOrdenada;
+ FormsCollection.IsVisible = true;
+ }
+ }
+ catch (Exception)
+ {
+ LoadingIndicator.IsRunning = false;
+ LoadingIndicator.IsVisible = false;
+ await DisplayAlert("Erro", "Não foi possível carregar o histórico.", "OK");
+ }
+ }
+
+ private async void OnFormSelected(object sender, SelectionChangedEventArgs e)
+ {
+ if (e.CurrentSelection.FirstOrDefault() is FormResult form)
+ {
+ string exercicio = form.FezExercicio ? "Sim" : "Não";
+ string mensagem = $"Humor: {form.Humor}\nStress: {form.Stress}/10\nSono: {form.Sono}\nExercício: {exercicio}\nNotas: {form.Notas}";
+
+ await DisplayAlert($"Detalhes de {form.Data}", mensagem, "Fechar");
+
+ // Limpa a seleção para permitir clicar novamente no mesmo
+ ((CollectionView)sender).SelectedItem = null;
+ }
+ }
+}
+
+
+
+// Classe de apoio para mapear os dados do Firebase
+public class FormResult
+{
+ public string? Data { get; set; }
+ public string? Humor { get; set; }
+ public double Stress { get; set; }
+ public string? Sono { get; set; }
+ public bool FezExercicio { get; set; }
+ public string? Notas { get; set; }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/FormsMenuPage.xaml b/GuilhermesApp/Pages/FormsMenuPage.xaml
new file mode 100644
index 0000000..ae9f691
--- /dev/null
+++ b/GuilhermesApp/Pages/FormsMenuPage.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/FormsMenuPage.xaml.cs b/GuilhermesApp/Pages/FormsMenuPage.xaml.cs
new file mode 100644
index 0000000..add8ec7
--- /dev/null
+++ b/GuilhermesApp/Pages/FormsMenuPage.xaml.cs
@@ -0,0 +1,19 @@
+namespace GuilhermesApp.Pages;
+
+public partial class FormsMenuPage : ContentPage
+{
+ public FormsMenuPage()
+ {
+ InitializeComponent();
+ }
+
+ private async void OnNewFormClicked(object sender, EventArgs e)
+ {
+ await Shell.Current.GoToAsync(nameof(NewFormPage));
+ }
+
+ private async void OnHistoryClicked(object sender, EventArgs e)
+ {
+ await Shell.Current.GoToAsync(nameof(FormsHistoryPage));
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/LoginPage.xaml b/GuilhermesApp/Pages/LoginPage.xaml
new file mode 100644
index 0000000..6ebef99
--- /dev/null
+++ b/GuilhermesApp/Pages/LoginPage.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/LoginPage.xaml.cs b/GuilhermesApp/Pages/LoginPage.xaml.cs
new file mode 100644
index 0000000..6f029ba
--- /dev/null
+++ b/GuilhermesApp/Pages/LoginPage.xaml.cs
@@ -0,0 +1,42 @@
+using GuilhermesApp.Helpers;
+
+namespace GuilhermesApp.Pages;
+
+public partial class LoginPage : ContentPage
+{
+ private FirebaseService _firebaseService = new FirebaseService();
+
+ public LoginPage()
+ {
+ InitializeComponent();
+ }
+
+ private async void OnLoginClicked(object sender, EventArgs e)
+ {
+ if (string.IsNullOrWhiteSpace(EmailEntry.Text) || string.IsNullOrWhiteSpace(PasswordEntry.Text))
+ {
+ await DisplayAlert("Erro", "Preenche o email e a password.", "OK");
+ return;
+ }
+
+ try
+ {
+ // Tenta fazer o login no Firebase
+ var user = await _firebaseService.AuthClient.SignInWithEmailAndPasswordAsync(EmailEntry.Text, PasswordEntry.Text);
+
+ // Se correr bem, vai para a página de Perfil
+ // O "//" define a HomePage como a nova raiz e impede de voltar atrás
+ await Shell.Current.GoToAsync("//MainTabs");
+ }
+ catch (Exception)
+ {
+ await DisplayAlert("Erro", "Login falhou. Verifica as credenciais.", "OK");
+ }
+ }
+
+ private async void OnRegisterClicked(object sender, EventArgs e)
+ {
+ // Vai para a página de registo
+ await Shell.Current.GoToAsync(nameof(RegisterPage));
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/NewFormPage.xaml b/GuilhermesApp/Pages/NewFormPage.xaml
new file mode 100644
index 0000000..0bb042a
--- /dev/null
+++ b/GuilhermesApp/Pages/NewFormPage.xaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Muito Bem
+ Bem
+ Neutro
+ Mal
+ Muito Mal
+
+
+
+
+
+
+
+
+
+
+
+
+ Sim, perfeitamente
+ Mais ou menos
+ Não, dormi mal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/NewFormPage.xaml.cs b/GuilhermesApp/Pages/NewFormPage.xaml.cs
new file mode 100644
index 0000000..859b306
--- /dev/null
+++ b/GuilhermesApp/Pages/NewFormPage.xaml.cs
@@ -0,0 +1,56 @@
+using GuilhermesApp.Helpers;
+using Firebase.Database.Query;
+
+namespace GuilhermesApp.Pages;
+
+public partial class NewFormPage : ContentPage
+{
+ private FirebaseService _firebaseService = new FirebaseService();
+
+ public NewFormPage()
+ {
+ InitializeComponent();
+ }
+
+ private async void OnSubmitClicked(object sender, EventArgs e)
+ {
+ // Obriga a responder a algumas
+ if (HumorPicker.SelectedIndex == -1 || SonoPicker.SelectedIndex == -1)
+ {
+ await DisplayAlert("Erro", "Responde pelo menos às perguntas de humor e sono.", "OK");
+ return;
+ }
+
+ try
+ {
+ var user = _firebaseService.AuthClient.User;
+ if (user == null) return;
+
+ // Prepara os dados do formulário
+ var novoFormulario = new
+ {
+ Data = DateTime.Now.ToString("dd/MM/yyyy HH:mm"),
+ Humor = HumorPicker.SelectedItem.ToString(),
+ Stress = Math.Round(StressSlider.Value),
+ Sono = SonoPicker.SelectedItem.ToString(),
+ FezExercicio = ExercicioSwitch.IsToggled,
+ Notas = string.IsNullOrWhiteSpace(NotasEntry.Text) ? "Sem notas" : NotasEntry.Text
+ };
+
+ // Guarda na Realtime Database na pasta "Forms" -> "ID do Utilizador"
+ await _firebaseService.DbClient
+ .Child("Forms")
+ .Child(user.Uid)
+ .PostAsync(novoFormulario); // PostAsync cria um novo registo na lista
+
+ await DisplayAlert("Sucesso", "Formulário submetido e guardado!", "OK");
+
+ // Volta à página anterior
+ await Shell.Current.GoToAsync("..");
+ }
+ catch (Exception ex)
+ {
+ await DisplayAlert("Erro", $"Não foi possível guardar. Erro: {ex.Message}", "OK");
+ }
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/ProfilePage.xaml b/GuilhermesApp/Pages/ProfilePage.xaml
new file mode 100644
index 0000000..526738a
--- /dev/null
+++ b/GuilhermesApp/Pages/ProfilePage.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/ProfilePage.xaml.cs b/GuilhermesApp/Pages/ProfilePage.xaml.cs
new file mode 100644
index 0000000..154ee54
--- /dev/null
+++ b/GuilhermesApp/Pages/ProfilePage.xaml.cs
@@ -0,0 +1,70 @@
+using GuilhermesApp.Helpers;
+using Firebase.Database.Query;
+
+namespace GuilhermesApp.Pages;
+
+public partial class ProfilePage : ContentPage
+{
+ private FirebaseService _firebaseService = new FirebaseService();
+
+ public ProfilePage()
+ {
+ InitializeComponent();
+ }
+
+ // Este método corre sempre que a página aparece no ecrã
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+ await CarregarPerfil();
+ }
+
+ private async Task CarregarPerfil()
+ {
+ try
+ {
+ var user = _firebaseService.AuthClient.User;
+ if (user != null)
+ {
+ // Vai buscar os dados à Realtime Database
+ var perfil = await _firebaseService.DbClient
+ .Child("Users")
+ .Child(user.Uid)
+ .OnceSingleAsync();
+
+ if (perfil != null)
+ {
+ NomeLabel.Text = perfil.Nome;
+ EmailLabel.Text = perfil.Email;
+ TelemovelLabel.Text = $"Telemóvel: {perfil.Telemovel}";
+ GeneroLabel.Text = $"Género: {perfil.Genero}";
+
+ // Esconde o loading e mostra os dados
+ LoadingIndicator.IsRunning = false;
+ LoadingIndicator.IsVisible = false;
+ ProfileInfoLayout.IsVisible = true;
+ }
+ }
+ }
+ catch (Exception)
+ {
+ await DisplayAlert("Erro", "Não foi possível carregar o perfil.", "OK");
+ }
+ }
+
+ private async void OnLogoutClicked(object sender, EventArgs e)
+ {
+ _firebaseService.AuthClient.SignOut();
+ // Volta para o Login e limpa o histórico
+ await Shell.Current.GoToAsync("//LoginPage");
+ }
+}
+
+// Classe simples no final do ficheiro para ajudar a ler os dados do Firebase
+public class UserProfile
+{
+ public string? Nome { get; set; }
+ public string? Email { get; set; }
+ public string? Telemovel { get; set; }
+ public string? Genero { get; set; }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/RegisterPage.xaml b/GuilhermesApp/Pages/RegisterPage.xaml
new file mode 100644
index 0000000..31c60eb
--- /dev/null
+++ b/GuilhermesApp/Pages/RegisterPage.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Masculino
+ Feminino
+ Outro
+ Prefiro não dizer
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/RegisterPage.xaml.cs b/GuilhermesApp/Pages/RegisterPage.xaml.cs
new file mode 100644
index 0000000..d10b110
--- /dev/null
+++ b/GuilhermesApp/Pages/RegisterPage.xaml.cs
@@ -0,0 +1,68 @@
+using GuilhermesApp.Helpers;
+using Firebase.Database.Query;
+
+namespace GuilhermesApp.Pages;
+
+public partial class RegisterPage : ContentPage
+{
+ private FirebaseService _firebaseService = new FirebaseService();
+
+ public RegisterPage()
+ {
+ InitializeComponent();
+ }
+
+ private async void OnRegisterAccountClicked(object sender, EventArgs e)
+ {
+ // 1. Validar se está tudo preenchido
+ if (string.IsNullOrWhiteSpace(NomeEntry.Text) || string.IsNullOrWhiteSpace(TelemovelEntry.Text) ||
+ GeneroPicker.SelectedIndex == -1 || string.IsNullOrWhiteSpace(EmailEntry.Text) ||
+ string.IsNullOrWhiteSpace(PasswordEntry.Text))
+ {
+ await DisplayAlert("Erro", "Preenche todos os campos.", "OK");
+ return;
+ }
+
+ // 2. Validar passwords
+ if (PasswordEntry.Text != ConfirmPasswordEntry.Text)
+ {
+ await DisplayAlert("Erro", "As passwords não coincidem.", "OK");
+ return;
+ }
+
+ if (PasswordEntry.Text.Length < 6)
+ {
+ await DisplayAlert("Erro", "A password tem de ter pelo menos 6 caracteres.", "OK");
+ return;
+ }
+
+ try
+ {
+ // 3. Cria a conta na Autenticação
+ var userCredential = await _firebaseService.AuthClient.CreateUserWithEmailAndPasswordAsync(EmailEntry.Text, PasswordEntry.Text);
+ var uid = userCredential.User.Uid; // O ID único do utilizador
+
+ // 4. Guarda os restantes dados na Realtime Database, na pasta "Users"
+ await _firebaseService.DbClient
+ .Child("Users")
+ .Child(uid)
+ .PutAsync(new
+ {
+ Nome = NomeEntry.Text,
+ Telemovel = TelemovelEntry.Text,
+ Genero = GeneroPicker.SelectedItem.ToString(),
+ Email = EmailEntry.Text
+ });
+
+ await DisplayAlert("Sucesso", "Conta criada com sucesso!", "OK");
+
+ // Volta para a página de Login
+ await Shell.Current.GoToAsync("..");
+ }
+ catch (Exception ex)
+ {
+ // Mostra o erro exato que vem do Firebase
+ await DisplayAlert("Erro", $"Não foi possível criar a conta. Detalhe: {ex.Message}", "OK");
+ }
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/SensorPage.xaml b/GuilhermesApp/Pages/SensorPage.xaml
new file mode 100644
index 0000000..b6c9485
--- /dev/null
+++ b/GuilhermesApp/Pages/SensorPage.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Pages/SensorPage.xaml.cs b/GuilhermesApp/Pages/SensorPage.xaml.cs
new file mode 100644
index 0000000..10f6664
--- /dev/null
+++ b/GuilhermesApp/Pages/SensorPage.xaml.cs
@@ -0,0 +1,83 @@
+using MQTTnet;
+using System.Text;
+using System.Buffers;
+
+namespace GuilhermesApp.Pages;
+
+public partial class SensorPage : ContentPage
+{
+ private IMqttClient? _mqttClient;
+ private MqttClientOptions? _options;
+ private bool _isLedOn = false;
+
+ public SensorPage()
+ {
+ InitializeComponent();
+ ConfigurarMqtt();
+ }
+
+ private async void ConfigurarMqtt()
+ {
+ try
+ {
+ // TENTATIVA A: MqttClientFactory (Novo padrão em algumas versões v5)
+ // Se der erro aqui, tenta mudar para: var factory = new MqttFactory();
+ var factory = new MqttClientFactory();
+ _mqttClient = factory.CreateMqttClient();
+
+ _options = new MqttClientOptionsBuilder()
+ .WithTcpServer("broker.hivemq.com", 1883)
+ .Build();
+
+ _mqttClient.ApplicationMessageReceivedAsync += e =>
+ {
+ // Extração manual de bytes para evitar o erro do ToArray
+ var buffer = e.ApplicationMessage.Payload;
+ byte[] payloadBytes = new byte[buffer.Length];
+ buffer.CopyTo(payloadBytes);
+
+ string payload = Encoding.UTF8.GetString(payloadBytes);
+
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ if (payload == "PRESSIONADO")
+ {
+ StatusLabel.Text = $"Último clique: {DateTime.Now:HH:mm:ss}";
+ StatusLabel.TextColor = Colors.Green;
+ }
+ });
+
+ return Task.CompletedTask;
+ };
+
+ await _mqttClient.ConnectAsync(_options);
+ await _mqttClient.SubscribeAsync("guilherme/app/botao");
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"Erro crítico MQTT: {ex.Message}");
+ }
+ }
+
+ private async void OnLedClicked(object sender, EventArgs e)
+ {
+ if (_mqttClient == null || !_mqttClient.IsConnected)
+ {
+ await DisplayAlert("Erro", "O MQTT não está ligado.", "OK");
+ return;
+ }
+
+ _isLedOn = !_isLedOn;
+ string comando = _isLedOn ? "ON" : "OFF";
+
+ var message = new MqttApplicationMessageBuilder()
+ .WithTopic("guilherme/app/led")
+ .WithPayload(comando)
+ .Build();
+
+ await _mqttClient.PublishAsync(message);
+
+ LedBtn.Text = _isLedOn ? "DESLIGAR LED" : "LIGAR LED";
+ LedBtn.BackgroundColor = _isLedOn ? Colors.Red : Colors.DarkSlateGray;
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Platforms/Android/AndroidManifest.xml b/GuilhermesApp/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 0000000..e9937ad
--- /dev/null
+++ b/GuilhermesApp/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Platforms/Android/MainActivity.cs b/GuilhermesApp/Platforms/Android/MainActivity.cs
new file mode 100644
index 0000000..770d56c
--- /dev/null
+++ b/GuilhermesApp/Platforms/Android/MainActivity.cs
@@ -0,0 +1,10 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+
+namespace GuilhermesApp;
+
+[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
+public class MainActivity : MauiAppCompatActivity
+{
+}
diff --git a/GuilhermesApp/Platforms/Android/MainApplication.cs b/GuilhermesApp/Platforms/Android/MainApplication.cs
new file mode 100644
index 0000000..670cf6c
--- /dev/null
+++ b/GuilhermesApp/Platforms/Android/MainApplication.cs
@@ -0,0 +1,15 @@
+using Android.App;
+using Android.Runtime;
+
+namespace GuilhermesApp;
+
+[Application]
+public class MainApplication : MauiApplication
+{
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/GuilhermesApp/Platforms/Android/Resources/values/colors.xml b/GuilhermesApp/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 0000000..c04d749
--- /dev/null
+++ b/GuilhermesApp/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
\ No newline at end of file
diff --git a/GuilhermesApp/Platforms/MacCatalyst/AppDelegate.cs b/GuilhermesApp/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 0000000..c34ef12
--- /dev/null
+++ b/GuilhermesApp/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace GuilhermesApp;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/GuilhermesApp/Platforms/MacCatalyst/Entitlements.plist b/GuilhermesApp/Platforms/MacCatalyst/Entitlements.plist
new file mode 100644
index 0000000..de4adc9
--- /dev/null
+++ b/GuilhermesApp/Platforms/MacCatalyst/Entitlements.plist
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+ com.apple.security.network.client
+
+
+
+
diff --git a/GuilhermesApp/Platforms/MacCatalyst/Info.plist b/GuilhermesApp/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 0000000..7268977
--- /dev/null
+++ b/GuilhermesApp/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UIDeviceFamily
+
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/GuilhermesApp/Platforms/MacCatalyst/Program.cs b/GuilhermesApp/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 0000000..9fef825
--- /dev/null
+++ b/GuilhermesApp/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace GuilhermesApp;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/GuilhermesApp/Platforms/Tizen/Main.cs b/GuilhermesApp/Platforms/Tizen/Main.cs
new file mode 100644
index 0000000..c67e280
--- /dev/null
+++ b/GuilhermesApp/Platforms/Tizen/Main.cs
@@ -0,0 +1,16 @@
+using System;
+using Microsoft.Maui;
+using Microsoft.Maui.Hosting;
+
+namespace GuilhermesApp;
+
+class Program : MauiApplication
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+}
diff --git a/GuilhermesApp/Platforms/Tizen/tizen-manifest.xml b/GuilhermesApp/Platforms/Tizen/tizen-manifest.xml
new file mode 100644
index 0000000..96098ab
--- /dev/null
+++ b/GuilhermesApp/Platforms/Tizen/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ maui-appicon-placeholder
+
+
+
+
+ http://tizen.org/privilege/internet
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Platforms/Windows/App.xaml b/GuilhermesApp/Platforms/Windows/App.xaml
new file mode 100644
index 0000000..1fbd9b2
--- /dev/null
+++ b/GuilhermesApp/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/GuilhermesApp/Platforms/Windows/App.xaml.cs b/GuilhermesApp/Platforms/Windows/App.xaml.cs
new file mode 100644
index 0000000..0f1bcef
--- /dev/null
+++ b/GuilhermesApp/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,24 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace GuilhermesApp.WinUI;
+
+///
+/// Provides application-specific behavior to supplement the default Application class.
+///
+public partial class App : MauiWinUIApplication
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
diff --git a/GuilhermesApp/Platforms/Windows/Package.appxmanifest b/GuilhermesApp/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 0000000..65e9d6e
--- /dev/null
+++ b/GuilhermesApp/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GuilhermesApp/Platforms/Windows/app.manifest b/GuilhermesApp/Platforms/Windows/app.manifest
new file mode 100644
index 0000000..6876a9b
--- /dev/null
+++ b/GuilhermesApp/Platforms/Windows/app.manifest
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
diff --git a/GuilhermesApp/Platforms/iOS/AppDelegate.cs b/GuilhermesApp/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 0000000..c34ef12
--- /dev/null
+++ b/GuilhermesApp/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace GuilhermesApp;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/GuilhermesApp/Platforms/iOS/Info.plist b/GuilhermesApp/Platforms/iOS/Info.plist
new file mode 100644
index 0000000..0004a4f
--- /dev/null
+++ b/GuilhermesApp/Platforms/iOS/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/GuilhermesApp/Platforms/iOS/Program.cs b/GuilhermesApp/Platforms/iOS/Program.cs
new file mode 100644
index 0000000..9fef825
--- /dev/null
+++ b/GuilhermesApp/Platforms/iOS/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace GuilhermesApp;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/GuilhermesApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/GuilhermesApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000..24ab3b4
--- /dev/null
+++ b/GuilhermesApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
@@ -0,0 +1,51 @@
+
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryFileTimestamp
+ NSPrivacyAccessedAPITypeReasons
+
+ C617.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategorySystemBootTime
+ NSPrivacyAccessedAPITypeReasons
+
+ 35F9.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryDiskSpace
+ NSPrivacyAccessedAPITypeReasons
+
+ E174.1
+
+
+
+
+
+
diff --git a/GuilhermesApp/Properties/launchSettings.json b/GuilhermesApp/Properties/launchSettings.json
new file mode 100644
index 0000000..4f85793
--- /dev/null
+++ b/GuilhermesApp/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "Project",
+ "nativeDebugging": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/GuilhermesApp/Resources/AppIcon/appicon.svg b/GuilhermesApp/Resources/AppIcon/appicon.svg
new file mode 100644
index 0000000..9d63b65
--- /dev/null
+++ b/GuilhermesApp/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Resources/AppIcon/appiconfg.svg b/GuilhermesApp/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/GuilhermesApp/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Resources/Fonts/OpenSans-Regular.ttf b/GuilhermesApp/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000..51763bf
Binary files /dev/null and b/GuilhermesApp/Resources/Fonts/OpenSans-Regular.ttf differ
diff --git a/GuilhermesApp/Resources/Fonts/OpenSans-Semibold.ttf b/GuilhermesApp/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 0000000..26a7dae
Binary files /dev/null and b/GuilhermesApp/Resources/Fonts/OpenSans-Semibold.ttf differ
diff --git a/GuilhermesApp/Resources/Images/dotnet_bot.png b/GuilhermesApp/Resources/Images/dotnet_bot.png
new file mode 100644
index 0000000..1d1b981
Binary files /dev/null and b/GuilhermesApp/Resources/Images/dotnet_bot.png differ
diff --git a/GuilhermesApp/Resources/Images/logo.png b/GuilhermesApp/Resources/Images/logo.png
new file mode 100644
index 0000000..b167729
Binary files /dev/null and b/GuilhermesApp/Resources/Images/logo.png differ
diff --git a/GuilhermesApp/Resources/Raw/AboutAssets.txt b/GuilhermesApp/Resources/Raw/AboutAssets.txt
new file mode 100644
index 0000000..89dc758
--- /dev/null
+++ b/GuilhermesApp/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with your package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/GuilhermesApp/Resources/Splash/splash.svg b/GuilhermesApp/Resources/Splash/splash.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/GuilhermesApp/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Resources/Styles/Colors.xaml b/GuilhermesApp/Resources/Styles/Colors.xaml
new file mode 100644
index 0000000..30307a5
--- /dev/null
+++ b/GuilhermesApp/Resources/Styles/Colors.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ #512BD4
+ #ac99ea
+ #242424
+ #DFD8F7
+ #9880e5
+ #2B0B98
+
+ White
+ Black
+ #D600AA
+ #190649
+ #1f1f1f
+
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GuilhermesApp/Resources/Styles/Styles.xaml b/GuilhermesApp/Resources/Styles/Styles.xaml
new file mode 100644
index 0000000..d4dded0
--- /dev/null
+++ b/GuilhermesApp/Resources/Styles/Styles.xaml
@@ -0,0 +1,440 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+