finalizare 1.0
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
@page "/patient/appointments"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
|
||||
@inject IPatientManagementService PatientManagementService;
|
||||
@inject IAuthenticationService AuthenticationService;
|
||||
|
||||
<h3>Doctors</h3>
|
||||
|
||||
@if (!string.IsNullOrEmpty(_statusMessage))
|
||||
{
|
||||
<div class="alert @(_isError ? "alert-danger" : "alert-success")" role="alert">
|
||||
@_statusMessage
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="card-deck">
|
||||
@if (_doctors == null || !_doctors.Any())
|
||||
{
|
||||
<div class="alert alert-info center-content" style="width: 100%; height: 200px;">No doctors available.</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var doctor in _doctors)
|
||||
{
|
||||
<div class="card doctor-card">
|
||||
<div class="doctor-card-content">
|
||||
<div class="user-icon"></div>
|
||||
<div class="doctor-info">
|
||||
<h5 class="card-title">Dr. @doctor.Name</h5>
|
||||
<p class="card-text">@doctor.Email</p>
|
||||
<button class="btn btn-primary" @onclick="() => ShowAppointmentOverlay(doctor)">Book Appointment</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (_showAppointmentOverlay)
|
||||
{
|
||||
<div class="overlay">
|
||||
<div class="overlay-content">
|
||||
<h5>Book Appointment with Dr. @_selectedDoctor.Name</h5>
|
||||
<EditForm Model="@_dateAndTimeAppointment" OnValidSubmit="BookAppointment">
|
||||
<div class="form-group">
|
||||
<label for="date">Date</label>
|
||||
<InputDate id="date" class="form-control" @bind-Value="_dateAndTimeAppointment.AppointmentDate" TValue="DateTime"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="time">Time</label>
|
||||
<InputText id="time" class="form-control" @bind-Value="_dateAndTimeAppointment.FormattedAppointmentTime"/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Book</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="HideAppointmentOverlay">Cancel</button>
|
||||
</EditForm>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<style>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.doctor-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.doctor-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.user-icon {
|
||||
background-image: url('user.png'); /* Ensure the path is correct */
|
||||
background-size: cover;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.doctor-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private List<Doctor> _doctors;
|
||||
private Doctor _selectedDoctor;
|
||||
private bool _showAppointmentOverlay = false;
|
||||
private NewAppointmentModel _newAppointmentModel = new();
|
||||
private DateAndTimeAppointment _dateAndTimeAppointment = new();
|
||||
private string _statusMessage = string.Empty;
|
||||
private bool _isError = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadDoctors();
|
||||
}
|
||||
|
||||
private async Task LoadDoctors()
|
||||
{
|
||||
_doctors = await PatientManagementService.GetAllDoctorsAsync();
|
||||
}
|
||||
|
||||
private void ShowAppointmentOverlay(Doctor doctor)
|
||||
{
|
||||
_selectedDoctor = doctor;
|
||||
_newAppointmentModel = new NewAppointmentModel
|
||||
{
|
||||
DoctorId = doctor.Id
|
||||
};
|
||||
_showAppointmentOverlay = true;
|
||||
}
|
||||
|
||||
private void HideAppointmentOverlay()
|
||||
{
|
||||
_showAppointmentOverlay = false;
|
||||
}
|
||||
|
||||
private async Task BookAppointment()
|
||||
{
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
|
||||
_newAppointmentModel.PatientId = userInfo.Id;
|
||||
_newAppointmentModel.Appointment = _dateAndTimeAppointment.GetAppointment();
|
||||
|
||||
var appointment = await PatientManagementService.BookAppointmentAsync(_newAppointmentModel);
|
||||
|
||||
_statusMessage = appointment.Message;
|
||||
_isError = appointment.StatusCode != 201;
|
||||
|
||||
if (!_isError)
|
||||
{
|
||||
_showAppointmentOverlay = false;
|
||||
}
|
||||
}
|
||||
|
||||
class DateAndTimeAppointment
|
||||
{
|
||||
public DateTime AppointmentDate { get; set; } = DateTime.Now.Date;
|
||||
public string FormattedAppointmentTime = DateTime.Now.ToString("HH:mm");
|
||||
|
||||
public DateTime GetAppointment()
|
||||
{
|
||||
// Parse FormattedAppointmentTime to a TimeSpan
|
||||
if (TimeSpan.TryParse(FormattedAppointmentTime, out var appointmentTime))
|
||||
{
|
||||
// Combine AppointmentDate with appointmentTime
|
||||
return AppointmentDate.Add(appointmentTime);
|
||||
}
|
||||
|
||||
throw new FormatException("FormattedAppointmentTime is not in the correct format.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
@page "/patient/chat"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
|
||||
<h3>Chat with Doctors</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 doctor in doctors)
|
||||
{
|
||||
<button class="list-group-item list-group-item-action" @onclick="() => OpenChat(doctor.Id, doctor.Name)">
|
||||
Dr. @doctor.Name
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
@if (selectedDoctor != null)
|
||||
{
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Chat with Dr. @selectedDoctor.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" : selectedDoctor.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<Doctor> doctors = new();
|
||||
private Doctor selectedDoctor;
|
||||
private List<Message> messages = new();
|
||||
private string newMessage = string.Empty;
|
||||
private UserInformation userInfo;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
userInfo = await AuthenticationService.GetUserInformation();
|
||||
doctors = await PatientManagementService.GetAllDoctorsAsync();
|
||||
}
|
||||
|
||||
private async Task OpenChat(Guid doctorId, string doctorName)
|
||||
{
|
||||
selectedDoctor = new Doctor { Id = doctorId, Name = doctorName };
|
||||
var chat = await PatientManagementService.GetConversationAsync(userInfo.Id, doctorId);
|
||||
messages = chat?.Messages ?? new List<Message>();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void CloseChat()
|
||||
{
|
||||
selectedDoctor = null;
|
||||
messages.Clear();
|
||||
}
|
||||
|
||||
private async Task SendMessage()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(newMessage) && selectedDoctor != null)
|
||||
{
|
||||
var success = await PatientManagementService.SendMessageAsync(userInfo.Id, selectedDoctor.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 "/patient/dashboard"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<h3>Dashboard</h3>
|
||||
|
||||
@if (errorMessage != string.Empty)
|
||||
{
|
||||
<div class="alert alert-danger" role="alert">
|
||||
@errorMessage
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (username != null)
|
||||
{
|
||||
<p>Welcome, @username!</p>
|
||||
<p>Here you have listed your active appointments.</p>
|
||||
}
|
||||
|
||||
@if (appointments != null && appointments.Count > 0)
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Doctor</th>
|
||||
<th>Time</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var appointment in appointments)
|
||||
{
|
||||
foreach (var appointmentTime in appointment.AppointmentsList)
|
||||
{
|
||||
<tr>
|
||||
<td>Dr. @doctors[Guid.Parse(appointment.DoctorId)]</td>
|
||||
<td>@appointmentTime.ToString("g")</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" @onclick="() => DeleteAppointment(appointment, appointmentTime)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
else if (errorMessage == string.Empty)
|
||||
{
|
||||
<p>No appointments exist.</p>
|
||||
}
|
||||
|
||||
@code {
|
||||
private string username;
|
||||
private List<Appointment> appointments = new();
|
||||
private Dictionary<Guid, string> doctors = new();
|
||||
private string errorMessage = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
username = userInfo.Name;
|
||||
appointments = await PatientManagementService.GetAppointmentsAsync(userInfo.Id);
|
||||
var allDoctors = await PatientManagementService.GetAllDoctorsAsync();
|
||||
doctors = allDoctors.ToDictionary(doc => doc.Id, doc => doc.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 PatientManagementService.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,137 @@
|
||||
@page "/patient/doctor_access"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<h3>Manage Access to Medical History</h3>
|
||||
|
||||
@if (!string.IsNullOrEmpty(statusMessage))
|
||||
{
|
||||
<div class="alert @(isSuccess ? "alert-success" : "alert-danger")" role="alert">
|
||||
@statusMessage
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row mt-4">
|
||||
@foreach (var doctor in doctors)
|
||||
{
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body text-center">
|
||||
<div>
|
||||
<strong>Status: </strong>
|
||||
@if (doctorHasAccess(doctor.Id))
|
||||
{
|
||||
<span class="text-success">Granted</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger">Revoked</span>
|
||||
}
|
||||
</div>
|
||||
<img src="user.png" style="width: 70px" alt="Doctor" class="img-fluid mt-3"/>
|
||||
<h5 class="mt-3">Dr. @doctor.Name</h5>
|
||||
<button class="btn btn-success mt-2" @onclick="() => GrantAccess(doctor.Id)">Grant Access</button>
|
||||
<button class="btn btn-warning mt-2" @onclick="() => RevokeAccess(doctor.Id)">Revoke Access</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private string statusMessage;
|
||||
private bool isSuccess;
|
||||
private List<Doctor> doctors = new();
|
||||
private List<Guid> grantedAccessDoctors = new();
|
||||
private Guid medicalRecordId;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadDoctorsAndAccessStatus();
|
||||
}
|
||||
|
||||
private async Task LoadDoctorsAndAccessStatus()
|
||||
{
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
var medicalHistory = await PatientManagementService.GetMedicalHistoryAsync(userInfo.Id);
|
||||
|
||||
if (medicalHistory != null)
|
||||
{
|
||||
medicalRecordId = medicalHistory.Id;
|
||||
doctors = await PatientManagementService.GetAllDoctorsAsync();
|
||||
await UpdateDoctorAccessStatuses(userInfo.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
statusMessage = "Failed to load medical history.";
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateDoctorAccessStatuses(Guid patientId)
|
||||
{
|
||||
if (medicalRecordId != Guid.Empty)
|
||||
{
|
||||
foreach (var doctor in doctors)
|
||||
{
|
||||
if (await PatientManagementService.CheckForAccessAsync(medicalRecordId, doctor.Id))
|
||||
{
|
||||
grantedAccessDoctors.Add(doctor.Id);
|
||||
}
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool doctorHasAccess(Guid doctorId)
|
||||
{
|
||||
return grantedAccessDoctors.Contains(doctorId);
|
||||
}
|
||||
|
||||
private async Task GrantAccess(Guid doctorId)
|
||||
{
|
||||
if (medicalRecordId != Guid.Empty)
|
||||
{
|
||||
var success = await PatientManagementService.GrantAccessAsync(medicalRecordId, doctorId);
|
||||
if (success)
|
||||
{
|
||||
grantedAccessDoctors.Add(doctorId);
|
||||
statusMessage = "Access granted successfully.";
|
||||
isSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusMessage = "Failed to grant access.";
|
||||
isSuccess = false;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RevokeAccess(Guid doctorId)
|
||||
{
|
||||
if (medicalRecordId != Guid.Empty)
|
||||
{
|
||||
var success = await PatientManagementService.RevokeAccessAsync(medicalRecordId, doctorId);
|
||||
if (success)
|
||||
{
|
||||
grantedAccessDoctors.Remove(doctorId);
|
||||
statusMessage = "Access revoked successfully.";
|
||||
isSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusMessage = "Failed to revoke access.";
|
||||
isSuccess = false;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
@page "/patient/doctors"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
|
||||
<h3 class="text-center mb-4">Meet Our Doctors</h3>
|
||||
|
||||
@if (doctors is null)
|
||||
{
|
||||
<p class="text-center"><em>Loading doctors...</em></p>
|
||||
}
|
||||
else if (doctors.Count == 0)
|
||||
{
|
||||
<p class="text-center">No doctors are available at the moment.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
@foreach (var doctor in doctors)
|
||||
{
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100" @onclick="() => ToggleOverlay(doctor)">
|
||||
<div class="card-body text-center">
|
||||
<img src="user.png" alt="Doctor Image" class="img-fluid rounded-circle mb-2" style="width: 70px; height: 70px;">
|
||||
<h5 class="card-title">@doctor.Name</h5>
|
||||
<p class="card-text"><small class="text-muted">@doctor.Email</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (selectedDoctor != null)
|
||||
{
|
||||
<div class="modal" tabindex="-1" style="display:block; background-color: rgba(0,0,0,0.5);">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Doctor Details</h5>
|
||||
<button type="button" class="close" @onclick="() => ToggleOverlay(null)">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Name: @selectedDoctor.Name</p>
|
||||
<p>Email: @selectedDoctor.Email</p>
|
||||
<p>Description: @((MarkupString)FormatDescription(selectedDoctor.Description))</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Doctor> doctors;
|
||||
private Doctor selectedDoctor;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
doctors = await PatientManagementService.GetAllDoctorsAsync();
|
||||
}
|
||||
|
||||
private void ToggleOverlay(Doctor doctor)
|
||||
{
|
||||
selectedDoctor = doctor;
|
||||
}
|
||||
|
||||
private string FormatDescription(string description)
|
||||
{
|
||||
// This is now handled directly in the modal body with MarkupString
|
||||
return description?.Replace(Environment.NewLine, "<br />") ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
@page "/patient/medical_history"
|
||||
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<script src="fileHelper.js"></script>
|
||||
<script src="downloadFile.js"></script>
|
||||
|
||||
<h3>Medical History</h3>
|
||||
|
||||
@if (!string.IsNullOrEmpty(statusMessage))
|
||||
{
|
||||
<div class="alert @(isSuccess ? "alert-success" : "alert-danger")" role="alert">
|
||||
@statusMessage
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (uploadedFile != null)
|
||||
{
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
Medical History
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<img src="pngtree-pdf-file-icon-png-png-image_4899509.png" style="width:100px" alt="Medical Document" id="medicalDocument"/>
|
||||
<div class="mt-4">
|
||||
<button class="btn btn-primary" @onclick="PromptFileUpdate">Update</button>
|
||||
<button class="btn btn-danger" @onclick="DeleteFile">Delete</button>
|
||||
<button class="btn btn-secondary" @onclick="DownloadFile">Download</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
Upload Medical History
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<InputFile OnChange="HandleFileSelected"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
private MedicalHistory uploadedFile;
|
||||
private string statusMessage;
|
||||
private bool isSuccess;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await CheckMedicalHistory();
|
||||
}
|
||||
|
||||
private async Task CheckMedicalHistory()
|
||||
{
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
uploadedFile = await PatientManagementService.GetMedicalHistoryAsync(userInfo.Id);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task HandleFileSelected(InputFileChangeEventArgs e)
|
||||
{
|
||||
var file = e.File;
|
||||
if (file == null)
|
||||
{
|
||||
statusMessage = "No file selected.";
|
||||
isSuccess = false;
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the file MIME type is 'application/pdf'
|
||||
if (!file.ContentType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
statusMessage = "Only PDF files are allowed.";
|
||||
isSuccess = false;
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
await file.OpenReadStream().CopyToAsync(memoryStream);
|
||||
var fileContent = memoryStream.ToArray();
|
||||
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
var response = await PatientManagementService.UploadMedicalHistoryAsync(userInfo.Id, fileContent);
|
||||
|
||||
statusMessage = response.Message;
|
||||
isSuccess = response.StatusCode == HttpStatusCodes.Created; // Assume HttpStatusCodes.Created represents successful upload
|
||||
await CheckMedicalHistory();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private void PromptFileUpdate()
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("document.getElementById", "hiddenFileInput");
|
||||
}
|
||||
|
||||
private async Task DeleteFile()
|
||||
{
|
||||
if (uploadedFile != null)
|
||||
{
|
||||
var success = await PatientManagementService.DeleteMedicalHistoryAsync(uploadedFile.Id);
|
||||
if (success)
|
||||
{
|
||||
uploadedFile = null;
|
||||
statusMessage = "File deleted successfully.";
|
||||
isSuccess = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
statusMessage = "Failed to delete file.";
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadFile()
|
||||
{
|
||||
if (uploadedFile != null)
|
||||
{
|
||||
var fileContent = await PatientManagementService.DownloadMedicalHistoryAsync(uploadedFile.Id);
|
||||
if (fileContent != null)
|
||||
{
|
||||
var base64 = Convert.ToBase64String(fileContent);
|
||||
var href = $"data:application/octet-stream;base64,{base64}";
|
||||
await JSRuntime.InvokeVoidAsync("downloadFile", "MedicalHistory.pdf", href);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
@page "/patient/profile"
|
||||
@attribute [Authorize(Roles = UserRoles.Patient)]
|
||||
@layout PatientLayout
|
||||
@inject NavigationManager Navigation
|
||||
@inject IPatientManagementService PatientManagementService
|
||||
@inject IAuthenticationService AuthenticationService
|
||||
|
||||
<h3>Profile</h3>
|
||||
|
||||
@if (!string.IsNullOrEmpty(updateMessage))
|
||||
{
|
||||
<div class="alert 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-group">
|
||||
<label for="name">Name</label>
|
||||
<InputText id="name" class="form-control" @bind-Value="profileModel.Name"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<InputText id="email" class="form-control" @bind-Value="profileModel.Email"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<InputText id="password" type="password" class="form-control" @bind-Value="profileModel.Password"/>
|
||||
</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 alert-danger mt-3">@deleteMessage</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private Patient profileModel = new();
|
||||
private string updateMessage = string.Empty;
|
||||
private string deleteMessage = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var userInfo = await AuthenticationService.GetUserInformation();
|
||||
if (userInfo != null)
|
||||
{
|
||||
profileModel = await PatientManagementService.GetPatientProfileAsync(userInfo.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateProfile()
|
||||
{
|
||||
updateMessage = string.Empty;
|
||||
|
||||
var success = await PatientManagementService.UpdatePatientProfileAsync(profileModel);
|
||||
if (success)
|
||||
{
|
||||
Navigation.NavigateTo("/dashboard/patient", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateMessage = "An error occurred while updating your profile. Please try again.";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteAccount()
|
||||
{
|
||||
deleteMessage = string.Empty;
|
||||
|
||||
var success = await PatientManagementService.DeletePatientProfileAsync(profileModel.Id);
|
||||
if (success)
|
||||
{
|
||||
await AuthenticationService.RemoveAuthToken();
|
||||
Navigation.NavigateTo("/goodbye");
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteMessage = "An error occurred while deleting your account. Please try again.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user