feat : complete create and edit product , add file controller
add upload and get files in file controller , complete create and edit product with uploading imagesrelease
parent
639d858476
commit
d6e0983f13
|
@ -1,105 +1,270 @@
|
||||||
@using Radzen.Blazor
|
@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">
|
<MudDialog class="mx-auto">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<MudStack>
|
<MudStack>
|
||||||
<MudDivider/>
|
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||||
<MudStack Spacing="0">
|
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||||
|
<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">
|
|
||||||
<MudTextField T="string" Label="نام فارسی محصول" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="4" md="6">
|
|
||||||
<MudTextField T="string" Label="نام انگلیسی محصول" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="4" md="6">
|
|
||||||
<MudTextField T="string" Label="قیمت محصول" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="4" md="6">
|
|
||||||
<MudTextField T="string" Label="مبلغ بسته بندی" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="4" md="6">
|
|
||||||
<MudTextField T="string" Label="بیشترین خرید" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="4" md="6">
|
|
||||||
<MudTextField T="string" Label="ایا ارسال سریع دارد" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem lg="12" md="12">
|
|
||||||
<MudTextField T="string" Label="توضیحاتــ" Variant="Variant.Outlined"></MudTextField>
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudStack class="mt-4 mx-4" Spacing="0">
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
<MudItem lg="4" md="6">
|
||||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
<MudTextField @bind-Value="@ViewModel.PersianName" T="string" Label="نام فارسی محصول" Variant="Variant.Outlined" />
|
||||||
</MudStack>
|
</MudItem>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="4" md="6">
|
||||||
<RadzenHtmlEditor class="min-h-[10rem]">
|
<MudTextField @bind-Value="@ViewModel.EnglishName" T="string" Label="نام انگلیسی محصول" Variant="Variant.Outlined" />
|
||||||
<RadzenHtmlEditorUndo />
|
</MudItem>
|
||||||
<RadzenHtmlEditorRedo />
|
<MudItem lg="4" md="6">
|
||||||
<RadzenHtmlEditorSeparator />
|
|
||||||
|
|
||||||
<RadzenHtmlEditorFormatBlock />
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel._selectedCategory"
|
||||||
<RadzenHtmlEditorSeparator />
|
SearchFunc="ViewModel.SearchProductCategory"
|
||||||
|
T="ProductCategorySDto"
|
||||||
|
Label="دسته بندی"
|
||||||
|
Variant="Variant.Outlined">
|
||||||
|
<ProgressIndicatorInPopoverTemplate>
|
||||||
|
<MudList Clickable="false">
|
||||||
|
<MudListItem>
|
||||||
|
<div class="flex flex-row w-full mx-auto">
|
||||||
|
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||||
|
</div>
|
||||||
|
</MudListItem>
|
||||||
|
</MudList>
|
||||||
|
</ProgressIndicatorInPopoverTemplate>
|
||||||
|
<ItemTemplate Context="e">
|
||||||
|
<p>@e.Name</p>
|
||||||
|
</ItemTemplate>
|
||||||
|
</MudAutocomplete>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
|
||||||
<RadzenHtmlEditorAlignLeft />
|
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel._selectedBrand"
|
||||||
<RadzenHtmlEditorAlignCenter />
|
SearchFunc="ViewModel.SearchBrand"
|
||||||
<RadzenHtmlEditorAlignRight />
|
T="BrandSDto"
|
||||||
<RadzenHtmlEditorJustify />
|
Label="برند"
|
||||||
<RadzenHtmlEditorSeparator />
|
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">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.Cost" T="double" Label="قیمت محصول" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.PackingCost" T="double" Label="مبلغ بسته بندی" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.MaxOrder" T="int" Label="بیشترین خرید" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.Warranty" T="string" Label="گارانتی" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<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="false" />
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="4" md="6">
|
||||||
|
<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="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>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="ویژگی های کلی" Icon="@Icons.Material.Outlined.AutoGraph">
|
||||||
|
|
||||||
<RadzenHtmlEditorSource />
|
<MudStack class="mt-4" Spacing="0">
|
||||||
<RadzenHtmlEditorBold />
|
|
||||||
<RadzenHtmlEditorItalic />
|
|
||||||
<RadzenHtmlEditorUnderline />
|
|
||||||
<RadzenHtmlEditorStrikeThrough />
|
|
||||||
<RadzenHtmlEditorRemoveFormat />
|
|
||||||
<RadzenHtmlEditorSeparator />
|
|
||||||
|
|
||||||
</RadzenHtmlEditor>
|
<MudText Typo="Typo.h6">ویژگی های کلی</MudText>
|
||||||
|
<MudText Typo="Typo.caption">می توانید ویگی های تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
|
||||||
</MudItem>
|
<MudItem lg="4" md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.SpecificationTitle" T="string" Label="عنوان" Variant="Variant.Outlined"></MudTextField>
|
||||||
<MudStack class="mt-4 mb-10 mx-4" Spacing="0">
|
</MudItem>
|
||||||
|
|
||||||
<MudText Typo="Typo.h6">تصاویر محصول</MudText>
|
<MudItem lg="4" md="6">
|
||||||
<MudText Typo="Typo.caption">می توانید برای محصول چند تصویر اپلود کنید</MudText>
|
<MudTextField @bind-Value="@ViewModel.SpecificationValue" T="string" Label="مقدار" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudStack>
|
</MudItem>
|
||||||
</MudGrid>
|
|
||||||
|
<MudItem lg="4" md="12">
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Size="Size.Large"
|
||||||
|
Color="Color.Info"
|
||||||
|
class="w-full py-3 mt-2"
|
||||||
|
OnClick="ViewModel.AddSpecification"
|
||||||
|
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="12">
|
||||||
|
<MudDataGrid Items="@ViewModel.Specifications" Elevation="0" Outlined="true" Bordered="true" Striped="true" Filterable="false" SortMode="@SortMode.None" Groupable="false">
|
||||||
|
<Columns>
|
||||||
|
<PropertyColumn Property="x => x.Title" Title="عنوان" />
|
||||||
|
<PropertyColumn Property="x => x.Value" Title="مقدار" />
|
||||||
|
<TemplateColumn T="SpecificationSDto" CellClass="d-flex justify-end">
|
||||||
|
<CellTemplate>
|
||||||
|
<MudStack Row>
|
||||||
|
<MudButton DisableElevation="true"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Filled"
|
||||||
|
OnClick="()=>ViewModel.RemoveSpecification(context.Item)"
|
||||||
|
Color="@Color.Error"
|
||||||
|
StartIcon="@Icons.Material.Outlined.Delete">حذف</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</CellTemplate>
|
||||||
|
</TemplateColumn>
|
||||||
|
</Columns>
|
||||||
|
</MudDataGrid>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="توضیحات تکمیلی" Icon="@Icons.Material.Outlined.Article">
|
||||||
|
|
||||||
|
<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.ExpertCheck" class="min-h-[10rem]">
|
||||||
|
<RadzenHtmlEditorUndo />
|
||||||
|
<RadzenHtmlEditorRedo />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorFormatBlock />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorAlignLeft />
|
||||||
|
<RadzenHtmlEditorAlignCenter />
|
||||||
|
<RadzenHtmlEditorAlignRight />
|
||||||
|
<RadzenHtmlEditorJustify />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorSource />
|
||||||
|
<RadzenHtmlEditorBold />
|
||||||
|
<RadzenHtmlEditorItalic />
|
||||||
|
<RadzenHtmlEditorUnderline />
|
||||||
|
<RadzenHtmlEditorStrikeThrough />
|
||||||
|
<RadzenHtmlEditorRemoveFormat />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
</RadzenHtmlEditor>
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</MudTabPanel>
|
||||||
|
</MudTabs>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudStack class="w-full" Row="true">
|
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||||
<MudButton DisableElevation="true" Size="Size.Large" StartIcon="@Icons.Material.Outlined.Check" Variant="Variant.Filled" Color="Color.Success" OnClick="Submit">تایید</MudButton>
|
|
||||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
|
||||||
|
|
||||||
</MudStack>
|
@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>
|
</DialogActions>
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter]
|
||||||
|
MudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
void Submit() => MudDialog.Close(DialogResult.Ok(true));
|
|
||||||
void Cancel() => MudDialog.Cancel();
|
|
||||||
|
|
||||||
private bool _isEditing = false;
|
|
||||||
private bool _isProcessing = false;
|
|
||||||
|
|
||||||
private ProductSDto? _product = null;
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public ProductSDto? Product
|
public ProductSDto? Product { get; set; }
|
||||||
|
|
||||||
|
public ProductActionDialogBoxViewModel ViewModel { get; set; }
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
get => _product;
|
if (Product == null)
|
||||||
set
|
ViewModel = new ProductActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
|
||||||
{
|
else
|
||||||
_product = value;
|
ViewModel = new ProductActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Product);
|
||||||
if (_product != null)
|
await ViewModel.InitializeAsync();
|
||||||
{
|
await base.OnInitializedAsync();
|
||||||
_isEditing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly MudDialogInstance _mudDialog;
|
||||||
|
|
||||||
|
public ProductActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
}
|
||||||
|
public ProductActionDialogBoxViewModel(ISnackbar snackbar,
|
||||||
|
IRestWrapper restWrapper,
|
||||||
|
IUserUtility userUtility,
|
||||||
|
IDialogService dialogService,
|
||||||
|
MudDialogInstance mudDialog,
|
||||||
|
ProductSDto product)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
Product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProductSDto? _product = null;
|
||||||
|
public ProductSDto? Product
|
||||||
|
{
|
||||||
|
get => _product;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_product = value;
|
||||||
|
if (_product != null)
|
||||||
|
{
|
||||||
|
IsEditing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
|
||||||
|
public bool IsEditing = false;
|
||||||
|
public string ExpertCheck = string.Empty;
|
||||||
|
public string Summery = string.Empty;
|
||||||
|
public bool BeDisplayed = true;
|
||||||
|
public bool HasExpressDelivery = false;
|
||||||
|
public string PersianName = string.Empty;
|
||||||
|
public string EnglishName = string.Empty;
|
||||||
|
public double Cost;
|
||||||
|
public double PackingCost;
|
||||||
|
public int MaxOrder;
|
||||||
|
public string Warranty = string.Empty;
|
||||||
|
public string Tags = string.Empty;
|
||||||
|
|
||||||
|
public string SpecificationTitle = string.Empty;
|
||||||
|
public string SpecificationValue = string.Empty;
|
||||||
|
public readonly ObservableCollection<SpecificationSDto> Specifications = new ObservableCollection<SpecificationSDto>();
|
||||||
|
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (Product == null || Product.Id == default)
|
||||||
|
throw new Exception("محصول اشتباه است");
|
||||||
|
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());
|
||||||
|
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(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 void AddSpecification()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (SpecificationTitle.IsNullOrEmpty())
|
||||||
|
throw new AppException("عنوان ویژگی مورد نظر را وارد کنید");
|
||||||
|
if (SpecificationValue.IsNullOrEmpty())
|
||||||
|
throw new AppException("مقدار ویژگی مورد نظر را وارد کنید");
|
||||||
|
Specifications.Add(new SpecificationSDto { Title = SpecificationTitle.ToString(), Value = SpecificationValue.ToString() });
|
||||||
|
|
||||||
|
SpecificationTitle = string.Empty;
|
||||||
|
SpecificationValue = string.Empty;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSpecification(SpecificationSDto specification)
|
||||||
|
{
|
||||||
|
var spec = Specifications.FirstOrDefault(s => s.Value == specification.Value && s.Title == specification.Title);
|
||||||
|
if (spec != null)
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
</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="@_isMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
<MudSelectItem T="bool" Value="true" ></MudSelectItem>
|
<MudSelectItem T="bool" Value="true" />
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
@using NetinaShop.AdminPanel.PWA.Extensions
|
||||||
|
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
|
||||||
|
<MudDialog class="mx-auto">
|
||||||
|
<DialogContent>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<MudStack class="grow " Spacing="0">
|
||||||
|
<MudText Typo="Typo.h6">انتخاب یا اپلود عکس جدید</MudText>
|
||||||
|
<MudText Typo="Typo.body2">میتوانید از بین عکس های اپلود شده یکی را انتخاب کرده یا عکس جدیدی اپلود کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudFileUpload class="flex-none" T="IBrowserFile" OnFilesChanged="FileChangeForUpload">
|
||||||
|
<ButtonTemplate>
|
||||||
|
|
||||||
|
<MudButton HtmlTag="label"
|
||||||
|
class="h-full"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Info"
|
||||||
|
StartIcon="@Icons.Material.Filled.CloudUpload"
|
||||||
|
for="@context.Id">
|
||||||
|
اپلود فایل جدید
|
||||||
|
</MudButton>
|
||||||
|
</ButtonTemplate>
|
||||||
|
</MudFileUpload>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام فایل" Adornment="Adornment.Start" Immediate="true"
|
||||||
|
Clearable="true"
|
||||||
|
ValueChanged="@SearchChanged"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
OnAdornmentClick="@SearchAsync"></MudTextField>
|
||||||
|
<MudContainer class="max-h-[30rem]" Style="overflow-y: scroll">
|
||||||
|
<div class="flex flex-wrap justify-center">
|
||||||
|
@foreach (var item in _files)
|
||||||
|
{
|
||||||
|
@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" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudImage @onclick="()=>SelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2" Src="@item.GetLink()" Elevation="25" />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</MudContainer>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<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"
|
||||||
|
OnClickCallback="SelectFile"
|
||||||
|
Content="انتخابــ" />
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
@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]
|
||||||
|
MudDialogInstance MudDialog { get; set; }
|
||||||
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
private readonly ObservableCollection<StorageFileSDto> _files = new ObservableCollection<StorageFileSDto>();
|
||||||
|
private List<StorageFileSDto> _originalFiles = new List<StorageFileSDto>();
|
||||||
|
private bool _isProcessing = false;
|
||||||
|
private string _search = string.Empty;
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,12 @@
|
||||||
|
using NetinaShop.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Extensions;
|
||||||
|
|
||||||
|
public static class StorageFileExtension
|
||||||
|
{
|
||||||
|
public static string GetLink(this StorageFileSDto file)
|
||||||
|
{
|
||||||
|
var link = $"https://storage.vesmook.com/{file.FileLocation}";
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,4 +13,5 @@ public static class Address
|
||||||
public static string ProductCategoryController = $"{BaseAddress}/product/category";
|
public static string ProductCategoryController = $"{BaseAddress}/product/category";
|
||||||
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";
|
||||||
}
|
}
|
|
@ -53,6 +53,8 @@
|
||||||
<Using Include="NetinaShop.AdminPanel.PWA.Utilities" />
|
<Using Include="NetinaShop.AdminPanel.PWA.Utilities" />
|
||||||
<Using Include="NetinaShop.Common.Models.Api" />
|
<Using Include="NetinaShop.Common.Models.Api" />
|
||||||
<Using Include="NetinaShop.Common.Models.Exception" />
|
<Using Include="NetinaShop.Common.Models.Exception" />
|
||||||
|
<Using Include="NetinaShop.Domain.CommandQueries.Commands" />
|
||||||
|
<Using Include="NetinaShop.Domain.Dtos.LargDtos" />
|
||||||
<Using Include="NetinaShop.Domain.Dtos.RequestDtos" />
|
<Using Include="NetinaShop.Domain.Dtos.RequestDtos" />
|
||||||
<Using Include="NetinaShop.Domain.Dtos.SmallDtos" />
|
<Using Include="NetinaShop.Domain.Dtos.SmallDtos" />
|
||||||
<Using Include="NetinaShop.Domain.Entities.ProductCategories" />
|
<Using Include="NetinaShop.Domain.Entities.ProductCategories" />
|
||||||
|
|
|
@ -46,12 +46,13 @@
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
Size="@Size.Small"
|
Size="@Size.Small"
|
||||||
Variant="@Variant.Outlined"
|
Variant="@Variant.Outlined"
|
||||||
Color="@Color.Info"></MudIconButton>
|
Color="@Color.Info"
|
||||||
|
OnClick="async()=>await ViewModel.EditProductClicked(context.Item)"/>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
Size="@Size.Small"
|
Size="@Size.Small"
|
||||||
Variant="@Variant.Outlined"
|
Variant="@Variant.Outlined"
|
||||||
OnClick="async () => await ViewModel.DeleteProductAsync(context.Item.Id)"
|
OnClick="async () => await ViewModel.DeleteProductAsync(context.Item.Id)"
|
||||||
Color="@Color.Error"></MudIconButton>
|
Color="@Color.Error"/>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IBrandRestApi
|
||||||
|
{
|
||||||
|
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BrandSDto>> ReadAll();
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BrandSDto>> ReadAll([Query] int page);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BrandSDto>> ReadAll([Query] int page, [Query] string brandName);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<BrandSDto>> ReadAll([Query] string brandName);
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ public interface ICrudDtoApiRest<T, TDto, in TKey> where T : class where TDto :
|
||||||
Task<List<TDto>> ReadAll();
|
Task<List<TDto>> ReadAll();
|
||||||
|
|
||||||
[Get("/{key}")]
|
[Get("/{key}")]
|
||||||
Task<TDto> ReadOne(TKey key, [Header("Authorization")] string authorization);
|
Task<TDto> ReadOne(TKey key);
|
||||||
|
|
||||||
[Put("")]
|
[Put("")]
|
||||||
Task Update([Body] T payload, [Header("Authorization")] string authorization);
|
Task Update([Body] T payload, [Header("Authorization")] string authorization);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IFileRestApi
|
||||||
|
{
|
||||||
|
[Get("")]
|
||||||
|
Task<List<StorageFileSDto>> GetFilesAsync([Header("Authorization")] string authorization);
|
||||||
|
[Post("")]
|
||||||
|
Task<FileUploadResponse> UploadFileAsync([Body] FileUploadRequest request, [Header("Authorization")] string authorization);
|
||||||
|
}
|
|
@ -10,4 +10,6 @@ public interface IRestWrapper
|
||||||
public IUserRestApi UserRestApi { get; }
|
public IUserRestApi UserRestApi { get; }
|
||||||
public IProductCategoryRestApi ProductCategoryRestApi { get; }
|
public IProductCategoryRestApi ProductCategoryRestApi { get; }
|
||||||
public IProductRestApi ProductRestApi { get; }
|
public IProductRestApi ProductRestApi { get; }
|
||||||
|
public IBrandRestApi BrandRestApi { get; }
|
||||||
|
public IFileRestApi FileRestApi { get; }
|
||||||
}
|
}
|
|
@ -22,4 +22,6 @@ public class RestWrapper : IRestWrapper
|
||||||
public IUserRestApi UserRestApi => RestService.For<IUserRestApi>(Address.UserController, setting);
|
public IUserRestApi UserRestApi => RestService.For<IUserRestApi>(Address.UserController, setting);
|
||||||
public IProductCategoryRestApi ProductCategoryRestApi => RestService.For<IProductCategoryRestApi>(Address.ProductCategoryController, setting);
|
public IProductCategoryRestApi ProductCategoryRestApi => RestService.For<IProductCategoryRestApi>(Address.ProductCategoryController, setting);
|
||||||
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 IFileRestApi FileRestApi => RestService.For<IFileRestApi>(Address.FileController, setting);
|
||||||
}
|
}
|
|
@ -501,6 +501,19 @@ video {
|
||||||
--tw-backdrop-saturate: ;
|
--tw-backdrop-saturate: ;
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.m-1 {
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
.m-1\.5 {
|
||||||
|
margin: 0.375rem;
|
||||||
|
}
|
||||||
|
.mx-1 {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
.mx-3 {
|
.mx-3 {
|
||||||
margin-left: 0.75rem;
|
margin-left: 0.75rem;
|
||||||
margin-right: 0.75rem;
|
margin-right: 0.75rem;
|
||||||
|
@ -537,9 +550,6 @@ video {
|
||||||
.-mt-3 {
|
.-mt-3 {
|
||||||
margin-top: -0.75rem;
|
margin-top: -0.75rem;
|
||||||
}
|
}
|
||||||
.mb-10 {
|
|
||||||
margin-bottom: 2.5rem;
|
|
||||||
}
|
|
||||||
.mb-2 {
|
.mb-2 {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -585,9 +595,15 @@ video {
|
||||||
.h-12 {
|
.h-12 {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
}
|
}
|
||||||
|
.h-28 {
|
||||||
|
height: 7rem;
|
||||||
|
}
|
||||||
.h-5 {
|
.h-5 {
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
}
|
}
|
||||||
|
.h-52 {
|
||||||
|
height: 13rem;
|
||||||
|
}
|
||||||
.h-64 {
|
.h-64 {
|
||||||
height: 16rem;
|
height: 16rem;
|
||||||
}
|
}
|
||||||
|
@ -600,6 +616,9 @@ video {
|
||||||
.h-screen {
|
.h-screen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
.max-h-\[30rem\] {
|
||||||
|
max-height: 30rem;
|
||||||
|
}
|
||||||
.min-h-\[10rem\] {
|
.min-h-\[10rem\] {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
|
@ -609,9 +628,15 @@ video {
|
||||||
.w-12 {
|
.w-12 {
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
}
|
}
|
||||||
|
.w-28 {
|
||||||
|
width: 7rem;
|
||||||
|
}
|
||||||
.w-5 {
|
.w-5 {
|
||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
}
|
}
|
||||||
|
.w-52 {
|
||||||
|
width: 13rem;
|
||||||
|
}
|
||||||
.w-64 {
|
.w-64 {
|
||||||
width: 16rem;
|
width: 16rem;
|
||||||
}
|
}
|
||||||
|
@ -624,30 +649,58 @@ video {
|
||||||
.w-screen {
|
.w-screen {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
.flex-none {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
.grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
.basis-full {
|
.basis-full {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
}
|
}
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.flex-col-reverse {
|
.flex-col-reverse {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
.flex-wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.justify-end {
|
.justify-end {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.overflow-hidden {
|
.overflow-hidden {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
.rounded-md {
|
.rounded-md {
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
}
|
}
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
.border-4 {
|
||||||
|
border-width: 4px;
|
||||||
|
}
|
||||||
|
.border-solid {
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
.border-blue-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
.bg-\[\#000000\] {
|
.bg-\[\#000000\] {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||||
|
|
|
@ -554,6 +554,23 @@ video {
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-1 {
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-1\.5 {
|
||||||
|
margin: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-1 {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mx-3 {
|
.mx-3 {
|
||||||
margin-left: 0.75rem;
|
margin-left: 0.75rem;
|
||||||
margin-right: 0.75rem;
|
margin-right: 0.75rem;
|
||||||
|
@ -600,10 +617,6 @@ video {
|
||||||
margin-top: -0.75rem;
|
margin-top: -0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb-10 {
|
|
||||||
margin-bottom: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb-2 {
|
.mb-2 {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -663,10 +676,18 @@ video {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-28 {
|
||||||
|
height: 7rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-5 {
|
.h-5 {
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-52 {
|
||||||
|
height: 13rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-64 {
|
.h-64 {
|
||||||
height: 16rem;
|
height: 16rem;
|
||||||
}
|
}
|
||||||
|
@ -683,6 +704,10 @@ video {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.max-h-\[30rem\] {
|
||||||
|
max-height: 30rem;
|
||||||
|
}
|
||||||
|
|
||||||
.min-h-\[10rem\] {
|
.min-h-\[10rem\] {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
|
@ -695,10 +720,18 @@ video {
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-28 {
|
||||||
|
width: 7rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-5 {
|
.w-5 {
|
||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-52 {
|
||||||
|
width: 13rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-64 {
|
.w-64 {
|
||||||
width: 16rem;
|
width: 16rem;
|
||||||
}
|
}
|
||||||
|
@ -715,10 +748,22 @@ video {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-none {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.basis-full {
|
.basis-full {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
@ -727,6 +772,10 @@ video {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
@ -735,10 +784,18 @@ video {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.overflow-hidden {
|
.overflow-hidden {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded-md {
|
.rounded-md {
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
}
|
}
|
||||||
|
@ -747,6 +804,19 @@ video {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-4 {
|
||||||
|
border-width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-solid {
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-blue-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-\[\#000000\] {
|
.bg-\[\#000000\] {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||||
|
|
Loading…
Reference in New Issue