Initial commit - ECommerce.RCL

This commit is contained in:
2026-08-05 21:16:01 +03:00
commit 6aae28d210
120 changed files with 12334 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
using Commerce.Contracts.DTOs;
using Generic.Contracts.Generics;
using Generic.Services;
using Microsoft.Extensions.Http;
namespace ECommerceModule.Services;
public class CategoryAPIConsumer
{
private readonly HttpClient client;
public CategoryAPIConsumer(IHttpClientFactory httpClientFactory)
{
this.client = httpClientFactory.CreateClient("Commerce");
}
public async Task<CategoryVM> GetCategory(string id)
{
try
{
var culture = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName ?? "ar";
var response = await client.GetFromJsonAsync<CategoryVM>($"category/{id}");
return response!;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
throw;
}
}
public async Task<(List<CategoryVM>, int)> FetchCategory(CategoryFilter filter, Pagination pagination)
{
try
{
var culture = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName ?? "ar";
var filterWithCulture = new CategoryFilter
{
Name = filter?.Name,
IsBundle = filter?.IsBundle,
Random = filter?.Random,
Language = culture
};
var query = new AdvancedQueryBuilder()
.AddPreText("categories?")
.AddModels(filterWithCulture, pagination)
.ToString();
var categories = new List<CategoryVM>();
var response = await client.GetAsync(query);
var itemsCount = 0;
if (response.IsSuccessStatusCode)
{
if (response.Headers.TryGetValues("x-pagination", out var values))
{
itemsCount = int.Parse(values.First());
}
categories = await response.Content.ReadFromJsonAsync<List<CategoryVM>>();
}
return (categories ?? new List<CategoryVM>(), itemsCount);
}
catch (HttpRequestException)
{
throw;
}
}
public async Task<List<CategoryVM>> FetchCategoryTree()
{
try
{
var response = await client.GetFromJsonAsync<List<CategoryVM>>("categories/tree");
return response ?? new List<CategoryVM>();
}
catch (HttpRequestException)
{
throw;
}
}
public async Task<bool> CreateCategory(CategoryVM category)
{
try
{
var response = await client.PostAsJsonAsync<CategoryVM>(
"category",
category,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
throw;
}
}
public async Task<bool> UpdateCategory(CategoryVM category)
{
try
{
var response = await client.PutAsJsonAsync<CategoryVM>(
"category",
category,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: Endpoint", endpoint);
throw;
}
}
public async Task<bool> DeleteCategory(string id)
{
try
{
var response = await client.DeleteAsync($"category/{id}");
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: Endpoint", endpoint);
throw;
}
}
}
+144
View File
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
using Commerce.Contracts.DTOs;
using Generic.Contracts.Generics;
using Generic.Services;
namespace ECommerceModule.Services;
public class ProductAPIConsumer
{
private readonly HttpClient client;
public ProductAPIConsumer(IHttpClientFactory httpClientFactory)
{
this.client = httpClientFactory.CreateClient("Commerce");
}
public virtual async Task<ProductVM> GetProduct(string id)
{
try
{
var culture = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName ?? "ar";
var response = await client.GetFromJsonAsync<ProductVM>($"product/{id}");
return response!;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
throw;
}
}
public virtual async Task<(List<ProductVM>, int)> FetchProduct(ProductFilter filter, Pagination pagination)
{
try
{
var culture = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName ?? "ar";
var filterWithCulture = new ProductFilter
{
Name = filter?.Name,
Price = filter?.Price,
Discount = filter?.Discount,
IsBundle = filter?.IsBundle,
CategoryId = filter?.CategoryId,
Random = filter?.Random,
Language = culture
};
var query = new AdvancedQueryBuilder()
.AddPreText("products?")
.AddModels(filterWithCulture, pagination)
.ToString();
var products = new List<ProductVM>();
var response = await client.GetAsync(query);
var itemsCount = 0;
if (response.IsSuccessStatusCode)
{
if (response.Headers.TryGetValues("x-pagination", out var values))
{
itemsCount = int.Parse(values.First());
}
products = await response.Content.ReadFromJsonAsync<List<ProductVM>>();
}
return (products ?? new List<ProductVM>(), itemsCount);
}
catch (HttpRequestException)
{
throw;
}
}
// public virtual async Task<List<ProductVM>> GetRandomProducts()
// {
// try
// {
// var response = await client.GetFromJsonAsync<List<ProductVM>>($"product/random");
// return response;
// }
// catch (HttpRequestException ex)
// {
// // _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
// throw;
// }
// }
public virtual async Task<bool> UpdateProduct(ProductVM product)
{
try
{
var response = await client.PutAsJsonAsync<ProductVM>(
"product",
product,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: Endpoint", endpoint);
throw;
}
}
public virtual async Task<bool> CreateProduct(ProductVM product)
{
try
{
var response = await client.PostAsJsonAsync<ProductVM>(
"product",
product,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
throw;
}
}
public virtual async Task<bool> DeleteProduct(string id)
{
try
{
var response = await client.DeleteAsync($"product/{id}");
return response.IsSuccessStatusCode;
}
catch (HttpRequestException)
{
// _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
throw;
}
}
}
+59
View File
@@ -0,0 +1,59 @@
using Blazored.LocalStorage;
namespace ECommerceModule.Services;
public class ShopStateService
{
private readonly ILocalStorageService _localStorage;
// keys
private const string FavoritesKey = "shop_favorites";
private const string CategoryIdKey = "shop_category_id";
// events
public event Action? OnChange;
public ShopStateService(ILocalStorageService localStorage)
{
_localStorage = localStorage;
}
public List<string> Favorites { get; private set; } = new();
public Guid? CategoryId { get; private set; }
public async Task InitializeAsync()
{
Favorites = await _localStorage.GetItemAsync<List<string>>(FavoritesKey) ?? new List<string>();
CategoryId = await _localStorage.GetItemAsync<Guid?>(CategoryIdKey);
NotifyStateChanged();
}
public async Task ToggleFavorite(string productId)
{
if (Favorites.Contains(productId))
{
Favorites.Remove(productId);
}
else
{
Favorites.Add(productId);
}
await _localStorage.SetItemAsync(FavoritesKey, Favorites);
NotifyStateChanged();
}
public bool IsFavorite(string productId)
{
return Favorites.Contains(productId);
}
public async Task SetCategoryId(Guid? categoryId)
{
CategoryId = categoryId;
await _localStorage.SetItemAsync(CategoryIdKey, CategoryId);
NotifyStateChanged();
}
private void NotifyStateChanged() => OnChange?.Invoke();
}