finalizare 1.0
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user