feat: full FrontOffice updates - discount store, blog, payment gateway, UI improvements
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:
masoodafar-web
2026-02-16 00:51:39 +03:30
parent f0d1156457
commit 6db83ccd90
104 changed files with 7668 additions and 1370 deletions
@@ -0,0 +1,114 @@
using System.Text.Json;
namespace FrontOffice.Main.Utilities;
public class SitePageService
{
private readonly CMSMicroservice.Protobuf.Protos.SitePage.SitePageContract.SitePageContractClient _client;
public SitePageService(CMSMicroservice.Protobuf.Protos.SitePage.SitePageContract.SitePageContractClient client)
{
_client = client;
}
public async Task<SitePageDto?> GetByKeyAsync(string pageKey)
{
try
{
var response = await _client.GetSitePageByKeyAsync(
new CMSMicroservice.Protobuf.Protos.SitePage.GetSitePageByKeyRequest { PageKey = pageKey });
if (response == null || response.Id <= 0) return null;
var dto = new SitePageDto
{
Id = response.Id,
PageKey = response.PageKey,
Title = response.Title,
MetaDescription = response.MetaDescription,
HeroTitle = response.HeroTitle,
HeroSubtitle = response.HeroSubtitle,
HeroImagePath = response.HeroImagePath,
IsActive = response.IsActive
};
foreach (var s in response.Sections.OrderBy(s => s.SortOrder))
{
dto.Sections.Add(new SitePageSectionDto
{
Id = s.Id,
SectionKey = s.SectionKey,
Title = s.Title,
Subtitle = s.Subtitle,
HtmlContent = s.HtmlContent,
IconName = s.IconName,
ImagePath = s.ImagePath,
ImageThumbnailPath = s.ImageThumbnailPath,
SortOrder = s.SortOrder,
IsActive = s.IsActive,
ExtraData = s.ExtraData
});
}
return dto;
}
catch (Exception ex)
{
#if DEBUG
Console.WriteLine($"SitePageService.GetByKeyAsync error: {ex.Message}");
#endif
return null;
}
}
}
public class SitePageDto
{
public long Id { get; set; }
public string PageKey { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string? MetaDescription { get; set; }
public string? HeroTitle { get; set; }
public string? HeroSubtitle { get; set; }
public string? HeroImagePath { get; set; }
public bool IsActive { get; set; }
public List<SitePageSectionDto> Sections { get; set; } = new();
public SitePageSectionDto? GetSection(string sectionKey) =>
Sections.FirstOrDefault(s => s.SectionKey == sectionKey && s.IsActive);
public List<SitePageSectionDto> GetSections(string prefix) =>
Sections.Where(s => s.SectionKey.StartsWith(prefix) && s.IsActive)
.OrderBy(s => s.SortOrder).ToList();
}
public class SitePageSectionDto
{
public long Id { get; set; }
public string SectionKey { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string? Subtitle { get; set; }
public string? HtmlContent { get; set; }
public string? IconName { get; set; }
public string? ImagePath { get; set; }
public string? ImageThumbnailPath { get; set; }
public int SortOrder { get; set; }
public bool IsActive { get; set; }
public string? ExtraData { get; set; }
public T? GetExtraData<T>() where T : class
{
if (string.IsNullOrWhiteSpace(ExtraData)) return null;
try
{
return JsonSerializer.Deserialize<T>(ExtraData, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
catch
{
return null;
}
}
}