1347 lines
52 KiB
C#
1347 lines
52 KiB
C#
using System.Collections.ObjectModel;
|
|
using System.Text.Json;
|
|
using System.Web;
|
|
using CommunityToolkit.Maui.Core.Extensions;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using gehGassi.Dto;
|
|
using gehGassi.Dto.Common;
|
|
using gehGassi.Dto.Walks;
|
|
using gehGassiApp.Core.Interfaces;
|
|
using gehGassiApp.Core.Mapper;
|
|
using gehGassiApp.Core.Messaging;
|
|
using gehGassiApp.Domain.Common;
|
|
using gehGassiApp.Domain.Dogs;
|
|
using gehGassiApp.Domain.Lookup;
|
|
using gehGassiApp.Domain.Walkers;
|
|
using gehGassiApp.Resources;
|
|
using gehGassiApp.Services;
|
|
using gehGassiApp.Views.Dogs;
|
|
using gehGassiApp.Views.More;
|
|
using gehGassiApp.Views.Payments;
|
|
using gehGassiApp.Views.Walks;
|
|
using Microsoft.Maui.Handlers;
|
|
|
|
namespace gehGassiApp.ViewModels.Walks
|
|
{
|
|
/// <summary>
|
|
/// Viewmodel für das Buchen eines Walks
|
|
/// </summary>
|
|
public partial class BookWalkViewModel : MenuViewModel, IQueryAttributable
|
|
{
|
|
private readonly IDogWalkerService _dogWalkerService;
|
|
private readonly IDogService _dogService;
|
|
private readonly ICountryService _countryService;
|
|
private readonly ILocationService _locationService;
|
|
private readonly IWalkService _walkService;
|
|
private readonly IWalkingTimeService _walkingTimeService;
|
|
private readonly IDialogService _dialogService;
|
|
private readonly IDispatcher _dispatcher;
|
|
|
|
private string _walkerId;
|
|
private bool _countryHandlerEnabled;
|
|
private bool _bookNow;
|
|
private int _addressChangedCounter;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="dogWalkerService">Instanz eines IDogWalkerService</param>
|
|
/// <param name="dogService">Instanz eines IDogService</param>
|
|
/// <param name="countryService">Instanz eines ICountryService</param>
|
|
/// <param name="locationService">Instanz eines ILocationService</param>
|
|
/// <param name="walkService">Instanz eines IWalkService</param>
|
|
/// <param name="walkingTimeService">Instanz eines IWalkingTimeService</param>
|
|
/// <param name="dialogService">Instanz eines IDialogService</param>
|
|
/// <param name="dispatcher">Instanz eines IDispatcher</param>
|
|
public BookWalkViewModel(IDogWalkerService dogWalkerService, IDogService dogService, ICountryService countryService, ILocationService locationService, IWalkService walkService,
|
|
IWalkingTimeService walkingTimeService, IDialogService dialogService, IDispatcher dispatcher)
|
|
{
|
|
_dogWalkerService = dogWalkerService;
|
|
_dogService = dogService;
|
|
_countryService = countryService;
|
|
_locationService = locationService;
|
|
_walkService = walkService;
|
|
_walkingTimeService = walkingTimeService;
|
|
_dialogService = dialogService;
|
|
_dispatcher = dispatcher;
|
|
_bookNow = false;
|
|
_addressChangedCounter = 0;
|
|
|
|
Dogs = new ObservableCollection<Dog>();
|
|
SelectedDogs = new ObservableCollection<object>();
|
|
DogsSelected = false;
|
|
|
|
Title = Text.View_Title_Walker;
|
|
SelectedMenu = MenuSelected.Walkers;
|
|
IsLoading = true;
|
|
|
|
//Event wenn Refresh für diesen View gesetzt werden soll
|
|
if (WeakReferenceMessenger.Default.IsRegistered<RefreshViewModelMessage>(this) == false)
|
|
WeakReferenceMessenger.Default.Register<RefreshViewModelMessage>(this, (recipient, message) =>
|
|
{
|
|
if (message.Value is Core.Messaging.Messages.Refresh_BookWalk or Core.Messaging.Messages.Refresh_All)
|
|
{
|
|
_refresh = true;
|
|
}
|
|
if (message.Value is Core.Messaging.Messages.Special_BookNow)
|
|
{
|
|
_bookNow = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Benutzer hat keinen Hund
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _hasNoDog;
|
|
|
|
/// <summary>
|
|
/// Liste der verfügbaren Hunde
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private ObservableCollection<Dog> _dogs;
|
|
|
|
/// <summary>
|
|
/// Liste der gewählten Hunde
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private ObservableCollection<object> _selectedDogs;
|
|
|
|
/// <summary>
|
|
/// Wurde zumindest ein Hund gewählt
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _dogsSelected;
|
|
|
|
[ObservableProperty]
|
|
private DogWalkerInfo _walker;
|
|
|
|
/// <summary>
|
|
/// Walk möglich
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _walkAllowed;
|
|
|
|
/// <summary>
|
|
/// Sitting möglich
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private bool _sittingAllowed;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<WalkingTime> _walkingTimes;
|
|
|
|
[ObservableProperty]
|
|
private WalkServiceType _serviceType;
|
|
|
|
[ObservableProperty]
|
|
private DateTime _startDate;
|
|
|
|
[ObservableProperty]
|
|
private TimeSpan _startTime;
|
|
|
|
[ObservableProperty]
|
|
private DateTime _endDate;
|
|
|
|
[ObservableProperty]
|
|
private TimeSpan _endTime;
|
|
|
|
[ObservableProperty]
|
|
private Address _pickupAddress;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<Country> _pickupCountries;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<State> _pickupStates;
|
|
|
|
[ObservableProperty]
|
|
private Country _selectedPickupCountry;
|
|
|
|
[ObservableProperty]
|
|
private State _selectedPickupState;
|
|
|
|
[ObservableProperty]
|
|
private bool _pickupAddressValid;
|
|
|
|
[ObservableProperty]
|
|
private bool _showPickupAddress;
|
|
|
|
[ObservableProperty]
|
|
private Address _returnAddress;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<Country> _returnCountries;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<State> _returnStates;
|
|
|
|
[ObservableProperty]
|
|
private Country _selectedReturnCountry;
|
|
|
|
[ObservableProperty]
|
|
private State _selectedReturnState;
|
|
|
|
[ObservableProperty]
|
|
private bool _returnAddressValid;
|
|
|
|
[ObservableProperty]
|
|
private bool _showReturnAddress;
|
|
|
|
[ObservableProperty]
|
|
private string _info;
|
|
|
|
[ObservableProperty]
|
|
private decimal _price;
|
|
|
|
[ObservableProperty]
|
|
private bool _directBooking;
|
|
|
|
#region Extended
|
|
|
|
partial void OnServiceTypeChanged(WalkServiceType value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnSelectedPickupCountryChanged(Country value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
if (!_countryHandlerEnabled)
|
|
return;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
PickupAddressValid = false;
|
|
SelectedPickupState = null;
|
|
if (value != null && !string.IsNullOrWhiteSpace(value.Iso2))
|
|
{
|
|
var states = await _countryService.GetStatesAsync(value.Iso2);
|
|
PickupStates = states.ToObservableCollection();
|
|
}
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnSelectedPickupStateChanged(State value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
PickupAddressValid = SelectedPickupState != null;
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
PickupAddress.CountryCode = SelectedPickupCountry.Iso2;
|
|
PickupAddress.State = SelectedPickupState != null ? SelectedPickupState.Code : string.Empty;
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnPickupAddressChanged(Address value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnSelectedReturnCountryChanged(Country value)
|
|
{
|
|
if (!_countryHandlerEnabled)
|
|
return;
|
|
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
ReturnAddressValid = false;
|
|
SelectedReturnState = null;
|
|
if (value != null && !string.IsNullOrWhiteSpace(value.Iso2))
|
|
{
|
|
var states = await _countryService.GetStatesAsync(value.Iso2);
|
|
ReturnStates = states.ToObservableCollection();
|
|
}
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnSelectedReturnStateChanged(State value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
ReturnAddressValid = SelectedReturnState != null;
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
ReturnAddress.CountryCode = SelectedReturnCountry.Iso2;
|
|
ReturnAddress.State = SelectedReturnState != null ? SelectedReturnState.Code : string.Empty;
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnReturnAddressChanged(Address value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
partial void OnStartDateChanged(DateTime value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
if (StartDate.Date == DateTime.Now.Date && StartTime.Hours <= DateTime.Now.Hour)
|
|
{
|
|
var helpDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds);
|
|
helpDate = helpDate.AddHours(1);
|
|
StartDate = helpDate.Date;
|
|
StartTime = helpDate.TimeOfDay;
|
|
}
|
|
HandleStartAndEndDateChange();
|
|
}
|
|
|
|
partial void OnStartTimeChanged(TimeSpan value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
if (StartDate.Date == DateTime.Now.Date && StartTime.Hours <= DateTime.Now.Hour)
|
|
{
|
|
var helpDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds);
|
|
helpDate = helpDate.AddHours(1);
|
|
StartDate = helpDate.Date;
|
|
StartTime = helpDate.TimeOfDay;
|
|
}
|
|
HandleStartAndEndDateChange();
|
|
}
|
|
|
|
partial void OnEndDateChanged(DateTime value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
HandleStartAndEndDateChange();
|
|
}
|
|
|
|
partial void OnEndTimeChanged(TimeSpan value)
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
HandleStartAndEndDateChange();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Behandeln der Änderungen für Startdatum und Zeit wie euch Enddatum und Zeit
|
|
/// </summary>
|
|
private void HandleStartAndEndDateChange()
|
|
{
|
|
if (IsBusy || _refresh)
|
|
return;
|
|
|
|
var helpDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds);
|
|
if (EndDate <= StartDate)
|
|
{
|
|
if (EndTime <= StartTime)
|
|
{
|
|
helpDate = helpDate.AddMinutes(60);
|
|
EndDate = helpDate.Date;
|
|
EndTime = helpDate.TimeOfDay;
|
|
}
|
|
}
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Commands
|
|
|
|
/// <summary>
|
|
/// Command wenn sich die Hundeauswahl geändert hat
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void DogSelectionChanged()
|
|
{
|
|
DogsSelected = SelectedDogs.Count > 0;
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Service-Typ auswählen
|
|
/// </summary>
|
|
/// <param name="serviceType"></param>
|
|
[RelayCommand]
|
|
public void SelectServiceType(WalkServiceType serviceType)
|
|
{
|
|
ServiceType = serviceType;
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das Anlegen eines Hundes
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task CreateDog()
|
|
{
|
|
await Shell.Current.GoToAsync($"{nameof(DogAddView)}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggle der Adressanzeige
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void TogglePickupAddress()
|
|
{
|
|
ShowPickupAddress = !ShowPickupAddress;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggle der Adressanzeige
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void ToggleReturnAddress()
|
|
{
|
|
ShowReturnAddress = !ShowReturnAddress;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aktuelle Adresse basierend auf Geo-Location holen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task SetPickupAddress()
|
|
{
|
|
var address = await _locationService.GetAddressByCurrentLocationAsync();
|
|
if (address != null)
|
|
{
|
|
PickupAddress = address;
|
|
SelectedPickupCountry = PickupCountries.First(c => c.Iso2 == PickupAddress.CountryCode);
|
|
var states = await _countryService.GetStatesAsync(SelectedPickupCountry.Iso2);
|
|
PickupStates = states.ToObservableCollection();
|
|
SelectedPickupState = PickupStates.First(c => c.Code == PickupAddress.State);
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command wenn sich die Abholadresse ändert
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task PickupAddressChanged()
|
|
{
|
|
if(_addressChangedCounter <= 8)
|
|
_addressChangedCounter += 1;
|
|
if (_addressChangedCounter > 8)
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command wenn sich die Rückgabeadresse ändert
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task ReturnAddressChanged()
|
|
{
|
|
if (_addressChangedCounter <= 8)
|
|
_addressChangedCounter += 1;
|
|
if (_addressChangedCounter > 8)
|
|
{
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aktuelle Adresse basierend auf Geo-Location holen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task SetReturnAddress()
|
|
{
|
|
var address = await _locationService.GetAddressByCurrentLocationAsync();
|
|
if (address != null)
|
|
{
|
|
ReturnAddress = address;
|
|
SelectedReturnCountry = ReturnCountries.First(c => c.Iso2 == ReturnAddress.CountryCode);
|
|
var states = await _countryService.GetStatesAsync(SelectedReturnCountry.Iso2);
|
|
ReturnStates = states.ToObservableCollection();
|
|
SelectedReturnState = ReturnStates.First(c => c.Code == ReturnAddress.State);
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Kopiert die Rückgabeadresse in die Abholadresse
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public async Task CopyReturnAddress()
|
|
{
|
|
PickupAddress.AddressLine1 = ReturnAddress.AddressLine1;
|
|
PickupAddress.AddressLine2 = ReturnAddress.AddressLine2;
|
|
PickupAddress.City = ReturnAddress.City;
|
|
PickupAddress.Zip = ReturnAddress.Zip;
|
|
SelectedPickupCountry = PickupCountries.First(c => c.Iso2 == SelectedReturnCountry.Iso2);
|
|
var states = await _countryService.GetStatesAsync(SelectedReturnCountry.Iso2);
|
|
PickupStates = states.ToObservableCollection();
|
|
SelectedPickupState = PickupStates.First(c => c.Code == SelectedReturnState.Code);
|
|
ShowPickupAddress = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Kopiert die Abholadresse in die Rückgabeadresse
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public async Task CopyPickupAddress()
|
|
{
|
|
ReturnAddress.AddressLine1 = PickupAddress.AddressLine1;
|
|
ReturnAddress.AddressLine2 = PickupAddress.AddressLine2;
|
|
ReturnAddress.City = PickupAddress.City;
|
|
ReturnAddress.Zip = PickupAddress.Zip;
|
|
SelectedReturnCountry = ReturnCountries.First(c => c.Iso2 == SelectedPickupCountry.Iso2);
|
|
var states = await _countryService.GetStatesAsync(SelectedReturnCountry.Iso2);
|
|
ReturnStates = states.ToObservableCollection();
|
|
SelectedReturnState = ReturnStates.First(c => c.Code == SelectedPickupState.Code);
|
|
ShowReturnAddress = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Auf Fehler prüfen
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task CheckErrors()
|
|
{
|
|
await CheckErrorAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das Öffnen des Kalenders
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void ShowCalendar(object obj)
|
|
{
|
|
if (obj is DatePicker picker)
|
|
{
|
|
#if ANDROID
|
|
//https://github.com/dotnet/maui/issues/8946
|
|
if (picker.Handler is IDatePickerHandler handler)
|
|
handler.PlatformView.PerformClick();
|
|
#endif
|
|
#if IOS
|
|
picker.Focus();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sofort-Buchen eines Walks
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task BookNow()
|
|
{
|
|
if (!HasError && DirectBooking)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(App.CurrentAppUser.PaymentId))
|
|
{
|
|
//Der User hat noch keinen PaymentUser...
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_AddPaymentUser));
|
|
await Shell.Current.GoToAsync($"{nameof(AddPaymentUserView)}", Core.Common.Constants.AnimateNavigation);
|
|
return;
|
|
}
|
|
|
|
var userOk = await _dialogService.ShowAlertAsync(Resources.Text.Common_Book, string.Format(Resources.Text.Walk_BookNow_Question, Walker.FirstName, Price.ToString("N2")), Resources.Text.Common_Yes, Resources.Text.Common_No);
|
|
|
|
if (userOk)
|
|
{
|
|
IsSaving = true;
|
|
await _dispatcher.DispatchAsync(async () =>
|
|
{
|
|
var selectedDogs = SelectedDogs.Cast<Dog>().ToList();
|
|
var dogWalkJsonList = selectedDogs.Select(selectedDog => new DogWalkJson() { Id = selectedDog.Id, Name = selectedDog.Name }).ToList();
|
|
var helpStartDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds, DateTimeOffset.Now.Offset);
|
|
var helpEndDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, EndTime.Seconds, DateTimeOffset.Now.Offset);
|
|
|
|
var walkCreateDto = new WalkCreateDto()
|
|
{
|
|
Type = WalkTypeDto.Scheduled,
|
|
ServiceType = (WalkServiceTypeDto)ServiceType,
|
|
DogWalkerId = Walker.Id,
|
|
DogOwnerId = App.CurrentAppUser.Id,
|
|
DogsJson = JsonSerializer.Serialize(dogWalkJsonList, new JsonSerializerOptions(JsonSerializerDefaults.Web)),
|
|
DogCount = selectedDogs.Count,
|
|
Start = helpStartDate,
|
|
End = helpEndDate,
|
|
PickupAddress = PickupAddress.ToDto(),
|
|
ReturnAddress = ReturnAddress.ToDto(),
|
|
Price = Price,
|
|
Info = Info
|
|
};
|
|
|
|
#region Pickupaddress
|
|
//Lat & Lng für die Adressen setzen
|
|
var lat = App.CurrentAppUser.Lat;
|
|
var lng = App.CurrentAppUser.Lng;
|
|
var location = await _locationService.GetLocationByAddressAsync(PickupAddress);
|
|
if (location != null)
|
|
{
|
|
lat = location.Latitude;
|
|
lng = location.Longitude;
|
|
}
|
|
|
|
walkCreateDto.PickupAddressLat = lat;
|
|
walkCreateDto.PickupAddressLng = lng;
|
|
#endregion
|
|
|
|
#region ReturnAddress
|
|
lat = App.CurrentAppUser.Lat;
|
|
lng = App.CurrentAppUser.Lng;
|
|
location = await _locationService.GetLocationByAddressAsync(ReturnAddress);
|
|
if (location != null)
|
|
{
|
|
lat = location.Latitude;
|
|
lng = location.Longitude;
|
|
}
|
|
|
|
walkCreateDto.ReturnAddressLat = lat;
|
|
walkCreateDto.ReturnAddressLng = lng;
|
|
#endregion
|
|
|
|
//Jetzt am Server anlegen. Wird bei Erfolg auch lokal gespeichert.
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.CreateTimeout);
|
|
var walkResponse = await _walkService.CreateWalkDirectAsync(walkCreateDto, App.CurrentUser.AccessToken, cts.Token);
|
|
if (walkResponse.Success)
|
|
{
|
|
if (walkResponse.Value.PaymentStatus == PaymentStatus.Authorized)
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Walks));
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Home));
|
|
|
|
var stackCount = Shell.Current.Navigation.NavigationStack.Count;
|
|
if (stackCount > 1)
|
|
{
|
|
//await Shell.Current.GoToAsync("..");
|
|
if (DeviceInfo.Platform == DevicePlatform.Android)
|
|
await Shell.Current.Navigation.PopToRootAsync();
|
|
}
|
|
await Shell.Current.GoToAsync($"//{nameof(WalksView)}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
else
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Home));
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Walks));
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_WalksList));
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Payment));
|
|
var menu = SelectedMenu.ToString();
|
|
await Shell.Current.GoToAsync($"{nameof(PayWalkView)}?walkId={walkResponse.Value.Id}&menu={menu}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (walkResponse.ErrorCode == CommunicationErrors.Walk_NotPossible)
|
|
await _dialogService.ShowAlertAsync(Resources.Text.Common_Error, walkResponse.ErrorMessage, Resources.Text.Button_Ok);
|
|
else
|
|
await _dialogService.ShowAlertAsync(Resources.Text.Common_Error, Resources.Text.Walk_Book_Error, Resources.Text.Button_Ok);
|
|
}
|
|
});
|
|
IsSaving = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Anfrage für einen Walk stellen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task RequestNow()
|
|
{
|
|
if (!HasError)
|
|
{
|
|
var userOk = await _dialogService.ShowAlertAsync(Resources.Text.Common_Request, string.Format(Resources.Text.Walk_Request_Question, Walker.FirstName, Price.ToString("N2")), Resources.Text.Common_Yes, Resources.Text.Common_No);
|
|
|
|
if (userOk)
|
|
{
|
|
IsSaving = true;
|
|
await _dispatcher.DispatchAsync(async () =>
|
|
{
|
|
var selectedDogs = SelectedDogs.Cast<Dog>().ToList();
|
|
var dogWalkJsonList = selectedDogs.Select(selectedDog => new DogWalkJson() { Id = selectedDog.Id, Name = selectedDog.Name }).ToList();
|
|
var helpStartDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds, DateTimeOffset.Now.Offset);
|
|
var helpEndDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, EndTime.Seconds, DateTimeOffset.Now.Offset);
|
|
|
|
var walkCreateDto = new WalkCreateDto()
|
|
{
|
|
Type = WalkTypeDto.Direct,
|
|
ServiceType = (WalkServiceTypeDto)ServiceType,
|
|
DogWalkerId = Walker.Id,
|
|
DogOwnerId = App.CurrentAppUser.Id,
|
|
DogsJson = JsonSerializer.Serialize(dogWalkJsonList, new JsonSerializerOptions(JsonSerializerDefaults.Web)),
|
|
DogCount = selectedDogs.Count,
|
|
Start = helpStartDate,
|
|
End = helpEndDate,
|
|
PickupAddress = PickupAddress.ToDto(),
|
|
ReturnAddress = ReturnAddress.ToDto(),
|
|
Price = Price,
|
|
Info = Info
|
|
};
|
|
|
|
#region Pickupaddress
|
|
//Lat & Lng für die Adressen setzen
|
|
var lat = App.CurrentAppUser.Lat;
|
|
var lng = App.CurrentAppUser.Lng;
|
|
var location = await _locationService.GetLocationByAddressAsync(PickupAddress);
|
|
if (location != null)
|
|
{
|
|
lat = location.Latitude;
|
|
lng = location.Longitude;
|
|
}
|
|
|
|
walkCreateDto.PickupAddressLat = lat;
|
|
walkCreateDto.PickupAddressLng = lng;
|
|
#endregion
|
|
|
|
#region ReturnAddress
|
|
lat = App.CurrentAppUser.Lat;
|
|
lng = App.CurrentAppUser.Lng;
|
|
location = await _locationService.GetLocationByAddressAsync(ReturnAddress);
|
|
if (location != null)
|
|
{
|
|
lat = location.Latitude;
|
|
lng = location.Longitude;
|
|
}
|
|
|
|
walkCreateDto.ReturnAddressLat = lat;
|
|
walkCreateDto.ReturnAddressLng = lng;
|
|
#endregion
|
|
|
|
//Jetzt am Server anlegen. Wird bei Erfolg auch lokal gespeichert.
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.CreateTimeout);
|
|
var walkResponse = await _walkService.CreateWalkRequestAsync(walkCreateDto, App.CurrentUser.AccessToken, cts.Token);
|
|
if (walkResponse.Success)
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Walks));
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Home));
|
|
|
|
var stackCount = Shell.Current.Navigation.NavigationStack.Count;
|
|
if (stackCount > 1)
|
|
{
|
|
//await Shell.Current.GoToAsync("..");
|
|
await Shell.Current.Navigation.PopToRootAsync();
|
|
}
|
|
await Shell.Current.GoToAsync($"//{nameof(WalksView)}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
else
|
|
{
|
|
if(walkResponse.ErrorCode == CommunicationErrors.Walk_NotPossible)
|
|
await _dialogService.ShowAlertAsync(Resources.Text.Common_Error, walkResponse.ErrorMessage, Resources.Text.Button_Ok);
|
|
else
|
|
await _dialogService.ShowAlertAsync(Resources.Text.Common_Error, Resources.Text.Walk_Book_Error, Resources.Text.Button_Ok);
|
|
}
|
|
});
|
|
IsSaving = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Laden der initialen Daten
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task LoadAsync()
|
|
{
|
|
await _dispatcher.DispatchAsync(async () =>
|
|
{
|
|
|
|
IsBusy = true;
|
|
|
|
WalkAllowed = false;
|
|
SittingAllowed = false;
|
|
ServiceType = WalkServiceType.Walking;
|
|
Price = 0m;
|
|
DirectBooking = false;
|
|
DogsSelected = false;
|
|
SelectedDogs = new ObservableCollection<object>();
|
|
|
|
await LoadDogsAsync();
|
|
await LoadWalkerAsync();
|
|
|
|
if (Walker == null)
|
|
{
|
|
var stackCount = Shell.Current.Navigation.NavigationStack.Count;
|
|
if (stackCount > 1)
|
|
{
|
|
await Shell.Current.Navigation.PopToRootAsync();
|
|
}
|
|
}
|
|
|
|
if(Walker.AllowedRequests == DogWalkRequestType.Walking || Walker.AllowedRequests == DogWalkRequestType.Both)
|
|
ServiceType = WalkServiceType.Walking;
|
|
else if(Walker.AllowedRequests == DogWalkRequestType.Sitting)
|
|
ServiceType = WalkServiceType.Sitting;
|
|
|
|
switch (Walker.AllowedRequests)
|
|
{
|
|
case DogWalkRequestType.None:
|
|
break;
|
|
case DogWalkRequestType.Walking:
|
|
WalkAllowed = true;
|
|
break;
|
|
case DogWalkRequestType.Sitting:
|
|
SittingAllowed = true;
|
|
break;
|
|
case DogWalkRequestType.Both:
|
|
WalkAllowed = true;
|
|
SittingAllowed = true;
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
var dateNow = DateTimeOffset.UtcNow.LocalDateTime;
|
|
var dateHelper = new DateTimeOffset(dateNow.Year, dateNow.Month, dateNow.Day, dateNow.Hour, 0, 0, DateTimeOffset.Now.Offset);
|
|
dateHelper = dateHelper.AddDays(1);
|
|
|
|
StartDate = dateHelper.Date;
|
|
StartTime = dateHelper.TimeOfDay;
|
|
|
|
dateHelper = dateHelper.AddHours(1);
|
|
EndDate = dateHelper.Date;
|
|
EndTime = dateHelper.TimeOfDay;
|
|
|
|
_countryHandlerEnabled = false;
|
|
|
|
PickupAddress = App.CurrentAppUser.Address.Clone();
|
|
ReturnAddress = App.CurrentAppUser.Address.Clone();
|
|
|
|
var countries = await _countryService.GetCountriesAsync();
|
|
PickupCountries = countries.ToObservableCollection();
|
|
SelectedPickupCountry = PickupCountries.First(c => c.Iso2 == PickupAddress.CountryCode);
|
|
|
|
var states = await _countryService.GetStatesAsync(PickupAddress.CountryCode);
|
|
PickupStates = states.ToObservableCollection();
|
|
SelectedPickupState = PickupStates.First(c => c.Code == PickupAddress.State);
|
|
|
|
countries = await _countryService.GetCountriesAsync();
|
|
ReturnCountries = countries.ToObservableCollection();
|
|
SelectedReturnCountry = ReturnCountries.First(c => c.Iso2 == ReturnAddress.CountryCode);
|
|
|
|
states = await _countryService.GetStatesAsync(ReturnAddress.CountryCode);
|
|
ReturnStates = states.ToObservableCollection();
|
|
SelectedReturnState = ReturnStates.First(c => c.Code == ReturnAddress.State);
|
|
|
|
if (SelectedPickupCountry != null && SelectedPickupState != null)
|
|
PickupAddressValid = true;
|
|
|
|
if (SelectedReturnCountry != null && SelectedReturnState != null)
|
|
ReturnAddressValid = true;
|
|
|
|
_countryHandlerEnabled = true;
|
|
|
|
|
|
IsBusy = false;
|
|
|
|
await CheckErrorAsync();
|
|
CalculatePrice();
|
|
|
|
IsLoading = false;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Laden der Hunde des Benutzers
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadDogsAsync()
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
|
|
//Zuerst die Rassen laden, falls diese noch nicht synchronisiert wurden...
|
|
var dogs = await _dogService.GetDogsAsync(App.CurrentAppUser.Id, App.CurrentUser.AccessToken, cts.Token);
|
|
if (dogs != null && dogs.Any())
|
|
{
|
|
Dogs = dogs.ToObservableCollection();
|
|
}
|
|
else
|
|
{
|
|
Dogs?.Clear();
|
|
}
|
|
|
|
HasNoDog = Dogs.Count == 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walker laden
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task LoadWalkerAsync()
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var walkerResult = await _dogWalkerService.GetDogWalkerAsync(_walkerId, App.CurrentUser.AccessToken, cts.Token);
|
|
if (walkerResult.Success && walkerResult.Value != null)
|
|
{
|
|
var walker = walkerResult.Value;
|
|
if (CurrentLocation.Lat != null && CurrentLocation.Lng != null)
|
|
walker.Distance = Location.CalculateDistance(CurrentLocation.Lat.Value, CurrentLocation.Lng.Value, walker.Lat, walker.Lng, DistanceUnits.Kilometers);
|
|
|
|
Walker = walker;
|
|
Title = string.Format(Resources.Text.BookWalk_Title, Walker.FirstName);
|
|
|
|
var walkingTimesResult = await _walkingTimeService.GetAllAsync(Walker.Id, true, App.CurrentUser.AccessToken, cts.Token);
|
|
if (walkingTimesResult.Success && walkingTimesResult.Value.Any(c => c.Enabled))
|
|
{
|
|
WalkingTimes = walkingTimesResult.Value.Where(c => c.Enabled).ToObservableCollection();
|
|
}
|
|
else
|
|
{
|
|
WalkingTimes = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Walker = null;
|
|
}
|
|
}
|
|
|
|
#region Initialisierung
|
|
|
|
/// <inheritdoc />
|
|
public void ApplyQueryAttributes(IDictionary<string, object> query)
|
|
{
|
|
_walkerId = HttpUtility.UrlDecode(query["id"].ToString());
|
|
var selectedMenu = HttpUtility.UrlDecode(query["menu"].ToString());
|
|
SelectedMenu = (MenuSelected)Enum.Parse(typeof(MenuSelected), selectedMenu);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialisieren des Viewmodels.
|
|
/// Soll überschrieben werden um lazy loading in Viewmodels ermöglicht wird
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
public override async Task InitializeAsync(object sender)
|
|
{
|
|
await base.InitializeAsync(sender);
|
|
IsBusy = false;
|
|
HasError = false;
|
|
ErrorMessage = string.Empty;
|
|
|
|
await TrackPageViewAsync("BookWalk");
|
|
|
|
if (App.AppMode == AppMode.DogOwner)
|
|
{
|
|
CheckSubscription(AppMode.DogOwner);
|
|
}
|
|
|
|
if (_refresh)
|
|
{
|
|
_addressChangedCounter = 0;
|
|
IsLoading = true;
|
|
IsBusy = true;
|
|
WalkAllowed = false;
|
|
SittingAllowed = false;
|
|
Info = string.Empty;
|
|
|
|
await Task.Delay(Core.Common.Constants.AnimationDelayDetails);
|
|
//await LoadAsync();
|
|
#pragma warning disable CS4014
|
|
Task.Run(LoadAsync);
|
|
#pragma warning restore CS4014
|
|
_refresh = false;
|
|
}
|
|
else
|
|
{
|
|
if (_bookNow)
|
|
{
|
|
await BookNow();
|
|
_bookNow = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Entladen des Viewmodels.
|
|
/// Soll überschrieben werden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
public override Task DisappearingAsync(object sender)
|
|
{
|
|
IsBusy = false;
|
|
HasError = false;
|
|
ErrorMessage = string.Empty;
|
|
_addressChangedCounter = 0;
|
|
|
|
return base.DisappearingAsync(sender);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Resumed
|
|
|
|
/// <summary>
|
|
/// Eventhandler wenn die App aus dem Sleepmode kommt
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal override Task AppResumed()
|
|
{
|
|
return base.AppResumed();
|
|
//await _dispatcher.DispatchAsync(async () =>
|
|
//{
|
|
// _addressChangedCounter = 0;
|
|
// IsLoading = true;
|
|
// await LoadAsync();
|
|
//});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper
|
|
|
|
/// <summary>
|
|
/// Eingaben auf "Fehler" prüfen
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task CheckErrorAsync()
|
|
{
|
|
if (IsLoading)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Empty;
|
|
return;
|
|
}
|
|
|
|
if (HasNoDog)
|
|
{
|
|
HasError = false;
|
|
ErrorMessage = string.Empty;
|
|
return;
|
|
}
|
|
|
|
//1. Prüfen ob mindestens ein Hunnd ausgewählt wurde
|
|
if (!DogsSelected)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_NoDog;
|
|
return;
|
|
}
|
|
|
|
//1.1 Walker gerade nicht verfügbar
|
|
if (Walker.NotAvailable)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_WalkerNotAvailable, Walker.FirstName);
|
|
return;
|
|
}
|
|
|
|
//2. Servicetype prüfen
|
|
if (Walker.AllowedRequests != DogWalkRequestType.Both)
|
|
{
|
|
//2.1 Prüfen ob der gewählte Service vom Walker angeboten wird
|
|
if (ServiceType == WalkServiceType.Walking && Walker.AllowedRequests != DogWalkRequestType.Walking)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_Walker_NoWalk, Walker.FirstName);
|
|
return;
|
|
}
|
|
|
|
//2.2 Prüfen ob der gewählte Service vom Walker angeboten wird
|
|
if (ServiceType == WalkServiceType.Sitting && Walker.AllowedRequests != DogWalkRequestType.Sitting)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_Walker_NoSitting, Walker.FirstName);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//3. Hunde prüfen. Größe und Aggro...
|
|
var selectedDogs = SelectedDogs.Cast<Dog>().ToList();
|
|
foreach (var selectedDog in selectedDogs)
|
|
{
|
|
if (selectedDog.Size > Walker.AcceptedSize)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_DogSize, selectedDog.Name, Walker.FirstName);
|
|
return;
|
|
}
|
|
if (selectedDog.IsAggressiv && !Walker.DifficultAllowed)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_Dog_NoAggression, Walker.FirstName, selectedDog.Name);
|
|
return;
|
|
}
|
|
if (selectedDog.IsAggressiv && Walker.DifficultAllowed && selectedDog.AggressionLevel > Walker.AggressionLevel)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_Dog_AggressionLevel, selectedDog.Name, Walker.FirstName);
|
|
return;
|
|
}
|
|
|
|
if (selectedDog.BirthDate.HasValue && selectedDog.BirthDate.Value < DateTimeOffset.UtcNow)
|
|
{
|
|
var age = (DateTimeOffset.UtcNow - selectedDog.BirthDate.Value).TotalDays;
|
|
if (age <= 126 && !Walker.PuppyAllowed)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_Dog_NoPuppy, Walker.FirstName, selectedDog.Name);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//4. Adressen prüfen & Radius des Walker berücksichtigen.
|
|
if (!PickupAddressValid)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_PickupAddress;
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(PickupAddress.AddressLine1) || string.IsNullOrWhiteSpace(PickupAddress.Zip) || string.IsNullOrWhiteSpace(PickupAddress.City))
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_PickupAddress;
|
|
return;
|
|
}
|
|
|
|
if (!ReturnAddressValid)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_ReturnAddress;
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(ReturnAddress.AddressLine1) || string.IsNullOrWhiteSpace(ReturnAddress.Zip) || string.IsNullOrWhiteSpace(ReturnAddress.City))
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_ReturnAddress;
|
|
return;
|
|
}
|
|
|
|
var pickupLocation = await _locationService.GetLocationByAddressAsync(PickupAddress);
|
|
if (pickupLocation == null)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_PickupAddress;
|
|
return;
|
|
}
|
|
|
|
var returnLocation = await _locationService.GetLocationByAddressAsync(ReturnAddress);
|
|
if (returnLocation == null)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_ReturnAddress;
|
|
return;
|
|
}
|
|
|
|
var pickupDistance = Location.CalculateDistance(pickupLocation.Latitude, pickupLocation.Longitude, Walker.Lat, Walker.Lng, DistanceUnits.Kilometers);
|
|
var returnDistance = Location.CalculateDistance(returnLocation.Latitude, returnLocation.Longitude, Walker.Lat, Walker.Lng, DistanceUnits.Kilometers);
|
|
if (pickupDistance > Walker.Radius)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_PickupDistance, Walker.FirstName, Walker.Radius.ToString("N2"), pickupDistance.ToString("N2"));
|
|
return;
|
|
}
|
|
if (returnDistance > Walker.Radius)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = string.Format(Resources.Text.Walk_Book_Error_ReturnDistance, Walker.FirstName, Walker.Radius.ToString("N2"), returnDistance.ToString("N2"));
|
|
return;
|
|
}
|
|
|
|
if (ServiceType == WalkServiceType.Walking && StartDate.Date != EndDate.Date)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_Walking;
|
|
return;
|
|
}
|
|
|
|
if (ServiceType == WalkServiceType.DayCare)
|
|
{
|
|
if ((EndDate.Date == StartDate.Date))
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_DayCare;
|
|
return;
|
|
}
|
|
var endDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
var startDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
|
|
if ((endDate - startDate).TotalHours > 24)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_DayCare;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (ServiceType == WalkServiceType.Sitting)
|
|
{
|
|
var endDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
var startDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
|
|
if ((endDate - startDate).TotalHours < 24)
|
|
{
|
|
HasError = true;
|
|
ErrorMessage = Resources.Text.Walk_Book_Error_Sitting;
|
|
return;
|
|
}
|
|
}
|
|
|
|
HasError = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hilfsmethode zum Kalkulieren des Preises
|
|
/// </summary>
|
|
private void CalculatePrice()
|
|
{
|
|
if (!HasError)
|
|
{
|
|
var dogCount = SelectedDogs != null ? SelectedDogs.Count : 0;
|
|
if (ServiceType == WalkServiceType.Walking)
|
|
{
|
|
var endDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
var startDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
|
|
var totalHours = (endDate - startDate).TotalHours;
|
|
var price = ((decimal)totalHours * Walker.PriceWalk) * dogCount;
|
|
|
|
_dispatcher.Dispatch(() =>
|
|
{
|
|
Price = price;
|
|
});
|
|
}
|
|
if (ServiceType == WalkServiceType.DayCare)
|
|
{
|
|
var endDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
var startDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
|
|
var totalHours = (endDate - startDate).TotalHours;
|
|
var price = ((decimal)totalHours * Walker.PriceDay) * dogCount;
|
|
|
|
_dispatcher.Dispatch(() =>
|
|
{
|
|
Price = price;
|
|
});
|
|
}
|
|
if (ServiceType == WalkServiceType.Sitting)
|
|
{
|
|
var endDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
var startDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, 0, DateTimeOffset.Now.Offset);
|
|
|
|
var totalDays = Math.Round((endDate - startDate).TotalDays, MidpointRounding.ToPositiveInfinity);
|
|
var price = ((decimal)totalDays * Walker.PriceSitting) * dogCount;
|
|
_dispatcher.Dispatch(() =>
|
|
{
|
|
Price = price;
|
|
});
|
|
}
|
|
|
|
_dispatcher.DispatchAsync(async () =>
|
|
{
|
|
await CheckDirectBookingAsync();
|
|
});
|
|
|
|
}
|
|
else
|
|
Price = 0m;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prüfen ob ein direktes buchen möglich ist.
|
|
/// Das geht für Walks und nur dann wennd er Temrin in den Openingtimes ist und diese frei sind
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task CheckDirectBookingAsync()
|
|
{
|
|
if (!HasError)
|
|
{
|
|
if (ServiceType == WalkServiceType.Walking)
|
|
{
|
|
if (WalkingTimes != null && WalkingTimes.Any())
|
|
{
|
|
var walkingDays = WalkingTimes.Where(c => c.Day == StartDate.DayOfWeek).ToList();
|
|
if (walkingDays.Any())
|
|
{
|
|
foreach (var walkingDay in walkingDays)
|
|
{
|
|
var available = walkingDay.Start <= StartTime && walkingDay.End >= EndTime;
|
|
if (available)
|
|
{
|
|
//Grundsätzlich kann man das Datum buchen. Nun online sehen ob es frei ist...
|
|
var helpStartDate = new DateTimeOffset(StartDate.Year, StartDate.Month, StartDate.Day, StartTime.Hours, StartTime.Minutes, StartTime.Seconds, DateTimeOffset.Now.Offset);
|
|
var helpEndDate = new DateTimeOffset(EndDate.Year, EndDate.Month, EndDate.Day, EndTime.Hours, EndTime.Minutes, EndTime.Seconds, DateTimeOffset.Now.Offset);
|
|
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var isPossible = await _walkService.IsWalkPossibleAsync(Walker.Id, helpStartDate, helpEndDate, App.CurrentUser.AccessToken, cts.Token);
|
|
DirectBooking = isPossible;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DirectBooking = false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|