diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/UserOrders/Default.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/UserOrders/Default.cshtml index e426ef10..e3e084fa 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/UserOrders/Default.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/UserOrders/Default.cshtml @@ -72,14 +72,14 @@ - + @L["UserOrders:ReturnProducts"] - + - + @L["UserOrders:AddReview"] - + diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpBrandingProvider.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpBrandingProvider.cs new file mode 100644 index 00000000..6ecc3b99 --- /dev/null +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpBrandingProvider.cs @@ -0,0 +1,10 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace EShopOnAbp.PublicWeb; + +[Dependency(ReplaceServices = true)] +public class EShopOnAbpBrandingProvider: DefaultBrandingProvider +{ + public override string AppName => "EShopOnAbp"; +} \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Index.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Index.cshtml index d7609e36..52e4a829 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Index.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Index.cshtml @@ -4,22 +4,22 @@ @using System.Globalization @using Microsoft.Extensions.Options @using Volo.Abp.Http.Client +@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating @model EShopOnAbp.PublicWeb.Pages.IndexModel @inject IStringLocalizer L @inject IOptions options @{ - const int productsColumnSize = 4; // TODO: update abp-column helper to plain html for proper row and columns css string pageHeader = L["OurProducts"]; } @section styles{ - + } @section scripts { - - + + } @if (Model.HasRemoteServiceError) @@ -27,50 +27,57 @@ pageHeader = L["CatalogServiceNotAvailable"]; } -
-
-

@pageHeader

+
+

@pageHeader

+
- @for (int i = 0; i < Math.Ceiling(Model.Products.Count / (double)productsColumnSize); i++) + @foreach (var product in Model.Products) { - - @for (int j = 0; j < productsColumnSize; j++) - { - - @if ((i * productsColumnSize) + j < Model.Products.Count) + var productPrice = product.Price.ToString("C", new CultureInfo("en-US")); + string productImage = !product.ImageName.IsNullOrEmpty() ? $"{options.Value.RemoteServices.Default.BaseUrl}product-images/{product.ImageName}" : $"{options.Value.RemoteServices.Default.BaseUrl}product-images/@product.ImageName"; + string buyText = L["Index:AddToBasket"]; +
+
+ +
+
+
+ Added to cart +
+ @if (product.StockCount > 0) { - var product = Model.Products[(i * productsColumnSize) + j]; - var productPrice = product.Price.ToString("C", new CultureInfo("en-US")); - string productImage = !product.ImageName.IsNullOrEmpty() ? $"{options.Value.RemoteServices.Default.BaseUrl}product-images/{product.ImageName}" : $"{options.Value.RemoteServices.Default.BaseUrl}product-images/@product.ImageName"; - string buyText = L["Index:AddToBasket"]; -
- -
-
-
@product.Name
- @product.Code - @L["StockCount"]: @product.StockCount -
-
- -
-
- @if (product.StockCount > 0) - { - - } - else - { - - } -
- @productPrice -
-
-
+ } - - } - + else + { + + } +
+ @productPrice +
+
+
+
}
diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/ProductDetail.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/ProductDetail.cshtml index 9f1dc773..24362a1d 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/ProductDetail.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/ProductDetail.cshtml @@ -1,60 +1,68 @@ @page "/products/{id:guid}" @using EShopOnAbp.Localization -@using EShopOnAbp.PublicWeb.Components.Basket @using Microsoft.Extensions.Localization @using System.Globalization @using Microsoft.Extensions.Options @using Volo.Abp.GlobalFeatures @using Volo.Abp.Http.Client -@using Volo.Abp.Users @using Volo.CmsKit.GlobalFeatures -@using Volo.CmsKit.Public.Comments @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating @inject IStringLocalizer L @inject IOptions options -@inject ICurrentUser CurrentUser @model EShopOnAbp.PublicWeb.Pages.ProductDetailModel + @section styles{ - + } - @section scripts { - - - +@section scripts { + + + } -
-
-
-
- @{ +
+
+
+
+ @{ var product = Model.Product; var productPrice = product.Price.ToString("C", new CultureInfo("en-US")); string productImage = !product.ImageName.IsNullOrEmpty() ? $"{options.Value.RemoteServices.Default.BaseUrl}product-images/{product.ImageName}" : $"{options.Value.RemoteServices.Default.BaseUrl}product-images/@product.ImageName"; string buyText = L["Index:AddToBasket"]; -
-
-
-
@product.Name
- @product.Code - @L["StockCount"]: @product.StockCount +
+ +
+ +
@product.Name
+ @product.Code +
+
+
+ +
+
+ @L["StockCount"]: @product.StockCount +
+
+
+
+
+ Added to cart
-
- -
@if (product.StockCount > 0) { } else { - + } -
+
@productPrice
@@ -66,13 +74,14 @@ @if (GlobalFeatureManager.Instance.IsEnabled() && Model.IsPurschased) { - @await Component.InvokeAsync(typeof(RatingViewComponent), new {entityType = "quote", entityId = @product.Id.ToString()}) + @await Component.InvokeAsync(typeof(RatingViewComponent), new { entityType = "quote", entityId = @product.Id.ToString() }) } - @if (GlobalFeatureManager.Instance.IsEnabled()) + @* Need read-only commenting system *@ + @if (GlobalFeatureManager.Instance.IsEnabled() && Model.IsPurschased) { - @await Component.InvokeAsync(typeof(CommentingViewComponent), new {entityType = "quote", entityId = @product.Id.ToString()}) + @await Component.InvokeAsync(typeof(CommentingViewComponent), new { entityType = "quote", entityId = @product.Id.ToString() }) } diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/_ViewStart.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/_ViewStart.cshtml index 0372fa28..45f621d3 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/_ViewStart.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/_ViewStart.cshtml @@ -2,4 +2,18 @@ @inject IThemeManager ThemeManager @{ Layout = ThemeManager.CurrentTheme.GetPublicLayout(); -} \ No newline at end of file +} + + diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.css b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.css index 9b2c3929..901524dd 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.css +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.css @@ -5,20 +5,67 @@ a, a:hover, a:visited, a:active { color: inherit; text-decoration: none; + padding-bottom: 1em; } -.product-list-item { +.product-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1em 2em; /* row-gap column gap */ +} + +.product-container { + text-align: center; background-color: #fff; - padding: 2em; + padding: 2em 2em 1em 2em; border: 1px solid #eee; border-radius: 3px; box-shadow: 0 0 10px rgba(0, 0, 0, .05); margin-bottom: 2em; transition: all .2s; + display: flex; + flex: 0 0 20%; + flex-direction: column; +} + +.product-list-item { + display: flex; + flex-direction: column; +} + +.product-ratings { + display: flex; + justify-content: center; +} + +.text-muted.ms-1.text-decoration-none { + display: none; +} + +.rating-undo-link.text-decoration-none { + display: none; } -.product-list-item:hover { - box-shadow: 0 0 20px rgba(0, 0, 0, .1); +.product-title { + min-height: 70px; + padding-bottom: 1em; +} + +.product-item-bottom { + display: flex; + flex-direction: column; + min-height: 70px; +} + +.product-count { + display: flex; + justify-content: center; + padding: 1em 0 1em 0em; +} + +.product-container:hover { + box-shadow: 1px 1px 20px rgba(0, 0, 0, .2); cursor: pointer; } @@ -30,10 +77,6 @@ a, a:hover, a:visited, a:active { opacity: .8 } -.product-info-box { - min-height: 80px; -} - .add-basket-button { display: none; font-weight: 500; @@ -41,6 +84,11 @@ a, a:hover, a:visited, a:active { .product-list-item:hover .add-basket-button { display: inline-block; + width: -webkit-fill-available; +} + +.info-section { + text-align: center; } .product-list-item:hover .info-section { @@ -51,4 +99,10 @@ a, a:hover, a:visited, a:active { font-weight: bolder; font-size: larger; line-height: 40px; +} + +.item-added { + display: none; + justify-content: center; + align-items: baseline; } \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js index 89ca351d..e3eec507 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js @@ -17,8 +17,22 @@ .data('abp-widget-manager') .refresh(); - abp.notify.success("Added product to your basket.", "Successfully added"); + abp.notify.success("Added product to your basket.", "Successfully added"); //TODO: localize the msg + var $itemAdded = $this.parent(".product-item-bottom").find(".item-added"); + $($itemAdded).css({display: "flex"}); + $this.css({opacity: 0.5}); + $this.animate({opacity: 1}, 2000); + }).catch(err => { + abp.notify.error(err.message, "Failed while adding item"); //TODO: localize the msg }); }); }); + + $(function () { + $(".item-link").click(function () { + var $this = $(this); + var productId = $this.attr('data-product-id'); + location.href += "products/" + productId; + }); + }) })(); \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/productDetails.css b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/productDetails.css new file mode 100644 index 00000000..56dc9ea7 --- /dev/null +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/productDetails.css @@ -0,0 +1,100 @@ +body { + background-color: #f9f9f9; +} + +a, a:hover, a:visited, a:active { + color: inherit; + text-decoration: none; + padding-bottom: 1em; +} + +.product-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1em 2em; /* row-gap column gap */ +} + +.product-container { + text-align: center; + background-color: #fff; + padding: 2em 2em 1em 2em; + border: 1px solid #eee; + border-radius: 3px; + box-shadow: 0 0 10px rgba(0, 0, 0, .05); + margin-bottom: 2em; + transition: all .2s; + display: flex; + flex: 0 0 20%; + flex-direction: column; +} + +.product-list-item { + display: flex; + flex-direction: column; +} + +.product-ratings { + display: flex; + justify-content: center; +} + +.product-title { + min-height: 70px; + padding-bottom: 1em; +} + +.product-item-bottom { + display: flex; + flex-direction: column; + min-height: 70px; +} + +.product-count { + display: flex; + justify-content: center; + padding: 1em 0 1em 0em; +} + +.product-container:hover { + box-shadow: 1px 1px 20px rgba(0, 0, 0, .2); + cursor: pointer; +} + +.product-list-item img { + width: 100%; +} + +.product-list-item .text-muted { + opacity: .8 +} + +.add-basket-button { + display: none; + font-weight: 500; +} + +.product-list-item:hover .add-basket-button { + display: inline-block; + width: -webkit-fill-available; +} + +.info-section { + text-align: center; +} + +.product-list-item:hover .info-section { + display: none; +} + +.product-price { + font-weight: bolder; + font-size: larger; + line-height: 40px; +} + +.item-added { + display: none; + justify-content: center; + align-items: baseline; +} \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/package.json b/apps/public-web/src/EShopOnAbp.PublicWeb/package.json index 6d0b9df6..d5fdb413 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/package.json +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/package.json @@ -3,7 +3,7 @@ "name": "EShopOnAbpPublicWeb", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~7.0.0", + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~2.0.0-rc.4", "@abp/signalr": "~7.0.0", "@abp/cms-kit": "~7.0.0" } diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/logo.png b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/logo.png new file mode 100644 index 00000000..a6b63f7b Binary files /dev/null and b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/logo.png differ diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/yarn.lock b/apps/public-web/src/EShopOnAbp.PublicWeb/yarn.lock index c88bea2e..443d0b88 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/yarn.lock +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-7.0.0.tgz#b61845e6c2d7486575ab0fd177e7c87005f51d54" - integrity sha512-T4rhCG+O3agwD0pt7m/977ID8Hm0ME9zlqyHIQWiIIaRbicmgblr3OY5szv0C5ttCTUsjzeYlxtcv7I+7SXcaA== +"@abp/aspnetcore.mvc.ui.theme.leptonxlite@~2.0.0-rc.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.leptonxlite/-/aspnetcore.mvc.ui.theme.leptonxlite-2.0.5.tgz#5b4a59beba91cdd11da77a2bac78e533212b7f0b" + integrity sha512-jO02MB/cm6+iUv5AORSahGOOeAEALccs6qsYoGCAK/1k8Ej2p51B/7UZZ3qvdQJ8zGPeFwyEXMQoq4vkg4c2gQ== dependencies: "@abp/aspnetcore.mvc.ui.theme.shared" "~7.0.0"