diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Behaviors/WebViewNavigationBehavior.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Behaviors/WebViewNavigationBehavior.cs new file mode 100644 index 000000000..07ae80120 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Behaviors/WebViewNavigationBehavior.cs @@ -0,0 +1,49 @@ +using System.Windows.Input; +using Xamarin.Forms; + +namespace eShopOnContainers.Core.Behaviors +{ + public class WebViewNavigationBehavior : Behavior + { + private VisualElement _element; + + public static readonly BindableProperty NavigateCommandProperty = + BindableProperty.Create("NavigateCommand", typeof(ICommand), + typeof(WebViewNavigationBehavior), default(ICommand), + BindingMode.OneWay, null); + + public ICommand NavigateCommand + { + get { return (ICommand)GetValue(NavigateCommandProperty); } + set { SetValue(NavigateCommandProperty, value); } + } + + protected override void OnAttachedTo(WebView bindable) + { + _element = bindable; + bindable.Navigating += OnWebViewNavigating; + bindable.BindingContextChanged += OnBindingContextChanged; + } + + protected override void OnDetachingFrom(WebView bindable) + { + _element = null; + BindingContext = null; + bindable.Navigating -= OnWebViewNavigating; + bindable.BindingContextChanged -= OnBindingContextChanged; + } + + private void OnBindingContextChanged(object sender, System.EventArgs e) + { + BindingContext = _element?.BindingContext; + } + + private void OnWebViewNavigating(object sender, WebNavigatingEventArgs e) + { + if (NavigateCommand != null && NavigateCommand.CanExecute(e.Url)) + { + NavigateCommand.Execute(e.Url); + } + } + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs index d942bc439..8db061124 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs @@ -1,11 +1,53 @@ namespace eShopOnContainers.Core { - public static class GlobalSetting + public class GlobalSetting { - public const string RegisterWebsite = "http://104.40.62.65/Account/Register"; + private string _baseEndpoint; + private static readonly GlobalSetting _instance = new GlobalSetting(); - public const string CatalogEndpoint = "http://104.40.62.65:5101/"; + public GlobalSetting() + { + BaseEndpoint = "http://104.40.62.65"; + } - public const string BasketEndpoint = "http://104.40.62.65:5103/"; + public static GlobalSetting Instance + { + get { return _instance; } + } + + public string BaseEndpoint + { + get { return _baseEndpoint; } + set + { + _baseEndpoint = value; + UpdateEndpoint(_baseEndpoint); + } + } + + public string RegisterWebsite { get; set; } + + public string CatalogEndpoint { get; set; } + + public string OrdersEndpoint { get; set; } + + public string BasketEndpoint { get; set; } + + public string IdentityEndpoint { get; set; } + + public string LogoutEndpoint { get; set; } + + public string IdentityCallback { get; set; } + + private void UpdateEndpoint(string baseEndpoint) + { + RegisterWebsite = string.Format("{0}/Account/Register", baseEndpoint); + CatalogEndpoint = string.Format("{0}:5101", baseEndpoint); + OrdersEndpoint = string.Format("{0}:5102", baseEndpoint); + BasketEndpoint = string.Format("{0}:5103", baseEndpoint); + IdentityEndpoint = string.Format("{0}:5105/connect/authorize", baseEndpoint); + LogoutEndpoint = string.Format("{0}:5105/connect/endsession", baseEndpoint); + IdentityCallback = "http://eshopxamarin/callback.html"; + } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/NumericHelper.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/NumericHelper.cs index 989d359a1..ea4022558 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/NumericHelper.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/NumericHelper.cs @@ -7,7 +7,7 @@ namespace eShopOnContainers.Core.Helpers public static ObservableCollection GetNumericList(int count = 100) { var result = new ObservableCollection(); - for (int i = 0; i < count; i++) + for (int i = 1; i < count; i++) { result.Add(i); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs new file mode 100644 index 000000000..3d2d99134 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/Settings.cs @@ -0,0 +1,41 @@ +using Plugin.Settings; +using Plugin.Settings.Abstractions; + +namespace eShopOnContainers.Core.Helpers +{ + /// + /// This is the Settings static class that can be used in your Core solution or in any + /// of your client applications. All settings are laid out the same exact way with getters + /// and setters. + /// + public static class Settings + { + private static ISettings AppSettings + { + get + { + return CrossSettings.Current; + } + } + + #region Setting Constants + + private const string AccessToken = "access_token"; + private static readonly string AccessTokenDefault = string.Empty; + + #endregion + + + public static string AuthAccessToken + { + get + { + return AppSettings.GetValueOrDefault(AccessToken, AccessTokenDefault); + } + set + { + AppSettings.AddOrUpdateValue(AccessToken, value); + } + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Basket/BasketItem.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Basket/BasketItem.cs index 9b5090e41..c10da754f 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Basket/BasketItem.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Basket/BasketItem.cs @@ -67,11 +67,14 @@ namespace eShopOnContainers.Core.Models.Basket get { return _quantity; } set { - _quantity = value; - RaisePropertyChanged(() => Quantity); - RaisePropertyChanged(() => Total); + if (_quantity != value) + { + _quantity = value; + RaisePropertyChanged(() => Quantity); + RaisePropertyChanged(() => Total); - MessagingCenter.Send(this, MessengerKeys.UpdateProduct); + MessagingCenter.Send(this, MessengerKeys.UpdateProduct); + } } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/CardType.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/CardType.cs new file mode 100644 index 000000000..07873e79c --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/CardType.cs @@ -0,0 +1,8 @@ +namespace eShopOnContainers.Core.Models.Orders +{ + public class CardType + { + public int Id { get; set; } + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs index 10712da68..8ec118a24 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs @@ -3,7 +3,6 @@ using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.ViewModels.Base; using System; using System.Collections.ObjectModel; -using Xamarin.Forms; namespace eShopOnContainers.Core.Models.Orders { @@ -71,8 +70,6 @@ namespace eShopOnContainers.Core.Models.Orders _quantity = value; RaisePropertyChanged(() => Quantity); RaisePropertyChanged(() => Total); - - MessagingCenter.Send(this, MessengerKeys.UpdateProduct); } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/User/LogoutParameter.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/User/LogoutParameter.cs new file mode 100644 index 000000000..a338c44bb --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/User/LogoutParameter.cs @@ -0,0 +1,7 @@ +namespace eShopOnContainers.Core.Models.User +{ + public class LogoutParameter + { + public bool Logout { get; set; } + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketMockService.cs index 6bdcf0df5..d7fce6abc 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketMockService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketMockService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Xamarin.Forms; -using System; namespace eShopOnContainers.Core.Services.Basket { @@ -18,11 +17,11 @@ namespace eShopOnContainers.Core.Services.Basket } }; - public async Task GetBasketAsync(string guidUser) + public async Task GetBasketAsync(string guidUser, string token) { await Task.Delay(500); - if(string.IsNullOrEmpty(guidUser)) + if(string.IsNullOrEmpty(guidUser) || string.IsNullOrEmpty(token)) { return new CustomerBasket(); } @@ -38,5 +37,15 @@ namespace eShopOnContainers.Core.Services.Basket return MockCustomBasket; } + + public async Task ClearBasketAsync(string guidUser) + { + await Task.Delay(500); + + if (!string.IsNullOrEmpty(guidUser)) + { + MockCustomBasket.Items.Clear(); + } + } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs index e5bc66202..cbed3317b 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs @@ -14,18 +14,18 @@ namespace eShopOnContainers.Core.Services.Basket _requestProvider = requestProvider; } - public async Task GetBasketAsync(string guidUser) + public async Task GetBasketAsync(string guidUser, string token) { try { - UriBuilder builder = new UriBuilder(GlobalSetting.BasketEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint); builder.Path = guidUser; string uri = builder.ToString(); CustomerBasket basket = - await _requestProvider.GetAsync(uri); + await _requestProvider.GetAsync(uri, token); return basket; } @@ -41,7 +41,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task UpdateBasketAsync(CustomerBasket customerBasket) { - UriBuilder builder = new UriBuilder(GlobalSetting.BasketEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint); string uri = builder.ToString(); @@ -49,5 +49,16 @@ namespace eShopOnContainers.Core.Services.Basket return result; } + + public async Task ClearBasketAsync(string guidUser) + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint); + + builder.Path = guidUser; + + string uri = builder.ToString(); + + await _requestProvider.DeleteAsync(uri); + } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/IBasketService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/IBasketService.cs index 356eb40f7..90ceb236f 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/IBasketService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/IBasketService.cs @@ -5,7 +5,8 @@ namespace eShopOnContainers.Core.Services.Basket { public interface IBasketService { - Task GetBasketAsync(string guidUser); + Task GetBasketAsync(string guidUser, string token); Task UpdateBasketAsync(CustomerBasket customerBasket); + Task ClearBasketAsync(string guidUser); } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs index fa78f3625..9234e4059 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs @@ -19,30 +19,44 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> FilterAsync(int catalogBrandId, int catalogTypeId) { - UriBuilder builder = new UriBuilder(GlobalSetting.CatalogEndpoint); + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId); + builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId); - string uri = builder.ToString(); + string uri = builder.ToString(); - CatalogRoot catalog = - await _requestProvider.GetAsync(uri); + CatalogRoot catalog = + await _requestProvider.GetAsync(uri); - return catalog?.Data?.ToObservableCollection(); + return catalog?.Data?.ToObservableCollection(); + } + catch + { + return new ObservableCollection(); + } } public async Task> GetCatalogAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.CatalogEndpoint); + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/items"; + builder.Path = "api/v1/catalog/items"; - string uri = builder.ToString(); + string uri = builder.ToString(); - CatalogRoot catalog = - await _requestProvider.GetAsync(uri); + CatalogRoot catalog = + await _requestProvider.GetAsync(uri); - return catalog?.Data?.ToObservableCollection(); + return catalog?.Data?.ToObservableCollection(); + } + catch + { + return new ObservableCollection(); + } } public Task GetCatalogItemAsync(string id) @@ -52,30 +66,44 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogBrandAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.CatalogEndpoint); + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/catalogbrands"; + builder.Path = "api/v1/catalog/catalogbrands"; - string uri = builder.ToString(); + string uri = builder.ToString(); - IEnumerable brands = - await _requestProvider.GetAsync>(uri); + IEnumerable brands = + await _requestProvider.GetAsync>(uri); - return brands?.ToObservableCollection(); + return brands?.ToObservableCollection(); + } + catch + { + return new ObservableCollection(); + } } public async Task> GetCatalogTypeAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.CatalogEndpoint); + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); - builder.Path = "api/v1/catalog/catalogtypes"; + builder.Path = "api/v1/catalog/catalogtypes"; - string uri = builder.ToString(); + string uri = builder.ToString(); - IEnumerable types = - await _requestProvider.GetAsync>(uri); + IEnumerable types = + await _requestProvider.GetAsync>(uri); - return types?.ToObservableCollection(); + return types?.ToObservableCollection(); + } + catch + { + return new ObservableCollection(); + } } } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IIdentityService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IIdentityService.cs new file mode 100644 index 000000000..134e2ee73 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IIdentityService.cs @@ -0,0 +1,9 @@ +namespace eShopOnContainers.Core.Services.Identity +{ + public interface IIdentityService + { + string CreateAuthorizeRequest(); + string CreateLogoutRequest(string token); + string DecodeToken(string token); + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs new file mode 100644 index 000000000..b6f61c420 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs @@ -0,0 +1,69 @@ +using IdentityModel.Client; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace eShopOnContainers.Core.Services.Identity +{ + public class IdentityService : IIdentityService + { + public string CreateAuthorizeRequest() + { + // Create URI to authorize endpoint + var authorizeRequest = + new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint); + + // Dictionary with values for the authorize request + var dic = new Dictionary(); + dic.Add("client_id", "xamarin"); + dic.Add("response_type", "id_token token"); + dic.Add("scope", "openid profile basket"); + + dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback); + dic.Add("nonce", Guid.NewGuid().ToString("N")); + + // Add CSRF token to protect against cross-site request forgery attacks. + var currentCSRFToken = Guid.NewGuid().ToString("N"); + dic.Add("state", currentCSRFToken); + + var authorizeUri = authorizeRequest.Create(dic); + + return authorizeUri; + } + + public string CreateLogoutRequest(string token) + { + return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}", + GlobalSetting.Instance.LogoutEndpoint, + token, + GlobalSetting.Instance.IdentityCallback); + } + + public string DecodeToken(string token) + { + var parts = token.Split('.'); + + string partToConvert = parts[1]; + partToConvert = partToConvert.Replace('-', '+'); + partToConvert = partToConvert.Replace('_', '/'); + switch (partToConvert.Length % 4) + { + case 0: + break; + case 2: + partToConvert += "=="; + break; + case 3: + partToConvert += "="; + break; + } + + var partAsBytes = Convert.FromBase64String(partToConvert); + var partAsUTF8String = Encoding.UTF8.GetString(partAsBytes, 0, partAsBytes.Count()); + + return JObject.Parse(partAsUTF8String).ToString(); + } + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs index 66a723baf..22383fdb1 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs @@ -1,4 +1,5 @@ -using eShopOnContainers.Core.ViewModels; +using eShopOnContainers.Core.Helpers; +using eShopOnContainers.Core.ViewModels; using eShopOnContainers.Core.Views; using eShopOnContainers.ViewModels.Base; using System; @@ -29,7 +30,10 @@ namespace eShopOnContainers.Services public Task InitializeAsync() { - return NavigateToAsync(); + if(string.IsNullOrEmpty(Settings.AuthAccessToken)) + return NavigateToAsync(); + else + return NavigateToAsync(); } public Task NavigateToAsync() where TViewModel : ViewModelBase @@ -67,7 +71,7 @@ namespace eShopOnContainers.Services public virtual Task RemoveLastFromBackStackAsync() { - var mainPage = CurrentApplication.MainPage as CustomNavigationPage; + var mainPage = CurrentApplication.MainPage as CustomNavigationView; if (mainPage != null) { @@ -80,7 +84,7 @@ namespace eShopOnContainers.Services public virtual Task RemoveBackStackAsync() { - var mainPage = CurrentApplication.MainPage as CustomNavigationPage; + var mainPage = CurrentApplication.MainPage as CustomNavigationView; if (mainPage != null) { @@ -100,11 +104,11 @@ namespace eShopOnContainers.Services if (page is LoginView) { - CurrentApplication.MainPage = new CustomNavigationPage(page); + CurrentApplication.MainPage = new CustomNavigationView(page); } else { - var navigationPage = CurrentApplication.MainPage as CustomNavigationPage; + var navigationPage = CurrentApplication.MainPage as CustomNavigationView; if (navigationPage != null) { @@ -112,7 +116,7 @@ namespace eShopOnContainers.Services } else { - CurrentApplication.MainPage = new CustomNavigationPage(page); + CurrentApplication.MainPage = new CustomNavigationView(page); } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/IOrderService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/IOrderService.cs new file mode 100644 index 000000000..5d63ea9e8 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/IOrderService.cs @@ -0,0 +1,13 @@ +using System.Collections.ObjectModel; +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.Order +{ + public interface IOrderService + { + Task CreateOrderAsync(Models.Orders.Order newOrder); + Task> GetOrdersAsync(); + Task GetOrderAsync(int orderId); + Task> GetCardTypesAsync(); + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderMockService.cs new file mode 100644 index 000000000..4b249fbd0 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderMockService.cs @@ -0,0 +1,61 @@ +using eShopOnContainers.Core.Extensions; +using eShopOnContainers.Core.Models.Orders; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.Order +{ + public class OrderMockService : IOrderService + { + private List MockOrders = new List() + { + new Models.Orders.Order { SequenceNumber = 123, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, + new Models.Orders.Order { SequenceNumber = 132, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, + new Models.Orders.Order { SequenceNumber = 231, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, + }; + + private static List MockOrderItems = new List() + { + new OrderItem { OrderId = Guid.NewGuid(), ProductId = "1", Discount = 15, ProductName = ".NET Bot Blue Sweatshirt (M)", Quantity = 1, UnitPrice = 16.50M }, + new OrderItem { OrderId = Guid.NewGuid(), ProductId = "3", Discount = 0, ProductName = ".NET Bot Black Sweatshirt (M)", Quantity = 2, UnitPrice = 19.95M } + }; + + private static List MockCardTypes = new List() + { + new CardType { Id = 1, Name = "Amex" }, + new CardType { Id = 2, Name = "Visa" }, + new CardType { Id = 3, Name = "MasterCard" }, + }; + + public async Task CreateOrderAsync(Models.Orders.Order newOrder) + { + await Task.Delay(500); + + MockOrders.Insert(0, newOrder); + } + + public async Task> GetOrdersAsync() + { + await Task.Delay(500); + + return MockOrders.ToObservableCollection(); + } + + public async Task GetOrderAsync(int orderId) + { + await Task.Delay(500); + + return MockOrders.FirstOrDefault(o => o.SequenceNumber == orderId); + } + + public async Task> GetCardTypesAsync() + { + await Task.Delay(500); + + return MockCardTypes.ToObservableCollection(); + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs new file mode 100644 index 000000000..50da93209 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs @@ -0,0 +1,91 @@ +using eShopOnContainers.Core.Services.RequestProvider; +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.Order +{ + public class OrderService : IOrderService + { + private readonly IRequestProvider _requestProvider; + + public OrderService(IRequestProvider requestProvider) + { + _requestProvider = requestProvider; + } + + public async Task CreateOrderAsync(Models.Orders.Order newOrder) + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + + builder.Path = "api/v1/orders/new"; + + string uri = builder.ToString(); + + await _requestProvider.PostAsync(uri, newOrder); + } + + public async Task> GetOrdersAsync() + { + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + + builder.Path = "api/v1/orders"; + + string uri = builder.ToString(); + + ObservableCollection orders = + await _requestProvider.GetAsync>(uri); + + return orders; + } + catch + { + return new ObservableCollection(); + } + } + + public async Task GetOrderAsync(int orderId) + { + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + + builder.Path = string.Format("api/v1/orders/{0}", orderId); + + string uri = builder.ToString(); + + Models.Orders.Order order = + await _requestProvider.GetAsync(uri); + + return order; + } + catch + { + return new Models.Orders.Order(); + } + } + + public async Task> GetCardTypesAsync() + { + try + { + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.OrdersEndpoint); + + builder.Path = "api/v1/orders/cardtypes"; + + string uri = builder.ToString(); + + ObservableCollection cardTypes = + await _requestProvider.GetAsync>(uri); + + return cardTypes; + } + catch + { + return new ObservableCollection(); + } + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/IRequestProvider.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/IRequestProvider.cs index 7c36620fa..81772cad6 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/IRequestProvider.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/IRequestProvider.cs @@ -6,6 +6,8 @@ namespace eShopOnContainers.Core.Services.RequestProvider { Task GetAsync(string uri); + Task GetAsync(string uri, string token); + Task PostAsync(string uri, TResult data); Task PostAsync(string uri, TRequest data); @@ -13,5 +15,7 @@ namespace eShopOnContainers.Core.Services.RequestProvider Task PutAsync(string uri, TResult data); Task PutAsync(string uri, TRequest data); + + Task DeleteAsync(string uri); } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/RequestProvider.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/RequestProvider.cs index dd6a1bce5..c926e56e3 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/RequestProvider.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/RequestProvider/RequestProvider.cs @@ -41,6 +41,22 @@ namespace eShopOnContainers.Core.Services.RequestProvider return result; } + public async Task GetAsync(string uri, string token) + { + HttpClient httpClient = CreateHttpClient(); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + HttpResponseMessage response = await httpClient.GetAsync(uri); + + await HandleResponse(response); + + string serialized = await response.Content.ReadAsStringAsync(); + + TResult result = await Task.Run(() => + JsonConvert.DeserializeObject(serialized, _serializerSettings)); + + return result; + } + public Task PostAsync(string uri, TResult data) { return PostAsync(uri, data); @@ -77,6 +93,13 @@ namespace eShopOnContainers.Core.Services.RequestProvider return await Task.Run(() => JsonConvert.DeserializeObject(responseData, _serializerSettings)); } + public async Task DeleteAsync(string uri) + { + HttpClient httpClient = CreateHttpClient(); + + await httpClient.DeleteAsync(uri); + } + private HttpClient CreateHttpClient() { var httpClient = new HttpClient(); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs index fac0a47a1..02d310c3a 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs @@ -1,12 +1,9 @@ -using eShopOnContainers.Core.Models.Orders; -using System.Collections.Generic; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace eShopOnContainers.Core.Services.User { public interface IUserService { Task GetUserAsync(); - Task> GetOrdersAsync(); } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs index 12c3f8e60..d273e704a 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs @@ -1,7 +1,4 @@ -using eShopOnContainers.Core.Models.Orders; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace eShopOnContainers.Core.Services.User { @@ -18,31 +15,12 @@ namespace eShopOnContainers.Core.Services.User Country = "United States" }; - private List MockOrders = new List() - { - new Order { SequenceNumber = 123, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, - new Order { SequenceNumber = 132, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, - new Order { SequenceNumber = 231, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = MockOrderItems }, - }; - - private static List MockOrderItems = new List() - { - new OrderItem { OrderId = Guid.NewGuid(), ProductId = "1", Discount = 15, ProductName = ".NET Bot Blue Sweatshirt (M)", Quantity = 1, UnitPrice = 16.50M }, - new OrderItem { OrderId = Guid.NewGuid(), ProductId = "3", Discount = 0, ProductName = ".NET Bot Black Sweatshirt (M)", Quantity = 2, UnitPrice = 19.95M } - }; - + public async Task GetUserAsync() { await Task.Delay(500); return MockUser; } - - public async Task> GetOrdersAsync() - { - await Task.Delay(500); - - return MockOrders; - } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs index 25fd28be6..4b0e7432f 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs @@ -15,6 +15,6 @@ public const string Filter = "Filter"; // Change selected Tab programmatically - public const string ChangeTab = "ChangeTab"; + public const string ChangeTab = "ChangeTab"; } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs index e1c28642a..dd269b659 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs @@ -7,6 +7,8 @@ using eShopOnContainers.Core.Services.OpenUrl; using eShopOnContainers.Core.Services.User; using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Services.Basket; +using eShopOnContainers.Core.Services.Identity; +using eShopOnContainers.Core.Services.Order; namespace eShopOnContainers.ViewModels.Base { @@ -37,6 +39,7 @@ namespace eShopOnContainers.ViewModels.Base RegisterSingleton(); _unityContainer.RegisterType(); _unityContainer.RegisterType(); + _unityContainer.RegisterType(); _unityContainer.RegisterType(); _unityContainer.RegisterType(); @@ -53,28 +56,29 @@ namespace eShopOnContainers.ViewModels.Base _unityContainer.RegisterType(); } - public void UpdateServices(bool useMockServices) + public void UpdateDependencies(bool useMockServices) { - if (!useMockServices) + if (useMockServices) { _unityContainer.RegisterInstance(new CatalogMockService()); _unityContainer.RegisterInstance(new BasketMockService()); + _unityContainer.RegisterInstance(new OrderMockService()); _unityContainer.RegisterInstance(new UserMockService()); - UseMockService = false; + UseMockService = true; } else { var requestProvider = Resolve(); _unityContainer.RegisterInstance(new CatalogService(requestProvider)); _unityContainer.RegisterInstance(new BasketService(requestProvider)); + _unityContainer.RegisterInstance(new OrderService(requestProvider)); _unityContainer.RegisterInstance(new UserMockService()); - UseMockService = true; + UseMockService = false; } } - - + public T Resolve() { return _unityContainer.Resolve(); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/BasketViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/BasketViewModel.cs index 0ffea52ad..c24f3cbba 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/BasketViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/BasketViewModel.cs @@ -1,6 +1,5 @@ using eShopOnContainers.Core.Models.Basket; using eShopOnContainers.Core.Models.Catalog; -using eShopOnContainers.Core.Models.Orders; using eShopOnContainers.Core.Models.User; using eShopOnContainers.Core.Services.Basket; using eShopOnContainers.Core.Services.User; @@ -69,10 +68,9 @@ namespace eShopOnContainers.Core.ViewModels { MessagingCenter.Subscribe>(this, MessengerKeys.UpdateBasket, (sender, arg) => { - BadgeCount = arg.Count; - foreach (var basketItem in arg) { + BadgeCount += basketItem.Quantity; AddBasketItem(basketItem); } }); @@ -84,7 +82,7 @@ namespace eShopOnContainers.Core.ViewModels AddCatalogItem(arg); }); - MessagingCenter.Subscribe(this, MessengerKeys.UpdateProduct, (sender) => + MessagingCenter.Subscribe(this, MessengerKeys.UpdateProduct, (sender) => { ReCalculateTotal(); }); @@ -126,12 +124,16 @@ namespace eShopOnContainers.Core.ViewModels { Total = 0; + if (BasketItems == null) + { + return; + } + foreach (var orderItem in BasketItems) { Total += (orderItem.Quantity * orderItem.UnitPrice); } - - + _basketService.UpdateBasketAsync(new CustomerBasket { BuyerId = _user.GuidUser, diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs index 5735c5633..aa9c13fee 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs @@ -9,6 +9,7 @@ using System.Windows.Input; using eShopOnContainers.Core.Services.User; using System.Linq; using eShopOnContainers.Core.Services.Basket; +using eShopOnContainers.Core.Helpers; namespace eShopOnContainers.Core.ViewModels { @@ -100,9 +101,10 @@ namespace eShopOnContainers.Core.ViewModels Products = await _productsService.GetCatalogAsync(); Brands = await _productsService.GetCatalogBrandAsync(); Types = await _productsService.GetCatalogTypeAsync(); - + var user = await _userService.GetUserAsync(); - var basket = await _basketService.GetBasketAsync(user.GuidUser); + var authToken = Settings.AuthAccessToken; + var basket = await _basketService.GetBasketAsync(user.GuidUser, authToken); if (basket != null && basket.Items.Any()) { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs index e842f310f..a2a6df96d 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs @@ -11,6 +11,8 @@ using System.Collections.ObjectModel; using System.Linq; using eShopOnContainers.Core.Models.Basket; using System.Collections.Generic; +using eShopOnContainers.Core.Services.Basket; +using eShopOnContainers.Core.Services.Order; namespace eShopOnContainers.Core.ViewModels { @@ -21,10 +23,16 @@ namespace eShopOnContainers.Core.ViewModels private User _user; private IUserService _userService; + private IBasketService _basketService; + private IOrderService _orderService; - public CheckoutViewModel(IUserService userService) + public CheckoutViewModel(IUserService userService, + IBasketService basketService, + IOrderService orderService) { + _basketService = basketService; _userService = userService; + _orderService = orderService; } public ObservableCollection OrderItems @@ -74,7 +82,7 @@ namespace eShopOnContainers.Core.ViewModels Order = new Order { ShippingAddress = User, - OrderItems = CreateOrderItems(orderItems.ToList()), + OrderItems = CreateOrderItems(orderItems), Status = OrderStatus.Pending, OrderDate = DateTime.Now, Total = GetOrderTotal() @@ -86,14 +94,17 @@ namespace eShopOnContainers.Core.ViewModels private async void Checkout() { + await _orderService.CreateOrderAsync(Order); + await _basketService.ClearBasketAsync(User.GuidUser); + await NavigationService.NavigateToAsync(new TabParameter { TabIndex = 1 }); await NavigationService.RemoveLastFromBackStackAsync(); - await DialogService.ShowAlertAsync("Order sent successfully", string.Format("Order {0}", Order.OrderNumber), "Ok"); + await DialogService.ShowAlertAsync("Order sent successfully!", string.Format("Order {0}", Order.OrderNumber), "Ok"); await NavigationService.RemoveLastFromBackStackAsync(); } - private List CreateOrderItems(List basketItems) + private List CreateOrderItems(ObservableCollection basketItems) { var orderItems = new List(); @@ -124,4 +135,4 @@ namespace eShopOnContainers.Core.ViewModels return total; } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs index 2381d0958..63f32f7cf 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs @@ -1,6 +1,11 @@ -using eShopOnContainers.Core.Services.OpenUrl; +using eShopOnContainers.Core.Helpers; +using eShopOnContainers.Core.Models.User; +using eShopOnContainers.Core.Services.Identity; +using eShopOnContainers.Core.Services.OpenUrl; using eShopOnContainers.Core.Validations; +using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.ViewModels.Base; +using IdentityModel.Client; using System; using System.Diagnostics; using System.Threading.Tasks; @@ -13,17 +18,24 @@ namespace eShopOnContainers.Core.ViewModels { private ValidatableObject _userName; private ValidatableObject _password; + private bool _isMock; private bool _isValid; + private string _authUrl; private IOpenUrlService _openUrlService; + private IIdentityService _identityService; - public LoginViewModel(IOpenUrlService openUrlService) + public LoginViewModel(IOpenUrlService openUrlService, + IIdentityService identityService) { _openUrlService = openUrlService; + _identityService = identityService; _userName = new ValidatableObject(); _password = new ValidatableObject(); + IsMock = ViewModelLocator.Instance.UseMockService; + AddValidations(); } @@ -53,6 +65,19 @@ namespace eShopOnContainers.Core.ViewModels } } + public bool IsMock + { + get + { + return _isMock; + } + set + { + _isMock = value; + RaisePropertyChanged(() => IsMock); + } + } + public bool IsValid { get @@ -66,11 +91,43 @@ namespace eShopOnContainers.Core.ViewModels } } - public ICommand SignInCommand => new Command(SignInAsync); + public string LoginUrl + { + get + { + return _authUrl; + } + set + { + _authUrl = value; + RaisePropertyChanged(() => LoginUrl); + } + } + + public ICommand MockSignInCommand => new Command(MockSignInAsync); + + public ICommand SignInCommand => new Command(async () => await SignInAsync()); public ICommand RegisterCommand => new Command(Register); - private async void SignInAsync() + public ICommand NavigateCommand => new Command(NavigateAsync); + + public override Task InitializeAsync(object navigationData) + { + if(navigationData is LogoutParameter) + { + var logoutParameter = (LogoutParameter)navigationData; + + if (logoutParameter.Logout) + { + Logout(); + } + } + + return base.InitializeAsync(navigationData); + } + + private async void MockSignInAsync() { IsBusy = true; IsValid = true; @@ -104,9 +161,54 @@ namespace eShopOnContainers.Core.ViewModels IsBusy = false; } + private async Task SignInAsync() + { + IsBusy = true; + + await Task.Delay(500); + + LoginUrl = _identityService.CreateAuthorizeRequest(); + + IsValid = true; + + IsBusy = false; + } + private void Register() { - _openUrlService.OpenUrl(GlobalSetting.RegisterWebsite); + _openUrlService.OpenUrl(GlobalSetting.Instance.RegisterWebsite); + } + + private void Logout() + { + var token = Settings.AuthAccessToken; + var logoutRequest = _identityService.CreateLogoutRequest(token); + + if(!string.IsNullOrEmpty(logoutRequest)) + { + IsValid = false; + LoginUrl = logoutRequest; + Settings.AuthAccessToken = string.Empty; + } + } + + private async void NavigateAsync(string url) + { + if (url.Contains(GlobalSetting.Instance.IdentityCallback)) + { + var authResponse = new AuthorizeResponse(url); + + if (!string.IsNullOrWhiteSpace(authResponse.AccessToken)) + { + if(authResponse.AccessToken != null) + { + Settings.AuthAccessToken = authResponse.AccessToken; + + await NavigationService.NavigateToAsync(); + await NavigationService.RemoveLastFromBackStackAsync(); + } + } + } } private bool Validate() @@ -123,4 +225,4 @@ namespace eShopOnContainers.Core.ViewModels _password.Validations.Add(new IsNotNullOrEmptyRule { ValidationMessage = "Password should not be empty" }); } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs index fe69f36a4..e006b24c1 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs @@ -1,6 +1,8 @@ using eShopOnContainers.Core.Extensions; using eShopOnContainers.Core.Models.Orders; -using eShopOnContainers.Core.Services.User; +using eShopOnContainers.Core.Models.User; +using eShopOnContainers.Core.Services.Order; +using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.ViewModels.Base; using System.Collections.ObjectModel; using System.Threading.Tasks; @@ -13,11 +15,11 @@ namespace eShopOnContainers.Core.ViewModels { private ObservableCollection _orders; - private IUserService _userService; + private IOrderService _orderService; - public ProfileViewModel(IUserService userService) + public ProfileViewModel(IOrderService orderService) { - _userService = userService; + _orderService = orderService; } public ObservableCollection Orders @@ -38,7 +40,7 @@ namespace eShopOnContainers.Core.ViewModels { IsBusy = true; - var orders = await _userService.GetOrdersAsync(); + var orders = await _orderService.GetOrdersAsync(); Orders = orders.ToObservableCollection(); IsBusy = false; @@ -48,7 +50,7 @@ namespace eShopOnContainers.Core.ViewModels { IsBusy = true; - await NavigationService.NavigateToAsync(); + await NavigationService.NavigateToAsync(new LogoutParameter { Logout = true }); await NavigationService.RemoveBackStackAsync(); IsBusy = false; diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs index 2cdacb480..77e0dbf9b 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs @@ -9,11 +9,12 @@ namespace eShopOnContainers.Core.ViewModels { private string _title; private string _description; - private bool _useMockServices; + private bool _useAzureServices; + private string _endpoint; public SettingsViewModel() { - UseMockServices = ViewModelLocator.Instance.UseMockService; + UseAzureServices = !ViewModelLocator.Instance.UseMockService; } public string Title @@ -36,13 +37,29 @@ namespace eShopOnContainers.Core.ViewModels } } - public bool UseMockServices + public bool UseAzureServices { - get { return _useMockServices; } + get { return _useAzureServices; } set { - _useMockServices = value; - RaisePropertyChanged(() => UseMockServices); + _useAzureServices = value; + RaisePropertyChanged(() => UseAzureServices); + } + } + + public string Endpoint + { + get { return _endpoint; } + set + { + _endpoint = value; + + if(!string.IsNullOrEmpty(_endpoint)) + { + UpdateEndpoint(_endpoint); + } + + RaisePropertyChanged(() => Endpoint); } } @@ -50,7 +67,7 @@ namespace eShopOnContainers.Core.ViewModels private void MockServices() { - ViewModelLocator.Instance.UpdateServices(UseMockServices); + ViewModelLocator.Instance.UpdateDependencies(!UseAzureServices); UpdateInfo(); } @@ -58,12 +75,14 @@ namespace eShopOnContainers.Core.ViewModels { UpdateInfo(); + Endpoint = GlobalSetting.Instance.BaseEndpoint; + return base.InitializeAsync(navigationData); } private void UpdateInfo() { - if (!UseMockServices) + if (!UseAzureServices) { Title = "Use Mock Services"; Description = "Mock Services are simulated objects that mimic the behavior of real services in controlled ways"; @@ -74,5 +93,10 @@ namespace eShopOnContainers.Core.ViewModels Description = "Azure Services are real objects that required a valid internet connection"; } } + + private void UpdateEndpoint(string endpoint) + { + GlobalSetting.Instance.BaseEndpoint = endpoint; + } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml index fd51414b6..870980ac2 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml @@ -58,7 +58,8 @@ + BackgroundColor="{StaticResource LightGreenColor}" + IsEnabled="{Binding Products.Count, Converter={StaticResource CountToBoolConverter}}"> \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml index f28f121c1..b13a4855d 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml @@ -43,6 +43,18 @@ Value="12, 12, 12, 0" /> + + @@ -82,6 +94,7 @@ + @@ -121,10 +134,31 @@ WinPhone="Assets/switchOff.png"/> - + + + diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml.cs index f7ad31a47..e57c8fd32 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Xamarin.Forms; +using Xamarin.Forms; namespace eShopOnContainers.Core.Views { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/BasketItemTemplate.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/BasketItemTemplate.xaml index 48ec265a9..76c37db3c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/BasketItemTemplate.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/BasketItemTemplate.xaml @@ -56,6 +56,8 @@