diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml.cs index d6523392d..c4aea5cd7 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml.cs @@ -9,16 +9,27 @@ namespace eShopOnContainers { public partial class App : Application { + public bool UseMockServices { get; set; } + public App() { InitializeComponent(); + InitApp(); + if (Device.OS == TargetPlatform.Windows) { InitNavigation(); } } + private void InitApp() + { + UseMockServices = true; + + ViewModelLocator.Instance.UpdateDependencies(UseMockServices); + } + private Task InitNavigation() { var navigationService = ViewModelLocator.Instance.Resolve(); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/ItemsToHeightConverter.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/ItemsToHeightConverter.cs index 6a1832fa1..419ca5082 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/ItemsToHeightConverter.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/ItemsToHeightConverter.cs @@ -6,7 +6,7 @@ namespace eShopOnContainers.Core.Converters { public class ItemsToHeightConverter : IValueConverter { - private const int ItemHeight = 144; + private const int ItemHeight = 156; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs index 5b3a5bbec..706f3592e 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs @@ -6,6 +6,8 @@ public const string CatalogEndpoint = "http://104.40.62.65:5101/"; + public const string OrdersEndpoint = "http://104.40.62.65:5102/"; + public const string BasketEndpoint = "http://104.40.62.65:5103/"; public const string IdentityEndpoint = "http://104.40.62.65:5105/connect/authorize"; 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/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/Services/Catalog/CatalogService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs index fa78f3625..dd8118a53 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.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.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.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.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 index 4ea347b96..134e2ee73 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IIdentityService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IIdentityService.cs @@ -3,6 +3,7 @@ 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 index 87fd53dc1..66c60cb21 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Identity/IdentityService.cs @@ -33,6 +33,14 @@ namespace eShopOnContainers.Core.Services.Identity return authorizeUri; } + public string CreateLogoutRequest(string token) + { + return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}", + GlobalSetting.LogoutEndpoint, + token, + GlobalSetting.IdentityCallback); + } + public string DecodeToken(string token) { var parts = token.Split('.'); 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..ed8e5fb7e --- /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.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.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.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.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/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..506892520 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs @@ -15,6 +15,9 @@ public const string Filter = "Filter"; // Change selected Tab programmatically - public const string ChangeTab = "ChangeTab"; + public const string ChangeTab = "ChangeTab"; + + // Logout + public const string Logout = "Logout"; } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs index e1d5faf98..dd269b659 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs @@ -8,6 +8,7 @@ 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 { @@ -55,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/CheckoutViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs index 2c1b19e36..b42fd9b67 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs @@ -12,6 +12,7 @@ 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 { @@ -23,12 +24,15 @@ namespace eShopOnContainers.Core.ViewModels private IUserService _userService; private IBasketService _basketService; + private IOrderService _orderService; public CheckoutViewModel(IUserService userService, - IBasketService basketService) + IBasketService basketService, + IOrderService orderService) { _basketService = basketService; _userService = userService; + _orderService = orderService; } public ObservableCollection OrderItems @@ -90,6 +94,7 @@ namespace eShopOnContainers.Core.ViewModels private async void Checkout() { + await _orderService.CreateOrderAsync(Order); await _basketService.ClearBasketAsync(User.GuidUser); await NavigationService.NavigateToAsync(new TabParameter { TabIndex = 1 }); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs index 62a8c8056..b17de8734 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/LoginViewModel.cs @@ -1,6 +1,8 @@ -using eShopOnContainers.Core.Services.Identity; +using eShopOnContainers.Core.Helpers; +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; @@ -17,7 +19,7 @@ namespace eShopOnContainers.Core.ViewModels private ValidatableObject _password; private bool _isMock; private bool _isValid; - private string _loginUrl; + private string _authUrl; private IOpenUrlService _openUrlService; private IIdentityService _identityService; @@ -31,6 +33,8 @@ namespace eShopOnContainers.Core.ViewModels _userName = new ValidatableObject(); _password = new ValidatableObject(); + IsMock = ViewModelLocator.Instance.UseMockService; + AddValidations(); } @@ -90,18 +94,18 @@ namespace eShopOnContainers.Core.ViewModels { get { - return _loginUrl; + return _authUrl; } set { - _loginUrl = value; + _authUrl = value; RaisePropertyChanged(() => LoginUrl); } } public ICommand MockSignInCommand => new Command(MockSignInAsync); - public ICommand SignInCommand => new Command(SignInAsync); + public ICommand SignInCommand => new Command(async () => await SignInAsync()); public ICommand RegisterCommand => new Command(Register); @@ -109,7 +113,10 @@ namespace eShopOnContainers.Core.ViewModels public override Task InitializeAsync(object navigationData) { - LoginUrl = _identityService.CreateAuthorizeRequest(); + MessagingCenter.Subscribe(this, MessengerKeys.Logout, (sender) => + { + Logout(); + }); return base.InitializeAsync(navigationData); } @@ -148,12 +155,14 @@ namespace eShopOnContainers.Core.ViewModels IsBusy = false; } - private async void SignInAsync() + private async Task SignInAsync() { IsBusy = true; await Task.Delay(500); + LoginUrl = _identityService.CreateAuthorizeRequest(); + IsValid = true; IsBusy = false; @@ -164,6 +173,19 @@ namespace eShopOnContainers.Core.ViewModels _openUrlService.OpenUrl(GlobalSetting.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.IdentityCallback)) @@ -177,6 +199,8 @@ namespace eShopOnContainers.Core.ViewModels if(decodedTokens != null) { + Settings.AuthAccessToken = decodedTokens; + await NavigationService.NavigateToAsync(); await NavigationService.RemoveLastFromBackStackAsync(); } @@ -198,4 +222,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..43f4d29da 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/ProfileViewModel.cs @@ -1,6 +1,7 @@ using eShopOnContainers.Core.Extensions; using eShopOnContainers.Core.Models.Orders; -using eShopOnContainers.Core.Services.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 +14,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 +39,7 @@ namespace eShopOnContainers.Core.ViewModels { IsBusy = true; - var orders = await _userService.GetOrdersAsync(); + var orders = await _orderService.GetOrdersAsync(); Orders = orders.ToObservableCollection(); IsBusy = false; @@ -48,6 +49,7 @@ namespace eShopOnContainers.Core.ViewModels { IsBusy = true; + MessagingCenter.Send(this, MessengerKeys.Logout); await NavigationService.NavigateToAsync(); await NavigationService.RemoveBackStackAsync(); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs index 2cdacb480..c0455b8cb 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs @@ -9,11 +9,11 @@ namespace eShopOnContainers.Core.ViewModels { private string _title; private string _description; - private bool _useMockServices; + private bool _useAzureServices; public SettingsViewModel() { - UseMockServices = ViewModelLocator.Instance.UseMockService; + UseAzureServices = !ViewModelLocator.Instance.UseMockService; } public string Title @@ -36,13 +36,13 @@ 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); } } @@ -50,7 +50,7 @@ namespace eShopOnContainers.Core.ViewModels private void MockServices() { - ViewModelLocator.Instance.UpdateServices(UseMockServices); + ViewModelLocator.Instance.UpdateDependencies(!UseAzureServices); UpdateInfo(); } @@ -63,7 +63,7 @@ namespace eShopOnContainers.Core.ViewModels 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"; 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}}"> - + + + + + + + + + + + + + + + + + + + diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml.cs index 6d85f97f4..6ab0aa074 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/LoginView.xaml.cs @@ -1,31 +1,59 @@ -using Xamarin.Forms; +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Xamarin.Forms; namespace eShopOnContainers.Core.Views { public partial class LoginView : ContentPage { + private bool _animate; + public LoginView() { InitializeComponent(); } - protected override void OnAppearing() + protected override async void OnAppearing() { - base.OnAppearing(); + var content = this.Content; + this.Content = null; + this.Content = content; - AuthWebView.Navigating += OnAuthWebViewNavigating; + _animate = true; + await AnimateIn(); } protected override void OnDisappearing() { - base.OnDisappearing(); + _animate = false; + } - AuthWebView.Navigating -= OnAuthWebViewNavigating; + public async Task AnimateIn() + { + await AnimateItem(Banner, 10500); } - private void OnAuthWebViewNavigating(object sender, WebNavigatingEventArgs e) + private async Task AnimateItem(View uiElement, uint duration) { + try + { + while (_animate) + { + await uiElement.ScaleTo(1.05, duration, Easing.SinInOut); + await Task.WhenAll( + uiElement.FadeTo(1, duration, Easing.SinInOut), + uiElement.LayoutTo(new Rectangle(new Point(0, 0), new Size(uiElement.Width, uiElement.Height))), + uiElement.FadeTo(.9, duration, Easing.SinInOut), + uiElement.ScaleTo(1.15, duration, Easing.SinInOut) + ); + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + } } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/MainView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/MainView.xaml index 3d8286840..2bf39db64 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/MainView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/MainView.xaml @@ -6,8 +6,13 @@ xmlns:controls="clr-namespace:eShopOnContainers.Core.Controls;assembly=eShopOnContainers.Core" BarBackgroundColor="{StaticResource DarkGreenColor}" BackgroundColor="{StaticResource BackgroundColor}" - BarTextColor="{StaticResource WhiteColor}" - Title="eShop on Containers"> + BarTextColor="{StaticResource WhiteColor}"> + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ 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..0be02df91 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml @@ -105,7 +105,7 @@ Grid.Column="1" Grid.Row="1" Animate="True" - Checked="{Binding UseMockServices, Mode=TwoWay}" + Checked="{Binding UseAzureServices, Mode=TwoWay}" Command="{Binding MockServicesCommand}" Style="{StaticResource SettingsToggleButtonStyle}"> 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/OrderItemTemplate.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/OrderItemTemplate.xaml index 0fe18371c..366adfde3 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/OrderItemTemplate.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/Templates/OrderItemTemplate.xaml @@ -15,6 +15,8 @@ Value="{StaticResource MediumSize}" /> +