finalizare 1.0
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
@namespace HealthcareManagerUiWebAssem.Components
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="/">MyApp</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/dashboard">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/users">Users</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/settings">Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link btn btn-link" @onclick="Logout">Logout</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@code {
|
||||
|
||||
private async Task Logout()
|
||||
{
|
||||
await AuthenticationService.Logout();
|
||||
// Redirect the user to the login page or somewhere relevant
|
||||
NavigationManager.NavigateTo("/login", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
@namespace HealthcareManagerUiWebAssem.Components
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="/">MyApp</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/login">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/register">Register</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/reset-password">Reset Password</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -0,0 +1,45 @@
|
||||
@namespace HealthcareManagerUiWebAssem.Components
|
||||
|
||||
<div class="sidebar">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="/">MyApp</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/doctor/dashboard">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/doctor/profile">Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/doctor/patients_medical_history">Patients' Medical History</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/doctor/ai">Sickness Software</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/doctor/chat">Chat</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link btn btn-link" @onclick="Logout">Logout</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@code {
|
||||
|
||||
private async Task Logout()
|
||||
{
|
||||
await AuthenticationService.Logout();
|
||||
// Redirect the user to the login page or somewhere relevant
|
||||
NavigationManager.NavigateTo("/login", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/AuthLayout.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
@Body
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
@if (!string.IsNullOrEmpty(ErrorMessage))
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<strong>Error:</strong> @ErrorMessage
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string ErrorMessage { get; set; }
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
@page "/"
|
||||
|
||||
@layout AuthLayout
|
||||
<head>
|
||||
<title>Choose Role</title>
|
||||
</head>
|
||||
<link rel="stylesheet" href="bootstrap/dist/css/bootstrap.min.css"/>
|
||||
<div class="text-center mt-5 centered-menu">
|
||||
<h1 class="landingTitle">Welcome to Healthcare Manager</h1>
|
||||
<p class="landingSubtitle">Please select your role:</p>
|
||||
<div class="button-container">
|
||||
<NavLink class="btn btn-primary m-2" href="/login/doctor">I'm a Doctor</NavLink>
|
||||
<NavLink class="btn btn-secondary m-2" href="/login/patient">I'm a Patient</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,44 +0,0 @@
|
||||
@page "/dashboard/{Role}"
|
||||
|
||||
<head>
|
||||
<title>Dashboard</title>
|
||||
</head>
|
||||
<link rel="stylesheet" href="/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.22.4/dist/bootstrap-table.min.css">
|
||||
<link href="https://cdn.datatables.net/2.0.4/css/dataTables.bootstrap5.css" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<style>
|
||||
.select,
|
||||
#locale {
|
||||
width: 100%;
|
||||
}
|
||||
.like {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.modal-backdrop.show {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<NavLink class="btn btn-primary m-2 position-absolute top-0 end-0" href="@($"/my-profile/{Role}")">My Profile</NavLink>
|
||||
|
||||
@switch (Role)
|
||||
{
|
||||
case "doctor":
|
||||
<DoctorDashboard/>
|
||||
break;
|
||||
case "patient":
|
||||
<PatientDashboard/>
|
||||
break;
|
||||
default:
|
||||
<p>Unknown role. Please contact support.</p>
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter] public string Role { get; set; }
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
@using System.Text.Json
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Profile
|
||||
@using HealthcareManagerUiWebAssem.Services.Appointment
|
||||
@using HealthcareManagerUiWebAssem.Services.User
|
||||
@inject UserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject IAppointmentService AppointmentService
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<div class="container mt-3">
|
||||
<h2 class="landingTitle">Doctor Menu</h2>
|
||||
<p class="landingSubtitle">Here you can manage appointments, review your patients' medical history and chat with your patients.</p>
|
||||
<div id="accordion">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<a class="btn" data-bs-toggle="collapse" href="#collapseOne">
|
||||
Appointments
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="collapse show" data-bs-parent="#accordion">
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>Patient Name</th>
|
||||
|
||||
<th>Appointment Time</th>
|
||||
|
||||
<th>Delete</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
@foreach (var appointment in appointments)
|
||||
|
||||
{
|
||||
|
||||
@foreach (var date in appointment.AppointmentsList)
|
||||
|
||||
{
|
||||
|
||||
<tr>
|
||||
|
||||
<td>@GetPatientName(new Guid(appointment.PatientId))</td>
|
||||
|
||||
<td>@date.ToString("yyyy-MM-dd HH:mm")</td>
|
||||
|
||||
<td><button class="btn btn-danger" @onclick="(() => DeleteAppointment(appointment))">Delete</button></td>
|
||||
|
||||
</tr>
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<AppointmentTableComponent appointments="appointments" OnAppointmentDeleted="HandleAppointmentDeleted" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ... other patient-specific cards ... -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<Patient> patients;
|
||||
private string selectedDoctorId;
|
||||
private DateTime? selectedDate;
|
||||
private List<Appointment> appointments;
|
||||
private List<byte[]> medicalHistoryFiles;
|
||||
[Parameter] public string Role { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await InitializePatients();
|
||||
await LoadAppointments();
|
||||
}
|
||||
|
||||
private async Task LoadAppointments()
|
||||
{
|
||||
var response = await AppointmentService.GetAppointmentsByDoctor(UserService.UserId);
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
if (response.StatusCode == HttpStatusCodes.OK)
|
||||
{
|
||||
appointments = JsonSerializer.Deserialize<List<Appointment>>(response.Data, jsonOptions) ?? new List<Appointment>();
|
||||
}
|
||||
else
|
||||
{
|
||||
appointments = new List<Appointment>();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializePatients()
|
||||
{
|
||||
var response = await ProfileService.GetPatients();
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
if (response.StatusCode == HttpStatusCodes.OK)
|
||||
{
|
||||
patients = JsonSerializer.Deserialize<List<Patient>>(response.Data, jsonOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void AddMedicalHistoryFile()
|
||||
|
||||
{
|
||||
|
||||
// Logic for adding a new appointment
|
||||
|
||||
}
|
||||
|
||||
private async Task DeleteAppointment(Appointment appointmentToDelete)
|
||||
|
||||
{
|
||||
|
||||
var appointmentModelToDelete = new AppointmentManagementModel
|
||||
|
||||
{
|
||||
|
||||
PatientId = new Guid(appointmentToDelete.PatientId),
|
||||
|
||||
DoctorId = new Guid(appointmentToDelete.DoctorId),
|
||||
|
||||
Appointment = appointmentToDelete.AppointmentsList.FirstOrDefault()
|
||||
|
||||
};
|
||||
|
||||
await AppointmentService.DeleteAppointment(appointmentModelToDelete);
|
||||
|
||||
appointments.Remove(appointmentToDelete);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string GetPatientName(Guid patientId)
|
||||
{
|
||||
var patient = patients.Select(d => d).FirstOrDefault(d => d.Id == patientId);
|
||||
return patient?.Name ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
@page "/login/{role}"
|
||||
@using System.Text.Json
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Authentication
|
||||
@using HealthcareManagerUiWebAssem.Services.User
|
||||
@using HealthcareManagerUiWebAssem.Services.UserSessionInformation
|
||||
|
||||
@layout AuthLayout
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject IUserSessionInformation UserSessionInformation;
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject UserService UserService
|
||||
|
||||
|
||||
<head>
|
||||
<title>Login</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<link rel="stylesheet" href="/LoginPage.css"/>
|
||||
<link rel="stylesheet" href="/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
|
||||
<EditForm Model="userLoginModel" OnValidSubmit="@HandleLogin" FormName="LoginForm" class="login-form container mt-5">
|
||||
<DataAnnotationsValidator/>
|
||||
<ValidationSummary/>
|
||||
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-center mb-3">Login</h3>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="email" class="form-control" placeholder="Email" @bind-Value="userLoginModel!.Email"></InputText>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="password" class="form-control" type="password" placeholder="Password" @bind-Value="userLoginModel!.Password"></InputText>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 mb-3">Log In</button>
|
||||
<div class="button-container">
|
||||
<NavLink class="btn btn-secondary m-2" href="@($"/register/{Role}")">Register</NavLink>
|
||||
<NavLink class="btn btn-secondary m-2" href="@($"/reset-password/{Role}")">Reset Password</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
<AlertMessage ErrorMessage="@errorMessage"/>
|
||||
|
||||
@code {
|
||||
[SupplyParameterFromForm] public UserLoginModel? userLoginModel { get; set; }
|
||||
private BaseResponse? loginResponse;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
userLoginModel ??= new UserLoginModel();
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public string Role { get; set; }
|
||||
private string errorMessage { get; set; }
|
||||
private bool loginSuccesful { get; set; }
|
||||
|
||||
private void ClearErrorMessage()
|
||||
{
|
||||
errorMessage = string.Empty;
|
||||
}
|
||||
|
||||
private async Task HandleLogin()
|
||||
{
|
||||
userLoginModel.UserType = Role;
|
||||
loginResponse = await AuthenticationService.Login(userLoginModel); // Store response instead of immediately processing
|
||||
if (loginResponse.StatusCode < 200 || loginResponse.StatusCode > 299)
|
||||
{
|
||||
errorMessage = loginResponse?.Message ?? "An error occurred."; // Handle error states immediately if required
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
var userId = Guid.Empty;
|
||||
var authToken = "";
|
||||
Console.WriteLine("Printing headers");
|
||||
foreach (var (key, value) in loginResponse.Headers)
|
||||
{
|
||||
Console.WriteLine($"{key} => {value}");
|
||||
}
|
||||
|
||||
if (loginResponse.Headers.TryGetValue("Authorization", out var token))
|
||||
{
|
||||
authToken = token;
|
||||
}
|
||||
|
||||
if (Role.Equals("doctor", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var doctor = JsonSerializer.Deserialize<Doctor>(
|
||||
loginResponse.Data,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
await UserSessionInformation.SaveUserInformationAsync(doctor.Id, Role, doctor.Email, doctor.Name, authToken);
|
||||
userId = doctor.Id;
|
||||
}
|
||||
else if (Role.Equals("patient", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var patient = JsonSerializer.Deserialize<Patient>(
|
||||
loginResponse.Data,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
await UserSessionInformation.SaveUserInformationAsync(patient.Id, Role, patient.Email, patient.Name, authToken);
|
||||
userId = patient.Id;
|
||||
}
|
||||
|
||||
loginResponse = null;
|
||||
|
||||
UserService.SetUserId(userId);
|
||||
NavigationManager.NavigateTo($"/dashboard/{Role}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
@page "/my-profile/{Role}"
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Authentication
|
||||
@using HealthcareManagerUiWebAssem.Services.Profile
|
||||
@using HealthcareManagerUiWebAssem.Services.User
|
||||
@using HealthcareManagerUiWebAssem.Services.UserSessionInformation
|
||||
|
||||
@layout AuthLayout
|
||||
@inject IUserSessionInformation UserSessionInformation;
|
||||
@inject IAuthenticationService AuthenticationService;
|
||||
@inject IProfileService ProfileService
|
||||
@inject UserService UserService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<head>
|
||||
<title>My Profile</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<link rel="stylesheet" href="/LoginPage.css"/>
|
||||
<link rel="stylesheet" href="/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
|
||||
<h3>My Profile</h3>
|
||||
@if (profile != null)
|
||||
{
|
||||
<EditForm Model="profile" OnValidSubmit="@HandleUpdateProfile" FormName="UpdateProfileForm" class="login-form container mt-5">
|
||||
<DataAnnotationsValidator/>
|
||||
<ValidationSummary/>
|
||||
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-body">
|
||||
<div class="form-group mb-3">
|
||||
<label for="name">Name:</label>
|
||||
<InputText id="name" class="form-control" @bind-Value="@profile!.Name"></InputText>
|
||||
</div>
|
||||
|
||||
@if (Role.Equals("doctor", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
<div class="form-group mb-3">
|
||||
<label for="description">Description:</label>
|
||||
<InputText id="description" class="form-control" @bind-Value="@profile!.Description"></InputText>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label for="email">Email:</label>
|
||||
<InputText id="email" class="form-control" @bind-Value="@profile!.Email"></InputText>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label for="password">Password:</label>
|
||||
<InputText id="password" class="form-control" type="password" @bind-Value="@profile!.Password"></InputText>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
<button type="button" class="btn btn-danger" @onclick="@HandleDeleteProfile">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
|
||||
<AlertMessage ErrorMessage="@errorMessage"/>
|
||||
}
|
||||
|
||||
@code {
|
||||
|
||||
[SupplyParameterFromForm] public UserUpdateProfileModel? profile { get; set; }
|
||||
|
||||
[Parameter] public string Role { get; set; }
|
||||
private string errorMessage;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var tokenDto = new TokenRefreshModel(await UserSessionInformation.GetTokenAsync());
|
||||
var refreshResult = await AuthenticationService.RefreshToken(tokenDto);
|
||||
if (refreshResult.StatusCode < HttpStatusCodes.BadRequest)
|
||||
{
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
|
||||
profile ??= await UserService.InitializeProfile(Role, ProfileService);
|
||||
var userId = await UserSessionInformation.GetIdAsync();
|
||||
}
|
||||
|
||||
private async Task HandleUpdateProfile()
|
||||
{
|
||||
profile.Id = UserService.UserId;
|
||||
var response = Role switch
|
||||
{
|
||||
"doctor" => await ProfileService.UpdateDoctorProfile(profile),
|
||||
"patient" => await ProfileService.UpdatePatientProfile(profile),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (response.StatusCode >= 200 && response.StatusCode <= 299)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/my-profile/{Role}");
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage = response?.Message ?? "An error occurred.";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleDeleteProfile()
|
||||
{
|
||||
var response = Role switch
|
||||
{
|
||||
"doctor" => await ProfileService.DeleteDoctorProfile(UserService.UserId),
|
||||
"patient" => await ProfileService.DeletePatientProfile(UserService.UserId),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (response.StatusCode >= 200 && response.StatusCode <= 299)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/login/{Role}");
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage = response?.Message ?? "An error occurred.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
@using System.Text.Json
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Profile
|
||||
@using HealthcareManagerUiWebAssem.Services.Appointment
|
||||
@using HealthcareManagerUiWebAssem.Services.User
|
||||
@inject UserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject IAppointmentService AppointmentService
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<div class="container mt-3">
|
||||
<h2 class="landingTitle">Patient Menu</h2>
|
||||
<p class="landingSubtitle">Here you can manage appointments, review your medical history and chat with doctors.</p>
|
||||
<div id="accordion">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<a class="btn" data-bs-toggle="collapse" href="#collapseOne">
|
||||
Appointments
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="collapse show" data-bs-parent="#accordion">
|
||||
<div class="card-body">
|
||||
<button @onclick="ShowAddAppointmentModal" class="btn btn-primary">Add Appointment</button>
|
||||
<table class="table">
|
||||
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>Doctor Name</th>
|
||||
|
||||
<th>Appointment Time</th>
|
||||
|
||||
<th>Delete</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
@foreach (var appointment in appointments)
|
||||
|
||||
{
|
||||
|
||||
@foreach (var date in appointment.AppointmentsList)
|
||||
|
||||
{
|
||||
|
||||
<tr>
|
||||
|
||||
<td>@GetDoctorName(new Guid(appointment.DoctorId))</td>
|
||||
|
||||
<td>@date.ToString("yyyy-MM-dd HH:mm")</td>
|
||||
|
||||
<td><button class="btn btn-danger" @onclick="(() => DeleteAppointment(appointment))">Delete</button></td>
|
||||
|
||||
</tr>
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<AppointmentTableComponent appointments="appointments" OnAppointmentDeleted="HandleAppointmentDeleted" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ... other patient-specific cards ... -->
|
||||
</div>
|
||||
<div class="modal" id="addAppointmentModal" tabindex="-1" aria-labelledby="addAppointmentModalLabel" data-backdrop="false">
|
||||
|
||||
<div class="modal-dialog">
|
||||
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
|
||||
<h5 class="modal-title" id="addAppointmentModalLabel">Add Appointment</h5>
|
||||
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
@if (doctors != null)
|
||||
|
||||
{
|
||||
|
||||
<select @bind="selectedDoctorId" class="form-select">
|
||||
|
||||
<option value="">Select a doctor</option>
|
||||
|
||||
@foreach (var doctor in doctors)
|
||||
|
||||
{
|
||||
|
||||
<option value="@doctor.Id">@doctor.Name</option>
|
||||
|
||||
}
|
||||
|
||||
</select>
|
||||
|
||||
<input type="datetime-local" @bind="selectedDate" class="form-control" />
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
<p>Loading doctors...</p>
|
||||
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
|
||||
<button @onclick="CreateAppointment" type="button" class="btn btn-primary">Create Appointment</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<Doctor> doctors;
|
||||
private string selectedDoctorId;
|
||||
private DateTime? selectedDate;
|
||||
private List<Appointment> appointments;
|
||||
private List<byte[]> medicalHistoryFiles;
|
||||
[Parameter] public string Role { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await InitializeDoctors();
|
||||
await LoadAppointments();
|
||||
}
|
||||
|
||||
private async Task LoadAppointments()
|
||||
{
|
||||
var response = await AppointmentService.GetAppointmentsByPatient(UserService.UserId);
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
if (response.StatusCode == HttpStatusCodes.OK)
|
||||
{
|
||||
appointments = JsonSerializer.Deserialize<List<Appointment>>(response.Data, jsonOptions) ?? new List<Appointment>();
|
||||
}
|
||||
else
|
||||
{
|
||||
appointments = new List<Appointment>();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ShowAddAppointmentModal()
|
||||
{
|
||||
await JS.InvokeVoidAsync("eval", "new bootstrap.Modal(document.getElementById('addAppointmentModal')).show();");
|
||||
}
|
||||
|
||||
private async Task InitializeDoctors()
|
||||
{
|
||||
var response = await ProfileService.GetDoctors();
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
if (response.StatusCode == HttpStatusCodes.OK)
|
||||
{
|
||||
doctors = JsonSerializer.Deserialize<List<Doctor>>(response.Data, jsonOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle error
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateAppointment()
|
||||
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(selectedDoctorId) || !selectedDate.HasValue)
|
||||
|
||||
{
|
||||
|
||||
// Handle validation
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Call AddAppointment method, which is not shown here
|
||||
|
||||
var createAppointmentModel = new AppointmentManagementModel
|
||||
|
||||
{
|
||||
|
||||
PatientId = UserService.UserId,
|
||||
|
||||
DoctorId = new Guid(selectedDoctorId),
|
||||
|
||||
Appointment = (DateTime)selectedDate
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
await AppointmentService.CreateAppointment(createAppointmentModel);
|
||||
|
||||
// You'll need to pass UserService.UserId, selectedDoctorId, and selectedDate.Value to it
|
||||
|
||||
|
||||
|
||||
// Close the modal after creation
|
||||
|
||||
await JS.InvokeVoidAsync("eval", "new bootstrap.Modal(document.getElementById('addAppointmentModal')).hide();");
|
||||
|
||||
|
||||
|
||||
// Optionally, refresh the appointments list
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void AddMedicalHistoryFile()
|
||||
|
||||
{
|
||||
|
||||
// Logic for adding a new appointment
|
||||
|
||||
}
|
||||
|
||||
private async Task DeleteAppointment(Appointment appointmentToDelete)
|
||||
|
||||
{
|
||||
|
||||
var appointmentModelToDelete = new AppointmentManagementModel
|
||||
|
||||
{
|
||||
|
||||
PatientId = new Guid(appointmentToDelete.PatientId),
|
||||
|
||||
DoctorId = new Guid(appointmentToDelete.DoctorId),
|
||||
|
||||
Appointment = appointmentToDelete.AppointmentsList.FirstOrDefault()
|
||||
|
||||
};
|
||||
|
||||
await AppointmentService.DeleteAppointment(appointmentModelToDelete);
|
||||
|
||||
appointments.Remove(appointmentToDelete);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string GetDoctorName(Guid doctorId)
|
||||
{
|
||||
var doctor = doctors.Select(d => d).FirstOrDefault(d => d.Id == doctorId);
|
||||
return doctor?.Name ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
@page "/register/{role}"
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Authentication
|
||||
|
||||
@layout AuthLayout
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<head>
|
||||
<title>Register</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<link rel="stylesheet" href="/LoginPage.css"/>
|
||||
<link rel="stylesheet" href="/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
|
||||
<EditForm Model="userRegisterModel" OnValidSubmit="@HandleRegister" FormName="RegisterForm" class="login-form container mt-5">
|
||||
<DataAnnotationsValidator/>
|
||||
<ValidationSummary/>
|
||||
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-center mb-3">Register</h3>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="name" class="form-control" placeholder="Name" @bind-Value="userRegisterModel!.Name"></InputText>
|
||||
</div>
|
||||
@if (Role.Equals("doctor", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="description" class="form-control" placeholder="Description" @bind-Value="userRegisterModel!.Description"></InputText>
|
||||
</div>
|
||||
}
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="email" class="form-control" placeholder="Email" @bind-Value="userRegisterModel!.Email"></InputText>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="password" class="form-control" type="password" placeholder="Password" @bind-Value="userRegisterModel!.Password"></InputText>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button type="submit" class="btn btn-primary w-100 mb-3">Register</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
<AlertMessage ErrorMessage="@errorMessage"/>
|
||||
|
||||
@code {
|
||||
[SupplyParameterFromForm] public UserRegisterModel? userRegisterModel { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
userRegisterModel ??= new UserRegisterModel();
|
||||
}
|
||||
|
||||
[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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
@page "/reset-password/{role}"
|
||||
@using HealthcareManagerUiWebAssem.Models
|
||||
@using HealthcareManagerUiWebAssem.Services.Authentication
|
||||
|
||||
@layout AuthLayout
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<head>
|
||||
<title>Reset your password</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<link rel="stylesheet" href="/LoginPage.css"/>
|
||||
<link rel="stylesheet" href="/bootstrap/dist/css/bootstrap.min.css"/>
|
||||
|
||||
<EditForm Model="userResetPasswordModel" OnValidSubmit="@HandleResetPassword" FormName="ResetPasswordForm" class="login-form container mt-5">
|
||||
<DataAnnotationsValidator/>
|
||||
<ValidationSummary/>
|
||||
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-center mb-3">Register</h3>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="email" class="form-control" placeholder="Email" @bind-Value="userResetPasswordModel!.Email"></InputText>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<InputText id="password" class="form-control" type="password" placeholder="New Password" @bind-Value="userResetPasswordModel!.Password"></InputText>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button type="submit" class="btn btn-primary w-100 mb-3">Reset Password</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
<AlertMessage ErrorMessage="@errorMessage"/>
|
||||
|
||||
@code {
|
||||
[SupplyParameterFromForm] public UserLoginModel? userResetPasswordModel { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
userResetPasswordModel ??= new UserLoginModel();
|
||||
}
|
||||
|
||||
[Parameter] public string Role { get; set; }
|
||||
private string errorMessage { get; set; }
|
||||
|
||||
private void ClearErrorMessage()
|
||||
{
|
||||
errorMessage = string.Empty;
|
||||
}
|
||||
|
||||
private async Task HandleResetPassword()
|
||||
{
|
||||
userResetPasswordModel.UserType = Role;
|
||||
var response = await AuthenticationService.ResetPassword(userResetPasswordModel);
|
||||
|
||||
if (response.StatusCode >= 200 && response.StatusCode <= 399)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/login/{Role}");
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage = response.Message;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
@namespace HealthcareManagerUiWebAssem.Components
|
||||
|
||||
<div class="sidebar">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="/">MyApp</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/dashboard">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/doctors">Meet Our Doctors</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/profile">Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/appointments">Appointments</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/medical_history">Medical History</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/doctor_access">Doctor Access</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/patient/chat">Chat</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link btn btn-link" @onclick="Logout">Logout</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@code {
|
||||
|
||||
private async Task Logout()
|
||||
{
|
||||
await AuthenticationService.Logout();
|
||||
// Redirect the user to the login page or somewhere relevant
|
||||
NavigationManager.NavigateTo("/login", true);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user