239 lines
8.7 KiB
C#
239 lines
8.7 KiB
C#
using LSFE.MobApp.Contracts;
|
|
using LSFE.MobApp.Entities.Doctor;
|
|
using LSFE.MobApp.Entities.Planning;
|
|
using LSFE.MobApp.Helpers;
|
|
using LSFE.MobApp.Pages.CoveragePlan;
|
|
using LSFE.MobApp.Services;
|
|
using LSFE.MobApp.Services.Coverage;
|
|
using LSFE.MobApp.ViewModels.Common;
|
|
using Microsoft.Extensions.Configuration;
|
|
using System.Collections.ObjectModel;
|
|
using System.Windows.Input;
|
|
|
|
namespace LSFE.MobApp.ViewModels.Coverage
|
|
{
|
|
public class ActualCoverageVM : BaseDoctorVM
|
|
{
|
|
private readonly Doctor _doctor;
|
|
private bool _isLoading;
|
|
private ObservableCollection<DoctorVM> _doctors;
|
|
private readonly Repository<MRRawPlan> _mrRawPlanRepository;
|
|
public ActualCoverageVM(
|
|
Doctor doctor,
|
|
Repository<Doctor> doctorRepository,
|
|
Repository<MRRawPlan> mrRawPlanrepository,
|
|
ISyncService syncService,
|
|
AddressService addressService,
|
|
IConfiguration configuration)
|
|
: base(doctorRepository, syncService, addressService, configuration)
|
|
{
|
|
_doctor = doctor;
|
|
_mrRawPlanRepository = mrRawPlanrepository;
|
|
|
|
CloseCommand = new Command(async () => await Close());
|
|
CopyEmailCommand = new Command(async () => await CopyEmail());
|
|
CallPhoneCommand = new Command(async () => await CallPhone());
|
|
StartCoverageCommand = new Command(async () => await StartCoverage());
|
|
}
|
|
|
|
#region Status Properties - Using Helper (DRY!)
|
|
public string StatusText => DoctorStatusHelper.GetStatusText(_doctor.Status);
|
|
public Color StatusBackgroundColor => DoctorStatusHelper.GetStatusBackgroundColor(_doctor.Status);
|
|
public Color StatusTextColor => DoctorStatusHelper.GetStatusTextColor(_doctor.Status);
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// This method is automatically called when status updates are broadcast
|
|
/// </summary>
|
|
protected override async void OnDoctorStatusUpdated(int doctorId)
|
|
{
|
|
// Only update if it's this doctor
|
|
if (_doctor.DoctorId == doctorId)
|
|
{
|
|
var updated = await RefreshDoctorFromRepositoryAsync(doctorId);
|
|
if (updated != null)
|
|
{
|
|
_doctor.Status = updated.Status;
|
|
|
|
// Notify UI to refresh
|
|
OnPropertyChanged(nameof(StatusText));
|
|
OnPropertyChanged(nameof(StatusBackgroundColor));
|
|
OnPropertyChanged(nameof(StatusTextColor));
|
|
}
|
|
}
|
|
}
|
|
|
|
public ObservableCollection<DoctorVM> Doctors
|
|
{
|
|
get => _doctors;
|
|
set
|
|
{
|
|
_doctors = value;
|
|
OnPropertyChanged();
|
|
}
|
|
}
|
|
|
|
#region Details information
|
|
public string FullName => $"Dr. {_doctor.FirstName} {_doctor.MiddleInitial} {_doctor.LastName}".Replace(" ", " ").Trim();
|
|
public string EmailAddress => _doctor.EmailAddress ?? "N/A";
|
|
public string PhoneNo => _doctor.PhoneNo ?? "N/A";
|
|
public string LicenseNo => _doctor.LicenseNo ?? "N/A";
|
|
public string Specialization => _doctor.SpecializationName ?? "General Practice";
|
|
public string InstitutionName => _doctor.InstitutionName ?? "No Institution Assigned";
|
|
public string Address => _doctor.Address ?? "No address provided";
|
|
public string MaxVisit => $"{_doctor.MaxVisit} doctors";
|
|
public string BirthDateFormatted => _doctor.BirthDate.ToString("MMMM dd, yyyy");
|
|
public string CreatedDateFormatted => _doctor.CreatedDate.ToString("MMMM dd, yyyy");
|
|
|
|
public bool HasInstitution => !string.IsNullOrEmpty(_doctor.InstitutionName);
|
|
public bool HasAddress => !string.IsNullOrEmpty(_doctor.Address);
|
|
#endregion
|
|
|
|
public bool IsLoading
|
|
{
|
|
get => _isLoading;
|
|
set
|
|
{
|
|
_isLoading = value;
|
|
OnPropertyChanged();
|
|
}
|
|
}
|
|
|
|
#region Commands
|
|
public ICommand StartCoverageCommand { get; }
|
|
public ICommand CloseCommand { get; }
|
|
public ICommand CopyEmailCommand { get; }
|
|
public ICommand CallPhoneCommand { get; }
|
|
#endregion
|
|
|
|
private async Task StartCoverage()
|
|
{
|
|
try
|
|
{
|
|
((Command)StartCoverageCommand).ChangeCanExecute();
|
|
|
|
if (_doctor.Status == 2)
|
|
{
|
|
await UtilityVM.ShowAlert(
|
|
"Warning:",
|
|
$"Failed to start coverage. The visitation for Dr. {_doctor.FirstName} {_doctor.LastName} has already been completed."
|
|
);
|
|
return;
|
|
}
|
|
|
|
var confirm = await Application.Current.MainPage.DisplayAlert(
|
|
"Start Coverage",
|
|
"Do you want to begin coverage now?",
|
|
"Yes, Start",
|
|
"Cancel");
|
|
|
|
if (!confirm)
|
|
{
|
|
return;
|
|
}
|
|
await EnsurePlanInitializedAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await UtilityVM.ShowAlert("Error", $"Failed to open Market Product page: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
((Command)StartCoverageCommand).ChangeCanExecute();
|
|
}
|
|
}
|
|
private async Task EnsurePlanInitializedAsync()
|
|
{
|
|
var today = DateTime.Today;
|
|
var tomorrow = today.AddDays(1);
|
|
|
|
var plan = await _mrRawPlanRepository.FirstOrDefaultAsync(
|
|
r => r.MRRawPlanId==_doctor.MRRawPlanId && r.DoctorId == _doctor.DoctorId);
|
|
|
|
var doctor = await _doctorRepository.FirstOrDefaultAsync(d => d.DoctorId == _doctor.DoctorId);
|
|
|
|
if (plan == null)
|
|
{
|
|
await Application.Current.MainPage.DisplayAlert("Error", "No plan found for today.", "OK");
|
|
return;
|
|
}
|
|
|
|
if (plan.StartTime == null)
|
|
{
|
|
plan.StartTime = DateTime.Now;
|
|
plan.ActualCallDate = today;
|
|
var result = await _mrRawPlanRepository.UpdateAsync(plan);
|
|
|
|
doctor.Status = 1;
|
|
await _doctorRepository.UpdateAsync(doctor);
|
|
|
|
// Broadcast to ALL ViewModels - ONE LINE!
|
|
DoctorStatusHelper.BroadcastStatusUpdate(_doctor.DoctorId);
|
|
|
|
if (result <= 0)
|
|
{
|
|
await Application.Current.MainPage.DisplayAlert(
|
|
"Failed",
|
|
"Actual coverage recording failed, please try again!",
|
|
"OK");
|
|
await Application.Current.MainPage.Navigation.PopAsync();
|
|
}
|
|
}
|
|
|
|
|
|
var viewVm = new MarketProductVM(
|
|
_doctor,
|
|
_doctorRepository,
|
|
ServiceHelper.GetService<IFileDownloadService>(),
|
|
ServiceHelper.GetService<Repository<ProductTransaction>>(),
|
|
ServiceHelper.GetService<Repository<InventoryTransaction>>(),
|
|
ServiceHelper.GetService<Repository<MRRawPlan>>(),
|
|
_syncService,
|
|
_configuration,
|
|
_addressService);
|
|
|
|
var viewPage = new MarketProductPage(viewVm);
|
|
|
|
IsLoading = true;
|
|
|
|
await Application.Current.MainPage.Navigation.PushAsync(viewPage);
|
|
}
|
|
private async Task Close()
|
|
{
|
|
await Application.Current.MainPage.Navigation.PopAsync();
|
|
}
|
|
|
|
private async Task CopyEmail()
|
|
{
|
|
if (!string.IsNullOrEmpty(_doctor.EmailAddress))
|
|
{
|
|
await Clipboard.SetTextAsync(_doctor.EmailAddress);
|
|
await Application.Current.MainPage.DisplayAlert("Copied", "Email address copied to clipboard", "OK");
|
|
}
|
|
}
|
|
|
|
private async Task CallPhone()
|
|
{
|
|
if (!string.IsNullOrEmpty(_doctor.PhoneNo))
|
|
{
|
|
try
|
|
{
|
|
if (PhoneDialer.Default.IsSupported)
|
|
{
|
|
PhoneDialer.Default.Open(_doctor.PhoneNo);
|
|
}
|
|
else
|
|
{
|
|
await Clipboard.SetTextAsync(_doctor.PhoneNo);
|
|
await Application.Current.MainPage.DisplayAlert("Phone Number", "Phone number copied to clipboard", "OK");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await Application.Current.MainPage.DisplayAlert("Error", $"Unable to dial: {ex.Message}", "OK");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |