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"/>