feat : storage dialog , blog dialog , blog category dialog
complate blog and blog category , add storage dialog for filesrelease
parent
d6e0983f13
commit
39d61e49f0
|
@ -64,10 +64,11 @@
|
||||||
TreeItems.Add(new TreeItemData("داشبورد", Icons.Material.Outlined.Dashboard, ""));
|
TreeItems.Add(new TreeItemData("داشبورد", Icons.Material.Outlined.Dashboard, ""));
|
||||||
TreeItems.Add(new TreeItemData("فروش", Icons.Material.Outlined.ShoppingCart, "products"));
|
TreeItems.Add(new TreeItemData("فروش", Icons.Material.Outlined.ShoppingCart, "products"));
|
||||||
TreeItems.Add(new TreeItemData("محصولات", Icons.Material.Outlined.CenterFocusStrong, "products"));
|
TreeItems.Add(new TreeItemData("محصولات", Icons.Material.Outlined.CenterFocusStrong, "products"));
|
||||||
TreeItems.Add(new TreeItemData("دسته بندی ها", Icons.Material.Outlined.AllInbox, "categories"));
|
TreeItems.Add(new TreeItemData("دسته بندی محصولات", Icons.Material.Outlined.AllInbox, "categories"));
|
||||||
TreeItems.Add(new TreeItemData("برند ها", Icons.Custom.Brands.Facebook, "brands"));
|
TreeItems.Add(new TreeItemData("برند محصولات", Icons.Custom.Brands.Facebook, "brands"));
|
||||||
|
TreeItems.Add(new TreeItemData("بلاگ ها", Icons.Material.Outlined.Web, "blogs"));
|
||||||
|
TreeItems.Add(new TreeItemData("دسته بندی بلاگ ها", Icons.Material.Outlined.Web, "blog/categories"));
|
||||||
TreeItems.Add(new TreeItemData("مشترکین", Icons.Material.Outlined.People, "products"));
|
TreeItems.Add(new TreeItemData("مشترکین", Icons.Material.Outlined.People, "products"));
|
||||||
TreeItems.Add(new TreeItemData("وبلاگ", Icons.Material.Outlined.Web, "products"));
|
|
||||||
TreeItems.Add(new TreeItemData("تنظیمات", Icons.Material.Outlined.Settings, "products"));
|
TreeItems.Add(new TreeItemData("تنظیمات", Icons.Material.Outlined.Settings, "products"));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
@using Radzen.Blazor
|
||||||
|
@using NetinaShop.AdminPanel.PWA.Extensions
|
||||||
|
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
@inject IDialogService DialogService
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<MudDialog class="mx-auto">
|
||||||
|
<DialogContent>
|
||||||
|
<MudContainer class="h-full">
|
||||||
|
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||||
|
<MudTabPanel class="h-full" Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||||
|
<div class="h-full">
|
||||||
|
<MudStack Spacing="0" class="mt-4">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||||
|
<MudText Typo="Typo.caption">اطلاعات کلی محصول را به دقت وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.Title" T="string" Label="عنوان بلاگ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
|
||||||
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||||
|
SearchFunc="ViewModel.SearchBlogCategory"
|
||||||
|
T="BlogCategorySDto"
|
||||||
|
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 lg="4" md="6">
|
||||||
|
<MudSelect T="bool" @bind-Value="@ViewModel.IsSuggested" Label="آیا پیشنهادویژه است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
|
<MudSelectItem T="bool" Value="true" />
|
||||||
|
<MudSelectItem T="bool" Value="false" />
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="12" md="12">
|
||||||
|
<MudStack>
|
||||||
|
<MudTextField @bind-Value="@ViewModel.Tags" T="string" Label="تگ ها" HelperText="تگ ها را با , میتوانید جدا کنید" HelperTextOnFocus="true" Variant="Variant.Outlined" />
|
||||||
|
</MudStack>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="12" md="12">
|
||||||
|
<MudTextField class="-mt-3" @bind-Value="@ViewModel.Summery" T="string" Label="توضیحاتــ کوتاه" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="متن اصلی بلاگ" Icon="@Icons.Material.Outlined.Article">
|
||||||
|
|
||||||
|
<div class="min-h-[33rem]">
|
||||||
|
<MudStack class="mt-4" Spacing="0">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">متن بلاگ</MudText>
|
||||||
|
<MudText Typo="Typo.caption">می توانید کتن کامل بلاگــــ خود را کامل وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem sm="12">
|
||||||
|
<RadzenHtmlEditor @bind-Value="@ViewModel.Content" class="min-h-[28rem]">
|
||||||
|
<RadzenHtmlEditorUndo />
|
||||||
|
<RadzenHtmlEditorRedo />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorFormatBlock />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorAlignLeft />
|
||||||
|
<RadzenHtmlEditorAlignCenter />
|
||||||
|
<RadzenHtmlEditorAlignRight />
|
||||||
|
<RadzenHtmlEditorJustify />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorSource />
|
||||||
|
<RadzenHtmlEditorBold />
|
||||||
|
<RadzenHtmlEditorItalic />
|
||||||
|
<RadzenHtmlEditorUnderline />
|
||||||
|
<RadzenHtmlEditorStrikeThrough />
|
||||||
|
<RadzenHtmlEditorRemoveFormat />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
</RadzenHtmlEditor>
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||||
|
|
||||||
|
<div class="min-h-[33rem]">
|
||||||
|
<MudStack class="mt-4 mb-2" 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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</MudTabPanel>
|
||||||
|
</MudTabs>
|
||||||
|
</MudContainer>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudStack Row="true" class="w-full h-fit mx-4 bottom-0">
|
||||||
|
|
||||||
|
@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
|
||||||
|
{
|
||||||
|
|
||||||
|
[CascadingParameter]
|
||||||
|
MudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public BlogSDto? Blog { get; set; }
|
||||||
|
|
||||||
|
public BlogActionDialogBoxViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (Blog == null)
|
||||||
|
ViewModel = new BlogActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
|
||||||
|
else
|
||||||
|
ViewModel = new BlogActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Blog);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
using NetinaShop.Domain.Dtos.LargDtos;
|
||||||
|
using NetinaShop.Domain.Entities.Blogs;
|
||||||
|
using NetinaShop.Domain.Entities.Products;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class BlogActionDialogBoxViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly MudDialogInstance _mudDialog;
|
||||||
|
|
||||||
|
public BlogActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
}
|
||||||
|
public BlogActionDialogBoxViewModel(ISnackbar snackbar,
|
||||||
|
IRestWrapper restWrapper,
|
||||||
|
IUserUtility userUtility,
|
||||||
|
IDialogService dialogService,
|
||||||
|
MudDialogInstance mudDialog,
|
||||||
|
BlogSDto blog)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
Blog = blog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlogSDto? _blog = null;
|
||||||
|
public BlogSDto? Blog
|
||||||
|
{
|
||||||
|
get => _blog;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_blog = value;
|
||||||
|
if (_blog != null)
|
||||||
|
{
|
||||||
|
IsEditing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool IsEditing = false;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public int ReadingTime { get; set; }
|
||||||
|
public string Tags { get; set; } = string.Empty;
|
||||||
|
public string Summery { get; set; } = string.Empty;
|
||||||
|
public bool IsSuggested { get; set; }
|
||||||
|
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
if (IsEditing && _blog != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
var blogLDto = await _restWrapper.CrudDtoApiRest<Blog, BlogLDto, Guid>(Address.BlogController).ReadOne(_blog.Id);
|
||||||
|
Title = blogLDto.Title;
|
||||||
|
Content = blogLDto.Content;
|
||||||
|
ReadingTime = blogLDto.ReadingTime;
|
||||||
|
Tags = blogLDto.Tags;
|
||||||
|
Summery = blogLDto.Summery;
|
||||||
|
Tags = blogLDto.Tags;
|
||||||
|
IsSuggested = blogLDto.IsSuggested;
|
||||||
|
blogLDto.Files.ForEach(f => Files.Add(f));
|
||||||
|
SelectedCategory = new BlogCategorySDto() { Id = blogLDto.CategoryId, Name = blogLDto.CategoryName };
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
|
||||||
|
public async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (Blog == null || Blog.Id == default)
|
||||||
|
throw new Exception("بلاگ اشتباه است");
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
|
||||||
|
var request = new BlogLDto
|
||||||
|
{
|
||||||
|
Id = Blog.Id,
|
||||||
|
Title = Title,
|
||||||
|
CategoryId = SelectedCategory.Id,
|
||||||
|
Content = Content,
|
||||||
|
Files = this.Files.ToList(),
|
||||||
|
IsSuggested = IsSuggested,
|
||||||
|
ReadingTime = ReadingTime,
|
||||||
|
Summery = Summery,
|
||||||
|
Tags = Tags
|
||||||
|
};
|
||||||
|
await _restWrapper.CrudApiRest<Blog, Guid>(Address.BlogController).Create<BlogLDto>(request, token);
|
||||||
|
_snackbar.Add($"ویرایش بلاگ {Title} با موفقیت انجام شد", Severity.Success);
|
||||||
|
_mudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var request = new BlogLDto
|
||||||
|
{
|
||||||
|
Title = Title,
|
||||||
|
CategoryId = SelectedCategory.Id,
|
||||||
|
Content = Content,
|
||||||
|
Files = this.Files.ToList(),
|
||||||
|
IsSuggested = IsSuggested,
|
||||||
|
ReadingTime = ReadingTime,
|
||||||
|
Summery = Summery,
|
||||||
|
Tags = Tags
|
||||||
|
};
|
||||||
|
await _restWrapper.CrudApiRest<Blog, Guid>(Address.BlogController).Create<BlogLDto>(request, token);
|
||||||
|
|
||||||
|
_snackbar.Add($"ساخت بلاگ {Title} با موفقیت انجام شد", Severity.Success);
|
||||||
|
_mudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<BlogCategorySDto> _blogCategories = new List<BlogCategorySDto>();
|
||||||
|
public BlogCategorySDto? SelectedCategory;
|
||||||
|
public async Task<IEnumerable<BlogCategorySDto>> SearchBlogCategory(string category)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (category.IsNullOrEmpty())
|
||||||
|
_blogCategories = await _restWrapper.BlogCategoryRestApi.ReadAll(0);
|
||||||
|
else
|
||||||
|
_blogCategories = await _restWrapper.BlogCategoryRestApi.ReadAll(category);
|
||||||
|
return _blogCategories;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
return _blogCategories;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
return _blogCategories;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
@using NetinaShop.Common.Models.Exception
|
||||||
|
@using NetinaShop.Domain.Entities.Blogs
|
||||||
|
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<MudTextField T="string" Label="نام دسته بندی" @bind-Value="@_name" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="12">
|
||||||
|
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||||
|
|
||||||
|
@if (_isEditing)
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||||
|
}
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
||||||
|
[Parameter]
|
||||||
|
public BlogCategorySDto? BlogCategory { get; set; }
|
||||||
|
|
||||||
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
private bool _isProcessing = false;
|
||||||
|
private string _name = string.Empty;
|
||||||
|
private string _description = string.Empty;
|
||||||
|
private bool _isEditing;
|
||||||
|
|
||||||
|
protected override Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
if (BlogCategory != null)
|
||||||
|
{
|
||||||
|
_isEditing = true;
|
||||||
|
_description = BlogCategory.Description;
|
||||||
|
_name = BlogCategory.Name;
|
||||||
|
}
|
||||||
|
return base.OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام دسته بندی را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
|
var request = new BlogCategorySDto{Name = _name,Description = _description};
|
||||||
|
await RestWrapper.CrudApiRest<BlogCategory, Guid>(Address.BlogCategoryController).Create<BlogCategorySDto>(request, token);
|
||||||
|
MudDialog.Close(DialogResult.Ok(true));
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
Snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
Snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (BlogCategory == null)
|
||||||
|
throw new AppException("دسته بندی به درستی ارسال نشده است");
|
||||||
|
if (_name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام دسته بندی را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
|
var request = new BlogCategorySDto {Id = BlogCategory.Id , Name = _name, Description = _description };
|
||||||
|
await RestWrapper.CrudApiRest<BlogCategory, Guid>(Address.BlogCategoryController).Update<BlogCategorySDto>(request, token);
|
||||||
|
MudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
Snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
Snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Snackbar.Add(e.Message, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
_isProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,15 +16,18 @@
|
||||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem lg="6" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField T="string" Label="نام برند" @bind-Value="@_name" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField T="string" Label="نام برند" @bind-Value="@_name" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="6" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@_isMain" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
<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="true"></MudSelectItem>
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField T="string" Label="لینک صفحه شخصی برند" @bind-Value="@_pageUrl" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="12" md="12">
|
||||||
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
@ -33,14 +36,22 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
@* <MudStack>
|
|
||||||
<BaseButtonUi Icon="@Icons.Material.Outlined.Check" Variant="Variant.Filled" Color="Color.Success" Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
|
||||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
|
||||||
|
|
||||||
</MudStack> *@
|
|
||||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||||
|
|
||||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing" Icon="@Icons.Material.Outlined.Check" Variant="Variant.Filled" Color="Color.Success" Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
@if (_isEditing)
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||||
|
}
|
||||||
<MudSpacer />
|
<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="Cancel">بستن</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
@ -48,12 +59,28 @@
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
||||||
|
[Parameter]
|
||||||
|
public BrandSDto? Brand { get; set; }
|
||||||
|
|
||||||
void Cancel() => MudDialog.Cancel();
|
void Cancel() => MudDialog.Cancel();
|
||||||
private bool _isProcessing = false;
|
private bool _isProcessing = false;
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private bool _isMain;
|
private bool _hasSpecialPage;
|
||||||
|
private bool _isEditing;
|
||||||
|
private string _pageUrl = string.Empty;
|
||||||
|
|
||||||
|
protected override Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
if (Brand != null)
|
||||||
|
{
|
||||||
|
_isEditing = true;
|
||||||
|
_hasSpecialPage = Brand.HasSpecialPage;
|
||||||
|
_description = Brand.Description;
|
||||||
|
_name = Brand.Name;
|
||||||
|
}
|
||||||
|
return base.OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SubmitCreateAsync()
|
private async Task SubmitCreateAsync()
|
||||||
{
|
{
|
||||||
|
@ -63,7 +90,7 @@
|
||||||
throw new AppException("لطفا نام برند را وارد کنید");
|
throw new AppException("لطفا نام برند را وارد کنید");
|
||||||
_isProcessing = true;
|
_isProcessing = true;
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
var request = new CreateBrandCommand(_name, _description, _isMain, string.Empty, new List<StorageFileSDto>());
|
var request = new CreateBrandCommand(_name, _description, _hasSpecialPage, string.Empty, new List<StorageFileSDto>());
|
||||||
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||||
MudDialog.Close(DialogResult.Ok(true));
|
MudDialog.Close(DialogResult.Ok(true));
|
||||||
}
|
}
|
||||||
|
@ -83,4 +110,40 @@
|
||||||
_isProcessing = false;
|
_isProcessing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Brand == null)
|
||||||
|
throw new AppException("برند به درستی ارسال نشده است");
|
||||||
|
if (_name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام برند را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
|
var request = new UpdateBrandCommand(Brand.Id, _name, _description, _hasSpecialPage, string.Empty , new List<StorageFileSDto>());
|
||||||
|
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Update<UpdateBrandCommand>(request, token);
|
||||||
|
MudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
Snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
Snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Snackbar.Add(e.Message, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
_isProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,223 +12,239 @@
|
||||||
|
|
||||||
<MudDialog class="mx-auto">
|
<MudDialog class="mx-auto">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<MudStack>
|
<MudContainer class="h-full">
|
||||||
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||||
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
<MudTabPanel class="h-full" Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||||
<MudStack Spacing="0" class="mt-4">
|
<div class="h-full">
|
||||||
|
<MudStack Spacing="0" class="mt-4">
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||||
<MudText Typo="Typo.caption">اطلاعات کلی محصول را به دقت وارد کنید</MudText>
|
<MudText Typo="Typo.caption">اطلاعات کلی محصول را به دقت وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
|
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.PersianName" T="string" Label="نام فارسی محصول" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.PersianName" T="string" Label="نام فارسی محصول" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.EnglishName" T="string" Label="نام انگلیسی محصول" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.EnglishName" T="string" Label="نام انگلیسی محصول" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
|
|
||||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel._selectedCategory"
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||||
SearchFunc="ViewModel.SearchProductCategory"
|
SearchFunc="ViewModel.SearchProductCategory"
|
||||||
T="ProductCategorySDto"
|
T="ProductCategorySDto"
|
||||||
Label="دسته بندی"
|
Label="دسته بندی"
|
||||||
Variant="Variant.Outlined">
|
Variant="Variant.Outlined">
|
||||||
<ProgressIndicatorInPopoverTemplate>
|
<ProgressIndicatorInPopoverTemplate>
|
||||||
<MudList Clickable="false">
|
<MudList Clickable="false">
|
||||||
<MudListItem>
|
<MudListItem>
|
||||||
<div class="flex flex-row w-full mx-auto">
|
<div class="flex flex-row w-full mx-auto">
|
||||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||||
</div>
|
</div>
|
||||||
</MudListItem>
|
</MudListItem>
|
||||||
</MudList>
|
</MudList>
|
||||||
</ProgressIndicatorInPopoverTemplate>
|
</ProgressIndicatorInPopoverTemplate>
|
||||||
<ItemTemplate Context="e">
|
<ItemTemplate Context="e">
|
||||||
<p>@e.Name</p>
|
<p>@e.Name</p>
|
||||||
</ItemTemplate>
|
</ItemTemplate>
|
||||||
</MudAutocomplete>
|
</MudAutocomplete>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
|
|
||||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel._selectedBrand"
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedBrand"
|
||||||
SearchFunc="ViewModel.SearchBrand"
|
SearchFunc="ViewModel.SearchBrand"
|
||||||
T="BrandSDto"
|
T="BrandSDto"
|
||||||
Label="برند"
|
Label="برند"
|
||||||
Variant="Variant.Outlined">
|
Variant="Variant.Outlined">
|
||||||
<ProgressIndicatorInPopoverTemplate>
|
<ProgressIndicatorInPopoverTemplate>
|
||||||
<MudList Clickable="false">
|
<MudList Clickable="false">
|
||||||
<MudListItem>
|
<MudListItem>
|
||||||
<div class="flex flex-row w-full mx-auto">
|
<div class="flex flex-row w-full mx-auto">
|
||||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||||
</div>
|
</div>
|
||||||
</MudListItem>
|
</MudListItem>
|
||||||
</MudList>
|
</MudList>
|
||||||
</ProgressIndicatorInPopoverTemplate>
|
</ProgressIndicatorInPopoverTemplate>
|
||||||
<ItemTemplate Context="e">
|
<ItemTemplate Context="e">
|
||||||
<p>@e.Name</p>
|
<p>@e.Name</p>
|
||||||
</ItemTemplate>
|
</ItemTemplate>
|
||||||
</MudAutocomplete>
|
</MudAutocomplete>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.Cost" T="double" Label="قیمت محصول" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.Cost" T="double" Label="قیمت محصول" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.PackingCost" T="double" Label="مبلغ بسته بندی" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.PackingCost" T="double" Label="مبلغ بسته بندی" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.MaxOrder" T="int" Label="بیشترین خرید" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.MaxOrder" T="int" Label="بیشترین خرید" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.Warranty" T="string" Label="گارانتی" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.Warranty" T="string" Label="گارانتی" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudSelect T="bool" @bind-Value="@ViewModel.HasExpressDelivery" Label="آیا ارسال سریع دارد ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
<MudSelect T="bool" @bind-Value="@ViewModel.HasExpressDelivery" Label="آیا ارسال سریع دارد ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
<MudSelectItem T="bool" Value="true" />
|
<MudSelectItem T="bool" Value="true" />
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudSelect T="bool" @bind-Value="@ViewModel.BeDisplayed" Label="آیا نمایش داده شود است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
<MudSelect T="bool" @bind-Value="@ViewModel.BeDisplayed" Label="آیا نمایش داده شود است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
<MudSelectItem T="bool" Value="true" />
|
<MudSelectItem T="bool" Value="true" />
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="12" md="12">
|
||||||
<MudStack>
|
<MudStack>
|
||||||
<MudTextField @bind-Value="@ViewModel.Tags" T="string" Label="تگ ها" HelperText="تگ ها را با , میتوانید جدا کنید" HelperTextOnFocus="true" Variant="Variant.Outlined" />
|
<MudTextField @bind-Value="@ViewModel.Tags" T="string" Label="تگ ها" HelperText="تگ ها را با , میتوانید جدا کنید" HelperTextOnFocus="true" Variant="Variant.Outlined" />
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="12" md="12">
|
||||||
<MudTextField class="-mt-3" @bind-Value="@ViewModel.Summery" T="string" Label="توضیحاتــ" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField class="-mt-3" @bind-Value="@ViewModel.Summery" T="string" Label="توضیحاتــ" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
</div>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="ویژگی های کلی" Icon="@Icons.Material.Outlined.AutoGraph">
|
<MudTabPanel Text="ویژگی های کلی" Icon="@Icons.Material.Outlined.AutoGraph">
|
||||||
|
<div class="min-h-[33rem]">
|
||||||
|
|
||||||
<MudStack class="mt-4" Spacing="0">
|
<MudStack class="mt-4" Spacing="0">
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">ویژگی های کلی</MudText>
|
<MudText Typo="Typo.h6">ویژگی های کلی</MudText>
|
||||||
<MudText Typo="Typo.caption">می توانید ویگی های تکمیلی محصول را کامل وارد کنید</MudText>
|
<MudText Typo="Typo.caption">می توانید ویگی های تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
|
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.SpecificationTitle" T="string" Label="عنوان" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField @bind-Value="@ViewModel.SpecificationTitle" T="string" Label="عنوان" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField @bind-Value="@ViewModel.SpecificationValue" T="string" Label="مقدار" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField @bind-Value="@ViewModel.SpecificationValue" T="string" Label="مقدار" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<MudItem lg="4" md="12">
|
<MudItem lg="4" md="12">
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Size="Size.Large"
|
Size="Size.Large"
|
||||||
Color="Color.Info"
|
Color="Color.Info"
|
||||||
class="w-full py-3 mt-2"
|
class="w-full py-3 mt-2"
|
||||||
OnClick="ViewModel.AddSpecification"
|
OnClick="ViewModel.AddSpecification"
|
||||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<MudItem sm="12">
|
<MudItem sm="12">
|
||||||
<MudDataGrid Items="@ViewModel.Specifications" Elevation="0" Outlined="true" Bordered="true" Striped="true" Filterable="false" SortMode="@SortMode.None" Groupable="false">
|
<MudDataGrid Items="@ViewModel.Specifications" Elevation="0" Outlined="true" Bordered="true" Striped="true" Filterable="false" SortMode="@SortMode.None" Groupable="false">
|
||||||
<Columns>
|
<Columns>
|
||||||
<PropertyColumn Property="x => x.Title" Title="عنوان" />
|
<PropertyColumn Property="x => x.Title" Title="عنوان" />
|
||||||
<PropertyColumn Property="x => x.Value" Title="مقدار" />
|
<PropertyColumn Property="x => x.Value" Title="مقدار" />
|
||||||
<TemplateColumn T="SpecificationSDto" CellClass="d-flex justify-end">
|
<TemplateColumn T="SpecificationSDto" CellClass="d-flex justify-end">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
<MudStack Row>
|
<MudStack Row>
|
||||||
<MudButton DisableElevation="true"
|
<MudButton DisableElevation="true"
|
||||||
Size="@Size.Small"
|
Size="@Size.Small"
|
||||||
Variant="@Variant.Filled"
|
Variant="@Variant.Filled"
|
||||||
OnClick="()=>ViewModel.RemoveSpecification(context.Item)"
|
OnClick="()=>ViewModel.RemoveSpecification(context.Item)"
|
||||||
Color="@Color.Error"
|
Color="@Color.Error"
|
||||||
StartIcon="@Icons.Material.Outlined.Delete">حذف</MudButton>
|
StartIcon="@Icons.Material.Outlined.Delete">حذف</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
</div>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="توضیحات تکمیلی" Icon="@Icons.Material.Outlined.Article">
|
<MudTabPanel Text="توضیحات تکمیلی" Icon="@Icons.Material.Outlined.Article">
|
||||||
|
|
||||||
<MudStack class="mt-4" Spacing="0">
|
<div class="min-h-[33rem]">
|
||||||
|
<MudStack class="mt-4" Spacing="0">
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem sm="12">
|
<MudItem sm="12">
|
||||||
<RadzenHtmlEditor @bind-Value="@ViewModel.ExpertCheck" class="min-h-[10rem]">
|
<RadzenHtmlEditor @bind-Value="@ViewModel.ExpertCheck" class="min-h-[28rem]">
|
||||||
<RadzenHtmlEditorUndo />
|
<RadzenHtmlEditorUndo />
|
||||||
<RadzenHtmlEditorRedo />
|
<RadzenHtmlEditorRedo />
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
<RadzenHtmlEditorFormatBlock />
|
<RadzenHtmlEditorFormatBlock />
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
<RadzenHtmlEditorAlignLeft />
|
<RadzenHtmlEditorAlignLeft />
|
||||||
<RadzenHtmlEditorAlignCenter />
|
<RadzenHtmlEditorAlignCenter />
|
||||||
<RadzenHtmlEditorAlignRight />
|
<RadzenHtmlEditorAlignRight />
|
||||||
<RadzenHtmlEditorJustify />
|
<RadzenHtmlEditorJustify />
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
<RadzenHtmlEditorSource />
|
<RadzenHtmlEditorSource />
|
||||||
<RadzenHtmlEditorBold />
|
<RadzenHtmlEditorBold />
|
||||||
<RadzenHtmlEditorItalic />
|
<RadzenHtmlEditorItalic />
|
||||||
<RadzenHtmlEditorUnderline />
|
<RadzenHtmlEditorUnderline />
|
||||||
<RadzenHtmlEditorStrikeThrough />
|
<RadzenHtmlEditorStrikeThrough />
|
||||||
<RadzenHtmlEditorRemoveFormat />
|
<RadzenHtmlEditorRemoveFormat />
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
</RadzenHtmlEditor>
|
</RadzenHtmlEditor>
|
||||||
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
</div>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||||
|
|
||||||
<MudStack class="mt-4 mb-2" Spacing="0">
|
<div class="min-h-[33rem]">
|
||||||
|
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">تصاویر محصول</MudText>
|
<MudText Typo="Typo.h6">تصاویر محصول</MudText>
|
||||||
<MudText Typo="Typo.caption">می توانید برای محصول چند تصویر اپلود کنید</MudText>
|
<MudText Typo="Typo.caption">می توانید برای محصول چند تصویر اپلود کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudIconButton HtmlTag="label"
|
<MudIconButton HtmlTag="label"
|
||||||
Color="Color.Info"
|
Color="Color.Info"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
class="w-28 h-28"
|
class="w-28 h-28"
|
||||||
Size="Size.Large"
|
Size="Size.Large"
|
||||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||||
OnClick="async () => await ViewModel.SelectFileAsync()">
|
OnClick="async () => await ViewModel.SelectFileAsync()">
|
||||||
</MudIconButton>
|
</MudIconButton>
|
||||||
@foreach (var item in ViewModel.Files)
|
@foreach (var item in ViewModel.Files)
|
||||||
{
|
{
|
||||||
<div class="w-28 h-28">
|
<div class="w-28 h-28">
|
||||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||||
|
|
||||||
<MudIconButton DisableElevation="true"
|
<MudIconButton DisableElevation="true"
|
||||||
class="absolute m-1.5"
|
class="absolute m-1.5"
|
||||||
Size="@Size.Small"
|
Size="@Size.Small"
|
||||||
Variant="@Variant.Filled"
|
Variant="@Variant.Filled"
|
||||||
OnClick="() => ViewModel.RemoveFile(item)"
|
OnClick="() => ViewModel.RemoveFile(item)"
|
||||||
Color="@Color.Error"
|
Color="@Color.Error"
|
||||||
Icon="@Icons.Material.Outlined.Delete" />
|
Icon="@Icons.Material.Outlined.Delete" />
|
||||||
</div>
|
@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>
|
</MudStack>
|
||||||
|
</div>
|
||||||
|
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
</MudTabs>
|
</MudTabs>
|
||||||
</MudStack>
|
</MudContainer>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
<MudStack Row="true" class="w-full h-fit mx-4 bottom-0">
|
||||||
|
|
||||||
@if (ViewModel.IsEditing)
|
@if (ViewModel.IsEditing)
|
||||||
{
|
{
|
||||||
|
@ -257,6 +273,7 @@
|
||||||
public ProductSDto? Product { get; set; }
|
public ProductSDto? Product { get; set; }
|
||||||
|
|
||||||
public ProductActionDialogBoxViewModel ViewModel { get; set; }
|
public ProductActionDialogBoxViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if (Product == null)
|
if (Product == null)
|
||||||
|
|
|
@ -66,6 +66,49 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
if (IsEditing && _product != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
|
||||||
|
ExpertCheck = productLDto.ExpertCheck;
|
||||||
|
Summery = productLDto.Summery;
|
||||||
|
BeDisplayed = productLDto.BeDisplayed;
|
||||||
|
HasExpressDelivery = productLDto.HasExpressDelivery;
|
||||||
|
PersianName = productLDto.PersianName;
|
||||||
|
EnglishName = productLDto.EnglishName;
|
||||||
|
Cost = productLDto.Cost;
|
||||||
|
PackingCost = productLDto.PackingCost;
|
||||||
|
MaxOrder = productLDto.MaxOrderCount;
|
||||||
|
Warranty = productLDto.Warranty;
|
||||||
|
productLDto.Specifications.ForEach(s => Specifications.Add(s));
|
||||||
|
productLDto.Files.ForEach(f => Files.Add(f));
|
||||||
|
SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
|
||||||
|
SelectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SubmitEditAsync()
|
public async Task SubmitEditAsync()
|
||||||
{
|
{
|
||||||
|
@ -74,8 +117,12 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
IsProcessing = true;
|
IsProcessing = true;
|
||||||
if (Product == null || Product.Id == default)
|
if (Product == null || Product.Id == default)
|
||||||
throw new Exception("محصول اشتباه است");
|
throw new Exception("محصول اشتباه است");
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||||
|
if (SelectedBrand == null)
|
||||||
|
throw new Exception("لطفا یک برند انتخاب کنید");
|
||||||
var token = await _userUtility.GetBearerTokenAsync();
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
var request = new UpdateProductCommand(Product.Id, PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, _selectedBrand?.Id ?? default, _selectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
|
var request = new UpdateProductCommand(Product.Id, PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
|
||||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
|
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
|
||||||
_snackbar.Add($"ویرایش محصول {PersianName} با موفقیت انجام شد", Severity.Success);
|
_snackbar.Add($"ویرایش محصول {PersianName} با موفقیت انجام شد", Severity.Success);
|
||||||
_mudDialog.Close();
|
_mudDialog.Close();
|
||||||
|
@ -99,6 +146,97 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
IsProcessing = false;
|
IsProcessing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||||
|
if (SelectedBrand == null)
|
||||||
|
throw new Exception("لطفا یک برند انتخاب کنید");
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var request = new CreateProductCommand(PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
|
||||||
|
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
||||||
|
|
||||||
|
_snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
|
||||||
|
_mudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
||||||
|
public ProductCategorySDto? SelectedCategory;
|
||||||
|
public async Task<IEnumerable<ProductCategorySDto>> SearchProductCategory(string category)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (category.IsNullOrEmpty())
|
||||||
|
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
|
||||||
|
else
|
||||||
|
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
|
||||||
|
return _productCategories;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
return _productCategories;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
return _productCategories;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BrandSDto> _brands = new List<BrandSDto>();
|
||||||
|
public BrandSDto? SelectedBrand;
|
||||||
|
public async Task<IEnumerable<BrandSDto>> SearchBrand(string brand)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (brand.IsNullOrEmpty())
|
||||||
|
_brands = await _restWrapper.BrandRestApi.ReadAll(0);
|
||||||
|
else
|
||||||
|
_brands = await _restWrapper.BrandRestApi.ReadAll(brand);
|
||||||
|
return _brands;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
return _brands;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
return _brands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void AddSpecification()
|
public void AddSpecification()
|
||||||
{
|
{
|
||||||
|
@ -125,135 +263,6 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
if (spec != null)
|
if (spec != null)
|
||||||
Specifications.Remove(spec);
|
Specifications.Remove(spec);
|
||||||
}
|
}
|
||||||
public async Task SubmitCreateAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IsProcessing = true;
|
|
||||||
var token = await _userUtility.GetBearerTokenAsync();
|
|
||||||
var request = new CreateProductCommand(PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, _selectedBrand?.Id ?? default, _selectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
|
|
||||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
|
||||||
|
|
||||||
_snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
|
|
||||||
_mudDialog.Close();
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
_snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
_snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
_mudDialog.Cancel();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_snackbar.Add(e.Message, Severity.Error);
|
|
||||||
_mudDialog.Cancel();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
|
|
||||||
IsProcessing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override async Task InitializeAsync()
|
|
||||||
{
|
|
||||||
if (IsEditing && _product != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IsProcessing = true;
|
|
||||||
var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
|
|
||||||
ExpertCheck = productLDto.ExpertCheck;
|
|
||||||
Summery = productLDto.Summery;
|
|
||||||
BeDisplayed = productLDto.BeDisplayed;
|
|
||||||
HasExpressDelivery = productLDto.HasExpressDelivery;
|
|
||||||
PersianName = productLDto.PersianName;
|
|
||||||
EnglishName = productLDto.EnglishName;
|
|
||||||
Cost = productLDto.Cost;
|
|
||||||
PackingCost = productLDto.PackingCost;
|
|
||||||
MaxOrder = productLDto.MaxOrderCount;
|
|
||||||
Warranty = productLDto.Warranty;
|
|
||||||
productLDto.Specifications.ForEach(s => Specifications.Add(s));
|
|
||||||
productLDto.Files.ForEach(f => Files.Add(f));
|
|
||||||
_selectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
|
|
||||||
_selectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
_snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
_snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
_mudDialog.Cancel();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_snackbar.Add(e.Message, Severity.Error);
|
|
||||||
_mudDialog.Cancel();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
|
|
||||||
IsProcessing = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
|
||||||
public ProductCategorySDto? _selectedCategory;
|
|
||||||
public async Task<IEnumerable<ProductCategorySDto>> SearchProductCategory(string category)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (category.IsNullOrEmpty())
|
|
||||||
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
|
|
||||||
else
|
|
||||||
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
|
|
||||||
return _productCategories;
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
_snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
_snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
return _productCategories;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_snackbar.Add(e.Message, Severity.Error);
|
|
||||||
return _productCategories;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BrandSDto> _brands = new List<BrandSDto>();
|
|
||||||
public BrandSDto? _selectedBrand;
|
|
||||||
public async Task<IEnumerable<BrandSDto>> SearchBrand(string brand)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (brand.IsNullOrEmpty())
|
|
||||||
_brands = await _restWrapper.BrandRestApi.ReadAll(0);
|
|
||||||
else
|
|
||||||
_brands = await _restWrapper.BrandRestApi.ReadAll(brand);
|
|
||||||
return _brands;
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
_snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
_snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
return _brands;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_snackbar.Add(e.Message, Severity.Error);
|
|
||||||
return _brands;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SelectFileAsync()
|
public async Task SelectFileAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,17 +19,17 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField T="string" @bind-Value="@_name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField T="string" @bind-Value="@ViewModel.Name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudSelect T="bool" @bind-Value="@_isMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
<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="true" />
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@_selectedCategory"
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||||
SearchFunc="SearchCity"
|
SearchFunc="ViewModel.SearchCity"
|
||||||
T="ProductCategorySDto"
|
T="ProductCategorySDto"
|
||||||
Label="دسته پدر"
|
Label="دسته پدر"
|
||||||
Variant="Variant.Outlined">
|
Variant="Variant.Outlined">
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<RadzenHtmlEditor @bind-Value="@_description" class="min-h-[10rem]">
|
<RadzenHtmlEditor @bind-Value="@ViewModel.Description" class="min-h-[10rem]">
|
||||||
<RadzenHtmlEditorUndo/>
|
<RadzenHtmlEditorUndo/>
|
||||||
<RadzenHtmlEditorRedo/>
|
<RadzenHtmlEditorRedo/>
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
@ -86,148 +86,42 @@
|
||||||
|
|
||||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
<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"
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
Variant="Variant.Filled" Color="Color.Success"
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||||
Icon="@Icons.Material.Outlined.Check"
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
Variant="Variant.Filled" Color="Color.Success"
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||||
}
|
}
|
||||||
<MudSpacer />
|
<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>
|
</MudStack>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
MudDialogInstance MudDialog { get; set; }
|
MudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
void Cancel() => MudDialog.Cancel();
|
public ProductCategoryActionDialogBoxViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
private string _name = string.Empty;
|
|
||||||
private string _description = string.Empty;
|
|
||||||
private bool _isMain;
|
|
||||||
private bool _isEditing = false;
|
|
||||||
private bool _isProcessing = false;
|
|
||||||
|
|
||||||
private ProductCategorySDto? _category = null;
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public ProductCategorySDto? Category
|
public ProductCategorySDto? Category { get; set; }
|
||||||
|
|
||||||
|
protected override Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
get => _category;
|
if (Category == null)
|
||||||
set
|
ViewModel = new ProductCategoryActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, MudDialog);
|
||||||
{
|
else
|
||||||
_category = value;
|
ViewModel = new ProductCategoryActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, MudDialog,Category);
|
||||||
if (_category != null)
|
return base.OnInitializedAsync();
|
||||||
{
|
|
||||||
_name = _category.Name;
|
|
||||||
_description = _category.Description;
|
|
||||||
_isEditing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SubmitCreateAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_name.IsNullOrEmpty())
|
|
||||||
throw new AppException("لطفا نام دسته را وارد کنید");
|
|
||||||
_isProcessing = true;
|
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
|
||||||
var request = new CreateProductCategoryCommand(_name, _description,_isMain, _selectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
|
||||||
await RestWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(request, token);
|
|
||||||
MudDialog.Close();
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
MudDialog.Cancel();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
MudDialog.Cancel();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
|
|
||||||
_isProcessing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SubmitEditAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Category == null)
|
|
||||||
throw new AppException("دسته به درستی ارسال نشده است");
|
|
||||||
if (_name.IsNullOrEmpty())
|
|
||||||
throw new AppException("لطفا نام دسته را وارد کنید");
|
|
||||||
_isProcessing = true;
|
|
||||||
await Task.Delay(1000);
|
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
|
||||||
var request = new UpdateProductCategoryCommand(Category.Id, _name, _description,_isMain, _selectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
|
||||||
await RestWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(request, token);
|
|
||||||
MudDialog.Close();
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
MudDialog.Cancel();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
MudDialog.Cancel();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
|
|
||||||
_isProcessing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
|
||||||
private ProductCategorySDto? _selectedCategory;
|
|
||||||
private async Task<IEnumerable<ProductCategorySDto>> SearchCity(string city)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_productCategories.Count == 0)
|
|
||||||
{
|
|
||||||
_productCategories = await RestWrapper.ProductCategoryRestApi.ReadAll();
|
|
||||||
}
|
|
||||||
if (city.IsNullOrEmpty())
|
|
||||||
return _productCategories;
|
|
||||||
return _productCategories.Where(c => c.Name.Contains(city));
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
return _productCategories;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
return _productCategories;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly MudDialogInstance _mudDialog;
|
||||||
|
|
||||||
|
public ProductCategoryActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, MudDialogInstance mudDialog)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductCategoryActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, MudDialogInstance mudDialog,ProductCategorySDto category)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
Category = category;
|
||||||
|
}
|
||||||
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
|
||||||
|
public string Name = string.Empty;
|
||||||
|
public string Description = string.Empty;
|
||||||
|
public bool IsMain;
|
||||||
|
public bool IsEditing = false;
|
||||||
|
|
||||||
|
private ProductCategorySDto? _category = null;
|
||||||
|
[Parameter]
|
||||||
|
public ProductCategorySDto? Category
|
||||||
|
{
|
||||||
|
get => _category;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_category = value;
|
||||||
|
if (_category != null)
|
||||||
|
{
|
||||||
|
Name = _category.Name;
|
||||||
|
Description = _category.Description;
|
||||||
|
IsEditing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام دسته را وارد کنید");
|
||||||
|
IsProcessing = true;
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var request = new CreateProductCategoryCommand(Name, Description, IsMain, SelectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
||||||
|
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(request, token);
|
||||||
|
_mudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Category == null)
|
||||||
|
throw new AppException("دسته به درستی ارسال نشده است");
|
||||||
|
if (Name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام دسته را وارد کنید");
|
||||||
|
IsProcessing = true;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var request = new UpdateProductCategoryCommand(Category.Id, Name, Description, IsMain, SelectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
||||||
|
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(request, token);
|
||||||
|
_mudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
_mudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
||||||
|
public ProductCategorySDto? SelectedCategory;
|
||||||
|
public async Task<IEnumerable<ProductCategorySDto>> SearchCity(string city)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_productCategories.Count == 0)
|
||||||
|
{
|
||||||
|
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll();
|
||||||
|
}
|
||||||
|
if (city.IsNullOrEmpty())
|
||||||
|
return _productCategories;
|
||||||
|
return _productCategories.Where(c => c.Name.Contains(city));
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
return _productCategories;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
return _productCategories;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
<MudText Typo="Typo.body2">میتوانید از بین عکس های اپلود شده یکی را انتخاب کرده یا عکس جدیدی اپلود کنید</MudText>
|
<MudText Typo="Typo.body2">میتوانید از بین عکس های اپلود شده یکی را انتخاب کرده یا عکس جدیدی اپلود کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<MudFileUpload class="flex-none" T="IBrowserFile" OnFilesChanged="FileChangeForUpload">
|
<MudFileUpload class="flex-none" T="IBrowserFile" OnFilesChanged="@ViewModel.FileChangeForUpload">
|
||||||
<ButtonTemplate>
|
<ButtonTemplate>
|
||||||
|
|
||||||
<MudButton HtmlTag="label"
|
<MudButton HtmlTag="label"
|
||||||
|
@ -29,21 +29,21 @@
|
||||||
|
|
||||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام فایل" Adornment="Adornment.Start" Immediate="true"
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام فایل" Adornment="Adornment.Start" Immediate="true"
|
||||||
Clearable="true"
|
Clearable="true"
|
||||||
ValueChanged="@SearchChanged"
|
ValueChanged="@ViewModel.SearchChanged"
|
||||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium"
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
OnAdornmentClick="@SearchAsync"></MudTextField>
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
<MudContainer class="max-h-[30rem]" Style="overflow-y: scroll">
|
<MudContainer class="max-h-[30rem]" Style="overflow-y: scroll">
|
||||||
<div class="flex flex-wrap justify-center">
|
<div class="flex flex-wrap justify-center">
|
||||||
@foreach (var item in _files)
|
@foreach (var item in ViewModel.Files)
|
||||||
{
|
{
|
||||||
@if (item.Selected)
|
@if (item.Selected)
|
||||||
{
|
{
|
||||||
<MudImage @onclick="()=>UnSelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2 border-solid border-4 border-blue-500" Src="@item.GetLink()" Elevation="25" />
|
<MudImage @onclick="()=>ViewModel.UnSelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2 border-solid border-4 border-blue-500" Src="@item.GetLink()" Elevation="25" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudImage @onclick="()=>SelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2" Src="@item.GetLink()" Elevation="25" />
|
<MudImage @onclick="()=>ViewModel.SelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2" Src="@item.GetLink()" Elevation="25" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,142 +51,33 @@
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
<MudStack Row="true" class="w-full mx-1 mb-2">
|
||||||
|
|
||||||
|
|
||||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||||
Icon="@Icons.Material.Outlined.Check"
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
Variant="Variant.Filled" Color="Color.Success"
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
OnClickCallback="SelectFile"
|
OnClickCallback="ViewModel.SelectFile"
|
||||||
Content="انتخابــ" />
|
Content="انتخابــ" />
|
||||||
|
<MudCheckBox class="my-auto" T="bool" Size="Size.Large" @bind-Value="@ViewModel.IsPrimary" Label="عکس اصلی" Color="Color.Primary" />
|
||||||
|
<MudCheckBox class="my-auto" T="bool" Size="Size.Large" @bind-Value="@ViewModel.IsHeader" Label="عکس هدر" Color="Color.Primary" />
|
||||||
<MudSpacer />
|
<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>
|
</MudStack>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
private void SelectFile(StorageFileSDto item)
|
|
||||||
{
|
|
||||||
var pastSelect = _files.FirstOrDefault(f => f.Selected);
|
|
||||||
if (pastSelect != null)
|
|
||||||
pastSelect.Selected = false;
|
|
||||||
item.Selected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnSelectFile(StorageFileSDto item) => item.Selected = false;
|
|
||||||
|
|
||||||
public void SearchChanged(string search)
|
|
||||||
{
|
|
||||||
if (search.IsNullOrEmpty() && !_search.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
_files.Clear();
|
|
||||||
_originalFiles.ForEach(f=>_files.Add(f));
|
|
||||||
}
|
|
||||||
_search = search;
|
|
||||||
}
|
|
||||||
public void SearchAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_search.IsNullOrEmpty())
|
|
||||||
throw new AppException("دسته بندی برای جست جو وارد نشده است");
|
|
||||||
_files.Clear();
|
|
||||||
foreach (var storageFileSDto in _originalFiles.Where(f => f.FileName.ToLower().Trim().Contains(_search.ToLower().Trim())))
|
|
||||||
_files.Add(storageFileSDto);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SelectFile()
|
|
||||||
{
|
|
||||||
var selected = _files.FirstOrDefault(f => f.Selected);
|
|
||||||
if (selected == null)
|
|
||||||
throw new Exception("یک فایل را انتخاب کنید");
|
|
||||||
MudDialog.Close(selected);
|
|
||||||
}
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
MudDialogInstance MudDialog { get; set; }
|
MudDialogInstance MudDialog { get; set; }
|
||||||
void Cancel() => MudDialog.Cancel();
|
|
||||||
private readonly ObservableCollection<StorageFileSDto> _files = new ObservableCollection<StorageFileSDto>();
|
public StorageDialogBoxViewModel ViewModel { get; set; }
|
||||||
private List<StorageFileSDto> _originalFiles = new List<StorageFileSDto>();
|
|
||||||
private bool _isProcessing = false;
|
|
||||||
private string _search = string.Empty;
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
ViewModel = new StorageDialogBoxViewModel(RestWrapper,UserUtility,Snackbar,MudDialog);
|
||||||
{
|
await ViewModel.InitializeAsync();
|
||||||
_isProcessing = true;
|
|
||||||
_files.Clear();
|
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
|
||||||
var files = await RestWrapper.FileRestApi.GetFilesAsync(token);
|
|
||||||
files.ForEach(f => _files.Add(f));
|
|
||||||
_originalFiles = files;
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_isProcessing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FileChangeForUpload(InputFileChangeEventArgs obj)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_isProcessing = true;
|
|
||||||
using var memoryStream = new MemoryStream();
|
|
||||||
var file = obj.File;
|
|
||||||
var stream = file.OpenReadStream();
|
|
||||||
await stream.CopyToAsync(memoryStream);
|
|
||||||
|
|
||||||
var fileUpload = new FileUploadRequest
|
|
||||||
{
|
|
||||||
ContentType = file.ContentType,
|
|
||||||
FileName = file.Name,
|
|
||||||
FileUploadType = FileUploadType.Image,
|
|
||||||
StringBaseFile = Convert.ToBase64String(memoryStream.ToArray())
|
|
||||||
};
|
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
|
||||||
var rest = await RestWrapper.FileRestApi.UploadFileAsync(fileUpload, token);
|
|
||||||
_files.Insert(0, new StorageFileSDto
|
|
||||||
{
|
|
||||||
FileLocation = rest.FileLocation,
|
|
||||||
FileName = rest.FileName,
|
|
||||||
FileType = StorageFileType.Image
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (ApiException ex)
|
|
||||||
{
|
|
||||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
|
||||||
if (exe != null)
|
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_isProcessing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class StorageDialogBoxViewModel:BaseViewModel
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
|
||||||
|
private readonly MudDialogInstance _mudDialog;
|
||||||
|
|
||||||
|
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||||
|
public List<StorageFileSDto> OriginalFiles = new List<StorageFileSDto>();
|
||||||
|
public string Search = string.Empty;
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
public bool IsHeader { get; set; }
|
||||||
|
|
||||||
|
public StorageDialogBoxViewModel(IRestWrapper restWrapper, IUserUtility userUtility, ISnackbar snackbar, MudDialogInstance mudDialog)
|
||||||
|
{
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
public void SelectFile(StorageFileSDto item)
|
||||||
|
{
|
||||||
|
var pastSelect = Files.FirstOrDefault(f => f.Selected);
|
||||||
|
if (pastSelect != null)
|
||||||
|
pastSelect.Selected = false;
|
||||||
|
item.Selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnSelectFile(StorageFileSDto item) => item.Selected = false;
|
||||||
|
|
||||||
|
public void SearchChanged(string search)
|
||||||
|
{
|
||||||
|
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
Files.Clear();
|
||||||
|
OriginalFiles.ForEach(f => Files.Add(f));
|
||||||
|
}
|
||||||
|
Search = search;
|
||||||
|
}
|
||||||
|
public void SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام فایل برای جست جو وارد نشده است");
|
||||||
|
Files.Clear();
|
||||||
|
foreach (var storageFileSDto in OriginalFiles.Where(f => f.FileName.ToLower().Trim().Contains(Search.ToLower().Trim())))
|
||||||
|
Files.Add(storageFileSDto);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectFile()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var selected = Files.FirstOrDefault(f => f.Selected);
|
||||||
|
if (selected == null)
|
||||||
|
throw new Exception("یک فایل را انتخاب کنید");
|
||||||
|
selected.IsHeader = IsHeader;
|
||||||
|
selected.IsPrimary = IsPrimary;
|
||||||
|
_mudDialog.Close(selected);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
Files.Clear();
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var files = await _restWrapper.FileRestApi.GetFilesAsync(token);
|
||||||
|
files.ForEach(f => Files.Add(f));
|
||||||
|
OriginalFiles = files;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task FileChangeForUpload(InputFileChangeEventArgs obj)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
using var memoryStream = new MemoryStream();
|
||||||
|
var file = obj.File;
|
||||||
|
var stream = file.OpenReadStream();
|
||||||
|
await stream.CopyToAsync(memoryStream);
|
||||||
|
|
||||||
|
var fileUpload = new FileUploadRequest
|
||||||
|
{
|
||||||
|
ContentType = file.ContentType,
|
||||||
|
FileName = file.Name,
|
||||||
|
FileUploadType = FileUploadType.Image,
|
||||||
|
StringBaseFile = Convert.ToBase64String(memoryStream.ToArray())
|
||||||
|
};
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
var rest = await _restWrapper.FileRestApi.UploadFileAsync(fileUpload, token);
|
||||||
|
Files.Insert(0, new StorageFileSDto
|
||||||
|
{
|
||||||
|
FileLocation = rest.FileLocation,
|
||||||
|
FileName = rest.FileName,
|
||||||
|
FileType = StorageFileType.Image
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
_snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
_snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,4 +14,6 @@ public static class Address
|
||||||
public static string ProductController = $"{BaseAddress}/product";
|
public static string ProductController = $"{BaseAddress}/product";
|
||||||
public static string BrandController = $"{BaseAddress}/brand";
|
public static string BrandController = $"{BaseAddress}/brand";
|
||||||
public static string FileController => $"{BaseAddress}/file";
|
public static string FileController => $"{BaseAddress}/file";
|
||||||
|
public static string BlogController => $"{BaseAddress}/blog";
|
||||||
|
public static string BlogCategoryController => $"{BaseAddress}/blog/category";
|
||||||
}
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
@page "/blog/categories"
|
||||||
|
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||||
|
|
||||||
|
@inject IDialogService DialogService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
|
||||||
|
<MudStack class="w-full p-8 h-screen bg-[--color-background]">
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12">
|
||||||
|
<MudStack Row="true" class="mb-5">
|
||||||
|
<MudText Typo="Typo.h4">دسته بندی بلاگـــــ ها</MudText>
|
||||||
|
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
DisableElevation="true"
|
||||||
|
StartIcon="@Icons.Material.Outlined.Add"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
OnClick="@ViewModel.AddBlogCategoryClicked"
|
||||||
|
class="my-auto">افزودن دسته بندی</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
<MudPaper>
|
||||||
|
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||||
|
T="BlogCategorySDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||||
|
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||||
|
SortMode="@SortMode.None" Groupable="false">
|
||||||
|
|
||||||
|
<ToolBarContent>
|
||||||
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||||
|
Clearable="true"
|
||||||
|
ValueChanged="@ViewModel.SearchChanged"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||||
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
|
</ToolBarContent>
|
||||||
|
<Columns>
|
||||||
|
<PropertyColumn Title="عنوان " Property="arg => arg.Name" />
|
||||||
|
<PropertyColumn Title="توضیحاتــ" Property="arg => arg.Description" />
|
||||||
|
<TemplateColumn CellClass="d-flex justify-end">
|
||||||
|
<CellTemplate>
|
||||||
|
<MudStack Row="true">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
Color="@Color.Info"
|
||||||
|
OnClick="async()=>await ViewModel.EditBlogCategoryClicked(context.Item)" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
OnClick="async () => await ViewModel.DeleteBlogCategoryAsync(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="my-4 mx-auto" />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
|
</MudDataGrid>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
public BlogCategoriesPageViewModel ViewModel { get; set; }
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
ViewModel = new BlogCategoriesPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
using NetinaShop.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class BlogCategoriesPageViewModel:BaseViewModel<ObservableCollection<BlogCategorySDto>>
|
||||||
|
{
|
||||||
|
private readonly NavigationManager _navigationManager;
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
|
||||||
|
public string Search = string.Empty;
|
||||||
|
public int CurrentPage = 0;
|
||||||
|
public int PageCount = 1;
|
||||||
|
|
||||||
|
public BlogCategoriesPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||||
|
{
|
||||||
|
_navigationManager = navigationManager;
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.CrudDtoApiRest<BlogCategory, BlogCategorySDto, Guid>(Address.BlogCategoryController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
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 ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page - 1;
|
||||||
|
if (CurrentPage > PageCount - 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
|
||||||
|
List<BlogCategorySDto> dto = new List<BlogCategorySDto>();
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.CrudDtoApiRest<BlogCategory, BlogCategorySDto, Guid>(Address.BlogCategoryController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.BlogCategoryRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddBlogCategoryClicked()
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
await _dialogService.ShowAsync<BlogCategoryActionDialogBox>("افزودن دسته بندی جدید", maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EditBlogCategoryClicked(BlogCategorySDto blogCategory)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<BlogCategoryActionDialogBox>();
|
||||||
|
parameters.Add(x => x.BlogCategory, blogCategory);
|
||||||
|
await _dialogService.ShowAsync<BlogCategoryActionDialogBox>($"ویرایش دسته بندی {blogCategory.Name}", parameters, maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteBlogCategoryAsync(Guid selectedCategoryId)
|
||||||
|
{
|
||||||
|
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||||
|
var parameters = new DialogParameters<QuestionDialog>();
|
||||||
|
parameters.Add(x => x.ContentText, "آیا از حذف بلاگ اطمینان دارید ?");
|
||||||
|
var dialogReference = await _dialogService.ShowAsync<QuestionDialog>("حذف بلاگ", parameters, options);
|
||||||
|
var result = await dialogReference.Result;
|
||||||
|
if (!result.Canceled)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = true;
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
await _restWrapper.CrudDtoApiRest<BlogCategory, BlogCategorySDto, Guid>(Address.BlogCategoryController)
|
||||||
|
.Delete(selectedCategoryId, token);
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SearchChanged(string search)
|
||||||
|
{
|
||||||
|
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||||
|
await InitializeAsync();
|
||||||
|
Search = search;
|
||||||
|
}
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام دسته بندی برای جست جو وارد نشده است");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.BlogCategoryRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
@page "/blogs"
|
||||||
|
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||||
|
|
||||||
|
@inject IDialogService DialogService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
|
||||||
|
<MudStack class="w-full p-8 h-screen bg-[--color-background]">
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12">
|
||||||
|
<MudStack Row="true" class="mb-5">
|
||||||
|
<MudText Typo="Typo.h4">بلاگـــــ ها</MudText>
|
||||||
|
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
DisableElevation="true"
|
||||||
|
StartIcon="@Icons.Material.Outlined.Add"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
OnClick="@ViewModel.AddBlogClicked"
|
||||||
|
class="my-auto">افزودن بلاگ</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
<MudPaper>
|
||||||
|
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||||
|
T="BlogSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||||
|
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||||
|
SortMode="@SortMode.None" Groupable="false">
|
||||||
|
|
||||||
|
<ToolBarContent>
|
||||||
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||||
|
Clearable="true"
|
||||||
|
ValueChanged="@ViewModel.SearchChanged"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||||
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
|
</ToolBarContent>
|
||||||
|
<Columns>
|
||||||
|
<PropertyColumn Title="عنوان بلاگ" Property="arg => arg.Title" />
|
||||||
|
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName" />
|
||||||
|
<PropertyColumn Title="میانگین زمان مطالعه" Property="arg => arg.ReadingTime" />
|
||||||
|
<TemplateColumn CellClass="d-flex justify-end">
|
||||||
|
<CellTemplate>
|
||||||
|
<MudStack Row="true">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
Color="@Color.Info"
|
||||||
|
OnClick="async()=>await ViewModel.EditBlogClicked(context.Item)" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
OnClick="async () => await ViewModel.DeleteBlogAsync(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="my-4 mx-auto" />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
|
</MudDataGrid>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
public BlogsPageViewModel ViewModel { get; set; }
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
ViewModel = new BlogsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
using NetinaShop.Domain.Entities.Blogs;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class BlogsPageViewModel : BaseViewModel<ObservableCollection<BlogSDto>>
|
||||||
|
{
|
||||||
|
private readonly NavigationManager _navigationManager;
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
|
||||||
|
public string Search = string.Empty;
|
||||||
|
public int CurrentPage = 0;
|
||||||
|
public int PageCount = 1;
|
||||||
|
|
||||||
|
public BlogsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||||
|
{
|
||||||
|
_navigationManager = navigationManager;
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.CrudDtoApiRest<Blog, BlogSDto, Guid>(Address.BlogController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
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 ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page - 1;
|
||||||
|
if (CurrentPage > PageCount - 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
|
||||||
|
List<BlogSDto> dto = new List<BlogSDto>();
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.CrudDtoApiRest<Blog, BlogSDto, Guid>(Address.BlogController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.BlogRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddBlogClicked()
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
await _dialogService.ShowAsync<BlogActionDialogBox>("افزودن بلاگ جدید", maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EditBlogClicked(BlogSDto blog)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<BlogActionDialogBox>();
|
||||||
|
parameters.Add(x => x.Blog, blog);
|
||||||
|
await _dialogService.ShowAsync<BlogActionDialogBox>($"ویرایش بلاگ {blog.Title}", parameters, maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteBlogAsync(Guid selectedCategoryId)
|
||||||
|
{
|
||||||
|
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||||
|
var parameters = new DialogParameters<QuestionDialog>();
|
||||||
|
parameters.Add(x => x.ContentText, "آیا از حذف بلاگ اطمینان دارید ?");
|
||||||
|
var dialogReference = await _dialogService.ShowAsync<QuestionDialog>("حذف بلاگ", parameters, options);
|
||||||
|
var result = await dialogReference.Result;
|
||||||
|
if (!result.Canceled)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = true;
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
await _restWrapper.CrudDtoApiRest<Blog, BlogSDto, Guid>(Address.BlogController)
|
||||||
|
.Delete(selectedCategoryId, token);
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SearchChanged(string search)
|
||||||
|
{
|
||||||
|
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||||
|
await InitializeAsync();
|
||||||
|
Search = search;
|
||||||
|
}
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام بلاگ برای جست جو وارد نشده است");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.BlogRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,10 +24,15 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudPaper>
|
<MudPaper>
|
||||||
<MudDataGrid Striped="true" T="BrandSDto" Items="@ViewModel.PageDto" Filterable="false" Loading="@ViewModel.IsProcessing"
|
<MudDataGrid Striped="true" T="BrandSDto" Items="@ViewModel.PageDto" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||||
|
CurrentPage="@ViewModel.CurrentPage"
|
||||||
|
RowsPerPage="15"
|
||||||
SortMode="@SortMode.None" Groupable="false">
|
SortMode="@SortMode.None" Groupable="false">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"></MudTextField>
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||||
|
ValueChanged="@ViewModel.SearchChanged"
|
||||||
|
Clearable="true"
|
||||||
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
</ToolBarContent>
|
</ToolBarContent>
|
||||||
<Columns>
|
<Columns>
|
||||||
<PropertyColumn Title="نام برند" Property="arg => arg.Name" />
|
<PropertyColumn Title="نام برند" Property="arg => arg.Name" />
|
||||||
|
@ -48,7 +53,11 @@
|
||||||
<TemplateColumn CellClass="d-flex justify-end">
|
<TemplateColumn CellClass="d-flex justify-end">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="@Size.Small" Variant="@Variant.Outlined" Color="@Color.Info"></MudIconButton>
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
Color="@Color.Info"
|
||||||
|
OnClick="async()=>await ViewModel.EditBrandAsync(context.Item)"></MudIconButton>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
Size="@Size.Small"
|
Size="@Size.Small"
|
||||||
Variant="@Variant.Outlined"
|
Variant="@Variant.Outlined"
|
||||||
|
@ -58,6 +67,14 @@
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
<PagerContent>
|
||||||
|
<MudStack Row="true" class="w-full">
|
||||||
|
|
||||||
|
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||||
|
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto" />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
|
@ -9,6 +9,9 @@ public class BrandsPageViewModel : BaseViewModel<List<BrandSDto>>
|
||||||
private readonly IUserUtility _userUtility;
|
private readonly IUserUtility _userUtility;
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly IRestWrapper _restWrapper;
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
public string Search = string.Empty;
|
||||||
|
public int CurrentPage = 0;
|
||||||
|
public int PageCount = 1;
|
||||||
|
|
||||||
public BrandsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
public BrandsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +54,12 @@ public class BrandsPageViewModel : BaseViewModel<List<BrandSDto>>
|
||||||
await _dialogService.ShowAsync<BrandActionDialogBox>("افزودن برند جدید", maxWidth);
|
await _dialogService.ShowAsync<BrandActionDialogBox>("افزودن برند جدید", maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task EditBrandAsync(BrandSDto brand)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<BrandActionDialogBox> { { x => x.Brand, brand } };
|
||||||
|
await _dialogService.ShowAsync<BrandActionDialogBox>($"ویرایش برند {brand.Name}", parameters, maxWidth);
|
||||||
|
}
|
||||||
public async Task DeleteBrandAsync(Guid selectedCategoryId)
|
public async Task DeleteBrandAsync(Guid selectedCategoryId)
|
||||||
{
|
{
|
||||||
var options = new DialogOptions { CloseOnEscapeKey = true };
|
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||||
|
@ -88,4 +97,85 @@ public class BrandsPageViewModel : BaseViewModel<List<BrandSDto>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task SearchChanged(string search)
|
||||||
|
{
|
||||||
|
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||||
|
await InitializeAsync();
|
||||||
|
Search = search;
|
||||||
|
}
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام برند برای جست جو وارد نشده است");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.BrandRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page - 1;
|
||||||
|
if (CurrentPage > PageCount - 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
|
||||||
|
List<BrandSDto> dto = new List<BrandSDto>();
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.CrudDtoApiRest<Brand, BrandSDto, Guid>(Address.BrandController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.BrandRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IBlogCategoryRestApi
|
||||||
|
{
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogCategorySDto>> ReadAll();
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogCategorySDto>> ReadAll([Query] int page);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogCategorySDto>> ReadAll([Query] int page, [Query] string productName);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogCategorySDto>> ReadAll([Query] string blogCategoryName);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IBlogRestApi
|
||||||
|
{
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogSDto>> ReadAll();
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogSDto>> ReadAll([Query] int page);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BlogSDto>> ReadAll([Query] int page, [Query] string blogName);
|
||||||
|
}
|
|
@ -12,4 +12,6 @@ public interface IRestWrapper
|
||||||
public IProductRestApi ProductRestApi { get; }
|
public IProductRestApi ProductRestApi { get; }
|
||||||
public IBrandRestApi BrandRestApi { get; }
|
public IBrandRestApi BrandRestApi { get; }
|
||||||
public IFileRestApi FileRestApi { get; }
|
public IFileRestApi FileRestApi { get; }
|
||||||
|
public IBlogRestApi BlogRestApi { get; }
|
||||||
|
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
|
||||||
}
|
}
|
|
@ -24,4 +24,6 @@ public class RestWrapper : IRestWrapper
|
||||||
public IProductRestApi ProductRestApi => RestService.For<IProductRestApi>(Address.ProductController, setting);
|
public IProductRestApi ProductRestApi => RestService.For<IProductRestApi>(Address.ProductController, setting);
|
||||||
public IBrandRestApi BrandRestApi => RestService.For<IBrandRestApi>(Address.BrandController, setting);
|
public IBrandRestApi BrandRestApi => RestService.For<IBrandRestApi>(Address.BrandController, setting);
|
||||||
public IFileRestApi FileRestApi => RestService.For<IFileRestApi>(Address.FileController, setting);
|
public IFileRestApi FileRestApi => RestService.For<IFileRestApi>(Address.FileController, setting);
|
||||||
|
public IBlogRestApi BlogRestApi => RestService.For<IBlogRestApi>(Address.BlogController, setting);
|
||||||
|
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For<IBlogCategoryRestApi>(Address.BlogCategoryController, setting);
|
||||||
}
|
}
|
|
@ -504,6 +504,9 @@ video {
|
||||||
.absolute {
|
.absolute {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
.bottom-0 {
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
.m-1 {
|
.m-1 {
|
||||||
margin: 0.25rem;
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -610,6 +613,10 @@ video {
|
||||||
.h-7 {
|
.h-7 {
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
}
|
}
|
||||||
|
.h-fit {
|
||||||
|
height: -moz-fit-content;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
.h-full {
|
.h-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -622,6 +629,12 @@ video {
|
||||||
.min-h-\[10rem\] {
|
.min-h-\[10rem\] {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
|
.min-h-\[28rem\] {
|
||||||
|
min-height: 28rem;
|
||||||
|
}
|
||||||
|
.min-h-\[33rem\] {
|
||||||
|
min-height: 33rem;
|
||||||
|
}
|
||||||
.w-10 {
|
.w-10 {
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
}
|
}
|
||||||
|
@ -712,6 +725,14 @@ video {
|
||||||
.bg-\[--color-background\] {
|
.bg-\[--color-background\] {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
.bg-blue-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.bg-pink-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(236 72 153 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
.bg-transparent {
|
.bg-transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
@ -728,10 +749,26 @@ video {
|
||||||
.p-8 {
|
.p-8 {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
.px-1 {
|
||||||
|
padding-left: 0.25rem;
|
||||||
|
padding-right: 0.25rem;
|
||||||
|
}
|
||||||
|
.px-1\.5 {
|
||||||
|
padding-left: 0.375rem;
|
||||||
|
padding-right: 0.375rem;
|
||||||
|
}
|
||||||
.px-4 {
|
.px-4 {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
.py-0 {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.py-0\.5 {
|
||||||
|
padding-top: 0.125rem;
|
||||||
|
padding-bottom: 0.125rem;
|
||||||
|
}
|
||||||
.py-2 {
|
.py-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
@ -772,6 +809,10 @@ video {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
.text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
.shadow-sm {
|
.shadow-sm {
|
||||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
|
|
@ -558,6 +558,10 @@ video {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bottom-0 {
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.m-1 {
|
.m-1 {
|
||||||
margin: 0.25rem;
|
margin: 0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -696,6 +700,11 @@ video {
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-fit {
|
||||||
|
height: -moz-fit-content;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
.h-full {
|
.h-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -712,6 +721,14 @@ video {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.min-h-\[28rem\] {
|
||||||
|
min-height: 28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-h-\[33rem\] {
|
||||||
|
min-height: 33rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-10 {
|
.w-10 {
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
}
|
}
|
||||||
|
@ -831,6 +848,16 @@ video {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-blue-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-pink-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(236 72 153 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-transparent {
|
.bg-transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
@ -852,11 +879,31 @@ video {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.px-1 {
|
||||||
|
padding-left: 0.25rem;
|
||||||
|
padding-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-1\.5 {
|
||||||
|
padding-left: 0.375rem;
|
||||||
|
padding-right: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
.px-4 {
|
.px-4 {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.py-0 {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-0\.5 {
|
||||||
|
padding-top: 0.125rem;
|
||||||
|
padding-bottom: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.py-2 {
|
.py-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
@ -909,6 +956,11 @@ video {
|
||||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.shadow-sm {
|
.shadow-sm {
|
||||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
|
Loading…
Reference in New Issue