finalizare 1.0

This commit is contained in:
andrei-mihnea-cerbu
2024-05-21 12:10:53 +03:00
parent f7795f7519
commit 1cc1d34003
11268 changed files with 2102399 additions and 10909 deletions
+103
View File
@@ -0,0 +1,103 @@
@page "/doctor/ai"
@attribute [Authorize(Roles = UserRoles.Doctor)]
@layout DoctorLayout
@inject IDoctorManagementService DoctorManagementService
<h3>AI Sickness Prediction</h3>
@if (!string.IsNullOrEmpty(statusMessage))
{
<div class="alert @(isSuccess ? "alert-success" : "alert-danger")" role="alert">
@statusMessage
</div>
}
<div class="card mt-4">
<div class="card-header">
Upload PDF Document
</div>
<div class="card-body">
<InputFile OnChange="HandleFileSelected"/>
</div>
</div>
@if (predictions != null && predictions.Count > 0)
{
<div class="mt-4">
<h4>Predictions:</h4>
<ul>
@foreach (var prediction in predictions)
{
<li>@prediction.Disease - Probability: @prediction.Probability%</li>
}
</ul>
</div>
}
@code {
private string statusMessage = string.Empty;
private bool isSuccess = false;
private List<PredictionResult> predictions;
private async Task HandleFileSelected(InputFileChangeEventArgs e)
{
try
{
var file = e.File;
await using var stream = file.OpenReadStream();
using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
var fileContent = memoryStream.ToArray();
var text = await ExtractTextFromPdf(fileContent);
Console.WriteLine(text);
if (!string.IsNullOrEmpty(text))
{
var result = await DoctorManagementService.GetSicknessPrediction(text);
if (result != null)
{
predictions = result.Data;
statusMessage = result.Message;
isSuccess = true;
}
else
{
statusMessage = "Failed to get predictions from the AI service.";
isSuccess = false;
}
}
else
{
statusMessage = "Failed to extract text from PDF.";
isSuccess = false;
}
}
catch (Exception ex)
{
statusMessage = $"Error: {ex.Message}";
isSuccess = false;
}
}
private async Task<string> ExtractTextFromPdf(byte[] pdfBytes)
{
using var reader = new MemoryStream(pdfBytes);
using var pdfReader = new PdfReader(reader);
using var pdfDoc = new PdfDocument(pdfReader);
var text = new StringBuilder();
for (int i = 1; i <= pdfDoc.GetNumberOfPages(); i++)
{
var strategy = new SimpleTextExtractionStrategy();
var pageText = PdfTextExtractor.GetTextFromPage(pdfDoc.GetPage(i), strategy);
text.AppendLine(pageText);
}
return text.ToString();
}
}
+129
View File
@@ -0,0 +1,129 @@
@page "/doctor/chat"
@attribute [Authorize(Roles = UserRoles.Doctor)]
@layout DoctorLayout
@inject IDoctorManagementService DoctorManagementService
@inject IAuthenticationService AuthenticationService
<h3>Chat with Patients</h3>
@if (!string.IsNullOrEmpty(statusMessage))
{
<div class="alert @(isSuccess ? "alert-success" : "alert-danger")" role="alert">
@statusMessage
</div>
}
<div class="row">
<div class="col-md-4">
<div class="list-group">
@foreach (var patient in patients)
{
<button class="list-group-item list-group-item-action" @onclick="() => OpenChat(patient.Id, patient.Name)">
@patient.Name
</button>
}
</div>
</div>
<div class="col-md-8">
@if (selectedPatient != null)
{
<div class="card">
<div class="card-header">
Chat with @selectedPatient.Name
<button class="btn btn-sm btn-danger float-right" @onclick="CloseChat">Close</button>
</div>
<div class="card-body chat-body">
@foreach (var message in messages)
{
<div class="chat-message @(message.UserId == userInfo.Id ? "chat-message-sender" : "chat-message-receiver")">
<strong>@(message.UserId == userInfo.Id ? "You" : selectedPatient.Name):</strong> @message.Content
</div>
}
</div>
<div class="card-footer">
<input type="text" class="form-control" @bind="newMessage" @onkeydown="HandleKeyDown" placeholder="Type your message..."/>
<button class="btn btn-primary mt-2" @onclick="SendMessage">Send</button>
</div>
</div>
}
</div>
</div>
<style>
.chat-body {
height: 300px;
overflow-y: scroll;
}
.chat-message {
margin-bottom: 10px;
}
.chat-message-sender {
text-align: right;
}
.chat-message-receiver {
text-align: left;
}
</style>
@code {
private string statusMessage = string.Empty;
private bool isSuccess = false;
private List<Patient> patients = new();
private Patient selectedPatient;
private List<Message> messages = new();
private string newMessage = string.Empty;
private UserInformation userInfo;
protected override async Task OnInitializedAsync()
{
userInfo = await AuthenticationService.GetUserInformation();
patients = await DoctorManagementService.GetAllPatientsAsync();
}
private async Task OpenChat(Guid patientId, string patientName)
{
selectedPatient = new Patient { Id = patientId, Name = patientName };
var chat = await DoctorManagementService.GetConversationAsync(userInfo.Id, patientId);
messages = chat?.Messages ?? new List<Message>();
StateHasChanged();
}
private void CloseChat()
{
selectedPatient = null;
messages.Clear();
}
private async Task SendMessage()
{
if (!string.IsNullOrWhiteSpace(newMessage) && selectedPatient != null)
{
var success = await DoctorManagementService.SendMessageAsync(userInfo.Id, selectedPatient.Id, newMessage);
if (success)
{
messages.Add(new Message(userInfo.Id, newMessage));
newMessage = string.Empty;
StateHasChanged();
}
else
{
statusMessage = "Failed to send message.";
isSuccess = false;
}
}
}
private void HandleKeyDown(KeyboardEventArgs e)
{
if (e.Key == "Enter")
{
SendMessage().GetAwaiter().GetResult();
}
}
}
+122
View File
@@ -0,0 +1,122 @@
@page "/doctor/dashboard"
@attribute [Authorize(Roles = UserRoles.Doctor)]
@layout DoctorLayout
@inject IAuthenticationService AuthenticationService
@inject IDoctorManagementService DoctorManagementService
@inject NavigationManager NavigationManager
<h3>Dashboard</h3>
@if (!string.IsNullOrEmpty(errorMessage))
{
<div class="alert alert-danger" role="alert">
@errorMessage
</div>
}
@if (!string.IsNullOrEmpty(username))
{
<p>Welcome, Dr. @username!</p>
<p>Here you have listed your active appointments with patients.</p>
}
@if (appointments != null && appointments.Count > 0)
{
<table class="table">
<thead>
<tr>
<th>Patient</th>
<th>Time</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var appointment in appointments)
{
foreach (var appointmentTime in appointment.AppointmentsList)
{
<tr>
<td>@patients[Guid.Parse(appointment.PatientId)]</td>
<td>@appointmentTime.ToString("g")</td>
<td>
<button class="btn btn-danger" @onclick="() => DeleteAppointment(appointment, appointmentTime)">Delete</button>
</td>
</tr>
}
}
</tbody>
</table>
}
else if (string.IsNullOrEmpty(errorMessage))
{
<p>No appointments exist.</p>
}
@code {
private string username;
private List<Appointment> appointments = new();
private Dictionary<Guid, string> patients = new();
private string errorMessage = string.Empty;
protected override async Task OnInitializedAsync()
{
try
{
var userInfo = await AuthenticationService.GetUserInformation();
username = userInfo.Name;
appointments = await DoctorManagementService.GetAppointmentsAsync(userInfo.Id);
var allPatients = await DoctorManagementService.GetAllPatientsAsync();
patients = allPatients.ToDictionary(pat => pat.Id, pat => pat.Name);
if (!appointments.Any())
{
errorMessage = "No appointments exist.";
}
}
catch (Exception ex)
{
errorMessage = $"Failed to load data: {ex.Message}";
}
}
private async Task DeleteAppointment(Appointment appointment, DateTime appointmentTime)
{
try
{
var success = await DoctorManagementService.CancelAppointmentAsync(
Guid.Parse(appointment.DoctorId),
Guid.Parse(appointment.PatientId),
appointmentTime
);
if (success)
{
var appList = appointments.FirstOrDefault(a => a.Id == appointment.Id)?.AppointmentsList;
if (appList != null)
{
appList.Remove(appointmentTime);
if (!appList.Any())
{
appointments.Remove(appointment);
}
}
if (!appointments.Any())
{
errorMessage = "No appointments exist.";
}
}
else
{
errorMessage = "Failed to delete the appointment.";
}
StateHasChanged();
}
catch (Exception ex)
{
errorMessage = $"Error deleting appointment: {ex.Message}";
}
}
}
@@ -0,0 +1,101 @@
@page "/doctor/patients_medical_history"
@attribute [Authorize(Roles = UserRoles.Doctor)]
@layout DoctorLayout
@inject IDoctorManagementService DoctorManagementService
@inject IAuthenticationService AuthenticationService
@inject IJSRuntime JSRuntime
<script src="fileHelper.js"></script>
<script src="downloadFile.js"></script>
<h3>Patient Medical Histories</h3>
@if (!string.IsNullOrEmpty(statusMessage))
{
<div class="alert @(isSuccess ? "alert-success" : "alert-danger")" role="alert">
@statusMessage
</div>
}
<div class="row mt-4">
@foreach (var patient in patients)
{
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body text-center">
<div>
<strong>Status: </strong>
@if (patientHasAccess(patient.Id))
{
<span class="text-success">Granted</span>
}
else
{
<span class="text-danger">Revoked</span>
}
</div>
<img src="user.png" style="width: 70px" alt="Patient" class="img-fluid mt-3"/>
<h5 class="mt-3">@patient.Name</h5>
<button class="btn btn-info mt-2" @onclick="() => DownloadMedicalHistory(patient.Id)" disabled="@(patientHasAccess(patient.Id) ? false : true)">Download Medical History</button>
</div>
</div>
</div>
}
</div>
@code {
private string statusMessage;
private bool isSuccess;
private List<Patient> patients = new();
private List<Guid> grantedAccessPatients = new();
protected override async Task OnInitializedAsync()
{
await LoadPatientsAndAccessStatus();
}
private async Task LoadPatientsAndAccessStatus()
{
var userInfo = await AuthenticationService.GetUserInformation();
patients = await DoctorManagementService.GetAllPatientsAsync();
await UpdatePatientAccessStatuses(userInfo.Id);
}
private async Task UpdatePatientAccessStatuses(Guid doctorId)
{
foreach (var patient in patients)
{
var medicalHistory = await DoctorManagementService.GetMedicalHistoryAsync(patient.Id);
if (medicalHistory == null) continue;
if (await DoctorManagementService.CheckForAccessAsync(medicalHistory.Id, doctorId))
{
grantedAccessPatients.Add(patient.Id);
}
}
StateHasChanged();
}
private bool patientHasAccess(Guid patientId)
{
return grantedAccessPatients.Contains(patientId);
}
private async Task DownloadMedicalHistory(Guid patientId)
{
var medicalHistory = await DoctorManagementService.DownloadMedicalHistoryAsync(patientId);
if (medicalHistory != null)
{
var base64 = Convert.ToBase64String(medicalHistory);
var href = $"data:application/octet-stream;base64,{base64}";
await JSRuntime.InvokeVoidAsync("downloadFile", "MedicalHistory.pdf", href);
}
else
{
statusMessage = "Failed to download medical history.";
isSuccess = false;
}
}
}
+107
View File
@@ -0,0 +1,107 @@
@page "/doctor/profile"
@attribute [Authorize(Roles = UserRoles.Doctor)]
@layout DoctorLayout
@inject NavigationManager Navigation
@inject IDoctorManagementService DoctorManagementService
@inject IAuthenticationService AuthenticationService
<h3>Profile</h3>
@if (!string.IsNullOrEmpty(updateMessage))
{
<div class="alert @(updateSuccess ? "alert-success" : "alert-danger") mt-3">@updateMessage</div>
}
<div class="card mt-4">
<div class="card-header">
Update Profile
</div>
<div class="card-body">
<EditForm Model="profileModel" OnValidSubmit="UpdateProfile">
<div class="form-row">
<div class="form-group col-md-6">
<label for="name">Name</label>
<InputText id="name" class="form-control" @bind-Value="profileModel.Name"/>
</div>
<div class="form-group col-md-6">
<label for="email">Email</label>
<InputText id="email" class="form-control" @bind-Value="profileModel.Email"/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="password">Password</label>
<InputText id="password" type="password" class="form-control" @bind-Value="profileModel.Password"/>
</div>
<div class="form-group col-md-6">
<label for="description">Description</label>
<InputTextArea id="description" class="form-control" @bind-Value="profileModel.Description" rows="5"/>
</div>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
</EditForm>
</div>
</div>
<div class="mt-4">
<button class="btn btn-danger" @onclick="DeleteAccount">Delete Account</button>
@if (!string.IsNullOrEmpty(deleteMessage))
{
<div class="alert @(deleteSuccess ? "alert-success" : "alert-danger") mt-3">@deleteMessage</div>
}
</div>
@code {
private Doctor profileModel = new();
private string updateMessage = string.Empty;
private string deleteMessage = string.Empty;
private bool updateSuccess = false;
private bool deleteSuccess = false;
protected override async Task OnInitializedAsync()
{
var userInfo = await AuthenticationService.GetUserInformation();
if (userInfo != null)
{
profileModel = await DoctorManagementService.GetDoctorProfileAsync(userInfo.Id);
}
}
private async Task UpdateProfile()
{
updateMessage = string.Empty;
updateSuccess = false;
var success = await DoctorManagementService.UpdateDoctorProfileAsync(profileModel);
if (success)
{
updateMessage = "Profile updated successfully.";
updateSuccess = true;
}
else
{
updateMessage = "An error occurred while updating your profile. Please try again.";
updateSuccess = false;
}
}
private async Task DeleteAccount()
{
deleteMessage = string.Empty;
deleteSuccess = false;
var success = await DoctorManagementService.DeleteDoctorProfileAsync(profileModel.Id);
if (success)
{
await AuthenticationService.RemoveAuthToken();
Navigation.NavigateTo("/goodbye");
}
else
{
deleteMessage = "An error occurred while deleting your account. Please try again.";
deleteSuccess = false;
}
}
}