feat: full FrontOffice updates - discount store, blog, payment gateway, UI improvements
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 4m55s
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 4m55s
- Discount store pages (products, cart, orders, order detail) - Blog pages and services - Payment gateway callback page - AppImage component, EmptyState, LoadingState, PageHeader - DiscountCartService, DiscountOrderService, DiscountProductService - BlogCategoryService, BlogPostService, SitePageService, ImageCacheService - PhoneVerifyForm component - Profile Hub page - UI/UX improvements across all pages - landing.js for homepage - Config and routing updates
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<MudStack Spacing="3">
|
||||
<MudText Typo="Typo.h4">سبد خرید</MudText>
|
||||
<PageHeader Title="سبد خرید" BackHref="@RouteConstants.Store.Products" />
|
||||
|
||||
@if (CartData.Items.Count == 0)
|
||||
{
|
||||
@@ -30,8 +30,8 @@
|
||||
<MudTd>
|
||||
<MudStack Spacing="1">
|
||||
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
|
||||
<MudImage Src="@GetProductImageUrl(context.ImageUrl)" Alt="@context.Title"
|
||||
Width="64" Height="64" Class="product-thumb" />
|
||||
<AppImage Path="@GetProductImageUrl(context.ImageUrl)" Alt="@context.Title"
|
||||
ImgWidth="64" ImgHeight="64" Class="product-thumb" />
|
||||
<MudText>@context.Title</MudText>
|
||||
</MudStack>
|
||||
@if (context.Discount > 0 || !string.IsNullOrWhiteSpace(context.Created) || !string.IsNullOrWhiteSpace(context.Description))
|
||||
@@ -86,8 +86,8 @@
|
||||
<MudStack Spacing="1">
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
|
||||
<MudImage Src="@GetProductImageUrl(item.ImageUrl)" Alt="@item.Title"
|
||||
Width="50" Height="50" Class="rounded-circle" />
|
||||
<AppImage Path="@GetProductImageUrl(item.ImageUrl)" Alt="@item.Title"
|
||||
ImgWidth="50" ImgHeight="50" Class="rounded-circle" />
|
||||
<MudText Typo="Typo.subtitle2">@item.Title</MudText>
|
||||
</MudStack>
|
||||
@if (item.Discount > 0)
|
||||
@@ -154,8 +154,8 @@
|
||||
</MudStack>
|
||||
}
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary" Style="font-weight:bold;">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
<MudText Typo="Typo.h6" Class="fw-bold">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary" Class="fw-bold">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
|
||||
@@ -185,8 +185,8 @@
|
||||
}
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight:bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight:bold;">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Class="fw-bold">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Class="fw-bold">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
@@ -66,7 +66,7 @@ public partial class Cart : ComponentBase, IDisposable
|
||||
private long VATAmount => VAT.CalculateVAT(CartData.Total);
|
||||
|
||||
private static string GetProductImageUrl(string? imageUrl)
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl;
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<PageTitle>دستهبندیها</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<PageHeader Title="دستهبندی محصولات" BackHref="@RouteConstants.Store.Products" />
|
||||
<MudPaper Elevation="1" Class="pa-4 mb-4 rounded-lg">
|
||||
<MudStack Spacing="1">
|
||||
<MudText Typo="Typo.h5">دستهبندی محصولات</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">
|
||||
از بین درخت دستهبندیها انتخاب کنید تا محصولات آن دسته را مشاهده نمایید.
|
||||
</MudText>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<PageTitle>خلاصه خرید</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<PageHeader Title="خلاصه خرید" BackHref="@RouteConstants.Store.Cart" />
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" md="8">
|
||||
<MudPaper Elevation="2" Class="pa-4 rounded-lg mb-3">
|
||||
@@ -30,7 +31,7 @@
|
||||
@foreach (var address in _addresses)
|
||||
{
|
||||
<MudPaper Outlined="@(_selectedAddress?.Id != address.Id)"
|
||||
Elevation="@(_selectedAddress?.Id == address.Id ? 4 : 0)"
|
||||
Elevation="@(_selectedAddress?.Id == address.Id ? 2 : 0)"
|
||||
Class="pa-3 rounded-xl cursor-pointer"
|
||||
Style="@(_selectedAddress?.Id == address.Id ? "border: 2px solid var(--mud-palette-primary);" : "")"
|
||||
@onclick="() => _selectedAddress = address">
|
||||
@@ -84,8 +85,8 @@
|
||||
<MudListItemText>
|
||||
<MudStack Spacing="1">
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudImage Src="@GetProductImageUrl(item.ImageUrl)" Alt="@item.Title"
|
||||
Width="48" Height="48" Class="rounded-circle" />
|
||||
<AppImage Path="@GetProductImageUrl(item.ImageUrl)" Alt="@item.Title"
|
||||
ImgWidth="48" ImgHeight="48" Class="rounded-circle" />
|
||||
<MudText Typo="Typo.subtitle2">@item.Title</MudText>
|
||||
<MudText Typo="Typo.subtitle2">@FormatPrice(item.LineTotal)</MudText>
|
||||
</MudStack>
|
||||
@@ -118,8 +119,8 @@
|
||||
}
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(VAT.AddVAT(Cart.Total))</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Class="fw-bold">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Class="fw-bold">@FormatPrice(VAT.AddVAT(Cart.Total))</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
|
||||
|
||||
@@ -113,5 +113,5 @@ public partial class CheckoutSummary : ComponentBase
|
||||
private long CalculateVAT() => VAT.CalculateVAT(Cart.Total);
|
||||
|
||||
private static string GetProductImageUrl(string? imageUrl)
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl;
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
|
||||
}
|
||||
@@ -6,24 +6,24 @@
|
||||
@if (_loading)
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||
<MudStack AlignItems="AlignItems.Center">
|
||||
<MudProgressCircular Indeterminate="true" Color="Color.Primary" />
|
||||
</MudStack>
|
||||
<LoadingState />
|
||||
</MudContainer>
|
||||
}
|
||||
else if (_order is null)
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||
<MudAlert Severity="Severity.Warning">سفارش یافت نشد.</MudAlert>
|
||||
<MudButton Variant="Variant.Text" StartIcon="@Icons.Material.Filled.ArrowBack" OnClick="() => Navigation.NavigateTo(RouteConstants.Store.Orders)">بازگشت</MudButton>
|
||||
<EmptyState Icon="@Icons.Material.Filled.SearchOff"
|
||||
Title="سفارش یافت نشد."
|
||||
ActionText="بازگشت"
|
||||
ActionHref="@RouteConstants.Store.Orders" />
|
||||
</MudContainer>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<PageHeader Title="@($"جزئیات سفارش #{_order.Id}")" BackHref="@RouteConstants.Store.Orders" />
|
||||
<MudPaper Elevation="2" Class="pa-4 rounded-lg">
|
||||
<MudStack Spacing="2">
|
||||
<MudText Typo="Typo.h5">سفارش #@_order.Id</MudText>
|
||||
@if (_order.PaymentDate != null)
|
||||
{
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">تاریخ پرداخت: @_order.PaymentDate.ToDateTime().MiladiToJalaliWithTime()</MudText>
|
||||
@@ -46,8 +46,8 @@ else
|
||||
<RowTemplate>
|
||||
<MudTd>
|
||||
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
|
||||
<MudImage Src="@GetProductImageUrl(context.ProductThumbnailPath)" Alt="@context.ProductTitle"
|
||||
Width="60" Height="60" Class="rounded-circle" />
|
||||
<AppImage Path="@GetProductImageUrl(context.ProductThumbnailPath)" Alt="@context.ProductTitle"
|
||||
ImgWidth="60" ImgHeight="60" Class="rounded-circle" />
|
||||
<MudText>@context.ProductTitle</MudText>
|
||||
</MudStack>
|
||||
</MudTd>
|
||||
@@ -65,8 +65,8 @@ else
|
||||
<MudPaper Class="pa-3 rounded-lg" Outlined="true">
|
||||
<MudStack Spacing="1">
|
||||
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
|
||||
<MudImage Src="@GetProductImageUrl(it.ProductThumbnailPath)" Alt="@it.ProductTitle"
|
||||
Width="60" Height="60" Class="rounded-circle" />
|
||||
<AppImage Path="@GetProductImageUrl(it.ProductThumbnailPath)" Alt="@it.ProductTitle"
|
||||
ImgWidth="60" ImgHeight="60" Class="rounded-circle" />
|
||||
<MudText>@it.ProductTitle</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
@@ -100,15 +100,15 @@ else
|
||||
</MudStack>
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(_order.VatInfo.TotalAmount)</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Class="fw-bold">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Class="fw-bold">@FormatPrice(_order.VatInfo.TotalAmount)</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(subtotal)</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Class="fw-bold">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Class="fw-bold">@FormatPrice(subtotal)</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
@@ -45,6 +45,6 @@ public partial class OrderDetail : ComponentBase
|
||||
}
|
||||
|
||||
private static string GetProductImageUrl(string? imageUrl)
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : UrlUtility.DownloadUrl+imageUrl;
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<PageTitle>پیگیری سفارش</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||
<PageHeader Title="پیگیری سفارش" BackHref="@RouteConstants.Store.Orders" />
|
||||
@if (_loading)
|
||||
{
|
||||
<MudStack AlignItems="AlignItems.Center">
|
||||
@@ -15,7 +16,7 @@
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning">سفارش یافت نشد.</MudAlert>
|
||||
<MudButton Variant="Variant.Text" StartIcon="@Icons.Material.Filled.ArrowBack"
|
||||
Href="@RouteConstants.Store.Orders">
|
||||
OnClick="GoBack">
|
||||
بازگشت به سفارشها
|
||||
</MudButton>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using CMSMicroservice.Protobuf.Protos.UserOrder;
|
||||
using FrontOffice.Main.Utilities;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Messages = CMSMicroservice.Protobuf.Protos;
|
||||
|
||||
namespace FrontOffice.Main.Pages.Store;
|
||||
@@ -8,6 +9,7 @@ namespace FrontOffice.Main.Pages.Store;
|
||||
public partial class OrderTracking : ComponentBase
|
||||
{
|
||||
[Inject] private OrderService OrderService { get; set; } = default!;
|
||||
[Inject] private IJSRuntime JS { get; set; } = default!;
|
||||
|
||||
[Parameter] public long id { get; set; }
|
||||
|
||||
@@ -123,4 +125,6 @@ public partial class OrderTracking : ComponentBase
|
||||
public bool IsCurrent { get; set; }
|
||||
public string Date { get; set; } = "";
|
||||
}
|
||||
|
||||
private async Task GoBack() => await JS.InvokeVoidAsync("history.back");
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
<PageTitle>سفارشات من</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<MudText Typo="Typo.h4" Class="mb-3">سفارشات من</MudText>
|
||||
<PageHeader Title="سفارشات من" BackHref="@RouteConstants.Store.Products" />
|
||||
@if (_loading)
|
||||
{
|
||||
<MudStack AlignItems="AlignItems.Center" Class="py-4">
|
||||
<MudProgressCircular Indeterminate="true" Color="Color.Primary" />
|
||||
</MudStack>
|
||||
<LoadingState />
|
||||
}
|
||||
else if (_orders.Count == 0)
|
||||
{
|
||||
|
||||
@@ -6,23 +6,22 @@
|
||||
@if (_loading)
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||
<MudStack AlignItems="AlignItems.Center">
|
||||
<MudProgressCircular Color="Color.Primary" Indeterminate="true"/>
|
||||
</MudStack>
|
||||
<LoadingState />
|
||||
</MudContainer>
|
||||
}
|
||||
else if (_product is null)
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||
<MudAlert Severity="Severity.Warning">محصول یافت نشد.</MudAlert>
|
||||
<MudButton Class="mt-2" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.ArrowBack"
|
||||
OnClick="() => Navigation.NavigateTo(RouteConstants.Store.Products)">بازگشت
|
||||
</MudButton>
|
||||
<EmptyState Icon="@Icons.Material.Filled.SearchOff"
|
||||
Title="محصول یافت نشد."
|
||||
ActionText="بازگشت"
|
||||
ActionHref="@RouteConstants.Store.Products" />
|
||||
</MudContainer>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<PageHeader Title="جزئیات محصول" BackHref="@RouteConstants.Store.Products" />
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" md="6">
|
||||
@if (_product is not null)
|
||||
@@ -32,7 +31,9 @@ else
|
||||
<MudPaper Class="rounded-lg pa-2">
|
||||
@if (!string.IsNullOrWhiteSpace(MainImageUrl))
|
||||
{
|
||||
<div class="rounded-lg" style="width:100%;height:360px;background-image: url('@MainImageUrl');background-size: cover; background-position: center;border-radius: 0.5rem;color: transparent;" >@MainImageAlt</div>
|
||||
<AppImage Path="@MainImageUrl" Alt="@MainImageAlt"
|
||||
ObjectFit="ObjectFit.Cover"
|
||||
Style="width:100%; max-height:400px; border-radius:12px;" />
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -45,7 +46,7 @@ else
|
||||
@foreach (var item in _galleryItems)
|
||||
{
|
||||
<MudButton Variant="Variant.Text" Class="p-0" Style="min-width:0;" OnClick="() => SelectGalleryImage(item)">
|
||||
<MudImage Src="@GetThumbnailUrl(item)" Alt="@item.Title" Class="rounded-sm" Style="@GetThumbnailStyle(item)" />
|
||||
<AppImage Path="@GetThumbnailUrl(item)" Alt="@item.Title" Class="rounded-sm" Style="@GetThumbnailStyle(item)" />
|
||||
</MudButton>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
@@ -3,7 +3,18 @@
|
||||
|
||||
<PageTitle>محصولات</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="pa-2 pa-md-6">
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||||
<!-- Hero Banner -->
|
||||
<MudPaper Class="store-hero pa-6 pa-md-8 mb-4 rounded-xl" Elevation="0">
|
||||
<MudStack AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Storefront" Size="Size.Large" Class="dash-hero-name" />
|
||||
<MudText Typo="Typo.h5" Align="Align.Center" Class="dash-hero-name">فروشگاه کارا بازار سلامت</MudText>
|
||||
<MudText Typo="Typo.body2" Align="Align.Center" Class="dash-hero-sub">
|
||||
محصولات با کیفیت با ضمانت اصالت و ارسال سریع
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="1" Class="pa-3 pa-md-4 mb-4 rounded-lg">
|
||||
<MudGrid Spacing="2" AlignItems="AlignItems.Center">
|
||||
@* ردیف اول: جستجو و دکمهها *@
|
||||
@@ -44,25 +55,25 @@
|
||||
Margin="Margin.Dense"
|
||||
AnchorOrigin="Origin.BottomCenter"
|
||||
AdornmentIcon="@Icons.Material.Filled.Sort">
|
||||
<MudSelectItem Value="ProductSortOption.PriceDesc">
|
||||
<MudSelectItem T="ProductSortOption" Value="ProductSortOption.PriceDesc">
|
||||
<div class="d-flex align-center gap-2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.ArrowDownward" Size="Size.Small"/>
|
||||
گرانترین
|
||||
</div>
|
||||
</MudSelectItem>
|
||||
<MudSelectItem Value="ProductSortOption.PriceAsc">
|
||||
<MudSelectItem T="ProductSortOption" Value="ProductSortOption.PriceAsc">
|
||||
<div class="d-flex align-center gap-2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.ArrowUpward" Size="Size.Small"/>
|
||||
ارزانترین
|
||||
</div>
|
||||
</MudSelectItem>
|
||||
<MudSelectItem Value="ProductSortOption.Newest">
|
||||
<MudSelectItem T="ProductSortOption" Value="ProductSortOption.Newest">
|
||||
<div class="d-flex align-center gap-2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.NewReleases" Size="Size.Small"/>
|
||||
جدیدترین
|
||||
</div>
|
||||
</MudSelectItem>
|
||||
<MudSelectItem Value="ProductSortOption.Title">
|
||||
<MudSelectItem T="ProductSortOption" Value="ProductSortOption.Title">
|
||||
<div class="d-flex align-center gap-2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.SortByAlpha" Size="Size.Small"/>
|
||||
الفبایی
|
||||
|
||||
Reference in New Issue
Block a user