diff --git a/.gitignore b/.gitignore index 09b158a..95925a7 100644 Binary files a/.gitignore and b/.gitignore differ diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI.sln b/frontend/HealthcareManagerUI/HealthcareManagerUI.sln index 0a6a25a..335ce5c 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI.sln +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI.sln @@ -1,6 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthcareManagerUI", "HealthcareManagerUI\HealthcareManagerUI.csproj", "{641DCB44-0CC9-43D0-AE58-5A722261F1E1}" +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34616.47 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthcareManagerUI", "HealthcareManagerUI\HealthcareManagerUI.csproj", "{641DCB44-0CC9-43D0-AE58-5A722261F1E1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,4 +16,10 @@ Global {641DCB44-0CC9-43D0-AE58-5A722261F1E1}.Release|Any CPU.ActiveCfg = Release|Any CPU {641DCB44-0CC9-43D0-AE58-5A722261F1E1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {55598450-70ED-4D22-913B-0C99AB8F3F7D} + EndGlobalSection EndGlobal diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Layout/AuthLayout.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Layout/AuthLayout.razor index 3ae314e..0e02478 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Layout/AuthLayout.razor +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Layout/AuthLayout.razor @@ -5,7 +5,7 @@ - +
diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/AlertMessage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/AlertMessage.razor new file mode 100644 index 0000000..32bdaeb --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/AlertMessage.razor @@ -0,0 +1,12 @@ +@if (!string.IsNullOrEmpty(ErrorMessage)) +{ + +} + +@code { + [Parameter] + public string ErrorMessage { get; set; } +} diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ChooseRolePage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ChooseRolePage.razor new file mode 100644 index 0000000..7a1af3f --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ChooseRolePage.razor @@ -0,0 +1,15 @@ +@page "/" +@using HealthcareManagerUI.Components.Layout +@layout AuthLayout + + Choose Role + + +
+

Welcome to Healthcare Manager

+

Please select your role:

+
+ I'm a Doctor + I'm a Patient +
+
diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/DashboardPage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/DashboardPage.razor new file mode 100644 index 0000000..5dee81c --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/DashboardPage.razor @@ -0,0 +1,9 @@ +@page "/dashboard" + + Dashboard + +

Dashboard

+

login success

+@code { + +} diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/LoginPage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/LoginPage.razor index 8deb0c4..6897c05 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/LoginPage.razor +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/LoginPage.razor @@ -1,54 +1,77 @@ -@page "/" +@page "/login/{role}" @using HealthcareManagerUI.Models @using HealthcareManagerUI.Services.Authentication @using HealthcareManagerUI.Components.Layout @layout AuthLayout -@inject AuthenticationService AuthenticationService +@inject IAuthenticationService AuthenticationService +@inject NavigationManager NavigationManager Login + - + + - +

Login

