From 4cf61f48bf85aaae44012e9e74da014bec458517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oziel=20Guimar=C3=A3es=20de=20Paula=20Silva?= Date: Sun, 9 Jun 2024 11:58:10 -0300 Subject: [PATCH] Resolvendo delay entre loading messages e sincronizando dados --- .../Constants/ConfigurationConstant.cs | 2 +- .../Ebd.MobileApp/DependencyInjection.cs | 13 + .../Ebd.MobileApp/Ebd.MobileApp.csproj | 7 + .../Ebd.Mobile/Ebd.MobileApp/MauiProgram.cs | 2 + .../Android/Resources/values/styles.xml | 4 + .../Ebd.MobileApp/Repository/Repository.cs | 6 +- .../Services/Implementations/AlunoService.cs | 2 +- .../Implementations/AvaliacaoService.cs | 4 +- .../Services/Implementations/BairroService.cs | 2 +- .../Implementations/Base/ApiService.cs | 367 +++++++++--------- .../Implementations/Base/BaseService.cs | 2 +- .../EscolherTurmaBottomSheetService.cs | 18 + .../Services/Implementations/CepService.cs | 2 +- .../Implementations/ChamadaService.cs | 3 +- .../ConfiguracoesDoUsuarioService.cs | 44 +++ .../Implementations/Dialog/DialogService.cs | 18 +- .../Services/Implementations/LicaoService.cs | 4 +- .../Implementations/RevistaService.cs | 24 +- .../Services/Implementations/SyncService.cs | 2 +- .../Services/Implementations/TurmaService.cs | 79 ++-- .../IEscolherTurmaBottomSheetService.cs | 6 + .../IConfiguracoesDoUsuarioService.cs | 11 + .../Services/Interfaces/ITurmaService.cs | 9 +- .../Requests/Turma/SelecionarTurmaRequest.cs | 3 + .../Services/Responses/Turma/TurmaResponse.cs | 39 +- .../ViewModels/Home/HomeViewModel.cs | 19 +- .../ViewModels/LoginViewModel.cs | 7 +- .../ViewModels/Perfil/PerfilPageViewModel.cs | 10 + .../Ebd.MobileApp/Views/HomePage.xaml | 23 ++ .../Ebd.MobileApp/Views/HomePage.xaml.cs | 28 +- .../Views/Perfil/PerfilPage.xaml | 12 + .../Views/Perfil/PerfilPage.xaml.cs | 9 + .../Views/Turma/EscolherTurmaBottomSheet.xaml | 21 + .../Turma/EscolherTurmaBottomSheet.xaml.cs | 11 + .../admp-prod - Web Deploy/profile.arm.json | 113 ++++++ 35 files changed, 617 insertions(+), 309 deletions(-) create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Platforms/Android/Resources/values/styles.xml create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BottomSheets/EscolherTurmaBottomSheetService.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ConfiguracoesDoUsuarioService.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/BottomSheets/IEscolherTurmaBottomSheetService.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/IConfiguracoesDoUsuarioService.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Requests/Turma/SelecionarTurmaRequest.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Perfil/PerfilPageViewModel.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml.cs create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml create mode 100644 EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml.cs create mode 100644 EscolaBiblicaDominical/Ebd.Presentation.Api/Properties/ServiceDependencies/admp-prod - Web Deploy/profile.arm.json diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Constants/ConfigurationConstant.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Constants/ConfigurationConstant.cs index 101cf5e..71dfd8b 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Constants/ConfigurationConstant.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Constants/ConfigurationConstant.cs @@ -5,7 +5,7 @@ public class ConfigurationConstant public const string DatabaseName = "Gtech.Ebd"; //public const string BaseUrl = "https://ozielguimaraes.dev/api"; - public const string BaseUrl = "https://101e-2804-14d-a4ba-8028-c9dc-ca4b-1b7d-d321.ngrok-free.app/api"; + public const string BaseUrl = "https://69a4-2804-14d-a4ba-8028-c9dc-ca4b-1b7d-d321.ngrok-free.app/api"; //public const string BaseUrl = "https://192.168.0.64:5005/api"; } } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/DependencyInjection.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/DependencyInjection.cs index f0da5ff..265e246 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/DependencyInjection.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/DependencyInjection.cs @@ -12,7 +12,10 @@ using Ebd.Mobile.Views.Chamada; using Ebd.MobileApp.Network; using Ebd.MobileApp.Services.Implementations; +using Ebd.MobileApp.Services.Implementations.BottomSheets; +using Ebd.MobileApp.Services.Interfaces.BottomSheets; using Ebd.MobileApp.ViewModels.Home; +using Ebd.MobileApp.ViewModels.Perfil; using Ebd.MobileApp.ViewModels.Welcome; using Ebd.MobileApp.Views.Welcome; @@ -49,6 +52,9 @@ public static IServiceCollection ConfigureAndHandleHttpClient(this IServiceColle public static IServiceCollection ConfigureServices(this IServiceCollection services) { + services.AddSingleton(); + services.AddSingleton(Preferences.Default); + //services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -67,6 +73,9 @@ public static IServiceCollection ConfigureServices(this IServiceCollection servi services.AddSingleton(); services.AddSingleton(); + //BottomSheets + services.AddSingleton(); + return services; } @@ -110,6 +119,10 @@ public static IServiceCollection ConfigureViewModels(this IServiceCollection ser services.AddTransient(); services.AddTransient(); + //Perfil + services.AddTransient(); + + return services; } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Ebd.MobileApp.csproj b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Ebd.MobileApp.csproj index f84c6a7..d22a003 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Ebd.MobileApp.csproj +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Ebd.MobileApp.csproj @@ -84,6 +84,7 @@ + @@ -199,6 +200,12 @@ MSBuild:Compile + + MSBuild:Compile + + + MSBuild:Compile + MSBuild:Compile diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/MauiProgram.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/MauiProgram.cs index 5552f58..fa1b0a0 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/MauiProgram.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/MauiProgram.cs @@ -1,6 +1,7 @@ using CommunityToolkit.Maui; using Controls.UserDialogs.Maui; using Microsoft.Extensions.Logging; +using The49.Maui.BottomSheet; namespace Ebd.Mobile; @@ -12,6 +13,7 @@ public static MauiApp CreateMauiApp() builder .UseMauiApp() .UseUserDialogs() + .UseBottomSheet() .ConfigureFonts(fonts => { fonts.AddFont("OpenSansRegular.ttf", "OpenSansRegular"); diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Platforms/Android/Resources/values/styles.xml b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Platforms/Android/Resources/values/styles.xml new file mode 100644 index 0000000..87dc1ee --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Platforms/Android/Resources/values/styles.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Repository/Repository.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Repository/Repository.cs index b01e828..9b08671 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Repository/Repository.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Repository/Repository.cs @@ -79,9 +79,9 @@ public bool DeleteItems(Expression> predicate) public IEnumerable FiltrarItens(Query query, int limit = int.MaxValue) { return DataBase - ?.GetCollection() - ?.Find(query: Query.All(Query.Descending), limit: limit) - ?.Take(limit); + .GetCollection() + .Find(query: Query.All(Query.Descending), limit: limit) + .Take(limit); } public IEnumerable FiltrarItens(Expression> predicate) => DataBase.GetCollection().Find(predicate); diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AlunoService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AlunoService.cs index 3d32e6a..381df5c 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AlunoService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AlunoService.cs @@ -6,7 +6,7 @@ namespace Ebd.Mobile.Services.Implementations { - public class AlunoService : BaseService, IAlunoService + internal sealed class AlunoService : BaseService, IAlunoService { private const string PathToService = "aluno"; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AvaliacaoService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AvaliacaoService.cs index ac9d008..bde43c0 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AvaliacaoService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/AvaliacaoService.cs @@ -2,12 +2,10 @@ using Ebd.Mobile.Services.Interfaces; using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Avaliacao; -using System.Collections.Generic; -using System.Threading.Tasks; namespace Ebd.Mobile.Services.Implementations { - public class AvaliacaoService : BaseService, IAvaliacaoService + internal sealed class AvaliacaoService : BaseService, IAvaliacaoService { private const string PathToService = "avaliacao"; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BairroService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BairroService.cs index b8f1ed2..fe0fb11 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BairroService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BairroService.cs @@ -5,7 +5,7 @@ namespace Ebd.Mobile.Services.Implementations { - public class BairroService : BaseService, IBairroService + internal sealed class BairroService : BaseService, IBairroService { private const string PathToService = "bairro"; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/ApiService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/ApiService.cs index 25adb21..e6a5e7b 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/ApiService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/ApiService.cs @@ -9,224 +9,223 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Ebd.Mobile.Services.Implementations.Base +namespace Ebd.Mobile.Services.Implementations.Base; + +public abstract class ApiService : IApiService { - public abstract class ApiService : IApiService + private const string AuthenticationScheme = "Bearer"; + private const string ApplicationJson = "application/json"; + private readonly JsonSerializerOptions _jsonSerializerOptions; + private readonly INetworkService _networkService; + private readonly ILoggerService _loggerService; + internal const int DefaultRetryCount = 1; + protected readonly HttpClient HttpClient; + + public ApiService(INetworkService networkService, ILoggerService loggerService) { - private const string AuthenticationScheme = "Bearer"; - private const string ApplicationJson = "application/json"; - private readonly JsonSerializerOptions _jsonSerializerOptions; - private readonly INetworkService _networkService; - private readonly ILoggerService _loggerService; - internal const int DefaultRetryCount = 1; - protected readonly HttpClient HttpClient; - - public ApiService(INetworkService networkService, ILoggerService loggerService) - { - _networkService = networkService; - _loggerService = loggerService; - - HttpClientHandler clientHandler = new() - { - ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; } - }; - _jsonSerializerOptions = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - IgnoreReadOnlyProperties = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - }; - - HttpClient = _networkService.GetHttpClient(); - - HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson)); - } + _networkService = networkService; + _loggerService = loggerService; - public async Task> GetAndRetry(string requestUri, int retryCount, Func onRetry = null, string accessToken = null) where T : class + HttpClientHandler clientHandler = new() + { + ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; } + }; + _jsonSerializerOptions = new JsonSerializerOptions { - if ((await _networkService.HasInternetConnection()).Not()) - return BaseResponse.Falha(new NoInternetConnectionException()); + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + IgnoreReadOnlyProperties = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; - TryAddAuthorization(accessToken); - var func = new Func>>(() => ProcessGetRequest(requestUri)); - return await _networkService.Retry(func, retryCount, onRetry); - } + HttpClient = _networkService.GetHttpClient(); + + HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson)); + } + + public async Task> GetAndRetry(string requestUri, int retryCount, Func onRetry = null, string accessToken = null) where T : class + { + if ((await _networkService.HasInternetConnection()).Not()) + return BaseResponse.Falha(new NoInternetConnectionException()); + + TryAddAuthorization(accessToken); + var func = new Func>>(() => ProcessGetRequest(requestUri)); + return await _networkService.Retry(func, retryCount, onRetry); + } + + public async Task PostAndRetry(string requestUri, TRequest request, Func onRetry = null, string accessToken = null) + where TRequest : class + { + if ((await _networkService.HasInternetConnection()).Not()) + return new EmptyResponse(new NoInternetConnectionException()); + + TryAddAuthorization(accessToken); + var func = new Func>(() => ProcessPostRequest(requestUri, request)); + return await _networkService.Retry(func, DefaultRetryCount, onRetry); + } - public async Task PostAndRetry(string requestUri, TRequest request, Func onRetry = null, string accessToken = null) - where TRequest : class + public async Task> PostAndRetry(string requestUri, TRequest request, Func onRetry = null, string accessToken = null) + where TRequest : class + where TResponse : class + { + if ((await _networkService.HasInternetConnection()).Not()) + return BaseResponse.Falha(new NoInternetConnectionException()); + + TryAddAuthorization(accessToken); + var func = new Func>>(() => ProcessPostRequest(requestUri, request)); + return await _networkService.Retry(func, DefaultRetryCount, onRetry); + } + + public async Task> GetAndRetry(string requestUri, Func sleepDurationProvider, int retryCount, Func onWaitAndRetry = null, string accessToken = null) where T : class + { + if ((await _networkService.HasInternetConnection()).Not()) + return new BaseResponse(new NoInternetConnectionException()); + + TryAddAuthorization(accessToken); + var func = new Func>>(() => ProcessGetRequest(requestUri)); + return await _networkService.WaitAndRetry(func, sleepDurationProvider, retryCount, onWaitAndRetry); + } + + protected virtual Task OnRetry(Exception exception, int retryCount) + { + return Task.Factory.StartNew(() => { - if ((await _networkService.HasInternetConnection()).Not()) - return new EmptyResponse(new NoInternetConnectionException()); + _loggerService.LogWarning($"Retry - Attempt #{retryCount}."); - TryAddAuthorization(accessToken); - var func = new Func>(() => ProcessPostRequest(requestUri, request)); - return await _networkService.Retry(func, DefaultRetryCount, onRetry); - } + if (exception is not null) + _loggerService.LogError("Erro ao realizar o request", exception); + }); + } - public async Task> PostAndRetry(string requestUri, TRequest request, Func onRetry = null, string accessToken = null) - where TRequest : class - where TResponse : class + private async Task> ProcessGetRequest(string requestUri) where T : class + { + Random rnd = new(); + int randomId = rnd.Next(1000, 9999); + + _loggerService.LogInformation($"Request Uri-{randomId}: [HttpGet] {HttpClient.BaseAddress}/{requestUri}"); + using HttpResponseMessage responseMessage = await HttpClient.GetAsync($"api/{requestUri}"); + string responseContent = null; + + try { - if ((await _networkService.HasInternetConnection()).Not()) - return BaseResponse.Falha(new NoInternetConnectionException()); + responseContent = await responseMessage.Content.ReadAsStringAsync(); + LogUrlAndResponse(requestId: randomId, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); - TryAddAuthorization(accessToken); - var func = new Func>>(() => ProcessPostRequest(requestUri, request)); - return await _networkService.Retry(func, DefaultRetryCount, onRetry); - } + if (responseMessage.IsSuccessStatusCode.Not()) + ExceptionFromHttpStatusCode(responseMessage, responseContent); + + if (string.IsNullOrWhiteSpace(responseContent)) return default; - public async Task> GetAndRetry(string requestUri, Func sleepDurationProvider, int retryCount, Func onWaitAndRetry = null, string accessToken = null) where T : class + return new BaseResponse(JsonSerializer.Deserialize(responseContent, _jsonSerializerOptions)); + } + catch (Exception ex) { - if ((await _networkService.HasInternetConnection()).Not()) - return new BaseResponse(new NoInternetConnectionException()); + _loggerService.LogError("Erro ao processar request", ex, + new Dictionary { + { "responseMessage", JsonSerializer.Serialize(responseMessage) } + }); - TryAddAuthorization(accessToken); - var func = new Func>>(() => ProcessGetRequest(requestUri)); - return await _networkService.WaitAndRetry(func, sleepDurationProvider, retryCount, onWaitAndRetry); + return new BaseResponse(ex); } + } - protected virtual Task OnRetry(Exception exception, int retryCount) + private async Task> ProcessPostRequest(string requestUri, TRequest request) + where TResponse : class + where TRequest : class + { + Random rnd = new Random(); + int randomId = rnd.Next(1000, 9999); + _loggerService.LogInformation($"Request Uri: [HttpPost] {HttpClient.BaseAddress}/{requestUri}"); + var contentRequest = JsonSerializer.Serialize(request); +#if DEBUG + Debug.WriteLine($"JSON request: {contentRequest}"); +#endif + using HttpResponseMessage responseMessage = await HttpClient.PostAsync( + $"api/{requestUri}", + new StringContent(contentRequest, Encoding.UTF8, ApplicationJson) + ); + var responseContent = await responseMessage.Content.ReadAsStringAsync(); + LogUrlAndResponse(requestId: randomId, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); + + try { - return Task.Factory.StartNew(() => - { - _loggerService.LogWarning($"Retry - Attempt #{retryCount}."); + if (responseMessage.IsSuccessStatusCode.Not()) + ExceptionFromHttpStatusCode(responseMessage, responseContent); - if (exception is not null) - _loggerService.LogError("Erro ao realizar o request", exception); - }); - } + if (string.IsNullOrWhiteSpace(responseContent)) + return BaseResponse.Falha(new EmptyResponseException()); - private async Task> ProcessGetRequest(string requestUri) where T : class + return new BaseResponse(JsonSerializer.Deserialize(responseContent, _jsonSerializerOptions)); + } + catch (Exception ex) { - Random rnd = new(); - int randomId = rnd.Next(1000, 9999); - - _loggerService.LogInformation($"Request Uri-{randomId}: [HttpGet] {HttpClient.BaseAddress}/{requestUri}"); - using HttpResponseMessage responseMessage = await HttpClient.GetAsync($"api/{requestUri}"); - string responseContent = null; - - try - { - responseContent = await responseMessage.Content.ReadAsStringAsync(); - LogUrlAndResponse(requestId: randomId, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); - - if (responseMessage.IsSuccessStatusCode.Not()) - ExceptionFromHttpStatusCode(responseMessage, responseContent); - - if (string.IsNullOrWhiteSpace(responseContent)) return default; - - return new BaseResponse(JsonSerializer.Deserialize(responseContent, _jsonSerializerOptions)); - } - catch (Exception ex) - { - _loggerService.LogError("Erro ao processar request", ex, - new Dictionary { - { "responseMessage", JsonSerializer.Serialize(responseMessage) } - }); - - return new BaseResponse(ex); - } + _loggerService.LogError("Erro ao processar request", ex, + new Dictionary { + { "requestBody", contentRequest }, + { "responseMessage", JsonSerializer.Serialize(responseMessage) } + }); + + return BaseResponse.Falha(ex); } + } - private async Task> ProcessPostRequest(string requestUri, TRequest request) - where TResponse : class - where TRequest : class - { - Random rnd = new Random(); - int randomId = rnd.Next(1000, 9999); - _loggerService.LogInformation($"Request Uri: [HttpPost] {HttpClient.BaseAddress}/{requestUri}"); - var contentRequest = JsonSerializer.Serialize(request); + private async Task ProcessPostRequest(string requestUri, TRequest request) + where TRequest : class + { + Random rnd = new Random(); + int id = rnd.Next(1000, 9999); + _loggerService.LogInformation($"Request Uri: [HttpPost] {HttpClient.BaseAddress}/{requestUri}"); + + var contentRequest = JsonSerializer.Serialize(request); #if DEBUG - Debug.WriteLine($"JSON request: {contentRequest}"); + Debug.WriteLine($"JSON request: {contentRequest}"); #endif - using HttpResponseMessage responseMessage = await HttpClient.PostAsync( - $"api/{requestUri}", - new StringContent(contentRequest, Encoding.UTF8, ApplicationJson) - ); - var responseContent = await responseMessage.Content.ReadAsStringAsync(); - LogUrlAndResponse(requestId: randomId, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); + using HttpResponseMessage responseMessage = await HttpClient.PostAsync( + $"api/{requestUri}", + new StringContent(contentRequest, Encoding.UTF8, ApplicationJson) + ); + var responseContent = await responseMessage.Content.ReadAsStringAsync(); + LogUrlAndResponse(requestId: id, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); + + try + { + if (!responseMessage.IsSuccessStatusCode) + ExceptionFromHttpStatusCode(responseMessage, responseContent); - try - { - if (responseMessage.IsSuccessStatusCode.Not()) - ExceptionFromHttpStatusCode(responseMessage, responseContent); - - if (string.IsNullOrWhiteSpace(responseContent)) - return BaseResponse.Falha(new EmptyResponseException()); - - return new BaseResponse(JsonSerializer.Deserialize(responseContent, _jsonSerializerOptions)); - } - catch (Exception ex) - { - _loggerService.LogError("Erro ao processar request", ex, - new Dictionary { - { "requestBody", contentRequest }, - { "responseMessage", JsonSerializer.Serialize(responseMessage) } - }); - - return BaseResponse.Falha(ex); - } + return new EmptyResponse(); } - - private async Task ProcessPostRequest(string requestUri, TRequest request) - where TRequest : class + catch (Exception ex) { - Random rnd = new Random(); - int id = rnd.Next(1000, 9999); - _loggerService.LogInformation($"Request Uri: [HttpPost] {HttpClient.BaseAddress}/{requestUri}"); + _loggerService.LogError("Erro ao processar request", ex, + new Dictionary { + { "requestBody", contentRequest }, + { "responseMessage", JsonSerializer.Serialize(responseMessage) } + }); - var contentRequest = JsonSerializer.Serialize(request); -#if DEBUG - Debug.WriteLine($"JSON request: {contentRequest}"); -#endif - using HttpResponseMessage responseMessage = await HttpClient.PostAsync( - $"api/{requestUri}", - new StringContent(contentRequest, Encoding.UTF8, ApplicationJson) - ); - var responseContent = await responseMessage.Content.ReadAsStringAsync(); - LogUrlAndResponse(requestId: id, jsonResponse: responseContent, responseMessage.RequestMessage.Method, requestUri: responseMessage.RequestMessage.RequestUri, statusCode: responseMessage.StatusCode); - - try - { - if (!responseMessage.IsSuccessStatusCode) - ExceptionFromHttpStatusCode(responseMessage, responseContent); - - return new EmptyResponse(); - } - catch (Exception ex) - { - _loggerService.LogError("Erro ao processar request", ex, - new Dictionary { - { "requestBody", contentRequest }, - { "responseMessage", JsonSerializer.Serialize(responseMessage) } - }); - - return new EmptyResponse(ex); - } + return new EmptyResponse(ex); } + } - private void LogUrlAndResponse(int requestId, string jsonResponse, HttpMethod httpMethod, Uri requestUri, HttpStatusCode statusCode) - { + private void LogUrlAndResponse(int requestId, string jsonResponse, HttpMethod httpMethod, Uri requestUri, HttpStatusCode statusCode) + { #if DEBUG - Debug.WriteLine($"Response Uri-{requestId}: [{httpMethod}] {requestUri} - {statusCode}"); - Debug.WriteLine($"JSON Response: {jsonResponse}"); + Debug.WriteLine($"Response Uri-{requestId}: [{httpMethod}] {requestUri} - {statusCode}"); + Debug.WriteLine($"JSON Response: {jsonResponse}"); #endif - } + } - private void TryAddAuthorization(string accessToken) - { - if (!string.IsNullOrWhiteSpace(accessToken)) - HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme: AuthenticationScheme, parameter: accessToken); - } + private void TryAddAuthorization(string accessToken) + { + if (!string.IsNullOrWhiteSpace(accessToken)) + HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme: AuthenticationScheme, parameter: accessToken); + } - private void ExceptionFromHttpStatusCode(HttpResponseMessage responseMessage, string responseContent) + private void ExceptionFromHttpStatusCode(HttpResponseMessage responseMessage, string responseContent) + { + throw responseMessage.StatusCode switch { - throw responseMessage.StatusCode switch - { - HttpStatusCode.BadRequest => new InvalidOperationException(JsonSerializer.Deserialize(responseContent)), - HttpStatusCode.Unauthorized => new UnauthorizedAccessException(), - _ => new InvalidOperationException("Erro desconhecido ao realizar essa operação"), - }; - } + HttpStatusCode.BadRequest => new InvalidOperationException(JsonSerializer.Deserialize(responseContent)), + HttpStatusCode.Unauthorized => new UnauthorizedAccessException(), + _ => new InvalidOperationException("Erro desconhecido ao realizar essa operação"), + }; } } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/BaseService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/BaseService.cs index 9f0f3f2..3f89912 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/BaseService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Base/BaseService.cs @@ -2,7 +2,7 @@ namespace Ebd.Mobile.Services.Implementations.Base { - public abstract class BaseService : ApiService + internal abstract class BaseService : ApiService { protected readonly ILoggerService loggerService; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BottomSheets/EscolherTurmaBottomSheetService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BottomSheets/EscolherTurmaBottomSheetService.cs new file mode 100644 index 0000000..6b4a8c4 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/BottomSheets/EscolherTurmaBottomSheetService.cs @@ -0,0 +1,18 @@ +using Ebd.MobileApp.Services.Interfaces.BottomSheets; +using Ebd.MobileApp.Views.Turma; + +namespace Ebd.MobileApp.Services.Implementations.BottomSheets; + +public class EscolherTurmaBottomSheetService : IEscolherTurmaBottomSheetService +{ + public async Task AbrirBottomSheetAsync() + { + var bottomSheet = new EscolherTurmaBottomSheet + { + HasHandle = true, + IsCancelable = false + }; + + await bottomSheet.ShowAsync(); + } +} diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/CepService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/CepService.cs index 1bf3ec8..8ef4acf 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/CepService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/CepService.cs @@ -6,7 +6,7 @@ namespace Ebd.Mobile.Services.Implementations { - public class CepService : BaseService, ICepService + internal sealed class CepService : BaseService, ICepService { public CepService(ILoggerService loggerService, INetworkService networkService) : base(loggerService, networkService) { } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ChamadaService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ChamadaService.cs index 010360e..569a67d 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ChamadaService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ChamadaService.cs @@ -3,11 +3,10 @@ using Ebd.Mobile.Services.Requests.Chamada; using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Chamada; -using System.Threading.Tasks; namespace Ebd.Mobile.Services.Implementations { - public class ChamadaService : BaseService, IChamadaService + internal sealed class ChamadaService : BaseService, IChamadaService { private const string PathToService = "chamada"; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ConfiguracoesDoUsuarioService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ConfiguracoesDoUsuarioService.cs new file mode 100644 index 0000000..4de2b58 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/ConfiguracoesDoUsuarioService.cs @@ -0,0 +1,44 @@ +using Ebd.Mobile.Services.Interfaces; +using Ebd.Mobile.Services.Responses; +using Ebd.Mobile.Services.Responses.Turma; +using Ebd.MobileApp.Services.Requests.Turma; +using System.Text.Json; + +namespace Ebd.Mobile.Services.Implementations; + +internal sealed class ConfiguracoesDoUsuarioService : IConfiguracoesDoUsuarioService +{ + private const string TurmaSelecionadaKey = "TurmaSelecionada"; + private readonly IPreferences settings; + + public ConfiguracoesDoUsuarioService(IPreferences settings) + { + this.settings = settings; + } + + public TurmaResponse? TurmaSelecionada + { + get + { + var json = settings.Get(TurmaSelecionadaKey, string.Empty); + return string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize(json); + } + set + { + var json = JsonSerializer.Serialize(value); + settings.Set(TurmaSelecionadaKey, json); + } + } + + public bool SelecionouUmaTurma => TurmaSelecionada != null; + + public Task> ObterTurmaSelecionadaAsync() + { + throw new NotImplementedException(); + } + + public Task> SelecionarAsync(SelecionarTurmaRequest request) + { + throw new NotImplementedException(); + } +} diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Dialog/DialogService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Dialog/DialogService.cs index 2c462ba..583d016 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Dialog/DialogService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/Dialog/DialogService.cs @@ -1,5 +1,6 @@ using Controls.UserDialogs.Maui; using Ebd.Mobile.Services.Interfaces; +using System.Diagnostics; namespace Ebd.Mobile.Services.Implementations.Dialog { @@ -12,28 +13,29 @@ public DialogService(IDiagnosticService diagnosticService) _diagnosticService = diagnosticService; } - public Task DisplayAlert(string title, string message) - => Application.Current.MainPage.DisplayAlert(title, message, "Ok"); + public Task DisplayAlert(string title, string message) => DisplayAlert(title, message, "Ok"); - public Task DisplayAlert(string title, string message, string cancel) - => Application.Current.MainPage.DisplayAlert(title, message, cancel); + public Task DisplayAlert(string title, string message, string cancel) => DisplayAlert(title, message, "Ok", cancel); public Task DisplayAlert(Exception ex) { return ex switch { - ArgumentException argumentException => Application.Current.MainPage.DisplayAlert(null, argumentException.Message, "Ok"), - InvalidOperationException invalidOperationException => Application.Current.MainPage.DisplayAlert(null, invalidOperationException.Message, "Ok"), - TaskCanceledException taskCanceledException => Application.Current.MainPage.DisplayAlert("Operação cancelada", "Operação cancelada pelo usuário", "Ok"), + ArgumentException argumentException => DisplayAlert(null, argumentException.Message, "Ok"), + InvalidOperationException invalidOperationException => DisplayAlert(null, invalidOperationException.Message, "Ok"), + TaskCanceledException taskCanceledException => DisplayAlert("Operação cancelada", "Operação cancelada pelo usuário", "Ok"), _ => Task.Factory.StartNew(() => { _diagnosticService.TrackError(ex); - return Application.Current.MainPage.DisplayAlert("Ah não", ex.Message, "Ok"); + return DisplayAlert("Ah não", ex.Message, "Ok"); }) }; } + private Task DisplayAlert(string? title, string message, string accept, string cancel) + => Application.Current?.MainPage?.DisplayAlert(title, message, accept, cancel) ?? Task.Run(() => Debug.WriteLine("Application.Current?.MainPage was null when trying to DisplayAlert")); + public void ShowLoading(string message) => UserDialogs.Instance.ShowLoading( message: message, diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/LicaoService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/LicaoService.cs index 6c9b737..694faa5 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/LicaoService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/LicaoService.cs @@ -3,12 +3,10 @@ using Ebd.Mobile.Services.Requests.Licao; using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Licao; -using System.Collections.Generic; -using System.Threading.Tasks; namespace Ebd.Mobile.Services.Implementations { - public class LicaoService : BaseService, ILicaoService + internal sealed class LicaoService : BaseService, ILicaoService { private const string PathToService = "licao"; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/RevistaService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/RevistaService.cs index 1f4a2c1..d47352a 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/RevistaService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/RevistaService.cs @@ -3,23 +3,21 @@ using Ebd.Mobile.Services.Requests.Revista; using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Revista; -using System.Threading.Tasks; -namespace Ebd.Mobile.Services.Implementations +namespace Ebd.Mobile.Services.Implementations; + +internal sealed class RevistaService : BaseService, IRevistaService { - public class RevistaService : BaseService, IRevistaService - { - private const string PathToService = "revista"; + private const string PathToService = "revista"; - public RevistaService(ILoggerService loggerService, INetworkService networkService) : base(loggerService, networkService) { } + public RevistaService(ILoggerService loggerService, INetworkService networkService) : base(loggerService, networkService) { } - public async Task> AdicionarAsync(AdicionarRevistaRequest request) - => await PostAndRetry(PathToService, request, OnRetry); + public async Task> AdicionarAsync(AdicionarRevistaRequest request) + => await PostAndRetry(PathToService, request, OnRetry); - public async Task> ObterPorIdAsync(int revistaId) - => await GetAndRetry($"{PathToService}/{revistaId}", retryCount: DefaultRetryCount, OnRetry); + public async Task> ObterPorIdAsync(int revistaId) + => await GetAndRetry($"{PathToService}/{revistaId}", retryCount: DefaultRetryCount, OnRetry); - public async Task> ObterPorPeriodoAsync(int turmaId, int ano, int trimestre) - => await GetAndRetry($"{PathToService}/turma/{turmaId}/trimestre/{trimestre}-{ano}", retryCount: DefaultRetryCount, OnRetry); - } + public async Task> ObterPorPeriodoAsync(int turmaId, int ano, int trimestre) + => await GetAndRetry($"{PathToService}/turma/{turmaId}/trimestre/{trimestre}-{ano}", retryCount: DefaultRetryCount, OnRetry); } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/SyncService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/SyncService.cs index 0fa24f1..d4cb840 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/SyncService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/SyncService.cs @@ -3,7 +3,7 @@ namespace Ebd.Mobile.Services.Implementations { - public class SyncService : BaseService, ISyncService + internal sealed class SyncService : BaseService, ISyncService { private readonly ITurmaService turmaService; private readonly IBairroService bairroService; diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/TurmaService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/TurmaService.cs index 16488c6..cb5e3ff 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/TurmaService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Implementations/TurmaService.cs @@ -5,54 +5,53 @@ using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Turma; -namespace Ebd.Mobile.Services.Implementations +namespace Ebd.Mobile.Services.Implementations; + +internal sealed class TurmaService : BaseService, ITurmaService { - public class TurmaService : BaseService, ITurmaService + private const string PathToService = "turma"; + private readonly IRepository repository; + + public TurmaService(ILoggerService loggerService, INetworkService networkService, IRepository repository) : base(loggerService, networkService) { - private const string PathToService = "turma"; - private readonly IRepository repository; + this.repository = repository; + } - public TurmaService(ILoggerService loggerService, INetworkService networkService, IRepository repository) : base(loggerService, networkService) - { - this.repository = repository; - } + public async Task>> ObterTodasAsync() + { + loggerService.LogInformation("Obtendo todas turmas"); + IEnumerable items = repository.ObterTodos(); + if (items.Any()) return new BaseResponse>(items); - public async Task>> ObterTodasAsync() + var result = await GetAndRetry>(PathToService, retryCount: DefaultRetryCount, OnRetry); + + if (result.IsSuccess) { - loggerService.LogInformation("Obtendo todas turmas"); - IEnumerable items = repository.ObterTodos(); - if (items.Any()) return new BaseResponse>(items); - - var result = await GetAndRetry>(PathToService, retryCount: DefaultRetryCount, OnRetry); - - if (result.IsSuccess) - { - loggerService.LogInformation("Guardar turmas no banco local"); - var foiAtualizado = repository.Upsert(result.Data); - if (foiAtualizado.Not()) - loggerService.LogError("Não foi possível adicionar as turmas no banco local"); - } - else loggerService.LogError($"{nameof(TurmaService)}::{nameof(ObterTodasAsync)} - Não foi possível obter as turmas"); - return result; + loggerService.LogInformation("Guardar turmas no banco local"); + var foiAtualizado = repository.Upsert(result.Data); + if (foiAtualizado.Not()) + loggerService.LogError("Não foi possível adicionar as turmas no banco local"); } + else loggerService.LogError($"{nameof(TurmaService)}::{nameof(ObterTodasAsync)} - Não foi possível obter as turmas"); + return result; + } + + public async Task>> ObterDoUsuarioLogadoAsync() + { + loggerService.LogInformation("Obtendo todas turmas"); + IEnumerable items = repository.ObterTodos(); + if (items.Any()) return new BaseResponse>(items); + + var result = await GetAndRetry>(PathToService, retryCount: DefaultRetryCount, OnRetry); - public async Task>> ObterDoUsuarioLogadoAsync() + if (result.IsSuccess) { - loggerService.LogInformation("Obtendo todas turmas"); - IEnumerable items = repository.ObterTodos(); - if (items.Any()) return new BaseResponse>(items); - - var result = await GetAndRetry>(PathToService, retryCount: DefaultRetryCount, OnRetry); - - if (result.IsSuccess) - { - loggerService.LogInformation("Guardar turmas no banco local"); - var foiAtualizado = repository.Upsert(result.Data); - if (foiAtualizado.Not()) - loggerService.LogError("Não foi possível adicionar as turmas no banco local"); - } - else loggerService.LogError($"{nameof(TurmaService)}::{nameof(ObterTodasAsync)} - Não foi possível obter as turmas"); - return result; + loggerService.LogInformation("Guardar turmas no banco local"); + var foiAtualizado = repository.Upsert(result.Data); + if (foiAtualizado.Not()) + loggerService.LogError("Não foi possível adicionar as turmas no banco local"); } + else loggerService.LogError($"{nameof(TurmaService)}::{nameof(ObterTodasAsync)} - Não foi possível obter as turmas"); + return result; } } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/BottomSheets/IEscolherTurmaBottomSheetService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/BottomSheets/IEscolherTurmaBottomSheetService.cs new file mode 100644 index 0000000..9b88e6d --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/BottomSheets/IEscolherTurmaBottomSheetService.cs @@ -0,0 +1,6 @@ +namespace Ebd.MobileApp.Services.Interfaces.BottomSheets; + +public interface IEscolherTurmaBottomSheetService +{ + Task AbrirBottomSheetAsync(); +} diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/IConfiguracoesDoUsuarioService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/IConfiguracoesDoUsuarioService.cs new file mode 100644 index 0000000..136881e --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/IConfiguracoesDoUsuarioService.cs @@ -0,0 +1,11 @@ +using Ebd.Mobile.Services.Responses.Turma; + +namespace Ebd.Mobile.Services.Interfaces; + +internal interface IConfiguracoesDoUsuarioService +{ + public bool SelecionouUmaTurma { get; } + public TurmaResponse? TurmaSelecionada { get; set; } + //Task> SelecionarAsync(SelecionarTurmaRequest request); + //Task> ObterTurmaSelecionadaAsync(); +} diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/ITurmaService.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/ITurmaService.cs index 13b3434..47a7b7a 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/ITurmaService.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Interfaces/ITurmaService.cs @@ -1,10 +1,9 @@ using Ebd.Mobile.Services.Responses; using Ebd.Mobile.Services.Responses.Turma; -namespace Ebd.Mobile.Services.Interfaces +namespace Ebd.Mobile.Services.Interfaces; + +internal interface ITurmaService { - public interface ITurmaService - { - Task>> ObterTodasAsync(); - } + Task>> ObterTodasAsync(); } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Requests/Turma/SelecionarTurmaRequest.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Requests/Turma/SelecionarTurmaRequest.cs new file mode 100644 index 0000000..0fd4935 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Requests/Turma/SelecionarTurmaRequest.cs @@ -0,0 +1,3 @@ +namespace Ebd.MobileApp.Services.Requests.Turma; + +internal record SelecionarTurmaRequest(int TurmaId, string Nome); diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Responses/Turma/TurmaResponse.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Responses/Turma/TurmaResponse.cs index 8b44172..8e405c5 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Responses/Turma/TurmaResponse.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Services/Responses/Turma/TurmaResponse.cs @@ -1,25 +1,24 @@ -namespace Ebd.Mobile.Services.Responses.Turma +namespace Ebd.Mobile.Services.Responses.Turma; + +public class TurmaResponse { - public class TurmaResponse - { - public int TurmaId { get; set; } - public string Nome { get; set; } - public int IdadeMinima { get; set; } - public int IdadeMaxima { get; set; } - public string FaixaIdadeNome => $"{IdadeMinima} à {IdadeMaxima} - {Nome}"; + public int TurmaId { get; set; } + public string Nome { get; set; } + public int IdadeMinima { get; set; } + public int IdadeMaxima { get; set; } + public string FaixaIdadeNome => $"{IdadeMinima} à {IdadeMaxima} - {Nome}"; - public override bool Equals(object obj) - { - return obj is TurmaResponse response && - TurmaId == response.TurmaId && - Nome == response.Nome && - IdadeMinima == response.IdadeMinima && - IdadeMaxima == response.IdadeMaxima; - } + public override bool Equals(object obj) + { + return obj is TurmaResponse response && + TurmaId == response.TurmaId && + Nome == response.Nome && + IdadeMinima == response.IdadeMinima && + IdadeMaxima == response.IdadeMaxima; + } - public override int GetHashCode() - { - return base.GetHashCode(); - } + public override int GetHashCode() + { + return base.GetHashCode(); } } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Home/HomeViewModel.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Home/HomeViewModel.cs index 31d7406..e8d5f72 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Home/HomeViewModel.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Home/HomeViewModel.cs @@ -1,8 +1,10 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Ebd.CrossCutting.Common.Extensions; using Ebd.Mobile.Services.Interfaces; using Ebd.Mobile.ViewModels.Aluno; using Ebd.Mobile.Views.Chamada; +using Ebd.MobileApp.Services.Interfaces.BottomSheets; using MvvmHelpers; using MvvmHelpers.Commands; @@ -12,11 +14,14 @@ internal sealed partial class HomeViewModel : BasePageViewModel { private readonly ISyncService syncService; private readonly ILoggerService loggerService; + private readonly IEscolherTurmaBottomSheetService escolherTurmaBottomSheetService; + private readonly IConfiguracoesDoUsuarioService configuracoesDoUsuarioService; - public HomeViewModel(ISyncService syncService, IDiagnosticService diagnosticService, IDialogService dialogService, ILoggerService loggerService) : base(diagnosticService, dialogService, loggerService) + public HomeViewModel(ISyncService syncService, IDiagnosticService diagnosticService, IDialogService dialogService, ILoggerService loggerService, IEscolherTurmaBottomSheetService escolherTurmaBottomSheetService, IConfiguracoesDoUsuarioService configuracoesDoUsuarioService) : base(diagnosticService, dialogService, loggerService) { this.syncService = syncService; this.loggerService = loggerService; + this.escolherTurmaBottomSheetService = escolherTurmaBottomSheetService; GoToAlunoPageCommand = new AsyncCommand( execute: ExecuteGoToAlunoPageCommand, @@ -25,6 +30,7 @@ public HomeViewModel(ISyncService syncService, IDiagnosticService diagnosticServ GoToEscolherTurmaPageCommand = new AsyncCommand( execute: ExecuteGoToEscolherTurmaPageCommand, onException: CommandOnException); + this.configuracoesDoUsuarioService = configuracoesDoUsuarioService; } public AsyncCommand GoToAlunoPageCommand { get; private set; } @@ -82,12 +88,17 @@ internal void OnAppearing() { try { - await syncService.SyncDataAsync(); + if (configuracoesDoUsuarioService.SelecionouUmaTurma.Not()) + { + await escolherTurmaBottomSheetService.AbrirBottomSheetAsync(); + return; + } + + await InitializeHomeTab(); } catch (Exception exception) { - loggerService.LogError("Não foi possível syncronizar os dados", exception); - //TODO Do something else with this error + loggerService.LogError($"{nameof(HomeViewModel)}::{nameof(OnAppearing)}", exception); } }); } diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/LoginViewModel.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/LoginViewModel.cs index c30d9b6..36c120a 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/LoginViewModel.cs +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/LoginViewModel.cs @@ -67,26 +67,25 @@ private async Task ClicouEmEfetuarLogin() Login = Login, Senha = Senha }); - DialogService.HideLoading(); if (resposta.IsSuccess) { DialogService.ShowLoading("Sincronizando seus dados..."); - await SyncData(); + await SincronizarDados(); DialogService.HideLoading(); await Navigate(); } else { + DialogService.HideLoading(); await DialogService.DisplayAlert("Oops", resposta.Exception.Message); } IsBusy = false; } - - private async Task SyncData() + private async Task SincronizarDados() { try { diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Perfil/PerfilPageViewModel.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Perfil/PerfilPageViewModel.cs new file mode 100644 index 0000000..b33ee4c --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/ViewModels/Perfil/PerfilPageViewModel.cs @@ -0,0 +1,10 @@ +using Ebd.Mobile.Services.Interfaces; + +namespace Ebd.MobileApp.ViewModels.Perfil; + +internal class PerfilPageViewModel : BasePageViewModel +{ + public PerfilPageViewModel(IDiagnosticService diagnosticService, IDialogService dialogService, ILoggerService logger) : base(diagnosticService, dialogService, logger) + { + } +} diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/HomePage.xaml b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/HomePage.xaml index e567c5b..a1854ba 100644 --- a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/HomePage.xaml +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/HomePage.xaml @@ -6,6 +6,7 @@ xmlns:components="clr-namespace:Ebd.Mobile.Views.Components" xmlns:icons="clr-namespace:Ebd.MobileApp" xmlns:styles="clr-namespace:Ebd.MobileApp.Resources.Styles" + xmlns:the49="https://schemas.the49.com/dotnet/2023/maui" xmlns:viewmodels="clr-namespace:Ebd.MobileApp.ViewModels.Home" x:DataType="viewmodels:HomeViewModel" BackgroundColor="{StaticResource Primary}"> @@ -17,6 +18,28 @@ TextColor="White" VerticalOptions="Center" /> + + + + + + + + (); + } - public HomePage() - { - InitializeComponent(); - BindingContext = viewModel = DependencyInjection.GetService(); - } + protected override void OnAppearing() + { + base.OnAppearing(); - protected override void OnAppearing() - { - base.OnAppearing(); - viewModel.OnAppearing(); - } + viewModel.OnAppearing(); } } \ No newline at end of file diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml new file mode 100644 index 0000000..ba6c907 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml.cs new file mode 100644 index 0000000..875d636 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Perfil/PerfilPage.xaml.cs @@ -0,0 +1,9 @@ +namespace Ebd.MobileApp.Views.Perfil; + +public partial class PerfilPage : ContentPage +{ + public PerfilPage() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml new file mode 100644 index 0000000..2a2d36d --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml.cs b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml.cs new file mode 100644 index 0000000..338d9d9 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Mobile/Ebd.MobileApp/Views/Turma/EscolherTurmaBottomSheet.xaml.cs @@ -0,0 +1,11 @@ +using The49.Maui.BottomSheet; + +namespace Ebd.MobileApp.Views.Turma; + +public partial class EscolherTurmaBottomSheet : BottomSheet +{ + public EscolherTurmaBottomSheet() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/EscolaBiblicaDominical/Ebd.Presentation.Api/Properties/ServiceDependencies/admp-prod - Web Deploy/profile.arm.json b/EscolaBiblicaDominical/Ebd.Presentation.Api/Properties/ServiceDependencies/admp-prod - Web Deploy/profile.arm.json new file mode 100644 index 0000000..dfb7eb9 --- /dev/null +++ b/EscolaBiblicaDominical/Ebd.Presentation.Api/Properties/ServiceDependencies/admp-prod - Web Deploy/profile.arm.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_dependencyType": "compute.appService.windows" + }, + "parameters": { + "resourceGroupName": { + "type": "string", + "defaultValue": "EBD", + "metadata": { + "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." + } + }, + "resourceGroupLocation": { + "type": "string", + "defaultValue": "southcentralus", + "metadata": { + "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support." + } + }, + "resourceName": { + "type": "string", + "defaultValue": "admp-prod", + "metadata": { + "description": "Name of the main resource to be created by this template." + } + }, + "resourceLocation": { + "type": "string", + "defaultValue": "[parameters('resourceGroupLocation')]", + "metadata": { + "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." + } + } + }, + "variables": { + "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "name": "[parameters('resourceGroupName')]", + "location": "[parameters('resourceGroupLocation')]", + "apiVersion": "2019-10-01" + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "resourceGroup": "[parameters('resourceGroupName')]", + "apiVersion": "2019-10-01", + "dependsOn": [ + "[parameters('resourceGroupName')]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "location": "[parameters('resourceLocation')]", + "name": "[parameters('resourceName')]", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "tags": { + "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty" + }, + "dependsOn": [ + "[variables('appServicePlan_ResourceId')]" + ], + "kind": "app", + "properties": { + "name": "[parameters('resourceName')]", + "kind": "app", + "httpsOnly": true, + "reserved": false, + "serverFarmId": "[variables('appServicePlan_ResourceId')]", + "siteConfig": { + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ] + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "location": "[parameters('resourceLocation')]", + "name": "[variables('appServicePlan_name')]", + "type": "Microsoft.Web/serverFarms", + "apiVersion": "2015-08-01", + "sku": { + "name": "S1", + "tier": "Standard", + "family": "S", + "size": "S1" + }, + "properties": { + "name": "[variables('appServicePlan_name')]" + } + } + ] + } + } + } + ] +} \ No newline at end of file