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 @@ -
+ + +
+
+

پنـــــل ادمین فروشگاه

+
+
+
+
+
+
+
+
+ ... در حال لود کردن اپلیکیشن +
+
@@ -40,8 +57,8 @@ 🗙
- - +