diff --git a/Api.eCommerce/Api.eCommerce.sln b/Api.eCommerce/Api.eCommerce.sln
new file mode 100644
index 0000000..8d1def1
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34723.18
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.eCommerce", "Api.eCommerce\Api.eCommerce.csproj", "{F7676AFD-7712-44DE-8F6E-558221D34E23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F7676AFD-7712-44DE-8F6E-558221D34E23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F7676AFD-7712-44DE-8F6E-558221D34E23}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F7676AFD-7712-44DE-8F6E-558221D34E23}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F7676AFD-7712-44DE-8F6E-558221D34E23}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B695E2FA-3851-4437-854F-908FEA78AEE7}
+ EndGlobalSection
+EndGlobal
diff --git a/Api.eCommerce/Api.eCommerce/Api.eCommerce.csproj b/Api.eCommerce/Api.eCommerce/Api.eCommerce.csproj
new file mode 100644
index 0000000..4d13065
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/Api.eCommerce.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+ ..\..\Library.eCommerce\bin\Debug\net8.0\Library.eCommerce.dll
+
+
+
+
diff --git a/Api.eCommerce/Api.eCommerce/Api.eCommerce.http b/Api.eCommerce/Api.eCommerce/Api.eCommerce.http
new file mode 100644
index 0000000..c0be77b
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/Api.eCommerce.http
@@ -0,0 +1,6 @@
+@Api.eCommerce_HostAddress = http://localhost:5149
+
+GET {{Api.eCommerce_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###
diff --git a/Api.eCommerce/Api.eCommerce/Controllers/InventoryController.cs b/Api.eCommerce/Api.eCommerce/Controllers/InventoryController.cs
new file mode 100644
index 0000000..0d41ede
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/Controllers/InventoryController.cs
@@ -0,0 +1,31 @@
+using Library.eCommerce.DTO;
+using Library.eCommerce.Models;
+using Microsoft.AspNetCore.Mvc;
+using Spring2025_Samples.Models;
+
+namespace Api.eCommerce.Controllers
+{
+ [ApiController]
+ [Route("[controller]")]
+ public class InventoryController : ControllerBase
+ {
+
+ private readonly ILogger _logger;
+
+ public InventoryController(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ [HttpGet]
+ public IEnumerable- Get()
+ {
+ return new List
-
+ {
+ new Item{ Product = new ProductDTO{Id = 1, Name ="Product 1"}, Id = 1, Quantity = 1 },
+ new Item{ Product = new ProductDTO{Id = 2, Name ="Product 2"}, Id = 2 , Quantity = 2 },
+ new Item{ Product = new ProductDTO{Id = 3, Name ="Product 3"}, Id=3 , Quantity = 3 }
+ };
+ }
+ }
+}
diff --git a/Api.eCommerce/Api.eCommerce/Program.cs b/Api.eCommerce/Api.eCommerce/Program.cs
new file mode 100644
index 0000000..48863a6
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/Program.cs
@@ -0,0 +1,25 @@
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/Api.eCommerce/Api.eCommerce/Properties/launchSettings.json b/Api.eCommerce/Api.eCommerce/Properties/launchSettings.json
new file mode 100644
index 0000000..d0100fd
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:48399",
+ "sslPort": 44355
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5149",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7009;http://localhost:5149",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/Api.eCommerce/Api.eCommerce/WeatherForecast.cs b/Api.eCommerce/Api.eCommerce/WeatherForecast.cs
new file mode 100644
index 0000000..1d2b25d
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/WeatherForecast.cs
@@ -0,0 +1,13 @@
+namespace Api.eCommerce
+{
+ public class WeatherForecast
+ {
+ public DateOnly Date { get; set; }
+
+ public int TemperatureC { get; set; }
+
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+ public string? Summary { get; set; }
+ }
+}
diff --git a/Api.eCommerce/Api.eCommerce/appsettings.Development.json b/Api.eCommerce/Api.eCommerce/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/Api.eCommerce/Api.eCommerce/appsettings.json b/Api.eCommerce/Api.eCommerce/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/Api.eCommerce/Api.eCommerce/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/Library.eCommerce/DTO/ProductDTO.cs b/Library.eCommerce/DTO/ProductDTO.cs
new file mode 100644
index 0000000..ade23a4
--- /dev/null
+++ b/Library.eCommerce/DTO/ProductDTO.cs
@@ -0,0 +1,48 @@
+using Spring2025_Samples.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Library.eCommerce.DTO
+{
+ public class ProductDTO
+ {
+ public int Id { get; set; }
+
+ public string? Name { get; set; }
+
+ public string? Display
+ {
+ get
+ {
+ return $"{Id}. {Name}";
+ }
+ }
+
+
+
+ public ProductDTO()
+ {
+ Name = string.Empty;
+ }
+
+ public ProductDTO(Product p)
+ {
+ Name = p.Name;
+ Id = p.Id;
+ }
+
+ public ProductDTO(ProductDTO p)
+ {
+ Name = p.Name;
+ Id = p.Id;
+ }
+
+ public override string ToString()
+ {
+ return Display ?? string.Empty;
+ }
+ }
+}
diff --git a/Library.eCommerce/Library.eCommerce.csproj b/Library.eCommerce/Library.eCommerce.csproj
index fa71b7a..bcd45d6 100644
--- a/Library.eCommerce/Library.eCommerce.csproj
+++ b/Library.eCommerce/Library.eCommerce.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/Library.eCommerce/Models/Item.cs b/Library.eCommerce/Models/Item.cs
new file mode 100644
index 0000000..dbb9a21
--- /dev/null
+++ b/Library.eCommerce/Models/Item.cs
@@ -0,0 +1,58 @@
+using Library.eCommerce.DTO;
+using Library.eCommerce.Services;
+using Spring2025_Samples.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace Library.eCommerce.Models
+{
+ public class Item
+ {
+ public int Id { get; set; }
+ public ProductDTO Product { get; set; }
+ public int? Quantity { get; set; }
+
+ public int Price { get; set; }
+
+ public ICommand? AddCommand { get; set; }
+
+ public override string ToString()
+ {
+ return $"{Product} Quantity:{Quantity}";
+ }
+
+ public string Display {
+ get
+ {
+ return $"{Product?.Display ?? string.Empty} x{Quantity} ${Price}";
+ }
+ }
+
+ public Item()
+ {
+ Product = new ProductDTO();
+ Quantity = 0;
+
+ AddCommand = new Command(DoAdd);
+ }
+
+ private void DoAdd()
+ {
+ ShoppingCartService.Current.AddOrUpdate(this);
+ }
+
+ public Item(Item i)
+ {
+ Product = new ProductDTO(i.Product);
+ Quantity = i.Quantity;
+ Id = i.Id;
+ Price = i.Price;
+
+ AddCommand = new Command(DoAdd);
+ }
+ }
+}
diff --git a/Library.eCommerce/Models/Product.cs b/Library.eCommerce/Models/Product.cs
index bd0a9e7..4a5b436 100644
--- a/Library.eCommerce/Models/Product.cs
+++ b/Library.eCommerce/Models/Product.cs
@@ -1,4 +1,5 @@
-using System;
+using Library.eCommerce.DTO;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -20,14 +21,34 @@ public string? Display
}
}
+ public string LegacyProperty1 { get; set; }
+ public string LegacyProperty2 { get; set; }
+ public string LegacyProperty3 { get; set; }
+ public string LegacyProperty4 { get; set; }
+ public string LegacyProperty5 { get; set; }
+ public string LegacyProperty6 { get; set; }
+
public Product()
{
Name = string.Empty;
}
+ public Product(Product p)
+ {
+ Name = p.Name;
+ Id = p.Id;
+ }
+
public override string ToString()
{
return Display ?? string.Empty;
}
+
+ public Product(ProductDTO p)
+ {
+ Name = p.Name;
+ Id = p.Id;
+ LegacyProperty1 = string.Empty;
+ }
}
}
diff --git a/Library.eCommerce/Services/ProductServiceProxy.cs b/Library.eCommerce/Services/ProductServiceProxy.cs
index 0137a8c..1c1b0eb 100644
--- a/Library.eCommerce/Services/ProductServiceProxy.cs
+++ b/Library.eCommerce/Services/ProductServiceProxy.cs
@@ -1,4 +1,6 @@
-using Spring2025_Samples.Models;
+using Library.eCommerce.DTO;
+using Library.eCommerce.Models;
+using Spring2025_Samples.Models;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,11 +13,11 @@ public class ProductServiceProxy
{
private ProductServiceProxy()
{
- Products = new List
+ Products = new List
-
{
- new Product{Id = 1, Name ="Product 1"},
- new Product{Id = 2, Name ="Product 2"},
- new Product{Id = 3, Name ="Product 3"}
+ new Item{ Product = new ProductDTO{Id = 1, Name ="Product 1"}, Id = 1, Quantity = 1, Price = 5 },
+ new Item{ Product = new ProductDTO{Id = 2, Name ="Product 2"}, Id = 2 , Quantity = 2,Price = 50 },
+ new Item{ Product = new ProductDTO{Id = 3, Name ="Product 3"}, Id=3 , Quantity = 3, Price = 500 }
};
}
@@ -50,35 +52,42 @@ public static ProductServiceProxy Current
}
}
- public List Products { get; private set; }
+ public List
- Products { get; private set; }
- public Product AddOrUpdate(Product product)
+ public Item AddOrUpdate(Item item)
{
- if(product.Id == 0)
+ if(item.Id == 0)
{
- product.Id = LastKey + 1;
- Products.Add(product);
+ item.Id = LastKey + 1;
+ item.Product.Id = item.Id;
+ Products.Add(item);
+ } else
+ {
+ var existingItem = Products.FirstOrDefault(p => p.Id == item.Id);
+ var index = Products.IndexOf(existingItem);
+ Products.RemoveAt(index);
+ Products.Insert(index,new Item(item));
}
- return product;
+ return item;
}
- public Product? Delete(int id)
+ public Item? Delete(int id)
{
if(id == 0)
{
return null;
}
- Product? product = Products.FirstOrDefault(p => p.Id == id);
+ Item? product = Products.FirstOrDefault(p => p.Id == id);
Products.Remove(product);
return product;
}
- public Product? GetById(int id)
+ public Item? GetById(int id)
{
return Products.FirstOrDefault(p => p.Id == id);
}
diff --git a/Library.eCommerce/Services/ShoppingCartService.cs b/Library.eCommerce/Services/ShoppingCartService.cs
new file mode 100644
index 0000000..474f64d
--- /dev/null
+++ b/Library.eCommerce/Services/ShoppingCartService.cs
@@ -0,0 +1,91 @@
+using Library.eCommerce.Models;
+
+namespace Library.eCommerce.Services
+{
+ public class ShoppingCartService
+ {
+ private ProductServiceProxy _prodSvc = ProductServiceProxy.Current;
+ private List
- items;
+ public double CheckoutPrice;
+ public List
- CartItems
+ {
+ get
+ {
+ return items;
+ }
+ }
+ public static ShoppingCartService Current {
+ get
+ {
+ if(instance == null)
+ {
+ instance = new ShoppingCartService();
+ }
+
+ return instance;
+ }
+ }
+ private static ShoppingCartService? instance;
+ private ShoppingCartService() {
+ items = new List
- ();
+ }
+
+ public void ClearList() { items = new List
- (); }
+ //Sets the list to an empty, new, list
+
+ public Item? AddOrUpdate(Item item)
+ {
+ var existingInvItem = _prodSvc.GetById(item.Id);
+ if(existingInvItem == null || existingInvItem.Quantity == 0) {
+ return null;
+ }
+
+ if (existingInvItem != null)
+ {
+ existingInvItem.Quantity--;
+ }
+
+ var existingItem = CartItems.FirstOrDefault(i => i.Id == item.Id);
+ if(existingItem == null)
+ {
+ //add
+ var newItem = new Item(item);
+ newItem.Quantity = 1;
+ CartItems.Add(newItem);
+ } else
+ {
+ //update
+ existingItem.Quantity++;
+ }
+
+
+ return existingInvItem;
+ }
+
+ public Item? ReturnItem(Item? item)
+ {
+ if (item?.Id <= 0 || item == null)
+ {
+ return null;
+ }
+
+ var itemToReturn = CartItems.FirstOrDefault(c => c.Id == item.Id);
+ if (itemToReturn != null)
+ {
+ itemToReturn.Quantity--;
+ var inventoryItem = _prodSvc.Products.FirstOrDefault(p => p.Id == itemToReturn.Id); ;
+ if(inventoryItem == null)
+ {
+ _prodSvc.AddOrUpdate(new Item(itemToReturn));
+ } else
+ {
+ inventoryItem.Quantity++;
+ }
+ }
+
+
+ return itemToReturn;
+ }
+
+ }
+}
diff --git a/Maui.eCommerce/AppShell.xaml b/Maui.eCommerce/AppShell.xaml
index 6dfbb3b..38fae71 100644
--- a/Maui.eCommerce/AppShell.xaml
+++ b/Maui.eCommerce/AppShell.xaml
@@ -20,4 +20,12 @@
Title="Inventory"
ContentTemplate="{DataTemplate views:ProductDetails}"
Route="Product" />
+
+
diff --git a/Maui.eCommerce/MainPage.xaml b/Maui.eCommerce/MainPage.xaml
index 978a47c..f132d58 100644
--- a/Maui.eCommerce/MainPage.xaml
+++ b/Maui.eCommerce/MainPage.xaml
@@ -12,7 +12,8 @@
Text="Inventory Management"
Clicked="InventoryClicked"/>
+ Text="Shop"
+ Clicked="ShopClicked"/>
diff --git a/Maui.eCommerce/MainPage.xaml.cs b/Maui.eCommerce/MainPage.xaml.cs
index 2b7fdb4..f5d59f3 100644
--- a/Maui.eCommerce/MainPage.xaml.cs
+++ b/Maui.eCommerce/MainPage.xaml.cs
@@ -16,6 +16,11 @@ private void InventoryClicked(object sender, EventArgs e)
{
Shell.Current.GoToAsync("//InventoryManagement");
}
+
+ private void ShopClicked(object sender, EventArgs e)
+ {
+ Shell.Current.GoToAsync("//ShoppingManagement");
+ }
}
}
diff --git a/Maui.eCommerce/Maui.eCommerce.csproj b/Maui.eCommerce/Maui.eCommerce.csproj
index 50ec32b..d8b082c 100644
--- a/Maui.eCommerce/Maui.eCommerce.csproj
+++ b/Maui.eCommerce/Maui.eCommerce.csproj
@@ -57,8 +57,8 @@
-
-
+
+
@@ -67,12 +67,18 @@
+
+ MSBuild:Compile
+
MSBuild:Compile
MSBuild:Compile
+
+ MSBuild:Compile
+
diff --git a/Maui.eCommerce/ViewModels/InventoryManagementViewModel.cs b/Maui.eCommerce/ViewModels/InventoryManagementViewModel.cs
index 2d5a259..0d0f245 100644
--- a/Maui.eCommerce/ViewModels/InventoryManagementViewModel.cs
+++ b/Maui.eCommerce/ViewModels/InventoryManagementViewModel.cs
@@ -1,4 +1,5 @@
-using Library.eCommerce.Services;
+using Library.eCommerce.Models;
+using Library.eCommerce.Services;
using Spring2025_Samples.Models;
using System;
using System.Collections.Generic;
@@ -13,7 +14,7 @@ namespace Maui.eCommerce.ViewModels
{
public class InventoryManagementViewModel : INotifyPropertyChanged
{
- public Product? SelectedProduct { get; set; }
+ public Item? SelectedProduct { get; set; }
public string? Query { get; set; }
private ProductServiceProxy _svc = ProductServiceProxy.Current;
@@ -34,16 +35,16 @@ public void RefreshProductList()
NotifyPropertyChanged(nameof(Products));
}
- public ObservableCollection Products
+ public ObservableCollection
- Products
{
get
{
- var filteredList = _svc.Products.Where(p => p?.Name?.ToLower().Contains(Query?.ToLower() ?? string.Empty) ?? false);
- return new ObservableCollection(filteredList);
+ var filteredList = _svc.Products.Where(p => p?.Product?.Name?.ToLower().Contains(Query?.ToLower() ?? string.Empty) ?? false);
+ return new ObservableCollection
- (filteredList);
}
}
- public Product? Delete()
+ public Item? Delete()
{
var item = _svc.Delete(SelectedProduct?.Id ?? 0);
NotifyPropertyChanged("Products");
diff --git a/Maui.eCommerce/ViewModels/ProductViewModel.cs b/Maui.eCommerce/ViewModels/ProductViewModel.cs
index 6b094b8..60a6bb5 100644
--- a/Maui.eCommerce/ViewModels/ProductViewModel.cs
+++ b/Maui.eCommerce/ViewModels/ProductViewModel.cs
@@ -1,4 +1,5 @@
-using Library.eCommerce.Services;
+using Library.eCommerce.Models;
+using Library.eCommerce.Services;
using Spring2025_Samples.Models;
using System;
using System.Collections.Generic;
@@ -10,35 +11,76 @@ namespace Maui.eCommerce.ViewModels
{
public class ProductViewModel
{
+ private Item? cachedModel { get; set; }
public string? Name {
get
{
- return Model?.Name ?? string.Empty;
+ return Model?.Product?.Name ?? string.Empty;
}
set
{
- if(Model != null && Model.Name != value)
+ if(Model != null && Model.Product?.Name != value)
{
- Model.Name = value;
+ Model.Product.Name = value;
}
}
}
- public Product? Model { get; set; }
+ public int? Quantity
+ {
+ get
+ {
+ return Model?.Quantity;
+ }
+
+ set
+ {
+ if( Model != null && Model.Quantity != value)
+ {
+ Model.Quantity = value;
+ }
+ }
+ }
+
+ public int? Price
+ {
+ get
+ {
+ return Model?.Price;
+ }
+ set
+ {
+ if (Model != null && Model.Price != value)
+ {
+ Model.Price = value ?? 0;
+ }
+ }
+ }
+ public Item? Model { get; set; }
public void AddOrUpdate()
{
ProductServiceProxy.Current.AddOrUpdate(Model);
}
+ public void Undo()
+ {
+ ProductServiceProxy.Current.AddOrUpdate(cachedModel);
+ }
+
public ProductViewModel() {
- Model = new Product();
+ Model = new Item();
+ cachedModel = null;
}
- public ProductViewModel(Product? model)
+ public ProductViewModel(Item? model)
{
Model = model;
+ if (model != null)
+ {
+ cachedModel = new Item(model);
+ }
}
}
}
diff --git a/Maui.eCommerce/ViewModels/ShoppingManagementViewModel.cs b/Maui.eCommerce/ViewModels/ShoppingManagementViewModel.cs
new file mode 100644
index 0000000..3ab37e3
--- /dev/null
+++ b/Maui.eCommerce/ViewModels/ShoppingManagementViewModel.cs
@@ -0,0 +1,110 @@
+using Library.eCommerce.Models;
+using Library.eCommerce.Services;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Maui.eCommerce.ViewModels
+{
+ public class ShoppingManagementViewModel : INotifyPropertyChanged
+ {
+ private ProductServiceProxy _invSvc = ProductServiceProxy.Current;
+ private ShoppingCartService _cartSvc = ShoppingCartService.Current;
+ public Item? SelectedItem { get; set; }
+ public Item? SelectedCartItem { get; set; }
+
+ public ObservableCollection
- Inventory
+ {
+ get
+ {
+ return new ObservableCollection
- (_invSvc.Products
+ .Where(i => i?.Quantity > 0)
+ );
+ }
+ }
+
+ public ObservableCollection
- ShoppingCart
+ {
+ get
+ {
+ return new ObservableCollection
- (_cartSvc.CartItems
+ .Where(i => i?.Quantity > 0)
+ );
+ }
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+ public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
+ {
+ if (propertyName is null)
+ {
+ throw new ArgumentNullException(nameof(propertyName));
+ }
+
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public void RefreshUX()
+ {
+ NotifyPropertyChanged(nameof(Inventory));
+ NotifyPropertyChanged(nameof(ShoppingCart));
+ }
+
+ public void PurchaseItem()
+ {
+ if (SelectedItem != null)
+ {
+ var shouldRefresh = SelectedItem.Quantity >= 1;
+ var updatedItem = _cartSvc.AddOrUpdate(SelectedItem);
+
+ if(updatedItem != null && shouldRefresh) {
+ NotifyPropertyChanged(nameof(Inventory));
+ NotifyPropertyChanged(nameof(ShoppingCart));
+ }
+
+ }
+ }
+
+ public void ReturnItem()
+ {
+ if (SelectedCartItem != null) {
+ var shouldRefresh = SelectedCartItem.Quantity >= 1;
+
+ var updatedItem = _cartSvc.ReturnItem(SelectedCartItem);
+
+ if (updatedItem != null && shouldRefresh)
+ {
+ NotifyPropertyChanged(nameof(Inventory));
+ NotifyPropertyChanged(nameof(ShoppingCart));
+ }
+ }
+ }
+ //Do stuff on list, then the next page will be a readout
+ public void Checkout()
+ {
+ /* int totalCost = 0;
+ foreach (var item in ShoppingCart)
+ {
+ totalCost += item?.Price ?? 0;
+ }
+ // _cartSvc.ClearList();
+
+ if (totalCost > 0)
+ {
+ NotifyPropertyChanged(nameof(ShoppingCart));
+ }
+ _cartSvc.CheckoutPrice = totalCost;
+ NotifyPropertyChanged(nameof(_cartSvc.CheckoutPrice));
+ */
+ // _cartSvc.ClearList();
+ NotifyPropertyChanged(nameof(ShoppingCart));
+
+ }
+
+ }
+}
diff --git a/Maui.eCommerce/ViewModels/TotalCostViewModel.cs b/Maui.eCommerce/ViewModels/TotalCostViewModel.cs
new file mode 100644
index 0000000..89f381f
--- /dev/null
+++ b/Maui.eCommerce/ViewModels/TotalCostViewModel.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using Library.eCommerce.Models;
+using Library.eCommerce.Services;
+
+namespace Maui.eCommerce.ViewModels
+{
+ public class TotalCostViewModel : INotifyPropertyChanged
+ {
+ private ShoppingCartService __svc = ShoppingCartService.Current;
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+
+ public double CheckoutCost
+ {
+ get {
+ var rounded = Math.Round(__svc.CheckoutPrice + (__svc.CheckoutPrice * .07), 2);
+ return rounded;
+ }
+ set
+ {
+ __svc.CheckoutPrice = value;
+
+ }
+ }
+
+ public ObservableCollection
- ShoppingCart
+ {
+ get
+ {
+ int totalCost = 0;
+ foreach (var item in __svc.CartItems)
+ {
+ totalCost += item?.Price ?? 0;
+ }
+ CheckoutCost = totalCost;
+ NotifyPropertyChanged(nameof(CheckoutCost));
+
+ var toRet = new ObservableCollection
- (__svc.CartItems
+ .Where(i => i?.Quantity > 0)
+ );
+ // __svc.CartItems.Clear();
+
+
+
+ return toRet;
+ }
+ }
+
+ public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
+ {
+ if (propertyName is null)
+ {
+ throw new ArgumentNullException(nameof(propertyName));
+ }
+
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public void RefreshUI()
+ {
+ NotifyPropertyChanged(nameof(CheckoutCost));
+ NotifyPropertyChanged(nameof(ShoppingCart));
+ }
+ public void ClearOnLeave()
+ {
+ __svc.CartItems.Clear();
+ CheckoutCost = 0;
+ }
+ }
+}
diff --git a/Maui.eCommerce/Views/CheckoutView.xaml b/Maui.eCommerce/Views/CheckoutView.xaml
new file mode 100644
index 0000000..f8e62b1
--- /dev/null
+++ b/Maui.eCommerce/Views/CheckoutView.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Maui.eCommerce/Views/CheckoutView.xaml.cs b/Maui.eCommerce/Views/CheckoutView.xaml.cs
new file mode 100644
index 0000000..4212cfd
--- /dev/null
+++ b/Maui.eCommerce/Views/CheckoutView.xaml.cs
@@ -0,0 +1,29 @@
+using Spring2025_Samples.Models;
+using Maui.eCommerce.ViewModels;
+using System.ComponentModel;
+namespace Maui.eCommerce.Views;
+
+//[QueryProperty(nameof(TotalPrice), "PriceKey")]
+
+public partial class CheckoutView : ContentPage
+{
+// public int TotalPrice { get; set; }
+ public CheckoutView()
+ {
+ InitializeComponent();
+ BindingContext = new TotalCostViewModel();
+ // (BindingContext as TotalCostViewModel).setDefaults();
+ }
+
+ public void GoHome(object sender, EventArgs e)
+ {
+ (BindingContext as TotalCostViewModel).RefreshUI();
+ Shell.Current.GoToAsync($"//MainPage");
+ }
+
+ public void CheckOutClicked(object sender, EventArgs e)
+ {
+ (BindingContext as TotalCostViewModel).RefreshUI();
+ (BindingContext as TotalCostViewModel).ClearOnLeave();
+ }
+}
\ No newline at end of file
diff --git a/Maui.eCommerce/Views/InventoryManagementView.xaml.cs b/Maui.eCommerce/Views/InventoryManagementView.xaml.cs
index f486963..1cd3c4a 100644
--- a/Maui.eCommerce/Views/InventoryManagementView.xaml.cs
+++ b/Maui.eCommerce/Views/InventoryManagementView.xaml.cs
@@ -32,7 +32,7 @@ private void ContentPage_NavigatedTo(object sender, NavigatedToEventArgs e)
}
private void EditClicked(object sender, EventArgs e)
- {//TODO: ?????????????
+ {
var productId = (BindingContext as InventoryManagementViewModel)?.SelectedProduct?.Id;
Shell.Current.GoToAsync($"//Product?productId={productId}");
}
diff --git a/Maui.eCommerce/Views/ProductDetails.xaml b/Maui.eCommerce/Views/ProductDetails.xaml
index 3e2c98a..4328c48 100644
--- a/Maui.eCommerce/Views/ProductDetails.xaml
+++ b/Maui.eCommerce/Views/ProductDetails.xaml
@@ -13,6 +13,20 @@
+
+
+
+
diff --git a/Maui.eCommerce/Views/ProductDetails.xaml.cs b/Maui.eCommerce/Views/ProductDetails.xaml.cs
index 317982a..eb8c74e 100644
--- a/Maui.eCommerce/Views/ProductDetails.xaml.cs
+++ b/Maui.eCommerce/Views/ProductDetails.xaml.cs
@@ -17,6 +17,7 @@ public ProductDetails()
private void GoBackClicked(object sender, EventArgs e)
{
+ (BindingContext as ProductViewModel).Undo();
Shell.Current.GoToAsync("//InventoryManagement");
}
diff --git a/Maui.eCommerce/Views/ShoppingManagementView.xaml b/Maui.eCommerce/Views/ShoppingManagementView.xaml
new file mode 100644
index 0000000..1c0ea33
--- /dev/null
+++ b/Maui.eCommerce/Views/ShoppingManagementView.xaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Maui.eCommerce/Views/ShoppingManagementView.xaml.cs b/Maui.eCommerce/Views/ShoppingManagementView.xaml.cs
new file mode 100644
index 0000000..225fc79
--- /dev/null
+++ b/Maui.eCommerce/Views/ShoppingManagementView.xaml.cs
@@ -0,0 +1,32 @@
+using Maui.eCommerce.ViewModels;
+
+namespace Maui.eCommerce.Views;
+
+public partial class ShoppingManagementView : ContentPage
+{
+ public ShoppingManagementView()
+ {
+ InitializeComponent();
+ BindingContext = new ShoppingManagementViewModel();
+ }
+
+ private void RemoveFromCartClicked(object sender, EventArgs e)
+ {
+ (BindingContext as ShoppingManagementViewModel).ReturnItem();
+ }
+ private void AddToCartClicked(object sender, EventArgs e)
+ {
+ (BindingContext as ShoppingManagementViewModel).PurchaseItem();
+ }
+
+ private void InlineAddClicked(object sender, EventArgs e)
+ {
+ (BindingContext as ShoppingManagementViewModel).RefreshUX();
+ }
+
+ public void GoToCheckoutClicked(object sender, EventArgs e)
+ {
+ Shell.Current.GoToAsync($"//CheckoutPage");
+ (BindingContext as ShoppingManagementViewModel).Checkout();
+ }
+}
\ No newline at end of file
diff --git a/Spring2025_Samples.sln b/Spring2025_Samples.sln
index 84ad8aa..5d49b62 100644
--- a/Spring2025_Samples.sln
+++ b/Spring2025_Samples.sln
@@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spring2025_Samples", "Sprin
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Library.eCommerce", "Library.eCommerce\Library.eCommerce.csproj", "{B113257B-6F53-4B61-B796-F733AAF021AA}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Maui.eCommerce", "Maui.eCommerce\Maui.eCommerce.csproj", "{0335E701-5D1D-449A-8615-BDC200AE7C4D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Maui.eCommerce", "Maui.eCommerce\Maui.eCommerce.csproj", "{0335E701-5D1D-449A-8615-BDC200AE7C4D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -16,7 +16,6 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8B000EBC-E610-4D5F-ABEE-E9CECF89C2D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8B000EBC-E610-4D5F-ABEE-E9CECF89C2D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B000EBC-E610-4D5F-ABEE-E9CECF89C2D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B000EBC-E610-4D5F-ABEE-E9CECF89C2D3}.Release|Any CPU.Build.0 = Release|Any CPU
{B113257B-6F53-4B61-B796-F733AAF021AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
diff --git a/Spring2025_Samples/Spring2025_Samples.csproj b/Spring2025_Samples/Spring2025_Samples.csproj
index 1f7d354..1e77c21 100644
--- a/Spring2025_Samples/Spring2025_Samples.csproj
+++ b/Spring2025_Samples/Spring2025_Samples.csproj
@@ -7,6 +7,10 @@
enable
+
+
+
+