feat(FaqInActions) , feat(FaqManagementPage) , feat(FaqController)
parent
77a6cf80a2
commit
8b4c9934b3
|
@ -40,7 +40,7 @@
|
|||
<MudNavGroup Title="مدیریت برگه ها" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Pages">
|
||||
<MudNavLink Href="management/pages" Icon="@Icons.Material.Filled.Pageview">برگه ها</MudNavLink>
|
||||
<MudNavLink Href="management/faqs" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
|
||||
<MudNavLink Href="setting/faq" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
|
||||
</MudNavGroup>
|
||||
|
||||
<MudNavGroup Title="شخصی سازی" Expanded="false" Icon="@Icons.Material.Filled.SettingsSystemDaydream">
|
||||
|
|
|
@ -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
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack>
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudContainer class="h-full p-0">
|
||||
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام فارسی برند" @bind-Value="@_persianName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام انگلیسی برند" @bind-Value="@_englishName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@_hasSpecialPage" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true"></MudSelectItem>
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="لینک صفحه شخصی برند" @bind-Value="@_pageUrl" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="12" md="12">
|
||||
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-1 mb-4" Spacing="0">
|
||||
<MudStack>
|
||||
<MudStack Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام فارسی برند" @bind-Value="@ViewModel.PageDto.PersianName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام انگلیسی برند" @bind-Value="@ViewModel.PageDto.EnglishName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@ViewModel.PageDto.HasSpecialPage" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true"></MudSelectItem>
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="لینک صفحه شخصی برند" @bind-Value="@ViewModel.PageDto.PageUrl" Variant="Variant.Outlined"></MudTextField>
|
||||
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-1 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()" />
|
||||
|
||||
@foreach (var item in ViewModel.PageDto.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.PageDto.Files.Remove(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="12" md="12">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.PageDto.Description" ></RichTextEditorUi>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
</MudTabPanel>
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="() => ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
@if (_isEditing)
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@code {
|
||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; }
|
||||
[Parameter]
|
||||
public BrandSDto? Brand { get; set; }
|
||||
|
||||
void Cancel() => MudDialog.Cancel();
|
||||
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||
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<Brand, BrandLDto, Guid>(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<ApiResult>();
|
||||
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<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||
MudDialog.Close(DialogResult.Ok(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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<Brand, Guid>(Address.BrandController).Update<UpdateBrandCommand>(request, token);
|
||||
MudDialog.Close();
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
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<StorageDialogBox>("انتخاب عکس برند", 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
using Netina.Domain.Entities.Brands;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class BrandActionDialogBoxViewModel : BaseViewModel<BrandLDto>
|
||||
{
|
||||
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<Brand, BrandLDto, Guid>(Address.BrandController).ReadOne(Brand.Id);
|
||||
var brandLDto = response;
|
||||
PageDto = brandLDto;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_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<string, string>());
|
||||
await _restWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||
_mudDialog.Close(DialogResult.Ok(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 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<string, string>());
|
||||
|
||||
await _restWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Update<UpdateBrandCommand>(request, token);
|
||||
_mudDialog.Close();
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_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<string, string> 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<StorageDialogBox>("انتخاب عکس برند", 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack>
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="6" md="6">
|
||||
<MudTextField T="string" Label="عنوان صفحه سوالات متداول" @bind-Value="@ViewModel.PageDto.Title" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="6" md="6">
|
||||
<MudTextField T="string" Label="اسلاگ صفحه سوالات متداول" @bind-Value="@ViewModel.PageDto.Slug" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.Question" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.Answer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.PageDto.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.PageDto.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="mx-4 mb-2 w-full">
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Info"
|
||||
Content="ثبت ویرایش" OnClickCallback="@ViewModel.SubmitUpdateAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="@ViewModel.SubmitAsync" />
|
||||
}
|
||||
<MudSpacer/>
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
using Netina.Domain.MartenEntities.Faqs;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class FaqActionDialogBoxViewModel : BaseViewModel<BaseFaq>
|
||||
{
|
||||
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<ApiResult>();
|
||||
_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<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,6 +106,7 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="ویژگی های کلی" Icon="@Icons.Material.Outlined.AutoGraph">
|
||||
<div class="min-h-[33rem]">
|
||||
|
||||
|
@ -157,6 +158,7 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="توضیحات تکمیلی" Icon="@Icons.Material.Outlined.Article">
|
||||
|
||||
<div class="min-h-[33rem]">
|
||||
|
@ -174,6 +176,62 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||
|
||||
<div class="min-h-[33rem]">
|
||||
|
@ -235,10 +293,10 @@
|
|||
|
||||
<MudItem xs="12" md="4">
|
||||
|
||||
<MudSelect Disabled="@ViewModel.IsSpecialOffer.Not()" T="DiscountAmountType"
|
||||
<MudSelect Disabled="@ViewModel.IsSpecialOffer.Not()" T="DiscountAmountType"
|
||||
ValueChanged="@ViewModel.AmountTypeChanged"
|
||||
Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()"
|
||||
Variant="Variant.Outlined"
|
||||
Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()"
|
||||
Variant="Variant.Outlined"
|
||||
Value="@ViewModel.Discount.AmountType"
|
||||
AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Percent" />
|
||||
|
|
|
@ -93,6 +93,14 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
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<ProductLDto>
|
|||
Discount.StartDate = StartDate.Value;
|
||||
PageDto.SpecialOffer = Discount;
|
||||
}
|
||||
var request = PageDto.Adapt<UpdateProductCommand>();
|
||||
|
||||
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<string, string>());
|
||||
|
||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
|
||||
_snackbar.Add($"ویرایش محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||
_mudDialog.Close();
|
||||
|
@ -205,7 +235,27 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
Discount.StartDate = StartDate.Value;
|
||||
PageDto.SpecialOffer = Discount;
|
||||
}
|
||||
var request = PageDto.Adapt<CreateProductCommand>();
|
||||
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<string, string>());
|
||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
||||
|
||||
_snackbar.Add($"ساخت محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||
|
@ -302,6 +352,28 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
}
|
||||
|
||||
|
||||
public string FaqQuestion { get; set; } = string.Empty;
|
||||
public string FaqAnswer { get; set; } = string.Empty;
|
||||
public Dictionary<string, string> 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<ProductLDto>
|
|||
_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<ProductLDto>
|
|||
if (file is StorageFileSDto storageFile)
|
||||
Files.Add(storageFile);
|
||||
}
|
||||
|
||||
public void RemoveFile(StorageFileSDto file)
|
||||
{
|
||||
Files.Remove(file);
|
||||
|
|
|
@ -6,122 +6,180 @@
|
|||
<MudDialog class="mx-auto" DisableSidePadding="true">
|
||||
<DialogContent>
|
||||
<MudContainer class="h-full">
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||
<MudStack Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack class="mx-5 overflow-x-hidden overflow-y-hidden">
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.Name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudSelect T="bool" @bind-Value="@ViewModel.IsMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true" />
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||
SearchFunc="ViewModel.SearchCategory"
|
||||
T="ProductCategorySDto"
|
||||
Label="دسته پدر"
|
||||
Variant="Variant.Outlined">
|
||||
<ProgressIndicatorInPopoverTemplate>
|
||||
<MudList Clickable="false">
|
||||
<MudListItem>
|
||||
<div class="flex flex-row w-full mx-auto">
|
||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack class="overflow-x-hidden overflow-y-hidden">
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.Name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudSelect T="bool" @bind-Value="@ViewModel.IsMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true" />
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||
SearchFunc="ViewModel.SearchCategory"
|
||||
T="ProductCategorySDto"
|
||||
Label="دسته پدر"
|
||||
Variant="Variant.Outlined">
|
||||
<ProgressIndicatorInPopoverTemplate>
|
||||
<MudList Clickable="false">
|
||||
<MudListItem>
|
||||
<div class="flex flex-row w-full mx-auto">
|
||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||
</div>
|
||||
</MudListItem>
|
||||
</MudList>
|
||||
</ProgressIndicatorInPopoverTemplate>
|
||||
<ItemTemplate Context="e">
|
||||
<p>@e.Name</p>
|
||||
</ItemTemplate>
|
||||
</MudAutocomplete>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-2 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in ViewModel.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
</MudListItem>
|
||||
</MudList>
|
||||
</ProgressIndicatorInPopoverTemplate>
|
||||
<ItemTemplate Context="e">
|
||||
<p>@e.Name</p>
|
||||
</ItemTemplate>
|
||||
</MudAutocomplete>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-2 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in ViewModel.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudContainer class="overflow-y-hidden overflow-x-hidden">
|
||||
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudContainer class="overflow-y-hidden overflow-x-hidden">
|
||||
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<div class="!text-black">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.Description" />
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudItem>
|
||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<div class="!text-black">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.Description" />
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="() => ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@code
|
||||
{
|
||||
|
|
|
@ -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<string, string>());
|
||||
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(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<string, string>());
|
||||
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(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<string, string> 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 };
|
||||
|
|
|
@ -64,44 +64,11 @@
|
|||
<MudMainContent class="bg-[--mud-palette-background-grey] h-screen overflow-y-auto">
|
||||
@Body
|
||||
</MudMainContent>
|
||||
<div dir="ltr">
|
||||
<PWAUpdater Text="@_updateText" ButtonCaption="اپدیت کنید" />
|
||||
</div>
|
||||
</MudLayout>
|
||||
</MudRTLProvider>
|
||||
|
||||
@* <MudRTLProvider RightToLeft="true">
|
||||
<MudThemeProvider IsDarkMode="@MainTheme.IsDarkMode" Theme="@MainTheme.MyCustomTheme"/>
|
||||
<MudDialogProvider/>
|
||||
<MudSnackbarProvider/>
|
||||
<MudLayout>
|
||||
<MudAppBar class="py-2" Color="Color.Transparent" Fixed="false" Elevation="2">
|
||||
<MudHidden Breakpoint="Breakpoint.MdAndUp">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" OnClick="@ToggleDrawer" Edge="Edge.Start"/>
|
||||
</MudHidden>
|
||||
|
||||
|
||||
<RadzenGravatar class="h-14 w-14" Email="@_user?.Email"/>
|
||||
<MudStack class="mr-2" Spacing="0">
|
||||
<MudText Color="Color.Inherit" Typo="Typo.body1"><b>@_user?.FullName</b></MudText>
|
||||
<MudText Color="Color.Inherit" Typo="Typo.caption">@_user?.PhoneNumber</MudText>
|
||||
</MudStack>
|
||||
<MudSpacer/>
|
||||
<MudToggleIconButton @bind-Toggled="@MainTheme.IsDarkMode"
|
||||
Icon="@Icons.Material.Outlined.DarkMode" Color="@Color.Default" Title="تاریک"
|
||||
ToggledIcon="@Icons.Material.Filled.LightMode" ToggledColor="@Color.Default" ToggledTitle="روشن"/>
|
||||
<MudIconButton Size="Size.Medium" Color="Color.Error" OnClick="LogoutAsync" Icon="@Icons.Material.Outlined.ExitToApp"/>
|
||||
</MudAppBar>
|
||||
|
||||
<MudDrawer @bind-Open="@open" ClipMode="DrawerClipMode.Always" Breakpoint="Breakpoint.MdAndUp" Elevation="1" Variant="@DrawerVariant.Responsive">
|
||||
<SideBarUi/>
|
||||
</MudDrawer>
|
||||
|
||||
<MudMainContent class="h-screen">
|
||||
@Body
|
||||
</MudMainContent>
|
||||
</MudLayout>
|
||||
<div dir="ltr">
|
||||
<PWAUpdater Align="PWAUpdater.Aligns.Buttom" Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
||||
</div>
|
||||
</MudRTLProvider> *@
|
||||
</Authorized>
|
||||
|
||||
<NotAuthorized>
|
||||
|
|
|
@ -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";
|
||||
}
|
|
@ -19,7 +19,7 @@ public class BaseViewModel<TPageDto>
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
<Using Include="Netina.Domain.Entities.ProductCategories" />
|
||||
<Using Include="Netina.Domain.Entities.Products" />
|
||||
<Using Include="Netina.Domain.Enums" />
|
||||
<Using Include="Netina.Domain.Extensions" />
|
||||
<Using Include="Netina.Domain.MartenEntities.Pages" />
|
||||
<Using Include="Netina.Domain.MartenEntities.Settings" />
|
||||
<Using Include="Netina.Domain.Models.Districts" />
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@page "/management/faqs"
|
||||
@page "/setting/faq"
|
||||
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
|
@ -10,45 +11,54 @@
|
|||
<MudStack class="h-full w-full p-8">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudStack Row="true" class="mb-8">
|
||||
<MudText Typo="Typo.h4">سوالات متداول فروشگاه من</MudText>
|
||||
<MudStack Row="true" class="mb-5">
|
||||
<MudText Typo="Typo.h4">سوالات متداول</MudText>
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Filled" Size="Size.Large" Color="Color.Success" OnClick="@ViewModel.SaveAsync">ذخیره سوالات</MudButton>
|
||||
<MudButton Variant="Variant.Filled"
|
||||
DisableElevation="true"
|
||||
StartIcon="@Icons.Material.Outlined.Add"
|
||||
Color="Color.Secondary"
|
||||
OnClick="@ViewModel.AddClicked"
|
||||
class="my-auto">افزودن سوالات متداول جدید</MudButton>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem sm="4">
|
||||
<MudTextField T="string" Label="سوال" @bind-Value="@ViewModel.Question" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="6">
|
||||
<MudTextField T="string" Label="پاسخ" @bind-Value="@ViewModel.Answer" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem>
|
||||
<MudButton class="mt-2 py-3" EndIcon="@Icons.Material.Outlined.Add"
|
||||
Variant="Variant.Outlined" Size="Size.Large" Color="Color.Info" OnClick="@ViewModel.AddNewQuestion">افزودن</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
<MudPaper>
|
||||
<MudExpansionPanels class="mt-8">
|
||||
@foreach (var item in ViewModel.PageDto.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="BaseFaq" Items="@ViewModel.PageDto" Filterable="false"
|
||||
CurrentPage="@ViewModel.CurrentPage"
|
||||
RowsPerPage="20"
|
||||
Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn Title="عنوان" Property="arg => arg.Title" />
|
||||
<PropertyColumn Title="اسلاگ" Property="arg => arg.Slug" />
|
||||
<PropertyColumn T="BaseFaq" TProperty="int" Title="تعداد سوالات" Property="arg => arg.Faqs.Count" />
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.RemoveQuestion(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
Color="@Color.Info"
|
||||
OnClick="async()=>await ViewModel.EditClicked(context.Item)" />
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.DeleteAsync(context.Item.Id)"
|
||||
Color="@Color.Error" />
|
||||
</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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,72 +1,25 @@
|
|||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
using Netina.Domain.MartenEntities.Faqs;
|
||||
|
||||
public class FaqManagementPageViewModel : BaseViewModel<FAQPage>
|
||||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
|
||||
public class FaqManagementPageViewModel(
|
||||
IDialogService dialogService,
|
||||
NavigationManager navigationManager,
|
||||
IRestWrapper restWrapper,
|
||||
ISnackbar snackbar,
|
||||
IUserUtility userUtility)
|
||||
: BaseViewModel<ObservableCollection<BaseFaq>> (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<FAQPage>();
|
||||
_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<ApiResult>();
|
||||
_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<FAQPage>
|
|||
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<ApiResult>();
|
||||
_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<FaqActionDialogBox>("افزودن اژانس هواپیمایی جدید", 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<FaqActionDialogBox>();
|
||||
parameters.Add(x => x.Faq, item);
|
||||
var reference = await dialogService.ShowAsync<FaqActionDialogBox>($"ویرایش سوالات متداول {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<ApiResult>();
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<List<BaseFaq>> GetFaqs([Query]int page,[Header("Authorization")] string token);
|
||||
|
||||
[Get("/slug")]
|
||||
Task<BaseFaq> ReadOne([Query]string slug);
|
||||
}
|
|
@ -23,4 +23,5 @@ public interface IRestWrapper
|
|||
public IDashboardApiRest DashboardApiRest { get; }
|
||||
public ISettingRestApi SettingRestApi { get; }
|
||||
public IDistrictApiRest DistrictApiRest { get; }
|
||||
public IFaqApiRest FaqApiRest { get; }
|
||||
}
|
|
@ -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<string>("ApiUrl") ?? string.Empty;
|
||||
}
|
||||
private string baseApiAddress = configuration.GetValue<string>("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<ISettingRestApi>($"{baseApiAddress}{Address.SettingController}", setting);
|
||||
public IDashboardApiRest DashboardApiRest => RestService.For<IDashboardApiRest>($"{baseApiAddress}{Address.DashboardController}", setting);
|
||||
public IDistrictApiRest DistrictApiRest => RestService.For<IDistrictApiRest>($"{baseApiAddress}{Address.DistrictController}", setting);
|
||||
public IFaqApiRest FaqApiRest => RestService.For<IFaqApiRest>($"{baseApiAddress}{Address.FaqController}", setting);
|
||||
}
|
|
@ -19,4 +19,5 @@
|
|||
@using Netina.Domain.Entities.Users
|
||||
@using Netina.AdminPanel.PWA.Components.Originals
|
||||
@using Netina.Domain.Models.Claims
|
||||
@using MudBlazor.Services
|
||||
@using MudBlazor.Services
|
||||
@using Netina.Domain.MartenEntities.Faqs
|
Loading…
Reference in New Issue