diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor b/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor
new file mode 100644
index 0000000..77b033f
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor
@@ -0,0 +1,187 @@
+@using Radzen.Blazor
+@using NetinaShop.AdminPanel.PWA.Extensions
+
+@inject ISnackbar Snackbar
+@inject IRestWrapper RestWrapper
+@inject IUserUtility UserUtility
+@inject IDialogService DialogService
+
+
+
+
+
+
+
+
+
+
+
+
+ اطلاعات کلی
+ اطلاعات کلی محصول را به دقت وارد کنید
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ انتخاب حالتــ تخفیفـــ
+ تخفیف مورد نظر میتواند برای هر یک از موارد زیر ایجاد شود
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @e.Name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @e.PersianName
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @if (ViewModel.IsEditing)
+ {
+
+ }
+ else
+ {
+
+ }
+
+ بستن
+
+
+
+@code {
+ [CascadingParameter]
+ MudDialogInstance MudDialog { get; set; }
+
+ [Parameter]
+ public DiscountSDto? Discount { get; set; }
+
+ public DiscountActionDialogBoxViewModel ViewModel { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ if (Discount == null)
+ ViewModel = new DiscountActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
+ else
+ ViewModel = new DiscountActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Discount);
+ await ViewModel.InitializeAsync();
+ await base.OnInitializedAsync();
+ }
+
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor.cs b/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor.cs
new file mode 100644
index 0000000..6d5b962
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/DiscountActionDialogBox.razor.cs
@@ -0,0 +1,321 @@
+using Mapster;
+using NetinaShop.Domain.Entities.Blogs;
+using NetinaShop.Domain.Entities.Discounts;
+using NetinaShop.Domain.Mappers;
+
+namespace NetinaShop.AdminPanel.PWA.Dialogs;
+
+public class DiscountActionDialogBoxViewModel : BaseViewModel
+{
+
+ private readonly ISnackbar _snackbar;
+ private readonly IRestWrapper _restWrapper;
+ private readonly IUserUtility _userUtility;
+ private readonly IDialogService _dialogService;
+ private readonly MudDialogInstance _mudDialog;
+
+ public DiscountActionDialogBoxViewModel(
+ ISnackbar snackbar,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
+ MudDialogInstance mudDialog)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _userUtility = userUtility;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ }
+ public DiscountActionDialogBoxViewModel(ISnackbar snackbar,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
+ MudDialogInstance mudDialog,
+ DiscountSDto discount)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _userUtility = userUtility;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ _discountId = discount.Id;
+ IsEditing = true;
+ }
+
+ private bool _isProductEnable;
+
+ public bool IsProductEnable
+ {
+ get => _isProductEnable;
+ set
+ {
+ _isProductEnable = value;
+ if (_isProductEnable)
+ {
+ IsCategoryEnable = false;
+ IsAllEnable = false;
+ }
+ }
+ }
+ private bool _isCategoryEnable;
+ public bool IsCategoryEnable
+ {
+ get => _isCategoryEnable;
+ set
+ {
+ _isCategoryEnable = value;
+ if (_isCategoryEnable)
+ {
+ IsProductEnable = false;
+ IsAllEnable = false;
+ }
+ }
+ }
+ private bool _isAllEnable;
+ public bool IsAllEnable
+ {
+ get => _isAllEnable;
+ set
+ {
+ _isAllEnable = value;
+ if (_isAllEnable)
+ {
+ IsCategoryEnable = false;
+ IsProductEnable = false;
+ }
+ }
+ }
+
+ public bool IsPercentType { get; set; } = true;
+ public bool IsAmountType { get; set; }
+
+ public DateTime? ExpireDate { get; set; }
+ public DateTime? StartDate { get; set; }
+ private Guid _discountId;
+ public bool IsEditing = false;
+
+ public void AmountTypeChanged(DiscountAmountType type)
+ {
+ switch (type)
+ {
+ case DiscountAmountType.Amount:
+ IsAmountType = true;
+ IsPercentType = false;
+ break;
+ case DiscountAmountType.Percent:
+ IsAmountType = false;
+ IsPercentType = true;
+ break;
+ }
+ }
+
+ public override async Task InitializeAsync()
+ {
+ if (IsEditing && _discountId != default)
+ {
+ try
+ {
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ IsProcessing = true;
+ var discount = await _restWrapper.DiscountRest.ReadOne(_discountId, token);
+ PageDto = discount;
+
+ if (PageDto.CategoryId != default)
+ SelectedCategory = new ProductCategorySDto { Id = PageDto.CategoryId, Name = PageDto.CategoryName };
+
+ if (PageDto.ProductId != default)
+ SelectedProduct = new ProductSDto { Id = PageDto.ProductId, PersianName = PageDto.ProductName };
+
+ ExpireDate = PageDto.ExpireDate;
+ StartDate = PageDto.StartDate;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+ else
+ {
+ StartDate = DateTime.Today;
+ ExpireDate = DateTime.Today.AddDays(7);
+ PageDto.IsInfinity = false;
+ PageDto.HasCode = false;
+ IsAllEnable = true;
+ }
+ await base.InitializeAsync();
+ }
+
+
+
+
+ public void Cancel() => _mudDialog.Cancel();
+
+ public async Task SubmitCreateAsync()
+ {
+ try
+ {
+ IsProcessing = true;
+ if (IsAllEnable)
+ {
+ PageDto.Type = DiscountType.All;
+ }
+ else if (IsCategoryEnable)
+ {
+ PageDto.Type = DiscountType.Category;
+ if (SelectedCategory == null)
+ throw new Exception("دسته بندی را برای تخفیف انتخاب نمایید");
+ PageDto.CategoryId = SelectedCategory.Id;
+ }
+ else if (IsProductEnable)
+ {
+ PageDto.Type = DiscountType.Product;
+ if (SelectedProduct == null)
+ throw new Exception("کالا مورد نظر را برای تخفیف انتخاب نمایید");
+ PageDto.ProductId = SelectedProduct.Id;
+ }
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ if (ExpireDate != null)
+ PageDto.ExpireDate = ExpireDate.Value;
+ if(StartDate != null)
+ PageDto.StartDate = StartDate.Value;
+
+ var request = PageDto.Adapt();
+ await _restWrapper.CrudApiRest(Address.DiscountController).Create(request, token);
+
+ _snackbar.Add($"ساخت تخفیف با موفقیت انجام شد", Severity.Success);
+ _mudDialog.Close();
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+ public async Task SubmitEditAsync()
+ {
+ try
+ {
+ IsProcessing = true;
+ if (_discountId == default)
+ throw new Exception("بلاگ اشتباه است");
+ if (SelectedCategory == null)
+ throw new Exception("لطفا یک دسته بندی انتخاب کنید");
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ PageDto.Id = _discountId;
+ var request = PageDto.Adapt();
+ await _restWrapper.CrudApiRest(Address.DiscountController).Create(request, token);
+ _snackbar.Add($"ویرایش تخفیف با موفقیت انجام شد", Severity.Success);
+ _mudDialog.Close();
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+
+
+ private List _productCategories = new List();
+ public ProductCategorySDto? SelectedCategory;
+ public async Task> SearchCategory(string category)
+ {
+ try
+ {
+ if (category.IsNullOrEmpty())
+ _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
+ else
+ _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
+ return _productCategories;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ return _productCategories;
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ return _productCategories;
+ }
+ }
+
+
+
+ private List _products = new List();
+ public ProductSDto? SelectedProduct;
+ public async Task> SearchProduct(string product)
+ {
+ try
+ {
+ if (product.IsNullOrEmpty())
+ _products = await _restWrapper.ProductRestApi.ReadAll(0);
+ else
+ _products = await _restWrapper.ProductRestApi.ReadAll(product);
+ return _products;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ return _products;
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ return _products;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
index 10144a3..51e2e10 100644
--- a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
@@ -24,10 +24,10 @@
-
+
-
+
@@ -74,36 +74,36 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -168,7 +168,7 @@
-
+
@@ -240,6 +240,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
index d1955d1..7abae27 100644
--- a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
@@ -1,6 +1,8 @@
-namespace NetinaShop.AdminPanel.PWA.Dialogs;
+using Mapster;
-public class ProductActionDialogBoxViewModel : BaseViewModel
+namespace NetinaShop.AdminPanel.PWA.Dialogs;
+
+public class ProductActionDialogBoxViewModel : BaseViewModel
{
private readonly ISnackbar _snackbar;
private readonly IRestWrapper _restWrapper;
@@ -17,9 +19,9 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
_mudDialog = mudDialog;
}
public ProductActionDialogBoxViewModel(ISnackbar snackbar,
- IRestWrapper restWrapper,
- IUserUtility userUtility,
- IDialogService dialogService,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
MudDialogInstance mudDialog,
ProductSDto product)
{
@@ -48,17 +50,22 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
public void Cancel() => _mudDialog.Cancel();
public bool IsEditing = false;
- public string ExpertCheck = string.Empty;
- public string Summery = string.Empty;
- public bool BeDisplayed = true;
- public bool HasExpressDelivery = false;
- public string PersianName = string.Empty;
- public string EnglishName = string.Empty;
- public double Cost;
- public double PackingCost;
- public int MaxOrder;
- public string Warranty = string.Empty;
- public string Tags = string.Empty;
+ private bool _isSpecialOffer;
+
+ public bool IsSpecialOffer
+ {
+ get => _isSpecialOffer;
+ set
+ {
+ _isSpecialOffer = value;
+ PageDto.IsSpecialOffer = value;
+ if(!value)
+ {
+ IsAmountType = value;
+ IsPercentType = value;
+ }
+ }
+ }
public string SpecificationTitle = string.Empty;
public string SpecificationValue = string.Empty;
@@ -74,20 +81,40 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
{
IsProcessing = true;
var productLDto = await _restWrapper.CrudDtoApiRest(Address.ProductController).ReadOne(_product.Id);
- ExpertCheck = productLDto.ExpertCheck;
- Summery = productLDto.Summery;
- BeDisplayed = productLDto.BeDisplayed;
- HasExpressDelivery = productLDto.HasExpressDelivery;
- PersianName = productLDto.PersianName;
- EnglishName = productLDto.EnglishName;
- Cost = productLDto.Cost;
- PackingCost = productLDto.PackingCost;
- MaxOrder = productLDto.MaxOrderCount;
- Warranty = productLDto.Warranty;
+ PageDto.ExpertCheck = productLDto.ExpertCheck;
+ PageDto.Summery = productLDto.Summery;
+ PageDto.BeDisplayed = productLDto.BeDisplayed;
+ PageDto.HasExpressDelivery = productLDto.HasExpressDelivery;
+ PageDto.PersianName = productLDto.PersianName;
+ PageDto.EnglishName = productLDto.EnglishName;
+ PageDto.Cost = productLDto.Cost;
+ PageDto.PackingCost = productLDto.PackingCost;
+ PageDto.MaxOrderCount = productLDto.MaxOrderCount;
+ PageDto.Warranty = productLDto.Warranty;
productLDto.Specifications.ForEach(s => Specifications.Add(s));
productLDto.Files.ForEach(f => Files.Add(f));
SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
SelectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
+ PageDto.IsSpecialOffer = productLDto.IsSpecialOffer;
+ IsSpecialOffer = PageDto.IsSpecialOffer;
+ if (productLDto.SpecialOffer != null)
+ {
+ Discount = productLDto.SpecialOffer;
+ switch (Discount.AmountType)
+ {
+ case DiscountAmountType.Amount:
+ IsAmountType = true;
+ IsPercentType = false;
+ break;
+ case DiscountAmountType.Percent:
+ IsAmountType = false;
+ IsPercentType = true;
+ break;
+ }
+
+ ExpireDate = Discount.ExpireDate;
+ StartDate = Discount.StartDate;
+ }
}
catch (ApiException ex)
{
@@ -122,9 +149,24 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
if (SelectedBrand == null)
throw new Exception("لطفا یک برند انتخاب کنید");
var token = await _userUtility.GetBearerTokenAsync();
- var request = new UpdateProductCommand(Product.Id, PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
+ if (token == null)
+ throw new Exception("Token is null");
+ PageDto.Specifications = Specifications.ToList();
+ PageDto.Files = Files.ToList();
+ PageDto.Id = Product.Id;
+ PageDto.CategoryId = SelectedCategory?.Id ?? default;
+ PageDto.BrandId = SelectedBrand?.Id ?? default;
+ if (PageDto.IsSpecialOffer)
+ {
+ if (ExpireDate != null)
+ Discount.ExpireDate = ExpireDate.Value;
+ if (StartDate != null)
+ Discount.StartDate = StartDate.Value;
+ PageDto.SpecialOffer = Discount;
+ }
+ var request = PageDto.Adapt();
await _restWrapper.CrudApiRest(Address.ProductController).Update(request, token);
- _snackbar.Add($"ویرایش محصول {PersianName} با موفقیت انجام شد", Severity.Success);
+ _snackbar.Add($"ویرایش محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close();
}
catch (ApiException ex)
@@ -156,10 +198,22 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
if (SelectedBrand == null)
throw new Exception("لطفا یک برند انتخاب کنید");
var token = await _userUtility.GetBearerTokenAsync();
- var request = new CreateProductCommand(PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
+ if (token == null)
+ throw new Exception("Token is null");
+ PageDto.Specifications = Specifications.ToList();
+ PageDto.Files = Files.ToList();
+ if (PageDto.IsSpecialOffer)
+ {
+ if (ExpireDate != null)
+ Discount.ExpireDate = ExpireDate.Value;
+ if (StartDate != null)
+ Discount.StartDate = StartDate.Value;
+ PageDto.SpecialOffer = Discount;
+ }
+ var request = PageDto.Adapt();
await _restWrapper.CrudApiRest(Address.ProductController).Create(request, token);
- _snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
+ _snackbar.Add($"ساخت محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close();
}
catch (ApiException ex)
@@ -182,6 +236,25 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
}
}
+ public bool IsPercentType { get; set; } = true;
+ public bool IsAmountType { get; set; }
+ public DateTime? ExpireDate { get; set; }
+ public DateTime? StartDate { get; set; }
+ public DiscountSDto Discount { get; set; } = new DiscountSDto();
+ public void AmountTypeChanged(DiscountAmountType type)
+ {
+ switch (type)
+ {
+ case DiscountAmountType.Amount:
+ IsAmountType = true;
+ IsPercentType = false;
+ break;
+ case DiscountAmountType.Percent:
+ IsAmountType = false;
+ IsPercentType = true;
+ break;
+ }
+ }
private List _productCategories = new List();
public ProductCategorySDto? SelectedCategory;
diff --git a/NetinaShop.AdminPanel.PWA/Extensions/BoolExtension.cs b/NetinaShop.AdminPanel.PWA/Extensions/BoolExtension.cs
new file mode 100644
index 0000000..7b88cbe
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Extensions/BoolExtension.cs
@@ -0,0 +1,6 @@
+namespace NetinaShop.AdminPanel.PWA.Extensions;
+
+public static class BoolExtension
+{
+ public static bool Not( this bool value ) => !value;
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Extensions/PersianCultureInfo.cs b/NetinaShop.AdminPanel.PWA/Extensions/PersianCultureInfo.cs
new file mode 100644
index 0000000..b1f60b7
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Extensions/PersianCultureInfo.cs
@@ -0,0 +1,41 @@
+using System.Globalization;
+using System.Reflection;
+
+namespace NetinaShop.AdminPanel.PWA.Extensions;
+
+public static class PersianCultureInfo
+{
+ public static CultureInfo GetPersianCulture()
+ {
+ var culture = new CultureInfo("fa-IR");
+ DateTimeFormatInfo formatInfo = culture.DateTimeFormat;
+ formatInfo.AbbreviatedDayNames = new[] { "ی", "د", "س", "چ", "پ", "ج", "ش" };
+ formatInfo.DayNames = new[] { "یکشنبه", "دوشنبه", "سه شنبه", "چهار شنبه", "پنجشنبه", "جمعه", "شنبه" };
+ var monthNames = new[]
+ {
+ "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن",
+ "اسفند",
+ "",
+ };
+ formatInfo.AbbreviatedMonthNames =
+ formatInfo.MonthNames =
+ formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = monthNames;
+ formatInfo.AMDesignator = "ق.ظ";
+ formatInfo.PMDesignator = "ب.ظ";
+ formatInfo.ShortDatePattern = "yyyy/MM/dd";
+ formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy";
+ formatInfo.FirstDayOfWeek = DayOfWeek.Saturday;
+ System.Globalization.Calendar cal = new PersianCalendar();
+ FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (fieldInfo != null)
+ fieldInfo.SetValue(culture, cal);
+ FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (info != null)
+ info.SetValue(formatInfo, cal);
+ culture.NumberFormat.NumberDecimalSeparator = "/";
+ culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational;
+ culture.NumberFormat.NumberNegativePattern = 0;
+ return culture;
+ }
+
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Extensions/StringCipher.cs b/NetinaShop.AdminPanel.PWA/Extensions/StringCipher.cs
deleted file mode 100644
index 77ab922..0000000
--- a/NetinaShop.AdminPanel.PWA/Extensions/StringCipher.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Security.Cryptography;
-using System.Text;
-
-namespace NetinaShop.AdminPanel.PWA.Extensions;
-
-public class StringCipher
-{
- public string Encrypt(string data, RSAParameters key)
- {
-
- using (var rsa = new RSACryptoServiceProvider())
- {
- rsa.ImportParameters(key);
- var byteData = Encoding.UTF8.GetBytes(data);
- var encryptData = rsa.Encrypt(byteData, false);
- return Convert.ToBase64String(encryptData);
- }
- }
-
- public string Decrypt(string cipherText, RSAParameters key)
- {
-
- using (var rsa = new RSACryptoServiceProvider())
- {
- var cipherByteData = Convert.FromBase64String(cipherText);
- rsa.ImportParameters(key);
-
- var encryptData = rsa.Decrypt(cipherByteData, false);
- return Encoding.UTF8.GetString(encryptData);
- }
- }
-}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Layout/MainLayout.razor b/NetinaShop.AdminPanel.PWA/Layout/MainLayout.razor
index 260ffc3..f986bac 100644
--- a/NetinaShop.AdminPanel.PWA/Layout/MainLayout.razor
+++ b/NetinaShop.AdminPanel.PWA/Layout/MainLayout.razor
@@ -32,7 +32,7 @@
-
+
diff --git a/NetinaShop.AdminPanel.PWA/Models/Address.cs b/NetinaShop.AdminPanel.PWA/Models/Address.cs
index 5c8e29b..a63ff0e 100644
--- a/NetinaShop.AdminPanel.PWA/Models/Address.cs
+++ b/NetinaShop.AdminPanel.PWA/Models/Address.cs
@@ -3,8 +3,8 @@
public static class Address
{
#if DEBUG
- //public static string BaseAddress = "http://localhost:32770/api";
- public static string BaseAddress = "https://api.vesmook.com/api";
+ public static string BaseAddress = "http://localhost:32770/api";
+ //public static string BaseAddress = "https://api.vesmook.com/api";
#else
public static string BaseAddress = "https://api.vesmook.com/api";
#endif
@@ -16,4 +16,5 @@ public static class Address
public static string FileController => $"{BaseAddress}/file";
public static string BlogController => $"{BaseAddress}/blog";
public static string BlogCategoryController => $"{BaseAddress}/blog/category";
+ public static string DiscountController => $"{BaseAddress}/discount";
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor b/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor
new file mode 100644
index 0000000..3274c2a
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor
@@ -0,0 +1,84 @@
+@page "/discounts"
+@attribute [Microsoft.AspNetCore.Authorization.Authorize]
+
+@inject IDialogService DialogService
+@inject NavigationManager NavigationManager
+@inject ISnackbar Snackbar
+@inject IUserUtility UserUtility
+@inject IRestWrapper RestWrapper
+
+
+
+
+
+ تخفیفــــ ها
+ 124 عدد
+
+ افزودن تخفیفــ جدید
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code
+{
+ public DiscountPageViewModel ViewModel { get; set; }
+ protected override async Task OnInitializedAsync()
+ {
+ ViewModel = new DiscountPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
+ await ViewModel.InitializeAsync();
+ await base.OnInitializedAsync();
+ }
+}
diff --git a/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor.cs b/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor.cs
new file mode 100644
index 0000000..f2f0bad
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Pages/DiscountPage.razor.cs
@@ -0,0 +1,197 @@
+using NetinaShop.Domain.Entities.Discounts;
+
+namespace NetinaShop.AdminPanel.PWA.Pages;
+
+public class DiscountPageViewModel : BaseViewModel>
+{
+ private readonly NavigationManager _navigationManager;
+ private readonly ISnackbar _snackbar;
+ private readonly IUserUtility _userUtility;
+ private readonly IDialogService _dialogService;
+ private readonly IRestWrapper _restWrapper;
+
+ public string Search = string.Empty;
+ public int CurrentPage = 0;
+ public int PageCount = 1;
+
+ public DiscountPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
+ {
+ _navigationManager = navigationManager;
+ _snackbar = snackbar;
+ _userUtility = userUtility;
+ _restWrapper = restWrapper;
+ _dialogService = dialogService;
+ }
+
+ public override async Task InitializeAsync()
+ {
+ try
+ {
+ IsProcessing = true;
+ PageDto.Clear();
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ var dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, token);
+ dto.ForEach(d => PageDto.Add(d));
+ if (PageDto.Count == 15)
+ PageCount = 2;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ await base.InitializeAsync();
+ }
+
+ public async Task ChangePageAsync(int page)
+ {
+ CurrentPage = page - 1;
+ if (CurrentPage > PageCount - 2)
+ {
+
+ try
+ {
+ IsProcessing = true;
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ List dto = new List();
+ if (Search.IsNullOrEmpty())
+ {
+ dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, token);
+ }
+ else
+ {
+ dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, Search, token);
+ }
+
+ dto.ForEach(d => PageDto.Add(d));
+ if (PageDto.Count % 20 == 0)
+ PageCount = CurrentPage + 2;
+
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+ }
+
+ public async Task AddAsync()
+ {
+ DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
+ await _dialogService.ShowAsync("افزودن بلاگ جدید", maxWidth);
+ }
+
+ public async Task EditAsync(DiscountSDto discount)
+ {
+ DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
+ var parameters = new DialogParameters();
+ parameters.Add(x => x.Discount, discount);
+ await _dialogService.ShowAsync($"ویرایش تخفیف {discount.Code}", parameters, maxWidth);
+ }
+
+ public async Task DeleteAsync(Guid selectedDiscountId)
+ {
+ var options = new DialogOptions { CloseOnEscapeKey = true };
+ var parameters = new DialogParameters();
+ parameters.Add(x => x.ContentText, "آیا از حذف تخفیف اطمینان دارید ?");
+ var dialogReference = await _dialogService.ShowAsync("حذف بلاگ", parameters, options);
+ var result = await dialogReference.Result;
+ if (!result.Canceled)
+ {
+
+ try
+ {
+
+ IsProcessing = true;
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ await _restWrapper.CrudDtoApiRest(Address.BlogController)
+ .Delete(selectedDiscountId, token);
+ _snackbar.Add("حذف تخفیف با موفقیت انجام شد", Severity.Success);
+
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+ }
+
+ public async Task SearchChanged(string search)
+ {
+ if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
+ await InitializeAsync();
+ Search = search;
+ }
+ public async Task SearchAsync()
+ {
+ try
+ {
+ if (Search.IsNullOrEmpty())
+ throw new AppException("کد تخفیفــ برای جست جو وارد نشده است");
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+ IsProcessing = true;
+ CurrentPage = 0;
+ PageCount = 1;
+ PageDto.Clear();
+ var dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, Search, token);
+ dto.ForEach(d => PageDto.Add(d));
+ if (PageDto.Count == 20)
+ PageCount = 2;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor b/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
index 0a1a808..edc0cd0 100644
--- a/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
+++ b/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
@@ -29,16 +29,55 @@
SortMode="@SortMode.None" Groupable="false">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @e.Name
+
+
+
+
-
+
+
+
+ @if (@context.Item.IsSpecial)
+ {
+ بلی
+ }
+ else
+ {
+ خیر
+
+ }
+
+
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IDiscountRestApi.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IDiscountRestApi.cs
new file mode 100644
index 0000000..5750c38
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IDiscountRestApi.cs
@@ -0,0 +1,15 @@
+namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
+
+public interface IDiscountRestApi
+{
+
+ [Get("")]
+ Task> ReadAll([Header("Authorization")] string authorization);
+
+ [Get("/{id}")]
+ Task ReadOne(Guid id,[Header("Authorization")] string authorization);
+ [Get("")]
+ Task> ReadAll([Query] int page, [Header("Authorization")] string authorization);
+ [Get("")]
+ Task> ReadAll([Query] int page, [Query] string discountCode, [Header("Authorization")] string authorization);
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IProductRestApi.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IProductRestApi.cs
index 9e3ff8d..7f6356a 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/IProductRestApi.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IProductRestApi.cs
@@ -9,4 +9,6 @@ public interface IProductRestApi
Task> ReadAll([Query] int page);
[Get("")]
Task> ReadAll([Query] int page, [Query] string productName);
+ [Get("")]
+ Task> ReadAll([Query] string productName);
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
index ea6d982..bbc1fed 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
@@ -13,5 +13,6 @@ public interface IRestWrapper
public IBrandRestApi BrandRestApi { get; }
public IFileRestApi FileRestApi { get; }
public IBlogRestApi BlogRestApi { get; }
+ public IDiscountRestApi DiscountRest { get; }
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
index ddc5e5c..484ac61 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
@@ -25,5 +25,6 @@ public class RestWrapper : IRestWrapper
public IBrandRestApi BrandRestApi => RestService.For(Address.BrandController, setting);
public IFileRestApi FileRestApi => RestService.For(Address.FileController, setting);
public IBlogRestApi BlogRestApi => RestService.For(Address.BlogController, setting);
+ public IDiscountRestApi DiscountRest => RestService.For(Address.DiscountController, setting);
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For(Address.BlogCategoryController, setting);
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
index e557122..df9d793 100644
--- a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
+++ b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
@@ -1080,6 +1080,10 @@ input:checked + .toggle-bg {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
}
+.my-10 {
+ margin-top: 2.5rem;
+ margin-bottom: 2.5rem;
+}
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;
@@ -1097,6 +1101,12 @@ input:checked + .toggle-bg {
.-mr-2 {
margin-right: -0.5rem;
}
+.-mt-0 {
+ margin-top: -0px;
+}
+.-mt-0\.5 {
+ margin-top: -0.125rem;
+}
.-mt-1 {
margin-top: -0.25rem;
}
@@ -1124,6 +1134,12 @@ input:checked + .toggle-bg {
.mr-2 {
margin-right: 0.5rem;
}
+.mt-1 {
+ margin-top: 0.25rem;
+}
+.mt-1\.5 {
+ margin-top: 0.375rem;
+}
.mt-2 {
margin-top: 0.5rem;
}
@@ -1178,6 +1194,9 @@ input:checked + .toggle-bg {
.h-14 {
height: 3.5rem;
}
+.h-24 {
+ height: 6rem;
+}
.h-28 {
height: 7rem;
}
@@ -1239,6 +1258,9 @@ input:checked + .toggle-bg {
.w-14 {
width: 3.5rem;
}
+.w-24 {
+ width: 6rem;
+}
.w-28 {
width: 7rem;
}
@@ -1311,6 +1333,15 @@ input:checked + .toggle-bg {
.transform-none {
transform: none;
}
+@keyframes spin {
+
+ to {
+ transform: rotate(360deg);
+ }
+}
+.animate-spin {
+ animation: spin 1s linear infinite;
+}
.cursor-default {
cursor: default;
}
@@ -1367,6 +1398,9 @@ input:checked + .toggle-bg {
.overflow-hidden {
overflow: hidden;
}
+.overflow-y-scroll {
+ overflow-y: scroll;
+}
.rounded-full {
border-radius: 9999px;
}
@@ -1401,6 +1435,12 @@ input:checked + .toggle-bg {
.border-4 {
border-width: 4px;
}
+.border-b-8 {
+ border-bottom-width: 8px;
+}
+.border-t-8 {
+ border-top-width: 8px;
+}
.border-solid {
border-style: solid;
}
@@ -1420,10 +1460,18 @@ input:checked + .toggle-bg {
--tw-border-opacity: 1;
border-color: rgb(243 244 246 / var(--tw-border-opacity));
}
+.border-gray-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(229 231 235 / var(--tw-border-opacity));
+}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity));
}
+.border-indigo-500 {
+ --tw-border-opacity: 1;
+ border-color: rgb(104 117 245 / var(--tw-border-opacity));
+}
.bg-\[\#000000\] {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
@@ -1555,6 +1603,9 @@ input:checked + .toggle-bg {
.text-justify {
text-align: justify;
}
+.text-5xl {
+ font-size: 3rem;
+}
.text-\[1\.8rem\] {
font-size: 1.8rem;
}
@@ -1988,6 +2039,10 @@ code {
height: 38rem;
}
+ .lg\:max-h-\[35rem\] {
+ max-height: 35rem;
+ }
+
.lg\:w-96 {
width: 24rem;
}
diff --git a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
index 31081d5..757a37c 100644
--- a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
+++ b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
@@ -1160,6 +1160,11 @@ input:checked + .toggle-bg {
margin-bottom: 0.25rem;
}
+.my-10 {
+ margin-top: 2.5rem;
+ margin-bottom: 2.5rem;
+}
+
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;
@@ -1182,6 +1187,14 @@ input:checked + .toggle-bg {
margin-right: -0.5rem;
}
+.-mt-0 {
+ margin-top: -0px;
+}
+
+.-mt-0\.5 {
+ margin-top: -0.125rem;
+}
+
.-mt-1 {
margin-top: -0.25rem;
}
@@ -1218,6 +1231,14 @@ input:checked + .toggle-bg {
margin-right: 0.5rem;
}
+.mt-1 {
+ margin-top: 0.25rem;
+}
+
+.mt-1\.5 {
+ margin-top: 0.375rem;
+}
+
.mt-2 {
margin-top: 0.5rem;
}
@@ -1289,6 +1310,10 @@ input:checked + .toggle-bg {
height: 3.5rem;
}
+.h-24 {
+ height: 6rem;
+}
+
.h-28 {
height: 7rem;
}
@@ -1370,6 +1395,10 @@ input:checked + .toggle-bg {
width: 3.5rem;
}
+.w-24 {
+ width: 6rem;
+}
+
.w-28 {
width: 7rem;
}
@@ -1464,6 +1493,16 @@ input:checked + .toggle-bg {
transform: none;
}
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.animate-spin {
+ animation: spin 1s linear infinite;
+}
+
.cursor-default {
cursor: default;
}
@@ -1538,6 +1577,10 @@ input:checked + .toggle-bg {
overflow: hidden;
}
+.overflow-y-scroll {
+ overflow-y: scroll;
+}
+
.rounded-full {
border-radius: 9999px;
}
@@ -1582,6 +1625,14 @@ input:checked + .toggle-bg {
border-width: 4px;
}
+.border-b-8 {
+ border-bottom-width: 8px;
+}
+
+.border-t-8 {
+ border-top-width: 8px;
+}
+
.border-solid {
border-style: solid;
}
@@ -1606,11 +1657,21 @@ input:checked + .toggle-bg {
border-color: rgb(243 244 246 / var(--tw-border-opacity));
}
+.border-gray-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(229 231 235 / var(--tw-border-opacity));
+}
+
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity));
}
+.border-indigo-500 {
+ --tw-border-opacity: 1;
+ border-color: rgb(104 117 245 / var(--tw-border-opacity));
+}
+
.bg-\[\#000000\] {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
@@ -1779,6 +1840,10 @@ input:checked + .toggle-bg {
text-align: justify;
}
+.text-5xl {
+ font-size: 3rem;
+}
+
.text-\[1\.8rem\] {
font-size: 1.8rem;
}
@@ -2272,6 +2337,10 @@ code {
height: 38rem;
}
+ .lg\:max-h-\[35rem\] {
+ max-height: 35rem;
+ }
+
.lg\:w-96 {
width: 24rem;
}
diff --git a/NetinaShop.AdminPanel.PWA/wwwroot/index.html b/NetinaShop.AdminPanel.PWA/wwwroot/index.html
index c5aefa9..d466c13 100644
--- a/NetinaShop.AdminPanel.PWA/wwwroot/index.html
+++ b/NetinaShop.AdminPanel.PWA/wwwroot/index.html
@@ -9,6 +9,7 @@
+
@@ -26,12 +27,28 @@
-
+
+
+
+
+
پنـــــل ادمین فروشگاه
+
+
+ ... در حال لود کردن اپلیکیشن
+
+
-
-
+