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:
@@ -0,0 +1,209 @@
|
||||
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using MudBlazor;
|
||||
|
||||
namespace FrontOffice.Main.Utilities;
|
||||
|
||||
// ── DTOs ──
|
||||
public record DiscountOrderSummary(
|
||||
long Id,
|
||||
string OrderNumber,
|
||||
long TotalPrice,
|
||||
long DiscountBalanceUsed,
|
||||
long GatewayAmount,
|
||||
bool PaymentCompleted,
|
||||
int DeliveryStatus,
|
||||
string? TrackingCode,
|
||||
int ItemsCount,
|
||||
DateTime Created);
|
||||
|
||||
public record DiscountOrderDetail(
|
||||
long Id,
|
||||
string OrderNumber,
|
||||
long TotalPrice,
|
||||
long DiscountBalanceUsed,
|
||||
long GatewayAmount,
|
||||
bool PaymentCompleted,
|
||||
string? TransactionId,
|
||||
int DeliveryStatus,
|
||||
string? TrackingCode,
|
||||
string? Notes,
|
||||
string? AdminNotes,
|
||||
DiscountOrderAddress? Address,
|
||||
List<DiscountOrderItem> Items,
|
||||
DateTime Created);
|
||||
|
||||
public record DiscountOrderAddress(
|
||||
long Id, string Title, string Address, string PostalCode, string? Phone);
|
||||
|
||||
public record DiscountOrderItem(
|
||||
long ProductId,
|
||||
string Title,
|
||||
long UnitPrice,
|
||||
int MaxDiscountPercent,
|
||||
int Count,
|
||||
long TotalPrice,
|
||||
long DiscountAmount,
|
||||
long FinalPrice);
|
||||
|
||||
public record PlaceDiscountOrderResult(
|
||||
bool Success,
|
||||
string Message,
|
||||
long OrderId,
|
||||
long GatewayAmount,
|
||||
string? PaymentUrl);
|
||||
|
||||
public record DiscountOrderListResult(
|
||||
List<DiscountOrderSummary> Orders,
|
||||
int TotalCount,
|
||||
int TotalPages,
|
||||
int CurrentPage);
|
||||
|
||||
// ── Service ──
|
||||
public class DiscountOrderService
|
||||
{
|
||||
private readonly DiscountOrderContract.DiscountOrderContractClient _client;
|
||||
|
||||
public DiscountOrderService(DiscountOrderContract.DiscountOrderContractClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
|
||||
public async Task<PlaceDiscountOrderResult> PlaceOrderAsync(long addressId, long discountBalanceToUse, string? notes = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new PlaceOrderRequest
|
||||
{
|
||||
UserAddressId = addressId,
|
||||
DiscountBalanceToUse = discountBalanceToUse
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(notes))
|
||||
request.Notes = notes;
|
||||
|
||||
var response = await _client.PlaceOrderAsync(request);
|
||||
return new PlaceDiscountOrderResult(
|
||||
Success: response.Success,
|
||||
Message: response.Message ?? string.Empty,
|
||||
OrderId: response.OrderId,
|
||||
GatewayAmount: response.GatewayAmount,
|
||||
PaymentUrl: response.PaymentUrl);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new PlaceDiscountOrderResult(false, ex.Message, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> CompletePaymentAsync(long orderId, string? transactionId, bool success)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _client.CompleteOrderPaymentAsync(new CompleteOrderPaymentRequest
|
||||
{
|
||||
OrderId = orderId,
|
||||
TransactionId = transactionId,
|
||||
PaymentSuccess = success
|
||||
});
|
||||
return response.Success;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
public async Task<DiscountOrderListResult> GetUserOrdersAsync(int page = 1, int pageSize = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _client.GetUserOrdersAsync(new GetUserOrdersRequest
|
||||
{
|
||||
PageNumber = page,
|
||||
PageSize = pageSize
|
||||
});
|
||||
|
||||
var orders = response.Models.Select(m => new DiscountOrderSummary(
|
||||
Id: m.Id,
|
||||
OrderNumber: m.OrderNumber ?? string.Empty,
|
||||
TotalPrice: m.TotalPrice,
|
||||
DiscountBalanceUsed: m.DiscountBalanceUsed,
|
||||
GatewayAmount: m.GatewayAmount,
|
||||
PaymentCompleted: m.PaymentCompleted,
|
||||
DeliveryStatus: (int)m.DeliveryStatus,
|
||||
TrackingCode: m.TrackingCode,
|
||||
ItemsCount: m.ItemsCount,
|
||||
Created: m.Created?.ToDateTime() ?? DateTime.MinValue
|
||||
)).ToList();
|
||||
|
||||
var totalCount = (int)(response.MetaData?.TotalCount ?? 0);
|
||||
var totalPages = (int)(response.MetaData?.TotalPage ?? 0);
|
||||
|
||||
return new DiscountOrderListResult(orders, totalCount, totalPages, page);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new DiscountOrderListResult(new(), 0, 0, page);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DiscountOrderDetail?> GetOrderByIdAsync(long orderId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var r = await _client.GetOrderByIdAsync(new GetOrderByIdRequest { OrderId = orderId });
|
||||
|
||||
var address = r.Address != null
|
||||
? new DiscountOrderAddress(r.Address.Id, r.Address.Title ?? "", r.Address.Address ?? "", r.Address.PostalCode ?? "", r.Address.Phone)
|
||||
: null;
|
||||
|
||||
var items = r.Items.Select(i => new DiscountOrderItem(
|
||||
ProductId: i.ProductId,
|
||||
Title: i.ProductTitle ?? string.Empty,
|
||||
UnitPrice: i.UnitPrice,
|
||||
MaxDiscountPercent: i.MaxDiscountPercent,
|
||||
Count: i.Count,
|
||||
TotalPrice: i.TotalPrice,
|
||||
DiscountAmount: i.DiscountAmount,
|
||||
FinalPrice: i.FinalPrice
|
||||
)).ToList();
|
||||
|
||||
return new DiscountOrderDetail(
|
||||
Id: r.Id,
|
||||
OrderNumber: r.OrderNumber ?? string.Empty,
|
||||
TotalPrice: r.TotalPrice,
|
||||
DiscountBalanceUsed: r.DiscountBalanceUsed,
|
||||
GatewayAmount: r.GatewayAmount,
|
||||
PaymentCompleted: r.PaymentCompleted,
|
||||
TransactionId: r.TransactionId,
|
||||
DeliveryStatus: (int)r.DeliveryStatus,
|
||||
TrackingCode: r.TrackingCode,
|
||||
Notes: r.Notes,
|
||||
AdminNotes: r.AdminNotes,
|
||||
Address: address,
|
||||
Items: items,
|
||||
Created: r.Created?.ToDateTime() ?? DateTime.MinValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetDeliveryStatusText(int status) => status switch
|
||||
{
|
||||
0 => "در انتظار",
|
||||
1 => "در حال پردازش",
|
||||
2 => "ارسال شده",
|
||||
3 => "تحویل داده شده",
|
||||
4 => "لغو شده",
|
||||
_ => "نامشخص"
|
||||
};
|
||||
|
||||
public static Color GetDeliveryStatusColor(int status) => status switch
|
||||
{
|
||||
0 => Color.Warning,
|
||||
1 => Color.Info,
|
||||
2 => Color.Primary,
|
||||
3 => Color.Success,
|
||||
4 => Color.Error,
|
||||
_ => Color.Default
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user