change to comment
parent
0fea79efe6
commit
4b13db02aa
|
@ -28,6 +28,12 @@
|
|||
</MudNavGroup>
|
||||
}
|
||||
|
||||
<MudNavGroup Title="نظرات و امتیازاتـــ" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Comment">
|
||||
<MudNavLink Href="reviews"
|
||||
Icon="@Icons.Material.Filled.Comment">مدیریت نظراتـــ</MudNavLink>
|
||||
</MudNavGroup>
|
||||
|
||||
<MudNavGroup Title="وبلاگــــ" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Web">
|
||||
|
||||
|
|
|
@ -97,8 +97,11 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
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)
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack>
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudGrid>
|
||||
<MudItem sm="8">
|
||||
<MudField Label="عنوان" Variant="Variant.Outlined">@ViewModel.PageDto.Title</MudField>
|
||||
</MudItem>
|
||||
<MudItem sm="4">
|
||||
<MudField Label="نام نام خانوادگی" Variant="Variant.Outlined">@ViewModel.PageDto.UserFullName</MudField>
|
||||
</MudItem>
|
||||
<MudItem sm="12">
|
||||
<MudTextField @bind-Value="@ViewModel.PageDto.Content" Lines="4" T="string" Label="متن نظر" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
<MudPaper>
|
||||
|
||||
</MudPaper>
|
||||
<MudDivider class="my-1" />
|
||||
<MudGrid>
|
||||
<MudItem sm="11">
|
||||
<MudTextField @bind-Value="ViewModel.AnswerContent" Lines="4" T="string" Label="پاسخ دادن به نظر" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="1">
|
||||
<MudButton class="mt-2 py-7 mr-1"
|
||||
FullWidth="true"
|
||||
Variant="Variant.Outlined"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info" OnClick="@(async()=>await ViewModel.SubmitAnswer())">ثبت</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید کردن نظر" />
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.CommentsDisabled"
|
||||
Variant="Variant.Outlined" Color="Color.Warning"
|
||||
Content="حذف کردن" />
|
||||
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="@(ViewModel.Cancel)">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
using MudBlazor;
|
||||
using Netina.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class ReviewActionDialogBoxViewModel : BaseViewModel<CommentSDto>
|
||||
{
|
||||
|
||||
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<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -5,8 +5,8 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
<AssemblyVersion>1.3.12.16</AssemblyVersion>
|
||||
<FileVersion>1.3.12.16</FileVersion>
|
||||
<AssemblyVersion>1.4.14.19</AssemblyVersion>
|
||||
<FileVersion>1.4.14.19</FileVersion>
|
||||
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
<MudStack class="h-full w-full p-8">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudStack Row="true" class="mb-5">
|
||||
<MudText Typo="Typo.h4">نظراتـــــــ</MudText>
|
||||
<MudSpacer />
|
||||
</MudStack>
|
||||
<MudPaper>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="CommentSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn Title="عنوان" Property="arg => arg.Title" />
|
||||
<PropertyColumn Title="نظر" Property="arg => arg.Content" />
|
||||
|
||||
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Color="Color.Primary"
|
||||
OnClick="@(async()=>await ViewModel.ConfirmAsync(context.Item))">تایید کردن</MudButton>
|
||||
|
||||
<MudIconButton Icon="@Icons.Material.Filled.RemoveRedEye"
|
||||
Size="@Size.Small"
|
||||
class="px-2"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Info"
|
||||
OnClick="@(async()=>await ViewModel.ShowAsync(context.Item))" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||
SelectedChanged="@ViewModel.ChangePageAsync" class="mx-auto my-4" />
|
||||
</MudStack>
|
||||
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
|
||||
|
||||
public class ReviewsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||
: BaseViewModel<ObservableCollection<CommentSDto>>(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<ApiResult>();
|
||||
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<ApiResult>();
|
||||
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<ReviewActionDialogBox>();
|
||||
parameters.Add(x => x.Review, review);
|
||||
var dialogResult = await dialogService.ShowAsync<ReviewActionDialogBox>($"", 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<CommentSDto> dto = new List<CommentSDto>();
|
||||
|
||||
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<ApiResult>();
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
namespace Netina.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IReviewRestApi
|
||||
{
|
||||
[Get("/{id}")]
|
||||
Task<CommentSDto> ReadOne(Guid id, [Header("Authorization")] string authorization);
|
||||
|
||||
[Get("")]
|
||||
Task<List<CommentSDto>> ReadAll([Query] int page, [Header("Authorization")] string authorization);
|
||||
|
||||
[Post("")]
|
||||
Task<Guid> CreateAsync([Body]CreateCommentCommand request, [Header("Authorization")] string authorization);
|
||||
|
||||
|
||||
[Put("/confirm/{id}")]
|
||||
Task<Guid> ConfirmAsync(Guid id, [Header("Authorization")] string authorization);
|
||||
}
|
|
@ -27,6 +27,7 @@ public class RestWrapper(IConfiguration configuration) : IRestWrapper
|
|||
public IFileRestApi FileRestApi => RestService.For<IFileRestApi>($"{baseApiAddress}{Address.FileController}", setting);
|
||||
public IBlogRestApi BlogRestApi => RestService.For<IBlogRestApi>($"{baseApiAddress}{Address.BlogController}", setting);
|
||||
public IDiscountRestApi DiscountRest => RestService.For<IDiscountRestApi>($"{baseApiAddress}{Address.DiscountController}",setting);
|
||||
public IReviewRestApi ReviewRestApi => RestService.For<IReviewRestApi>($"{baseApiAddress}{Address.CommentController}", setting);
|
||||
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For<IBlogCategoryRestApi>($"{baseApiAddress}{Address.BlogCategoryController}", setting);
|
||||
public IRoleRestApi RoleRestApi => RestService.For<IRoleRestApi>($"{baseApiAddress}{Address.RoleController}", setting);
|
||||
public IOrderRestApi OrderRestApi => RestService.For<IOrderRestApi>($"{baseApiAddress}{Address.OrderController}", setting);
|
||||
|
|
|
@ -1178,6 +1178,9 @@ input:checked + .toggle-bg {
|
|||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.ml-1 {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
.ml-16 {
|
||||
margin-left: 4rem;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue