diff --git a/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor b/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor
index e51a3a8..50a0eda 100644
--- a/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor
+++ b/Netina.AdminPanel.PWA/Components/Originals/SideBarUi.razor
@@ -28,6 +28,12 @@
}
+
+ مدیریت نظراتـــ
+
+
diff --git a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
index b5a0204..e01d2d4 100644
--- a/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
+++ b/Netina.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
@@ -97,8 +97,11 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
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 (faq.Faqs != null)
+ {
+ foreach (var pair in faq.Faqs)
+ Faqs.Add(pair.Key, pair.Value);
+ }
}
if (productLDto.SpecialOffer != null)
diff --git a/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor b/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor
new file mode 100644
index 0000000..128edc8
--- /dev/null
+++ b/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor
@@ -0,0 +1,79 @@
+@inject ISnackbar Snackbar
+@inject IRestWrapper RestWrapper
+@inject IUserUtility UserUtility
+@inject IDialogService DialogService
+
+
+
+
+
+
+
+ @ViewModel.PageDto.Title
+
+
+ @ViewModel.PageDto.UserFullName
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ثبت
+
+
+
+
+
+
+
+
+
+
+
+
+
+ بستن
+
+
+
+
+
+@code {
+
+ [CascadingParameter]
+ MudDialogInstance MudDialog { get; set; }
+
+ [Parameter]
+ public CommentSDto? Review { get; set; }
+
+ public ReviewActionDialogBoxViewModel ViewModel { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ if (Review == null)
+ ViewModel = new ReviewActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
+ else
+ ViewModel = new ReviewActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Review);
+ await ViewModel.InitializeAsync();
+ await base.OnInitializedAsync();
+ }
+}
diff --git a/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor.cs b/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor.cs
new file mode 100644
index 0000000..784d44d
--- /dev/null
+++ b/Netina.AdminPanel.PWA/Dialogs/ReviewActionDialogBox.razor.cs
@@ -0,0 +1,87 @@
+using MudBlazor;
+using Netina.AdminPanel.PWA.Services.RestServices;
+
+namespace Netina.AdminPanel.PWA.Dialogs;
+
+public class ReviewActionDialogBoxViewModel : BaseViewModel
+{
+
+ private readonly ISnackbar _snackbar;
+ private readonly IRestWrapper _restWrapper;
+ private readonly IDialogService _dialogService;
+ private readonly MudDialogInstance _mudDialog;
+
+ public ReviewActionDialogBoxViewModel(ISnackbar snackbar,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
+ MudDialogInstance mudDialog) : base(userUtility)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ }
+ public ReviewActionDialogBoxViewModel(ISnackbar snackbar,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
+ MudDialogInstance mudDialog,
+ CommentSDto review) : base(userUtility)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ Review = review;
+ PageDto = Review;
+ }
+
+ private CommentSDto? _review = null;
+ public CommentSDto? Review
+ {
+ get => _review;
+ set
+ {
+ _review = value;
+ if (_review != null)
+ {
+ IsEditing = true;
+ }
+ }
+ }
+
+ public void Cancel() => _mudDialog.Cancel();
+
+ public bool IsEditing = false;
+ public string AnswerContent { get; set; } = string.Empty;
+ public async Task SubmitAnswer()
+ {
+
+ try
+ {
+ IsProcessing = true;
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+
+ await _restWrapper.ReviewRestApi.CreateAsync(new CreateCommentCommand($"پاسخ به نظر - {PageDto.Title}", AnswerContent,6,false,true,PageDto.Id,null,null,null), token);
+
+ }
+ 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/Models/Address.cs b/Netina.AdminPanel.PWA/Models/Address.cs
index 7ace4e2..b62c0fc 100644
--- a/Netina.AdminPanel.PWA/Models/Address.cs
+++ b/Netina.AdminPanel.PWA/Models/Address.cs
@@ -24,4 +24,5 @@ public static class Address
public static string SettingController => $"/setting";
public static string DistrictController => $"/district";
public static string FaqController => $"/faq";
+ public static string CommentController => $"/comment";
}
\ No newline at end of file
diff --git a/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj b/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj
index f993cdd..d958cf1 100644
--- a/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj
+++ b/Netina.AdminPanel.PWA/Netina.AdminPanel.PWA.csproj
@@ -5,8 +5,8 @@
enable
enable
service-worker-assets.js
- 1.3.12.16
- 1.3.12.16
+ 1.4.14.19
+ 1.4.14.19
$(MSBuildProjectName)
diff --git a/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor b/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor
new file mode 100644
index 0000000..ec3df9c
--- /dev/null
+++ b/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor
@@ -0,0 +1,67 @@
+@page "/reviews"
+@attribute [Microsoft.AspNetCore.Authorization.Authorize]
+
+@inject IDialogService DialogService
+@inject NavigationManager NavigationManager
+@inject ISnackbar Snackbar
+@inject IUserUtility UserUtility
+@inject IRestWrapper RestWrapper
+
+
+
+
+
+ نظراتـــــــ
+
+
+
+
+
+
+
+
+
+
+
+
+ تایید کردن
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code
+{
+ public ReviewsPageViewModel ViewModel { get; set; }
+ protected override async Task OnInitializedAsync()
+ {
+ ViewModel = new ReviewsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
+ await ViewModel.InitializeAsync();
+ await base.OnInitializedAsync();
+ }
+}
\ No newline at end of file
diff --git a/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor.cs b/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor.cs
new file mode 100644
index 0000000..17116e9
--- /dev/null
+++ b/Netina.AdminPanel.PWA/Pages/ReviewsPage.razor.cs
@@ -0,0 +1,125 @@
+namespace Netina.AdminPanel.PWA.Pages;
+
+
+public class ReviewsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
+ : BaseViewModel>(userUtility)
+{
+
+ public int CurrentPage = 0;
+ public int PageCount = 1;
+
+ 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.ReviewRestApi.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 ConfirmAsync(CommentSDto review)
+ {
+
+ try
+ {
+ IsProcessing = true;
+
+ var token = await _userUtility.GetBearerTokenAsync();
+ if (token == null)
+ throw new Exception("Token is null");
+
+ await restWrapper.ReviewRestApi.ConfirmAsync(review.Id, token);
+ review.IsConfirmed = 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 ShowAsync(CommentSDto review)
+ {
+
+ DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
+ var parameters = new DialogParameters();
+ parameters.Add(x => x.Review, review);
+ var dialogResult = await dialogService.ShowAsync($"", parameters, maxWidth);
+ var result = await dialogResult.Result;
+ if (!result.Canceled && result.Data is bool and true)
+ {
+ await 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();
+
+ dto = await restWrapper.ReviewRestApi.ReadAll(CurrentPage, 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;
+ }
+ }
+ }
+}
\ 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 42a7636..e5023e8 100644
--- a/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
+++ b/Netina.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
@@ -14,6 +14,7 @@ public interface IRestWrapper
public IFileRestApi FileRestApi { get; }
public IBlogRestApi BlogRestApi { get; }
public IDiscountRestApi DiscountRest { get; }
+ public IReviewRestApi ReviewRestApi { get; }
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
public IRoleRestApi RoleRestApi { get; }
public IOrderRestApi OrderRestApi { get; }
diff --git a/Netina.AdminPanel.PWA/Services/RestServices/IReviewRestApi.cs b/Netina.AdminPanel.PWA/Services/RestServices/IReviewRestApi.cs
new file mode 100644
index 0000000..fdea319
--- /dev/null
+++ b/Netina.AdminPanel.PWA/Services/RestServices/IReviewRestApi.cs
@@ -0,0 +1,17 @@
+namespace Netina.AdminPanel.PWA.Services.RestServices;
+
+public interface IReviewRestApi
+{
+ [Get("/{id}")]
+ Task ReadOne(Guid id, [Header("Authorization")] string authorization);
+
+ [Get("")]
+ Task> ReadAll([Query] int page, [Header("Authorization")] string authorization);
+
+ [Post("")]
+ Task CreateAsync([Body]CreateCommentCommand request, [Header("Authorization")] string authorization);
+
+
+ [Put("/confirm/{id}")]
+ Task ConfirmAsync(Guid id, [Header("Authorization")] string authorization);
+}
\ 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 80b1813..ce783be 100644
--- a/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
+++ b/Netina.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
@@ -27,6 +27,7 @@ public class RestWrapper(IConfiguration configuration) : IRestWrapper
public IFileRestApi FileRestApi => RestService.For($"{baseApiAddress}{Address.FileController}", setting);
public IBlogRestApi BlogRestApi => RestService.For($"{baseApiAddress}{Address.BlogController}", setting);
public IDiscountRestApi DiscountRest => RestService.For($"{baseApiAddress}{Address.DiscountController}",setting);
+ public IReviewRestApi ReviewRestApi => RestService.For($"{baseApiAddress}{Address.CommentController}", setting);
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For($"{baseApiAddress}{Address.BlogCategoryController}", setting);
public IRoleRestApi RoleRestApi => RestService.For($"{baseApiAddress}{Address.RoleController}", setting);
public IOrderRestApi OrderRestApi => RestService.For($"{baseApiAddress}{Address.OrderController}", setting);
diff --git a/Netina.AdminPanel.PWA/wwwroot/css/app.min.css b/Netina.AdminPanel.PWA/wwwroot/css/app.min.css
index ca6cd92..f5b76b7 100644
--- a/Netina.AdminPanel.PWA/wwwroot/css/app.min.css
+++ b/Netina.AdminPanel.PWA/wwwroot/css/app.min.css
@@ -1178,6 +1178,9 @@ input:checked + .toggle-bg {
.mb-8 {
margin-bottom: 2rem;
}
+.ml-1 {
+ margin-left: 0.25rem;
+}
.ml-16 {
margin-left: 4rem;
}