diff --git a/src/Mobile/eShopOnContainers.Xamarin.sln b/src/Mobile/eShopOnContainers.Xamarin.sln index 68893edc2..7082291a3 100644 --- a/src/Mobile/eShopOnContainers.Xamarin.sln +++ b/src/Mobile/eShopOnContainers.Xamarin.sln @@ -240,6 +240,8 @@ Global {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|ARM.Deploy.0 = Debug|ARM {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhone.ActiveCfg = Debug|x86 {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86 + {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhoneSimulator.Build.0 = Debug|x86 + {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|iPhoneSimulator.Deploy.0 = Debug|x86 {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.ActiveCfg = Debug|x64 {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.Build.0 = Debug|x64 {C3C1E2CF-B1F7-4654-BBDC-50143DB22E0B}.Debug|x64.Deploy.0 = Debug|x64 diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml index 91a8ede8b..9a5c14319 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/App.xaml @@ -103,6 +103,7 @@ + diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Controls/BindablePicker.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Controls/BindablePicker.cs index 78dce2ef5..c0ad76a05 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Controls/BindablePicker.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Controls/BindablePicker.cs @@ -101,10 +101,12 @@ namespace eShopOnContainers.Core.Controls private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue) { var boundPicker = (BindablePicker)bindable; + if (boundPicker.ItemSelected != null) { boundPicker.ItemSelected(boundPicker, new SelectedItemChangedEventArgs(newValue)); } + boundPicker.InternalUpdateSelectedIndex(); } } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/InverseBoolConverter.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/InverseBoolConverter.cs new file mode 100644 index 000000000..622c85d85 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Converters/InverseBoolConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Globalization; +using Xamarin.Forms; + +namespace eShopOnContainers.Core.Converters +{ + public class InverseBoolConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is bool)) + { + throw new InvalidOperationException("The target must be a boolean"); + } + + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs new file mode 100644 index 000000000..800f9a031 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Extensions/ObservableExtension.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace eShopOnContainers.Core.Extensions +{ + public static class ObservableExtension + { + public static ObservableCollection ToObservableCollection(this IEnumerable source) + { + ObservableCollection collection = new ObservableCollection(); + + foreach (T item in source) + { + collection.Add(item); + } + + return collection; + } + } +} \ 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 new file mode 100644 index 000000000..989d359a1 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Helpers/NumericHelper.cs @@ -0,0 +1,18 @@ +using System.Collections.ObjectModel; + +namespace eShopOnContainers.Core.Helpers +{ + public class NumericHelper + { + public static ObservableCollection GetNumericList(int count = 100) + { + var result = new ObservableCollection(); + for (int i = 0; i < count; i++) + { + result.Add(i); + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogBrand.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogBrand.cs new file mode 100644 index 000000000..773c9e2a8 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogBrand.cs @@ -0,0 +1,13 @@ +namespace eShopOnContainers.Core.Models.Catalog +{ + public class CatalogBrand + { + public int CatalogBrandId { get; set; } + public string Name { get; set; } + + public override string ToString() + { + return Name; + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogItem.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogItem.cs index 95dff1f60..649afa008 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogItem.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogItem.cs @@ -11,6 +11,5 @@ public string CatalogBrand { get; set; } public int CatalogTypeId { get; set; } public string CatalogType { get; set; } - } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogType.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogType.cs new file mode 100644 index 000000000..55277463c --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Catalog/CatalogType.cs @@ -0,0 +1,13 @@ +namespace eShopOnContainers.Core.Models.Catalog +{ + public class CatalogType + { + public int CatalogTypeId { get; set; } + public string Name { get; set; } + + public override string ToString() + { + return Name; + } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Navigation/TabParameter.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Navigation/TabParameter.cs new file mode 100644 index 000000000..8fbf2b495 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Navigation/TabParameter.cs @@ -0,0 +1,7 @@ +namespace eShopOnContainers.Core.Models.Navigation +{ + public class TabParameter + { + public int TabIndex { get; set; } + } +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/Order.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/Order.cs index dc40b5cf8..256ba9cd9 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/Order.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/Order.cs @@ -6,7 +6,7 @@ namespace eShopOnContainers.Core.Models.Orders public class Order { public int SequenceNumber { get; set; } - public double Total { get; set; } + public decimal Total { get; set; } public DateTime OrderDate { get; set; } public OrderStatus Status { get; set; } public User.User ShippingAddress { get; set; } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs index 77bf8b220..ada28ef5f 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Models/Orders/OrderItem.cs @@ -1,5 +1,9 @@ -using eShopOnContainers.ViewModels.Base; +using eShopOnContainers.Core.Helpers; +using eShopOnContainers.Core.ViewModels.Base; +using eShopOnContainers.ViewModels.Base; using System; +using System.Collections.ObjectModel; +using Xamarin.Forms; namespace eShopOnContainers.Core.Models.Orders { @@ -12,6 +16,12 @@ namespace eShopOnContainers.Core.Models.Orders private decimal _unitPrice; private int _quantity; private decimal _discount; + private ObservableCollection _numbers; + + public OrderItem() + { + Numbers = NumericHelper.GetNumericList(); + } public int ProductId { @@ -60,6 +70,9 @@ namespace eShopOnContainers.Core.Models.Orders { _quantity = value; RaisePropertyChanged(() => Quantity); + RaisePropertyChanged(() => Total); + + MessagingCenter.Send(this, MessengerKeys.UpdateProduct); } } @@ -85,9 +98,19 @@ namespace eShopOnContainers.Core.Models.Orders } } + public ObservableCollection Numbers + { + get { return _numbers; } + set + { + _numbers = value; + RaisePropertyChanged(() => Numbers); + } + } + public override string ToString() { return String.Format("Product Id: {0}, Quantity: {1}", ProductId, Quantity); } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogMockService.cs index 1282d4782..19447bc6a 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogMockService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogMockService.cs @@ -1,4 +1,5 @@ -using eShopOnContainers.Core.Models.Catalog; +using eShopOnContainers.Core.Extensions; +using eShopOnContainers.Core.Models.Catalog; using System; using System.Collections.ObjectModel; using System.Linq; @@ -9,11 +10,25 @@ namespace eShopOnContainers.Core.Services.Catalog { public class CatalogMockService : ICatalogService { + private ObservableCollection MockCatalogBrand = new ObservableCollection + { + new CatalogBrand { CatalogBrandId = 1, Name = "Azure" }, + new CatalogBrand { CatalogBrandId = 2, Name = "Visual Studio" } + }; + + private ObservableCollection MockCatalogType = new ObservableCollection + { + new CatalogType { CatalogTypeId = 1, Name = "Mug" }, + new CatalogType { CatalogTypeId = 2, Name = "T-Shirt" } + }; + private ObservableCollection MockCatalog = new ObservableCollection { - new CatalogItem { Id = "1", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_01" : "Assets/fake_product_01.png", Name = ".NET Bot Blue Sweatshirt (M)", Price = 19.50M }, - new CatalogItem { Id = "2", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_02": "Assets/fake_product_02.png", Name = ".NET Bot Purple Sweatshirt (M)", Price = 19.50M }, - new CatalogItem { Id = "3", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_03": "Assets/fake_product_03.png", Name = ".NET Bot Black Sweatshirt (M)", Price = 19.95M } + new CatalogItem { Id = "1", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_01" : "Assets/fake_product_01.png", Name = ".NET Bot Blue Sweatshirt (M)", Price = 19.50M, CatalogBrand = "Visual Studio", CatalogType = "T-Shirt" }, + new CatalogItem { Id = "2", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_02": "Assets/fake_product_02.png", Name = ".NET Bot Purple Sweatshirt (M)", Price = 19.50M, CatalogBrand = "Visual Studio", CatalogType = "T-Shirt" }, + new CatalogItem { Id = "3", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_03": "Assets/fake_product_03.png", Name = ".NET Bot Black Sweatshirt (M)", Price = 19.95M, CatalogBrand = "Visual Studio", CatalogType = "T-Shirt" }, + new CatalogItem { Id = "4", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_04": "Assets/fake_product_04.png", Name = ".NET Black Cupt", Price = 17.00M, CatalogBrand = "Visual Studio", CatalogType = "Mug" }, + new CatalogItem { Id = "5", PictureUri = Device.OS != TargetPlatform.Windows? "fake_product_05": "Assets/fake_product_05.png", Name = "Azure Black Sweatshirt (M)", Price = 19.50M, CatalogBrand = "Azure", CatalogType = "T-Shirt" } }; public async Task> GetCatalogAsync() @@ -23,6 +38,30 @@ namespace eShopOnContainers.Core.Services.Catalog return MockCatalog; } + public async Task> FilterAsync(string catalogBrand, string catalogType) + { + await Task.Delay(500); + + return MockCatalog + .Where(c => c.CatalogBrand.Equals(catalogBrand, StringComparison.CurrentCultureIgnoreCase) && + c.CatalogType.Equals(catalogType, StringComparison.CurrentCultureIgnoreCase)) + .ToObservableCollection(); + } + + public async Task> GetCatalogBrandAsync() + { + await Task.Delay(500); + + return MockCatalogBrand; + } + + public async Task> GetCatalogTypeAsync() + { + await Task.Delay(500); + + return MockCatalogType; + } + public async Task GetCatalogItemAsync(string id) { await Task.Delay(500); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/ICatalogService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/ICatalogService.cs index 4cac65467..e6817a8a9 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/ICatalogService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/ICatalogService.cs @@ -6,6 +6,9 @@ namespace eShopOnContainers.Core.Services.Catalog { public interface ICatalogService { + Task> GetCatalogBrandAsync(); + Task> FilterAsync(string catalogBrand, string catalogType); + Task> GetCatalogTypeAsync(); Task> GetCatalogAsync(); Task GetCatalogItemAsync(string id); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs index 638a71f15..69669af9c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Navigation/NavigationService.cs @@ -149,6 +149,7 @@ namespace eShopOnContainers.Services { _mappings.Add(typeof(CartViewModel), typeof(CartView)); _mappings.Add(typeof(CatalogViewModel), typeof(CatalogView)); + _mappings.Add(typeof(CheckoutViewModel), typeof(CheckoutView)); _mappings.Add(typeof(LoginViewModel), typeof(LoginView)); _mappings.Add(typeof(MainViewModel), typeof(MainView)); _mappings.Add(typeof(OrderDetailViewModel), typeof(OrderDetailView)); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Orders/OrdersMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Orders/OrdersMockService.cs index 351975663..9c4a7b42c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Orders/OrdersMockService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Orders/OrdersMockService.cs @@ -14,9 +14,9 @@ namespace eShopOnContainers.Core.Services.Orders return new ObservableCollection { - new Order { SequenceNumber = 123, Total = 56.40, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, - new Order { SequenceNumber = 132, Total = 56.40, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, - new Order { SequenceNumber = 231, Total = 56.40, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, + new Order { SequenceNumber = 123, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, + new Order { SequenceNumber = 132, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, + new Order { SequenceNumber = 231, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Delivered, OrderItems = GetOrderItems() }, }; } @@ -24,7 +24,7 @@ namespace eShopOnContainers.Core.Services.Orders { await Task.Delay(500); - return new Order { SequenceNumber = 0123456789, Total = 56.40, OrderDate = DateTime.Now, Status = OrderStatus.Pending, OrderItems = GetOrderItems() }; + return new Order { SequenceNumber = 0123456789, Total = 56.40M, OrderDate = DateTime.Now, Status = OrderStatus.Pending, OrderItems = GetOrderItems() }; } private List GetOrderItems() diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs new file mode 100644 index 000000000..4ed3e5755 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/IUserService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.User +{ + public interface IUserService + { + Task GetUserAsync(); + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs new file mode 100644 index 000000000..67f7a0bb1 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/User/UserMockService.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; + +namespace eShopOnContainers.Core.Services.User +{ + public class UserMockService : IUserService + { + private Models.User.User MockUser = new Models.User.User + { + Name = "Jhon", + LastName = "Doe", + City = "Seattle, WA", + Street = "120 E 87th Street", + CountryCode = "98122", + Country = "United States" + }; + + public async Task GetUserAsync() + { + await Task.Delay(500); + + return MockUser; + } + } +} \ 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 b5e1bdb46..ec49e8802 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/MessengerKeys.cs @@ -4,5 +4,14 @@ { // Add product to cart public const string AddProduct = "AddProduct"; + + // Update product cart + public const string UpdateProduct = "UpdateProduct"; + + // Filter + public const string Filter = "Filter"; + + // Change selected Tab programmatically + 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 f8f351a0c..578bfe482 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelLocator.cs @@ -5,6 +5,7 @@ using eShopOnContainers.Services; using System; using eShopOnContainers.Core.Services.Catalog; using eShopOnContainers.Core.Services.OpenUrl; +using eShopOnContainers.Core.Services.User; namespace eShopOnContainers.ViewModels.Base { @@ -16,10 +17,7 @@ namespace eShopOnContainers.ViewModels.Base public static ViewModelLocator Instance { - get - { - return _instance; - } + get { return _instance; } } protected ViewModelLocator() @@ -30,12 +28,15 @@ namespace eShopOnContainers.ViewModels.Base _unityContainer.RegisterType(); RegisterSingleton(); _unityContainer.RegisterType(); + _unityContainer.RegisterType(); _unityContainer.RegisterType(); + _unityContainer.RegisterType(); // view models _unityContainer.RegisterType(); _unityContainer.RegisterType(); + _unityContainer.RegisterType(); _unityContainer.RegisterType(); _unityContainer.RegisterType(); _unityContainer.RegisterType(); @@ -67,4 +68,4 @@ namespace eShopOnContainers.ViewModels.Base _unityContainer.RegisterType(new ContainerControlledLifetimeManager()); } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CartViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CartViewModel.cs index 238d5e2e0..8001fa834 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CartViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CartViewModel.cs @@ -1,4 +1,5 @@ -using eShopOnContainers.Core.Models.Catalog; +using eShopOnContainers.Core.Helpers; +using eShopOnContainers.Core.Models.Catalog; using eShopOnContainers.Core.Models.Orders; using eShopOnContainers.Core.Services.Orders; using eShopOnContainers.Core.ViewModels.Base; @@ -7,6 +8,7 @@ using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; +using System.Windows.Input; using Xamarin.Forms; namespace eShopOnContainers.Core.ViewModels @@ -43,7 +45,7 @@ namespace eShopOnContainers.Core.ViewModels RaisePropertyChanged(() => OrderItems); } } - + public decimal Total { get { return _total; } @@ -54,6 +56,8 @@ namespace eShopOnContainers.Core.ViewModels } } + public ICommand CheckoutCommand => new Command(Checkout); + public override Task InitializeAsync(object navigationData) { MessagingCenter.Subscribe(this, MessengerKeys.AddProduct, (sender, arg) => @@ -62,6 +66,11 @@ namespace eShopOnContainers.Core.ViewModels AddCartItem(arg); }); + + MessagingCenter.Subscribe(this, MessengerKeys.UpdateProduct, (sender) => + { + ReCalculateTotal(); + }); OrderItems = new ObservableCollection(); @@ -99,5 +108,10 @@ namespace eShopOnContainers.Core.ViewModels Total += orderItem.Total; } } + + private void Checkout() + { + NavigationService.NavigateToAsync(OrderItems); + } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs index 58076add3..bbdfea6ec 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CatalogViewModel.cs @@ -12,6 +12,10 @@ namespace eShopOnContainers.Core.ViewModels public class CatalogViewModel : ViewModelBase { private ObservableCollection _products; + private ObservableCollection _brands; + private CatalogBrand _brand; + private ObservableCollection _types; + private CatalogType _type; private ICatalogService _productsService; @@ -30,13 +34,63 @@ namespace eShopOnContainers.Core.ViewModels } } + public ObservableCollection Brands + { + get { return _brands; } + set + { + _brands = value; + RaisePropertyChanged(() => Brands); + } + } + + public CatalogBrand Brand + { + get { return _brand; } + set + { + _brand = value; + RaisePropertyChanged(() => Brand); + RaisePropertyChanged(() => IsFilter); + } + } + + public ObservableCollection Types + { + get { return _types; } + set + { + _types = value; + RaisePropertyChanged(() => Types); + } + } + + public CatalogType Type + { + get { return _type; } + set + { + _type = value; + RaisePropertyChanged(() => Type); + RaisePropertyChanged(() => IsFilter); + } + } + + public bool IsFilter { get { return Brand != null || Type != null; } } + public ICommand AddCatalogItemCommand => new Command(AddCatalogItem); + public ICommand FilterCommand => new Command(Filter); + + public ICommand ClearFilterCommand => new Command(ClearFilter); + public override async Task InitializeAsync(object navigationData) { IsBusy = true; Products = await _productsService.GetCatalogAsync(); + Brands = await _productsService.GetCatalogBrandAsync(); + Types = await _productsService.GetCatalogTypeAsync(); IsBusy = false; } @@ -45,5 +99,31 @@ namespace eShopOnContainers.Core.ViewModels { MessagingCenter.Send(this, MessengerKeys.AddProduct, catalogItem); } + + private async void Filter() + { + if(Brand == null && Type == null) + { + return; + } + + IsBusy = true; + + MessagingCenter.Send(this, MessengerKeys.Filter); + Products = await _productsService.FilterAsync(Brand.Name, Type.Name); + + IsBusy = false; + } + + private async void ClearFilter() + { + IsBusy = true; + + Brand = null; + Type = null; + Products = await _productsService.GetCatalogAsync(); + + IsBusy = false; + } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs new file mode 100644 index 000000000..938170d6a --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/CheckoutViewModel.cs @@ -0,0 +1,106 @@ +using eShopOnContainers.Core.Models.Navigation; +using eShopOnContainers.Core.Services.User; +using eShopOnContainers.ViewModels.Base; +using System.Windows.Input; +using Xamarin.Forms; +using System.Threading.Tasks; +using eShopOnContainers.Core.Models.User; +using eShopOnContainers.Core.Models.Orders; +using System; +using System.Collections.ObjectModel; +using System.Linq; + +namespace eShopOnContainers.Core.ViewModels +{ + public class CheckoutViewModel : ViewModelBase + { + private ObservableCollection _orderItems; + private Order _order; + private User _user; + + private IUserService _userService; + + public CheckoutViewModel(IUserService userService) + { + _userService = userService; + } + + public ObservableCollection OrderItems + { + get { return _orderItems; } + set + { + _orderItems = value; + RaisePropertyChanged(() => OrderItems); + } + } + + public Order Order + { + get { return _order; } + set + { + _order = value; + RaisePropertyChanged(() => Order); + } + } + + public User User + { + get { return _user; } + set + { + _user = value; + RaisePropertyChanged(() => User); + } + } + + public ICommand CheckoutCommand => new Command(Checkout); + + public override async Task InitializeAsync(object navigationData) + { + if (navigationData is ObservableCollection) + { + IsBusy = true; + + var orderItems = ((ObservableCollection)navigationData); + + OrderItems = orderItems; + + User = await _userService.GetUserAsync(); + + Order = new Order + { + ShippingAddress = User, + OrderItems = orderItems.ToList(), + Status = OrderStatus.Pending, + OrderDate = DateTime.Now, + Total = GetOrderTotal() + }; + + IsBusy = false; + } + } + + private async void Checkout() + { + await NavigationService.NavigateToAsync(new TabParameter { TabIndex = 1 }); + await NavigationService.RemoveLastFromBackStackAsync(); + + await DialogService.ShowAlertAsync("Order sent successfully", string.Format("Order {0}", Order.OrderNumber), "Ok"); + await NavigationService.RemoveLastFromBackStackAsync(); + } + + private decimal GetOrderTotal() + { + decimal total = 0; + + foreach (var orderItem in OrderItems) + { + total += orderItem.Total; + } + + return total; + } + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/MainViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/MainViewModel.cs index 097b92869..cf7d8032d 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/MainViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/MainViewModel.cs @@ -1,9 +1,22 @@ -using eShopOnContainers.ViewModels.Base; +using System.Threading.Tasks; +using eShopOnContainers.ViewModels.Base; +using eShopOnContainers.Core.Models.Navigation; +using Xamarin.Forms; +using eShopOnContainers.Core.ViewModels.Base; namespace eShopOnContainers.Core.ViewModels { public class MainViewModel : ViewModelBase { - + public override Task InitializeAsync(object navigationData) + { + if (navigationData is TabParameter) + { + var tabIndex = ((TabParameter)navigationData).TabIndex; + MessagingCenter.Send(this, MessengerKeys.ChangeTab, tabIndex); + } + + return base.InitializeAsync(navigationData); + } } -} +} \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/OrderDetailViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/OrderDetailViewModel.cs index b82e2ffae..9d63851f6 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/OrderDetailViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/OrderDetailViewModel.cs @@ -3,21 +3,27 @@ using eShopOnContainers.Core.Models.Orders; using eShopOnContainers.ViewModels.Base; using eShopOnContainers.Core.Services.Orders; using eShopOnContainers.Core.Services.Catalog; +using eShopOnContainers.Core.Services.User; +using eShopOnContainers.Core.Models.User; namespace eShopOnContainers.Core.ViewModels { public class OrderDetailViewModel : ViewModelBase { private Order _order; + private User _user; private IOrdersService _orderService; private ICatalogService _catalogService; + private IUserService _userService; public OrderDetailViewModel(IOrdersService orderService, - ICatalogService catalogService) + ICatalogService catalogService, + IUserService userService) { _orderService = orderService; _catalogService = catalogService; + _userService = userService; } public Order Order @@ -30,6 +36,16 @@ namespace eShopOnContainers.Core.ViewModels } } + public User User + { + get { return _user; } + set + { + _user = value; + RaisePropertyChanged(() => User); + } + } + public override async Task InitializeAsync(object navigationData) { if(navigationData is Order) @@ -45,6 +61,7 @@ namespace eShopOnContainers.Core.ViewModels } Order = order; + User = await _userService.GetUserAsync(); IsBusy = false; } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CartView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CartView.xaml index ee7f9eacf..c3c127656 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CartView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CartView.xaml @@ -81,7 +81,7 @@ - + diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml index 4b2db156d..6f6220146 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CatalogView.xaml @@ -30,7 +30,6 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + (this, MessengerKeys.Filter, (sender) => + { + Filter(); + }); } public Action HideMenuAction @@ -31,7 +42,20 @@ namespace eShopOnContainers.Core.Views set; } + + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + + _filterView.BindingContext = BindingContext; + } + private void OnFilterChanged(object sender, EventArgs e) + { + Filter(); + } + + private void Filter() { if (SlideMenu.IsShown) { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml new file mode 100644 index 000000000..2cc066c56 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml.cs new file mode 100644 index 000000000..f6a5f00b5 --- /dev/null +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/CheckoutView.xaml.cs @@ -0,0 +1,12 @@ +using Xamarin.Forms; + +namespace eShopOnContainers.Core.Views +{ + public partial class CheckoutView : ContentPage + { + public CheckoutView() + { + InitializeComponent(); + } + } +} diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/FiltersView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/FiltersView.xaml index ba7cc5e3f..ba6f4b0fa 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/FiltersView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/FiltersView.xaml @@ -2,71 +2,93 @@ - - + + - - - + + + - - - - - - - - - - -