feat: Add package management features and update checkout summary
- Added PackageService to handle package-related operations. - Introduced MyPackages and Packages pages for user package management. - Updated CheckoutSummary to display VAT calculations. - Enhanced OrderDetail to show financial details including VAT. - Added ChangePassword page for user profile management. - Implemented OrderTracking page for tracking order status. - Updated RouteConstants to include new routes for packages and password change.
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
using FrontOffice.BFF.Package.Protobuf.Protos.Package;
|
||||
|
||||
namespace FrontOffice.Main.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Package data transfer object for UI display
|
||||
/// </summary>
|
||||
public record PackageDto(
|
||||
long Id,
|
||||
string Title,
|
||||
string Description,
|
||||
string ImageUrl,
|
||||
long Price)
|
||||
{
|
||||
public string FormattedPrice => string.Format("{0:N0} تومان", Price);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User's package purchase status
|
||||
/// </summary>
|
||||
public record UserPackageStatusDto(
|
||||
bool HasPurchasedPackage,
|
||||
string? PurchaseMethod, // DayaLoan, DirectPurchase, or null
|
||||
bool IsClubMemberActive,
|
||||
long WalletBalance,
|
||||
bool CanActivateClubMembership,
|
||||
DateTime? PurchaseDate);
|
||||
|
||||
/// <summary>
|
||||
/// Service for managing packages in FrontOffice
|
||||
/// </summary>
|
||||
public class PackageService
|
||||
{
|
||||
private readonly PackageContract.PackageContractClient _client;
|
||||
|
||||
public PackageService(PackageContract.PackageContractClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all available packages
|
||||
/// </summary>
|
||||
public async Task<List<PackageDto>> GetAllPackagesAsync(CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new GetAllPackageByFilterRequest
|
||||
{
|
||||
PaginationState = new PaginationState
|
||||
{
|
||||
PageNumber = 1,
|
||||
PageSize = 100
|
||||
}
|
||||
};
|
||||
|
||||
var response = await _client.GetAllPackageByFilterAsync(request, cancellationToken: ct);
|
||||
|
||||
return response.Models
|
||||
.Select(m => new PackageDto(
|
||||
m.Id,
|
||||
m.Title,
|
||||
m.Description,
|
||||
UrlUtility.DownloadUrl + m.ImagePath,
|
||||
m.Price))
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine($"Error fetching packages: {ex.Message}");
|
||||
#endif
|
||||
return new List<PackageDto>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a single package by ID
|
||||
/// </summary>
|
||||
public async Task<PackageDto?> GetPackageByIdAsync(long id, CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _client.GetPackageAsync(
|
||||
new GetPackageRequest { Id = id },
|
||||
cancellationToken: ct);
|
||||
|
||||
if (response == null) return null;
|
||||
|
||||
return new PackageDto(
|
||||
response.Id,
|
||||
response.Title,
|
||||
response.Description,
|
||||
UrlUtility.DownloadUrl + response.ImagePath,
|
||||
response.Price);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine($"Error fetching package {id}: {ex.Message}");
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get user's package purchase status (Mock for now - needs BFF implementation)
|
||||
/// </summary>
|
||||
public Task<UserPackageStatusDto> GetUserPackageStatusAsync(CancellationToken ct = default)
|
||||
{
|
||||
// TODO: Connect to GetUserPackageStatus RPC when available in FrontOffice.BFF
|
||||
// For now, return a mock status
|
||||
return Task.FromResult(new UserPackageStatusDto(
|
||||
HasPurchasedPackage: false,
|
||||
PurchaseMethod: null,
|
||||
IsClubMemberActive: false,
|
||||
WalletBalance: 0,
|
||||
CanActivateClubMembership: false,
|
||||
PurchaseDate: null));
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public static class RouteConstants
|
||||
public const string Personal = "/profile/personal";
|
||||
public const string Addresses = "/profile/addresses";
|
||||
public const string Settings = "/profile/settings";
|
||||
public const string ChangePassword = "/profile/change-password";
|
||||
public const string Tree = "/profile/tree";
|
||||
public const string Wallet = "/profile/wallet";
|
||||
}
|
||||
@@ -43,7 +44,10 @@ public static class RouteConstants
|
||||
|
||||
public static class Package
|
||||
{
|
||||
public const string List = "/packages";
|
||||
public const string Detail = "/package/";
|
||||
public const string MyPackages = "/my-packages";
|
||||
public const string Purchase = "/purchase-package/";
|
||||
}
|
||||
|
||||
public static class About
|
||||
@@ -74,6 +78,7 @@ public static class RouteConstants
|
||||
public const string CheckoutSummary = "/checkout-summary";
|
||||
public const string Orders = "/orders";
|
||||
public const string OrderDetail = "/order/"; // usage: /order/{id}
|
||||
public const string OrderTracking = "/order-tracking/"; // usage: /order-tracking/{id}
|
||||
public const string Categories = "/categories";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user