-
- +
+
-
- +
+
- +
+ Register + Reset Password +
+ + @code { - private UserLoginModel userLoginModel = new UserLoginModel(); + [SupplyParameterFromForm] + public UserLoginModel? userLoginModel { get; set; } + + protected override void OnInitialized() + { + userLoginModel ??= new(); + } + + [Parameter] public string Role { get; set; } + private string errorMessage { get; set; } + + private void ClearErrorMessage() + { + errorMessage = string.Empty; + } private async Task HandleLogin() { - var result = await AuthenticationService.Login(userLoginModel); - if (result) + var response = Role switch { - // Handle the successful login, e.g., navigate to another page + "doctor" => await AuthenticationService.LoginDoctor(userLoginModel), + "patient" => await AuthenticationService.LoginPatient(userLoginModel), + _ => null + }; + + if (response.StatusCode >= 200 && response.StatusCode <= 399) + { + NavigationManager.NavigateTo("/dashboard"); } else { - // Handle the failed login, e.g., show an error message + errorMessage = response.Message; } } - - private void HandleSignUp() - { - // Logic for handling sign up - } } \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/RegisterPage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/RegisterPage.razor new file mode 100644 index 0000000..526a43f --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/RegisterPage.razor @@ -0,0 +1,84 @@ +@page "/register/{role}" +@using HealthcareManagerUI.Models +@using HealthcareManagerUI.Services.Authentication +@using HealthcareManagerUI.Components.Layout + +@layout AuthLayout + +@inject IAuthenticationService AuthenticationService +@inject NavigationManager NavigationManager + + + Register + + + + + + + + + +@code { + [SupplyParameterFromForm] + public UserRegisterModel? userRegisterModel { get; set; } + + protected override void OnInitialized() + { + userRegisterModel ??= new(); + } + + [Parameter] public string Role { get; set; } + private string errorMessage { get; set; } + + private void ClearErrorMessage() + { + errorMessage = string.Empty; + } + + private async Task HandleRegister() + { + var response = Role switch + { + "doctor" => await AuthenticationService.RegisterDoctor(userRegisterModel), + "patient" => await AuthenticationService.RegisterPatient(userRegisterModel), + _ => null + }; + + if (response.StatusCode >=200 && response.StatusCode <= 399) + { + NavigationManager.NavigateTo($"/login/{Role}"); + } + else + { + errorMessage = response.Message; + } + } +} \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ResetPasswordPage.razor b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ResetPasswordPage.razor new file mode 100644 index 0000000..2da382d --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Components/Pages/ResetPasswordPage.razor @@ -0,0 +1,75 @@ +@page "/reset-password/{role}" +@using HealthcareManagerUI.Models +@using HealthcareManagerUI.Services.Authentication +@using HealthcareManagerUI.Components.Layout + +@layout AuthLayout + +@inject IAuthenticationService AuthenticationService +@inject NavigationManager NavigationManager + + + Reset your password + + + + + + + + + +@code { + [SupplyParameterFromForm] + public UserRegisterModel? userResetPasswordModel { get; set; } + + protected override void OnInitialized() + { + userResetPasswordModel ??= new(); + } + + [Parameter] public string Role { get; set; } + private string errorMessage { get; set; } + + private void ClearErrorMessage() + { + errorMessage = string.Empty; + } + + private async Task HandleResetPassword() + { + var response = Role switch + { + "doctor" => await AuthenticationService.ResetDoctorPassword(userResetPasswordModel), + "patient" => await AuthenticationService.ResetPatientPassword(userResetPasswordModel), + _ => null + }; + + if (response.StatusCode >= 200 && response.StatusCode <= 399) + { + NavigationManager.NavigateTo($"/login/{Role}"); + } + else + { + errorMessage = response.Message; + } + } +} \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/HealthcareManagerUI.csproj b/frontend/HealthcareManagerUI/HealthcareManagerUI/HealthcareManagerUI.csproj index 7e84133..c487b18 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/HealthcareManagerUI.csproj +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/HealthcareManagerUI.csproj @@ -7,8 +7,8 @@ - <_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css"/> - <_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css.map"/> + <_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css" /> + <_ContentIncludedByDefault Remove="wwwroot\bootstrap\bootstrap.min.css.map" /> diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/BaseResponse.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/BaseResponse.cs new file mode 100644 index 0000000..079adf2 --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/BaseResponse.cs @@ -0,0 +1,10 @@ +namespace HealthcareManagerUI.Models +{ + public class BaseResponse + { + public int StatusCode { get; set; } + public string? Message { get; set; } + public object? Data { get; set; } + } + +} diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/PacientRegisterModel.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/PacientRegisterModel.cs new file mode 100644 index 0000000..2cb4110 --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/PacientRegisterModel.cs @@ -0,0 +1,8 @@ +namespace HealthcareManagerUI.Models; + +public class PatientRegisterModel +{ + public string Name { get; set; } + public string Email { get; set; } + public string Password { get; set; } +} \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/UserRegisterModel.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/UserRegisterModel.cs new file mode 100644 index 0000000..92dde3b --- /dev/null +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Models/UserRegisterModel.cs @@ -0,0 +1,9 @@ +namespace HealthcareManagerUI.Models; + +public class UserRegisterModel +{ + public string Name { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string Description { get; set; } +} \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Program.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Program.cs index 2a38b58..cff7cba 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Program.cs +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Program.cs @@ -1,5 +1,6 @@ using HealthcareManagerUI.Components; using HealthcareManagerUI.Services.Authentication; +using HealthcareManagerUI.Services.Http; var builder = WebApplication.CreateBuilder(args); @@ -7,7 +8,12 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); -builder.Services.AddTransient(); +builder.Services.AddScoped(provider => +{ + var configuration = provider.GetRequiredService(); + return new HttpService(configuration); +}); +builder.Services.AddScoped(); var app = builder.Build(); @@ -22,7 +28,6 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); - app.MapRazorComponents() .AddInteractiveServerRenderMode(); diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/AuthenticationService.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/AuthenticationService.cs index a36ae50..47fb2e1 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/AuthenticationService.cs +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/AuthenticationService.cs @@ -2,17 +2,128 @@ using HealthcareManagerUI.Services.Http; namespace HealthcareManagerUI.Services.Authentication; +// In AuthenticationService.cs public class AuthenticationService : IAuthenticationService { - public async Task Register(UserLoginModel userLoginModel) + private readonly IHttpService _httpService; + private readonly string _apiUrl = "http://localhost:5151/api"; + + public AuthenticationService(IHttpService httpService) { - var requestHandler = new HttpService(); - await requestHandler.PostAsync<>() - return true; + _httpService = httpService; } - public async Task Login(UserLoginModel userLoginModel) + public async Task LoginDoctor(UserLoginModel userLoginModel) { - return true; + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Doctors/login", userLoginModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse + { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } } -} \ No newline at end of file + + public async Task LoginPatient(UserLoginModel userLoginModel) + { + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Patients/login", userLoginModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } + } + + public async Task RegisterDoctor(UserRegisterModel userRegistrationModel) + { + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Doctors/register", userRegistrationModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse + { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } + } + + public async Task RegisterPatient(UserRegisterModel userRegisterModel) + { + var patientRegisterDto = new PatientRegisterModel + { + Name = userRegisterModel.Name, + Email = userRegisterModel.Email, + Password = userRegisterModel.Password + }; + + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Patients/register", userRegisterModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse + { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } + } + + public async Task ResetDoctorPassword(UserRegisterModel userResetPasswordModel) + { + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Doctors/reset_password", userResetPasswordModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse + { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } + } + + public async Task ResetPatientPassword(UserRegisterModel userResetPasswordModel) + { + try + { + var response = await _httpService.PostAsync($"{_apiUrl}/Patients/reset_password", userResetPasswordModel); + return response; + } + catch (Exception ex) + { + return new BaseResponse + { + StatusCode = 400, + Data = null, + Message = ex.Message + }; + } + } +} diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/IAuthenticationService.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/IAuthenticationService.cs index c929b9c..00eb339 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/IAuthenticationService.cs +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Authentication/IAuthenticationService.cs @@ -4,6 +4,15 @@ namespace HealthcareManagerUI.Services.Authentication; public interface IAuthenticationService { - Task Register(UserLoginModel userLoginModel); - Task Login(UserLoginModel userLoginModel); + Task LoginDoctor(UserLoginModel userLoginModel); + + Task LoginPatient(UserLoginModel userLoginModel); + + Task RegisterDoctor(UserRegisterModel userRegistrationModel); + + Task RegisterPatient(UserRegisterModel userRegistrationModel); + + Task ResetDoctorPassword(UserRegisterModel userResetPasswordModel); + + Task ResetPatientPassword(UserRegisterModel userResetPasswordModel); } \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Http/HttpService.cs b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Http/HttpService.cs index ee03956..5ba0f68 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Http/HttpService.cs +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/Services/Http/HttpService.cs @@ -5,6 +5,13 @@ namespace HealthcareManagerUI.Services.Http; public class HttpService : IHttpService { + private readonly string _apiKey; + + public HttpService(IConfiguration configuration) + { + _apiKey = configuration.GetValue("ApiKey") ?? "NoKey"; + } + public async Task GetAsync(string uri, IDictionary headers = null) { using var httpClient = new HttpClient(); @@ -12,7 +19,6 @@ public class HttpService : IHttpService AddHeaders(request, headers); var response = await httpClient.SendAsync(request); - response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize( @@ -32,7 +38,6 @@ public class HttpService : IHttpService request.Content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json"); var response = await httpClient.SendAsync(request); - response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize( @@ -47,7 +52,6 @@ public class HttpService : IHttpService request.Content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json"); var response = await httpClient.SendAsync(request); - response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize( @@ -61,13 +65,19 @@ public class HttpService : IHttpService AddHeaders(request, headers); var response = await httpClient.SendAsync(request); - response.EnsureSuccessStatusCode(); } private void AddHeaders(HttpRequestMessage request, IDictionary headers) { + // Add the API key header to every request + request.Headers.Add("ApiKey", _apiKey); + if (headers != null) + { foreach (var header in headers) + { request.Headers.Add(header.Key, header.Value); + } + } } } \ No newline at end of file diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/appsettings.json b/frontend/HealthcareManagerUI/HealthcareManagerUI/appsettings.json index 10f68b8..bb3dc9e 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/appsettings.json +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/appsettings.json @@ -5,5 +5,6 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ApiKey": "testapikey" } diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/AuthLayout.css b/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/AuthLayout.css index b0ff3ce..d90a803 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/AuthLayout.css +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/AuthLayout.css @@ -29,5 +29,43 @@ body { } .container { - z-index: 1; /* Above the background */ + z-index: 1; +} + +/* New styles for title and subtitle */ +.landingTitle { + color: #ffffff; + text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.7); + font-size: 3.5rem; + font-weight: bold; + background: rgba(255, 255, 255, 0.2); + padding: 0.5rem; + border-radius: 0.5rem; + display: inline-block; /* Wrap the background to the text */ + margin-top: 2rem; /* Give some space from the top */ +} + +.landingSubtitle { + color: #dcdcdc; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); + font-size: 2rem; + padding: 0.25rem; + border-radius: 0.5rem; + display: block; /* Wrap the background to the text */ + margin-bottom: 2rem; /* Give some space before the buttons */ +} + +.centered-menu { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + text-align: center; +} + +.button-container { + display: flex; + flex-direction: row; /* This will align the buttons side by side */ + justify-content: center; /* Center the buttons within the container */ } diff --git a/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/LoginPage.css b/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/LoginPage.css index 159fcaa..a4410da 100644 --- a/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/LoginPage.css +++ b/frontend/HealthcareManagerUI/HealthcareManagerUI/wwwroot/LoginPage.css @@ -61,7 +61,6 @@ input { width: 70%; padding: 1rem; margin: 0.7rem; - background-color: #1B1A55; border-radius: 10px; }