diff --git a/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor b/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor index a9ed763..3d3c610 100644 --- a/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor +++ b/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor @@ -40,7 +40,7 @@ برگه ها - سوالات متداول + سوالات متداول diff --git a/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor b/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor index 679dc88..69a6e80 100644 --- a/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor +++ b/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor @@ -1,236 +1,180 @@ -@using Netina.AdminPanel.PWA.Models.Api -@using Netina.AdminPanel.PWA.Models -@using Netina.Domain.Entities.Brands - -@inject ISnackbar Snackbar +@inject ISnackbar Snackbar @inject IRestWrapper RestWrapper @inject IUserUtility UserUtility @inject IDialogService DialogService - - - + + + - اطلاعات کلی - اطلاعات کلی دسته بندی محصول را به دقت وارد کنید - - - - - - - - - - - - - - - - - - - - - - + + - تصاویر برند - می توانید برای برند چند تصویر اپلود کنید + اطلاعات کلی + اطلاعات کلی دسته بندی محصول را به دقت وارد کنید + + + + + + + + + + + + + + + + + + + + + + + تصاویر برند + می توانید برای برند چند تصویر اپلود کنید + + + + + @foreach (var item in ViewModel.PageDto.Files) + { +
+ + + + @if (item.IsHeader) + { +

هدر

+ } + @if (item.IsPrimary) + { +

اصلی

+ } +
+ } + +
+
+ + + + + +
- - - - @foreach (var item in Files) - { -
- + - - @if (item.IsHeader) - { -

هدر

- } - @if (item.IsPrimary) - { -

اصلی

- } -
- } + -
-
+ + - -
+ سوالات متداول + می توانید سوالات متداول شهر موردنظر را وارد کنید + + + + + + + + + + + + افزودن + + + + + @foreach (var item in ViewModel.Faqs) + { + + + + + + @item.Key + + + + @item.Value + + + } + + + + + + + + +
- @if (_isEditing) + @if (ViewModel.IsEditing) { - + Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" /> } else { - + Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" /> } - بستن + بستن
@code { - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] + MudDialogInstance MudDialog { get; set; } [Parameter] public BrandSDto? Brand { get; set; } - void Cancel() => MudDialog.Cancel(); - public readonly ObservableCollection Files = new ObservableCollection(); - private bool _isProcessing = false; - private string _persianName = string.Empty; - private string _englishName = string.Empty; - private string _description = string.Empty; - private bool _hasSpecialPage; - private bool _isEditing; - private string _pageUrl = string.Empty; - protected override async Task OnParametersSetAsync() + public BrandActionDialogBoxViewModel ViewModel { get; set; } + + protected override async Task OnInitializedAsync() { - if (Brand != null) - { - _isEditing = true; - try - { - _isProcessing = true; - var response = await RestWrapper.CrudDtoApiRest(Address.BrandController).ReadOne(Brand.Id); - var brandLDto = response; - brandLDto.Files.ForEach(f => Files.Add(f)); - - _hasSpecialPage = brandLDto.HasSpecialPage; - _description = brandLDto.Description; - _englishName = brandLDto.EnglishName; - _persianName = brandLDto.PersianName; - } - catch (ApiException ex) - { - var exe = await ex.GetContentAsAsync(); - Snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error); - MudDialog.Cancel(); - } - catch (Exception e) - { - Snackbar.Add(e.Message, Severity.Error); - MudDialog.Cancel(); - } - finally - { - - _isProcessing = false; - } - - } - await base.OnParametersSetAsync(); - } - - private async Task SubmitCreateAsync() - { - try - { - if (_englishName.IsNullOrEmpty()) - throw new AppException("لطفا نام برند را وارد کنید"); - _isProcessing = true; - var token = await UserUtility.GetBearerTokenAsync(); - if (token == null) - throw new AppException("Token is null"); - var request = new CreateBrandCommand(_persianName, _englishName, _description, _hasSpecialPage, _pageUrl, Files.ToList()); - await RestWrapper.CrudApiRest(Address.BrandController).Create(request, token); - MudDialog.Close(DialogResult.Ok(true)); - } - 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; - } - } - - - private async Task SubmitEditAsync() - { - try - { - if (Brand == null) - throw new AppException("برند به درستی ارسال نشده است"); - if (_englishName.IsNullOrEmpty()) - throw new AppException("لطفا نام برند را وارد کنید"); - _isProcessing = true; - var token = await UserUtility.GetBearerTokenAsync(); - if (token == null) - throw new AppException("Token is null"); - var request = new UpdateBrandCommand(Brand.Id, _persianName, _englishName, _description, _hasSpecialPage, _pageUrl, Files.ToList()); - await RestWrapper.CrudApiRest(Address.BrandController).Update(request, token); - MudDialog.Close(); - } - catch (ApiException ex) - { - var exe = await ex.GetContentAsAsync(); - Snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error); - MudDialog.Cancel(); - } - catch (Exception e) - { - Snackbar.Add(e.Message, Severity.Error); - MudDialog.Cancel(); - } - finally - { - - _isProcessing = false; - } - } - - - public async Task SelectFileAsync() - { - DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true }; - var dialog = await DialogService.ShowAsync("انتخاب عکس برند", maxWidth); - var result = await dialog.Result; - var file = result.Data; - if (file is StorageFileSDto storageFile) - Files.Add(storageFile); - } - - public void RemoveFile(StorageFileSDto file) - { - Files.Remove(file); + ViewModel = Brand == null ? new BrandActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog) : + new BrandActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Brand); + await ViewModel.InitializeAsync(); + await base.OnInitializedAsync(); } } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor.cs new file mode 100644 index 0000000..2534e84 --- /dev/null +++ b/Netina.AdminPanel.PWA/Dialogs/BrandActionDialogBox.razor.cs @@ -0,0 +1,209 @@ +using Netina.Domain.Entities.Brands; + +namespace Netina.AdminPanel.PWA.Dialogs; + +public class BrandActionDialogBoxViewModel : BaseViewModel +{ + private readonly ISnackbar _snackbar; + private readonly IRestWrapper _restWrapper; + private readonly IUserUtility _userUtility; + private readonly IDialogService _dialogService; + private readonly MudDialogInstance _mudDialog; + + public BrandActionDialogBoxViewModel(ISnackbar snackbar, + IRestWrapper restWrapper, + IUserUtility userUtility, + IDialogService dialogService, + MudDialogInstance mudDialog) : base(userUtility) + { + _snackbar = snackbar; + _restWrapper = restWrapper; + _userUtility = userUtility; + _dialogService = dialogService; + _mudDialog = mudDialog; + } + public BrandActionDialogBoxViewModel(ISnackbar snackbar, + IRestWrapper restWrapper, + IUserUtility userUtility, + IDialogService dialogService, + MudDialogInstance mudDialog, + BrandSDto brand) : base(userUtility) + { + _snackbar = snackbar; + _restWrapper = restWrapper; + _userUtility = userUtility; + _dialogService = dialogService; + _mudDialog = mudDialog; + Brand = brand; + } + + private BrandSDto? _brand = null; + public BrandSDto? Brand + { + get => _brand; + set + { + _brand = value; + if (_brand != null) + { + IsEditing = true; + } + } + } + + public void Cancel() => _mudDialog.Cancel(); + + public bool IsEditing = false; + + public override async Task InitializeAsync() + { + if (Brand != null) + { + IsEditing = true; + try + { + IsProcessing = true; + var response = await _restWrapper.CrudDtoApiRest(Address.BrandController).ReadOne(Brand.Id); + var brandLDto = response; + PageDto = brandLDto; + } + catch (ApiException ex) + { + var exe = await ex.GetContentAsAsync(); + _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error); + _mudDialog.Cancel(); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + _mudDialog.Cancel(); + } + finally + { + + IsProcessing = false; + } + + } + await base.InitializeAsync(); + } + + + public async Task SubmitCreateAsync() + { + try + { + if (PageDto.EnglishName.IsNullOrEmpty()) + throw new AppException("لطفا نام برند را وارد کنید"); + IsProcessing = true; + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + throw new AppException("Token is null"); + var request = new CreateBrandCommand(PageDto.PersianName, + PageDto.EnglishName, + PageDto.Description, + PageDto.HasSpecialPage, + PageDto.PageUrl, + PageDto.Files, + Faqs, + new Dictionary()); + await _restWrapper.CrudApiRest(Address.BrandController).Create(request, token); + _mudDialog.Close(DialogResult.Ok(true)); + } + 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 SubmitEditAsync() + { + try + { + if (Brand == null) + throw new AppException("برند به درستی ارسال نشده است"); + if (PageDto.EnglishName.IsNullOrEmpty()) + throw new AppException("لطفا نام برند را وارد کنید"); + IsProcessing = true; + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + throw new AppException("Token is null"); + var request = new UpdateBrandCommand( + PageDto.Id, + PageDto.PersianName, + PageDto.EnglishName, + PageDto.Description, + PageDto.HasSpecialPage, + PageDto.PageUrl, + PageDto.Files, + Faqs, + new Dictionary()); + + await _restWrapper.CrudApiRest(Address.BrandController).Update(request, token); + _mudDialog.Close(); + } + catch (ApiException ex) + { + var exe = await ex.GetContentAsAsync(); + _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error); + _mudDialog.Cancel(); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + _mudDialog.Cancel(); + } + finally + { + + IsProcessing = false; + } + } + + public string FaqQuestion { get; set; } = string.Empty; + public string FaqAnswer { get; set; } = string.Empty; + public Dictionary Faqs = new(); + public void AddFaq() + { + try + { + if (FaqAnswer.IsNullOrEmpty()) + throw new Exception("لطفا پاسخ را وارد کنید"); + + if (FaqQuestion.IsNullOrEmpty()) + throw new Exception("لطفا سوال را وارد کنید"); + + Faqs.Add(FaqQuestion, FaqAnswer); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + } + } + + + public async Task SelectFileAsync() + { + DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true }; + var dialog = await _dialogService.ShowAsync("انتخاب عکس برند", maxWidth); + var result = await dialog.Result; + var file = result.Data; + if (file is StorageFileSDto storageFile) + PageDto.Files.Add(storageFile); + } + + public void RemoveFile(StorageFileSDto file) + { + PageDto.Files.Remove(file); + } +} \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor b/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor new file mode 100644 index 0000000..96601c5 --- /dev/null +++ b/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor @@ -0,0 +1,117 @@ +@inject ISnackbar Snackbar +@inject IRestWrapper RestWrapper +@inject IUserUtility UserUtility +@inject IDialogService DialogService + + + + + + + اطلاعات کلی + اطلاعات کلی را به دقت وارد کنید + + + + + + + + + + سوالات متداول + می توانید سوالات متداول شهر موردنظر را وارد کنید + + + + + + + + + + + + افزودن + + + + + @foreach (var item in ViewModel.PageDto.Faqs) + { + + + + + + @item.Key + + + + @item.Value + + + } + + + + + + + + + + + @if (ViewModel.IsEditing) + { + + + } + else + { + + + } + + بستن + + + + +@code +{ + [CascadingParameter] + MudDialogInstance MudDialog { get; set; } + + void Cancel() => MudDialog.Cancel(); + [Parameter] + public BaseFaq? Faq { get; set; } + + public FaqActionDialogBoxViewModel ViewModel; + + protected override async Task OnInitializedAsync() + { + if (Faq != null) + ViewModel = new FaqActionDialogBoxViewModel(Faq,UserUtility, Snackbar, RestWrapper, MudDialog); + else + ViewModel = new FaqActionDialogBoxViewModel(UserUtility, Snackbar, RestWrapper, MudDialog); + + await ViewModel.InitializeAsync(); + await base.OnInitializedAsync(); + } +} \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor.cs new file mode 100644 index 0000000..fc9cb34 --- /dev/null +++ b/Netina.AdminPanel.PWA/Dialogs/FaqActionDialogBox.razor.cs @@ -0,0 +1,104 @@ +using Netina.Domain.MartenEntities.Faqs; + +namespace Netina.AdminPanel.PWA.Dialogs; + +public class FaqActionDialogBoxViewModel : BaseViewModel +{ + private readonly IRestWrapper _restWrapper; + private readonly ISnackbar _snackbar; + private readonly MudDialogInstance _dialogInstance; + public bool IsEditing = false; + + public FaqActionDialogBoxViewModel(IUserUtility userUtility, ISnackbar snackbar, IRestWrapper restWrapper, MudDialogInstance dialogInstance) : base(userUtility) + { + _snackbar = snackbar; + _restWrapper = restWrapper; + _dialogInstance = dialogInstance; + } + + public FaqActionDialogBoxViewModel(BaseFaq faq,IUserUtility userUtility, ISnackbar snackbar, IRestWrapper restWrapper, MudDialogInstance dialogInstance) : base(userUtility) + { + PageDto = faq; + IsEditing = true; + _snackbar = snackbar; + _restWrapper = restWrapper; + _dialogInstance = dialogInstance; + } + + public string Question { get; set; } = string.Empty; + public string Answer { get; set; } = string.Empty; + + public void AddFaq() + { + try + { + if (Question.IsNullOrEmpty()) + throw new Exception("سوال را وارد کنید"); + if (Answer.IsNullOrEmpty()) + throw new Exception("پاسخ را وارد کنید"); + PageDto.Faqs.Add(Question,Answer); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + } + } + public async Task SubmitAsync() + { + try + { + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + throw new Exception("token is null"); + if (PageDto.Slug.IsNullOrEmpty()) + throw new Exception("اسلاگ صفحه سوال متداول را وارد کنید"); + if (PageDto.Title.IsNullOrEmpty()) + throw new Exception("عنوان صفحه سوالات متداول را وارد کنید"); + + await _restWrapper.FaqApiRest.Create(PageDto, token); + _snackbar.Add("تغییر سوالات متداول با موفقیت انجام شد", Severity.Success); + _dialogInstance.Close(DialogResult.Ok(true)); + + } + 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); + } + } + public async Task SubmitUpdateAsync() + { + try + { + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + throw new Exception("token is null"); + if (PageDto.Slug.IsNullOrEmpty()) + throw new Exception("اسلاگ صفحه سوال متداول را وارد کنید"); + if (PageDto.Title.IsNullOrEmpty()) + throw new Exception("عنوان صفحه سوالات متداول را وارد کنید"); + if (PageDto.Id == default) + throw new Exception("ای دی معتبر نمی باشد"); + + await _restWrapper.FaqApiRest.Update(PageDto, token); + _snackbar.Add("تغییر سوالات متداول با موفقیت انجام شد", Severity.Success); + _dialogInstance.Close(DialogResult.Ok(true)); + + } + 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); + } + } +} diff --git a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor index a3f9105..daef7a9 100644 --- a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor +++ b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor @@ -106,6 +106,7 @@ +
@@ -157,6 +158,7 @@
+
@@ -174,6 +176,62 @@
+ + + + + + + سوالات متداول + می توانید سوالات متداول شهر موردنظر را وارد کنید + + + + + + + + + + + + افزودن + + + + + @foreach (var item in ViewModel.Faqs) + { + + + + + + @item.Key + + + + @item.Value + + + } + + + + + + + +
@@ -235,10 +293,10 @@ - diff --git a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs index a219b93..b5a0204 100644 --- a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs +++ b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs @@ -93,6 +93,14 @@ public class ProductActionDialogBoxViewModel : BaseViewModel SelectedBrand = new BrandSDto { Id = productLDto.BrandId, PersianName = productLDto.BrandName }; PageDto.IsSpecialOffer = productLDto.IsSpecialOffer; IsSpecialOffer = PageDto.IsSpecialOffer; + + if (!PageDto.Slug.IsNullOrEmpty()) + { + var faq = await _restWrapper.FaqApiRest.ReadOne(PageDto.GetWebSiteUrl()); + foreach (var pair in faq.Faqs) + Faqs.Add(pair.Key, pair.Value); + } + if (productLDto.SpecialOffer != null) { Discount = productLDto.SpecialOffer; @@ -161,7 +169,29 @@ public class ProductActionDialogBoxViewModel : BaseViewModel Discount.StartDate = StartDate.Value; PageDto.SpecialOffer = Discount; } - var request = PageDto.Adapt(); + + var request = new UpdateProductCommand(PageDto.Id, + PageDto.PersianName, + PageDto.EnglishName, + PageDto.Summery, + PageDto.ExpertCheck, + PageDto.Tags, + PageDto.Warranty, + PageDto.BeDisplayed, + PageDto.Cost, + PageDto.PackingCost, + PageDto.Stock, + PageDto.HasExpressDelivery, + PageDto.MaxOrderCount, + PageDto.IsSpecialOffer, + PageDto.BrandId, + PageDto.CategoryId, + PageDto.SpecialOffer ?? new DiscountSDto(), + PageDto.Specifications, + PageDto.Files, + Faqs, + new Dictionary()); + await _restWrapper.CrudApiRest(Address.ProductController).Update(request, token); _snackbar.Add($"ویرایش محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success); _mudDialog.Close(); @@ -205,7 +235,27 @@ public class ProductActionDialogBoxViewModel : BaseViewModel Discount.StartDate = StartDate.Value; PageDto.SpecialOffer = Discount; } - var request = PageDto.Adapt(); + var request = new CreateProductCommand( + PageDto.PersianName, + PageDto.EnglishName, + PageDto.Summery, + PageDto.ExpertCheck, + PageDto.Tags, + PageDto.Warranty, + PageDto.BeDisplayed, + PageDto.Cost, + PageDto.PackingCost, + PageDto.Stock, + PageDto.HasExpressDelivery, + PageDto.MaxOrderCount, + PageDto.IsSpecialOffer, + PageDto.BrandId, + PageDto.CategoryId, + PageDto.SpecialOffer ?? new DiscountSDto(), + PageDto.Specifications, + PageDto.Files, + Faqs, + new Dictionary()); await _restWrapper.CrudApiRest(Address.ProductController).Create(request, token); _snackbar.Add($"ساخت محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success); @@ -302,6 +352,28 @@ public class ProductActionDialogBoxViewModel : BaseViewModel } + public string FaqQuestion { get; set; } = string.Empty; + public string FaqAnswer { get; set; } = string.Empty; + public Dictionary Faqs = new(); + public void AddFaq() + { + try + { + if (FaqAnswer.IsNullOrEmpty()) + throw new Exception("لطفا پاسخ را وارد کنید"); + + if (FaqQuestion.IsNullOrEmpty()) + throw new Exception("لطفا سوال را وارد کنید"); + + Faqs.Add(FaqQuestion, FaqAnswer); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + } + } + + public void AddSpecification() { try @@ -320,7 +392,6 @@ public class ProductActionDialogBoxViewModel : BaseViewModel _snackbar.Add(e.Message, Severity.Error); } } - public void RemoveSpecification(SpecificationSDto specification) { var spec = Specifications.FirstOrDefault(s => s.Value == specification.Value && s.Title == specification.Title); @@ -337,7 +408,6 @@ public class ProductActionDialogBoxViewModel : BaseViewModel if (file is StorageFileSDto storageFile) Files.Add(storageFile); } - public void RemoveFile(StorageFileSDto file) { Files.Remove(file); diff --git a/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor b/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor index 216c27c..8a313d1 100644 --- a/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor +++ b/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor @@ -6,122 +6,180 @@ - - + + + - اطلاعات کلی - اطلاعات کلی دسته بندی محصول را به دقت وارد کنید - - - - - - - - - - - - - - - - - -
- -

منتظر بمانید

+ اطلاعات کلی + اطلاعات کلی دسته بندی محصول را به دقت وارد کنید + + + + + + + + + + + + + + + + + +
+ +

منتظر بمانید

+
+
+
+
+ +

@e.Name

+
+
+
+ + + + تصاویر برند + می توانید برای برند چند تصویر اپلود کنید + + + + + @foreach (var item in ViewModel.Files) + { +
+ + + + @if (item.IsHeader) + { +

هدر

+ } + @if (item.IsPrimary) + { +

اصلی

+ }
- - - - -

@e.Name

-
- -
- - - - تصاویر برند - می توانید برای برند چند تصویر اپلود کنید - - - - - @foreach (var item in ViewModel.Files) - { -
- - - - @if (item.IsHeader) - { -

هدر

} - @if (item.IsPrimary) - { -

اصلی

- } -
- } -
-
- - - + + + + + - توضیحات تکمیلی - می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید - -
- -
-
-
+ توضیحات تکمیلی + می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید +
+
+ +
+ + - - - + + + - + - @if (ViewModel.IsEditing) - { - - } - else - { - - } - - بستن - + + + + سوالات متداول + می توانید سوالات متداول شهر موردنظر را وارد کنید + + + + + + + + + + + + افزودن + + + + + @foreach (var item in ViewModel.Faqs) + { + + + + + + @item.Key + + + + @item.Value + + + } + + + + + + + + + + + + @if (ViewModel.IsEditing) + { + + } + else + { + + } + + بستن + + @code { diff --git a/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor.cs index 1a2a350..86d937b 100644 --- a/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor.cs +++ b/Netina.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor.cs @@ -94,7 +94,13 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel var token = await _userUtility.GetBearerTokenAsync(); if (token == null) throw new AppException("Token is null"); - var request = new CreateProductCategoryCommand(Name, Description, IsMain, SelectedCategory?.Id ?? default, Files.ToList()); + var request = new CreateProductCategoryCommand(Name, + Description, + IsMain, + SelectedCategory?.Id ?? default, + Files.ToList(), + Faqs, + new Dictionary()); await _restWrapper.CrudApiRest(Address.ProductCategoryController).Create(request, token); _mudDialog.Close(DialogResult.Ok(true)); } @@ -127,7 +133,14 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel IsProcessing = true; await Task.Delay(1000); var token = await _userUtility.GetBearerTokenAsync(); - var request = new UpdateProductCategoryCommand(Category.Id, Name, Description, IsMain, SelectedCategory?.Id ?? default, Files.ToList()); + var request = new UpdateProductCategoryCommand(Category.Id, + Name, + Description, + IsMain, + SelectedCategory?.Id ?? default, + Files.ToList(), + Faqs, + new Dictionary()); await _restWrapper.CrudApiRest(Address.ProductCategoryController).Update(request, token); _mudDialog.Close(DialogResult.Ok(true)); } @@ -177,6 +190,28 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel } + + public string FaqQuestion { get; set; } = string.Empty; + public string FaqAnswer { get; set; } = string.Empty; + public Dictionary Faqs = new(); + public void AddFaq() + { + try + { + if (FaqAnswer.IsNullOrEmpty()) + throw new Exception("لطفا پاسخ را وارد کنید"); + + if (FaqQuestion.IsNullOrEmpty()) + throw new Exception("لطفا سوال را وارد کنید"); + + Faqs.Add(FaqQuestion, FaqAnswer); + } + catch (Exception e) + { + _snackbar.Add(e.Message, Severity.Error); + } + } + public async Task SelectFileAsync() { DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true }; diff --git a/Netina.AdminPanel.PWA/Layout/MainLayout.razor b/Netina.AdminPanel.PWA/Layout/MainLayout.razor index dab3278..69a1412 100644 --- a/Netina.AdminPanel.PWA/Layout/MainLayout.razor +++ b/Netina.AdminPanel.PWA/Layout/MainLayout.razor @@ -64,44 +64,11 @@ @Body +
+ +
- - @* - - - - - - - - - - - - - @_user?.FullName - @_user?.PhoneNumber - - - - - - - - - - - - @Body - - -
- -
-
*@ diff --git a/Netina.AdminPanel.PWA/Models/Address.cs b/Netina.AdminPanel.PWA/Models/Address.cs index 70e8006..7ace4e2 100644 --- a/Netina.AdminPanel.PWA/Models/Address.cs +++ b/Netina.AdminPanel.PWA/Models/Address.cs @@ -23,4 +23,5 @@ public static class Address public static string DashboardController => $"/dashboard"; public static string SettingController => $"/setting"; public static string DistrictController => $"/district"; + public static string FaqController => $"/faq"; } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Models/BaseViewModel.cs b/Netina.AdminPanel.PWA/Models/BaseViewModel.cs index c7165dd..b50f1b5 100644 --- a/Netina.AdminPanel.PWA/Models/BaseViewModel.cs +++ b/Netina.AdminPanel.PWA/Models/BaseViewModel.cs @@ -19,7 +19,7 @@ public class BaseViewModel public bool IsProcessing { get; set; } = false; public TPageDto PageDto { get; set; } private string[] _permissions = new string[]{}; - private readonly IUserUtility _userUtility; + protected readonly IUserUtility _userUtility; public bool IsPermitted { get; set; } = false; public BaseViewModel(IUserUtility userUtility,params string[] permissions) { diff --git a/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj b/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj index 87d4b8c..9889480 100644 --- a/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj +++ b/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj @@ -96,6 +96,7 @@ + diff --git a/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor b/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor index 795ff9e..6eefcc0 100644 --- a/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor +++ b/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor @@ -1,4 +1,5 @@ -@page "/management/faqs" +@page "/setting/faq" + @attribute [Microsoft.AspNetCore.Authorization.Authorize] @inject IDialogService DialogService @@ -10,45 +11,54 @@ - - سوالات متداول فروشگاه من + + سوالات متداول - ذخیره سوالات + افزودن سوالات متداول جدید - - - - - - - - - افزودن - - - - @foreach (var item in ViewModel.PageDto.Faqs) - { - - - + + + + + + + - - @item.Key - - - - @item.Value - - - } - + Color="@Color.Info" + OnClick="async()=>await ViewModel.EditClicked(context.Item)" /> + + + + + + + + + + + + + @@ -59,8 +69,8 @@ public FaqManagementPageViewModel ViewModel { get; set; } protected override async Task OnInitializedAsync() { - ViewModel = new FaqManagementPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService); + ViewModel = new FaqManagementPageViewModel(DialogService, NavigationManager, RestWrapper, Snackbar, UserUtility); await ViewModel.InitializeAsync(); await base.OnInitializedAsync(); } -} \ No newline at end of file +} diff --git a/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor.cs b/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor.cs index 5b48448..3deac53 100644 --- a/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor.cs +++ b/Netina.AdminPanel.PWA/Pages/FaqManagementPage.razor.cs @@ -1,72 +1,25 @@ -namespace Netina.AdminPanel.PWA.Pages; +using Netina.Domain.MartenEntities.Faqs; -public class FaqManagementPageViewModel : BaseViewModel +namespace Netina.AdminPanel.PWA.Pages; + +public class FaqManagementPageViewModel( + IDialogService dialogService, + NavigationManager navigationManager, + IRestWrapper restWrapper, + ISnackbar snackbar, + IUserUtility userUtility) + : BaseViewModel> (userUtility) { - private readonly NavigationManager _navigationManager; - private readonly ISnackbar _snackbar; - private readonly IUserUtility _userUtility; - private readonly IDialogService _dialogService; - private readonly IRestWrapper _restWrapper; + public int CurrentPage = 0; + public int PageCount = 2; - public FaqManagementPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService) : base(userUtility) - { - _navigationManager = navigationManager; - _snackbar = snackbar; - _userUtility = userUtility; - _restWrapper = restWrapper; - _dialogService = dialogService; - } - - - public string Question { get; set; } = string.Empty; - public string Answer { get; set; } = string.Empty; - private PageActionRequestDto? _request; public override async Task InitializeAsync() { - try - { - var token = await _userUtility.GetBearerTokenAsync(); - if (token == null) - throw new Exception("Token is null"); - IsProcessing = true; - PageDto.Faqs.Clear(); - var typeName = typeof(FAQPage).FullName; - var dto = await _restWrapper.PageRestApi.ReadByType(typeName, token); - if (!dto.Data.IsNullOrEmpty()) - { - - PageDto = dto.GetData(); - _request = new PageActionRequestDto - { - Title = dto.Title, - Content = dto.Content, - Description = dto.Description, - Id = dto.Id, - IsCustomPage = dto.IsCustomPage, - IsHtmlBasePage = dto.IsHtmlBasePage, - Slug = dto.Slug, - Type = typeof(FAQPage).FullName - }; - } - } - 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 GetEntitiesAsync(); await base.InitializeAsync(); } - public async Task SaveAsync() + public async Task GetEntitiesAsync() { try { @@ -74,64 +27,97 @@ public class FaqManagementPageViewModel : BaseViewModel if (token == null) throw new Exception("Token is null"); IsProcessing = true; - var request = new PageActionRequestDto - { - Title = "سوالات متداول", - Content = string.Empty, - Description = string.Empty, - Data = PageDto, - IsCustomPage = true, - IsHtmlBasePage = false, - Slug = "faq", - Type = typeof(FAQPage).FullName - }; - if (_request != null) - { - request = _request; - } - request.Data = PageDto; - await _restWrapper.PageRestApi.CreatePage(request, token); + var faqs = await restWrapper.FaqApiRest.GetFaqs(CurrentPage, token); + PageDto.Clear(); + faqs.ForEach(f => PageDto.Add(f)); + 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); + if (ex.StatusCode == HttpStatusCode.Unauthorized) + { + await userUtility.LogoutAsync(); + navigationManager.NavigateTo("login", true, true); + } + + snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error); } catch (Exception e) { - _snackbar.Add(e.Message, Severity.Error); + snackbar.Add(e.Message, Severity.Error); } finally { - IsProcessing = false; } - } - public void AddNewQuestion() - { - try - { - if (Question.IsNullOrEmpty()) - throw new Exception("سوال را وارد کنید"); - if (Answer.IsNullOrEmpty()) - throw new Exception("پاسخ را وارد کنید"); - PageDto.Faqs.Add(Question,Answer); - } - catch (Exception e) - { - _snackbar.Add(e.Message, Severity.Error); - } } - public void RemoveQuestion(string question) + + public async Task ChangePageAsync(int page) { - try + CurrentPage = page - 1; + await GetEntitiesAsync(); + } + + public async Task AddClicked() + { + DialogOptions maxWidth = new DialogOptions() + { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true }; + var reference = await dialogService.ShowAsync("افزودن اژانس هواپیمایی جدید", maxWidth); + var result = await reference.Result; + if (result.Data is bool and true) + await InitializeAsync(); + } + + public async Task EditClicked(BaseFaq item) + { + DialogOptions maxWidth = new DialogOptions() + { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true }; + var parameters = new DialogParameters(); + parameters.Add(x => x.Faq, item); + var reference = await dialogService.ShowAsync($"ویرایش سوالات متداول {item.Title}", parameters, maxWidth); + var result = await reference.Result; + if (result.Data is bool and true) + await InitializeAsync(); + } + + public async Task DeleteAsync(Guid selectedId) + { + var reference = await dialogService.ShowQuestionDialog($"آیا از حذف سوالات متداول مورد نظر اطمینان دارید ?"); + var result = await reference.Result; + if (!result.Canceled) { - PageDto.Faqs.Remove(question); - } - catch (Exception e) - { - _snackbar.Add(e.Message, Severity.Error); + + try + { + + IsProcessing = true; + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + throw new Exception("Token is null"); + await restWrapper.FaqApiRest.Delete(selectedId, token); + await InitializeAsync(); + 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; + } } } + } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Services/RestServices/IFaqApiRest.cs b/Netina.AdminPanel.PWA/Services/RestServices/IFaqApiRest.cs new file mode 100644 index 0000000..afa8939 --- /dev/null +++ b/Netina.AdminPanel.PWA/Services/RestServices/IFaqApiRest.cs @@ -0,0 +1,21 @@ +using Netina.Domain.MartenEntities.Faqs; + +namespace Netina.AdminPanel.PWA.Services.RestServices; + +public interface IFaqApiRest +{ + [Delete("/{id}")] + Task Delete(Guid id, [Header("Authorization")] string token); + + [Post("")] + Task Create([Body] BaseFaq faq, [Header("Authorization")] string token); + + [Put("")] + Task Update([Body] BaseFaq faq, [Header("Authorization")] string token); + + [Get("")] + Task> GetFaqs([Query]int page,[Header("Authorization")] string token); + + [Get("/slug")] + Task ReadOne([Query]string slug); +} \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs b/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs index d5e447b..42a7636 100644 --- a/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs +++ b/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs @@ -23,4 +23,5 @@ public interface IRestWrapper public IDashboardApiRest DashboardApiRest { get; } public ISettingRestApi SettingRestApi { get; } public IDistrictApiRest DistrictApiRest { get; } + public IFaqApiRest FaqApiRest { get; } } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs b/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs index 47f5a6e..80b1813 100644 --- a/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs +++ b/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs @@ -1,12 +1,9 @@ namespace Netina.AdminPanel.PWA.Services.RestServices; -public class RestWrapper : IRestWrapper +public class RestWrapper(IConfiguration configuration) : IRestWrapper { - private string baseApiAddress; - public RestWrapper(IConfiguration configuration) - { - baseApiAddress = configuration.GetValue("ApiUrl") ?? string.Empty; - } + private string baseApiAddress = configuration.GetValue("ApiUrl") ?? string.Empty; + private static RefitSettings setting = new RefitSettings(new NewtonsoftJsonContentSerializer(new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, @@ -39,4 +36,5 @@ public class RestWrapper : IRestWrapper public ISettingRestApi SettingRestApi => RestService.For($"{baseApiAddress}{Address.SettingController}", setting); public IDashboardApiRest DashboardApiRest => RestService.For($"{baseApiAddress}{Address.DashboardController}", setting); public IDistrictApiRest DistrictApiRest => RestService.For($"{baseApiAddress}{Address.DistrictController}", setting); + public IFaqApiRest FaqApiRest => RestService.For($"{baseApiAddress}{Address.FaqController}", setting); } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/_Imports.razor b/Netina.AdminPanel.PWA/_Imports.razor index 261f4dc..c1453e8 100644 --- a/Netina.AdminPanel.PWA/_Imports.razor +++ b/Netina.AdminPanel.PWA/_Imports.razor @@ -19,4 +19,5 @@ @using Netina.Domain.Entities.Users @using Netina.AdminPanel.PWA.Components.Originals @using Netina.Domain.Models.Claims -@using MudBlazor.Services \ No newline at end of file +@using MudBlazor.Services +@using Netina.Domain.MartenEntities.Faqs \ No newline at end of file