parent
97457f89cc
commit
c3d4c265ce
|
@ -0,0 +1,187 @@
|
||||||
|
@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" DisableSidePadding="true">
|
||||||
|
<DialogContent >
|
||||||
|
<MudContainer class="max-h-[30rem] lg:max-h-[35rem] overflow-y-scroll">
|
||||||
|
|
||||||
|
<MudStack>
|
||||||
|
<MudStack Spacing="0">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||||
|
<MudText Typo="Typo.caption">اطلاعات کلی محصول را به دقت وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
|
||||||
|
<MudItem sm="8">
|
||||||
|
<MudTextField Disabled="@ViewModel.PageDto.HasCode.Not()" @bind-Value="@ViewModel.PageDto.Code" T="string" Label="کد تخفیف" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="4">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.PageDto.HasCode" class="mt-2" Size="Size.Large" T="bool" Label="با کد تخفیف باشد" Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="8">
|
||||||
|
<MudTextField Disabled="@ViewModel.PageDto.IsInfinity" @bind-Value="@ViewModel.PageDto.Count" T="int" Label="تعداد قابل استفاده" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="4">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.PageDto.IsInfinity" class="mt-2" Size="Size.Large" T="bool" Label="نامحدود باشد ؟" Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
|
||||||
|
<MudSelect T="DiscountAmountType" ValueChanged="@ViewModel.AmountTypeChanged" Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
|
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Percent" />
|
||||||
|
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Amount" />
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
<MudTextField Disabled="@ViewModel.IsPercentType.Not()" @bind-Value="@ViewModel.PageDto.DiscountPercent" T="int" Label="درصد تخفیف" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
<MudTextField Disabled="@ViewModel.IsAmountType.Not()" @bind-Value="@ViewModel.PageDto.DiscountAmount" T="long" Label="مبلغ تخفیفــ" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
|
||||||
|
<MudItem md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.PageDto.PriceFloor" T="long" Label="کف قیمت برای تخفیف" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
|
||||||
|
<MudItem md="6">
|
||||||
|
<MudTextField @bind-Value="@ViewModel.PageDto.PriceCeiling" T="long" Label="سقف قیمت برای تخفیف" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="6">
|
||||||
|
<MudDatePicker @bind-Date="@ViewModel.StartDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ شروع تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="6">
|
||||||
|
<MudDatePicker @bind-Date="@ViewModel.ExpireDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ پایان تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
</MudGrid>
|
||||||
|
|
||||||
|
<MudStack class="mt-4" Spacing="0">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">انتخاب حالتــ تخفیفـــ</MudText>
|
||||||
|
<MudText Typo="Typo.caption">تخفیف مورد نظر میتواند برای هر یک از موارد زیر ایجاد شود</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
|
||||||
|
<MudItem sm="7">
|
||||||
|
|
||||||
|
<MudAutocomplete Disabled="@ViewModel.IsCategoryEnable.Not()" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||||
|
SearchFunc="ViewModel.SearchCategory"
|
||||||
|
T="ProductCategorySDto"
|
||||||
|
Label="دسته بندی"
|
||||||
|
Variant="Variant.Outlined">
|
||||||
|
<ProgressIndicatorInPopoverTemplate>
|
||||||
|
<MudList Clickable="false">
|
||||||
|
<MudListItem>
|
||||||
|
<div class="flex flex-row w-full mx-auto">
|
||||||
|
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||||
|
</div>
|
||||||
|
</MudListItem>
|
||||||
|
</MudList>
|
||||||
|
</ProgressIndicatorInPopoverTemplate>
|
||||||
|
<ItemTemplate Context="e">
|
||||||
|
<p>@e.Name</p>
|
||||||
|
</ItemTemplate>
|
||||||
|
</MudAutocomplete>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="5">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.IsCategoryEnable" class="mt-2" Size="Size.Large" T="bool" Label="تخفیف برای دسته خاص" Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="7">
|
||||||
|
|
||||||
|
<MudAutocomplete Disabled="@ViewModel.IsProductEnable.Not()" ToStringFunc="dto => dto.PersianName" @bind-Value="@ViewModel.SelectedProduct"
|
||||||
|
SearchFunc="ViewModel.SearchProduct"
|
||||||
|
T="ProductSDto"
|
||||||
|
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.PersianName</p>
|
||||||
|
</ItemTemplate>
|
||||||
|
</MudAutocomplete>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="5">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.IsProductEnable" class="mt-2" Size="Size.Large" T="bool" Label="تخفیف برای غذای خاص" Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="7">
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="5">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.IsAllEnable" class="mt-1.5 mx-auto" Size="Size.Large" T="bool" Label="تخفیف برای تمامی کالاهای " Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
</MudContainer>
|
||||||
|
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||||
|
|
||||||
|
@if (ViewModel.IsEditing)
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||||
|
}
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
@code {
|
||||||
|
[CascadingParameter]
|
||||||
|
MudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public DiscountSDto? Discount { get; set; }
|
||||||
|
|
||||||
|
public DiscountActionDialogBoxViewModel ViewModel { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (Discount == null)
|
||||||
|
ViewModel = new DiscountActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
|
||||||
|
else
|
||||||
|
ViewModel = new DiscountActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Discount);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,321 @@
|
||||||
|
using Mapster;
|
||||||
|
using NetinaShop.Domain.Entities.Blogs;
|
||||||
|
using NetinaShop.Domain.Entities.Discounts;
|
||||||
|
using NetinaShop.Domain.Mappers;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class DiscountActionDialogBoxViewModel : BaseViewModel<DiscountLDto>
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly MudDialogInstance _mudDialog;
|
||||||
|
|
||||||
|
public DiscountActionDialogBoxViewModel(
|
||||||
|
ISnackbar snackbar,
|
||||||
|
IRestWrapper restWrapper,
|
||||||
|
IUserUtility userUtility,
|
||||||
|
IDialogService dialogService,
|
||||||
|
MudDialogInstance mudDialog)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
}
|
||||||
|
public DiscountActionDialogBoxViewModel(ISnackbar snackbar,
|
||||||
|
IRestWrapper restWrapper,
|
||||||
|
IUserUtility userUtility,
|
||||||
|
IDialogService dialogService,
|
||||||
|
MudDialogInstance mudDialog,
|
||||||
|
DiscountSDto discount)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_mudDialog = mudDialog;
|
||||||
|
_discountId = discount.Id;
|
||||||
|
IsEditing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isProductEnable;
|
||||||
|
|
||||||
|
public bool IsProductEnable
|
||||||
|
{
|
||||||
|
get => _isProductEnable;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isProductEnable = value;
|
||||||
|
if (_isProductEnable)
|
||||||
|
{
|
||||||
|
IsCategoryEnable = false;
|
||||||
|
IsAllEnable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool _isCategoryEnable;
|
||||||
|
public bool IsCategoryEnable
|
||||||
|
{
|
||||||
|
get => _isCategoryEnable;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isCategoryEnable = value;
|
||||||
|
if (_isCategoryEnable)
|
||||||
|
{
|
||||||
|
IsProductEnable = false;
|
||||||
|
IsAllEnable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool _isAllEnable;
|
||||||
|
public bool IsAllEnable
|
||||||
|
{
|
||||||
|
get => _isAllEnable;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isAllEnable = value;
|
||||||
|
if (_isAllEnable)
|
||||||
|
{
|
||||||
|
IsCategoryEnable = false;
|
||||||
|
IsProductEnable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPercentType { get; set; } = true;
|
||||||
|
public bool IsAmountType { get; set; }
|
||||||
|
|
||||||
|
public DateTime? ExpireDate { get; set; }
|
||||||
|
public DateTime? StartDate { get; set; }
|
||||||
|
private Guid _discountId;
|
||||||
|
public bool IsEditing = false;
|
||||||
|
|
||||||
|
public void AmountTypeChanged(DiscountAmountType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DiscountAmountType.Amount:
|
||||||
|
IsAmountType = true;
|
||||||
|
IsPercentType = false;
|
||||||
|
break;
|
||||||
|
case DiscountAmountType.Percent:
|
||||||
|
IsAmountType = false;
|
||||||
|
IsPercentType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
if (IsEditing && _discountId != default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
IsProcessing = true;
|
||||||
|
var discount = await _restWrapper.DiscountRest.ReadOne(_discountId, token);
|
||||||
|
PageDto = discount;
|
||||||
|
|
||||||
|
if (PageDto.CategoryId != default)
|
||||||
|
SelectedCategory = new ProductCategorySDto { Id = PageDto.CategoryId, Name = PageDto.CategoryName };
|
||||||
|
|
||||||
|
if (PageDto.ProductId != default)
|
||||||
|
SelectedProduct = new ProductSDto { Id = PageDto.ProductId, PersianName = PageDto.ProductName };
|
||||||
|
|
||||||
|
ExpireDate = PageDto.ExpireDate;
|
||||||
|
StartDate = PageDto.StartDate;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartDate = DateTime.Today;
|
||||||
|
ExpireDate = DateTime.Today.AddDays(7);
|
||||||
|
PageDto.IsInfinity = false;
|
||||||
|
PageDto.HasCode = false;
|
||||||
|
IsAllEnable = true;
|
||||||
|
}
|
||||||
|
await base.InitializeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
|
||||||
|
public async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (IsAllEnable)
|
||||||
|
{
|
||||||
|
PageDto.Type = DiscountType.All;
|
||||||
|
}
|
||||||
|
else if (IsCategoryEnable)
|
||||||
|
{
|
||||||
|
PageDto.Type = DiscountType.Category;
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("دسته بندی را برای تخفیف انتخاب نمایید");
|
||||||
|
PageDto.CategoryId = SelectedCategory.Id;
|
||||||
|
}
|
||||||
|
else if (IsProductEnable)
|
||||||
|
{
|
||||||
|
PageDto.Type = DiscountType.Product;
|
||||||
|
if (SelectedProduct == null)
|
||||||
|
throw new Exception("کالا مورد نظر را برای تخفیف انتخاب نمایید");
|
||||||
|
PageDto.ProductId = SelectedProduct.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
if (ExpireDate != null)
|
||||||
|
PageDto.ExpireDate = ExpireDate.Value;
|
||||||
|
if(StartDate != null)
|
||||||
|
PageDto.StartDate = StartDate.Value;
|
||||||
|
|
||||||
|
var request = PageDto.Adapt<CreateDiscountCommand>();
|
||||||
|
await _restWrapper.CrudApiRest<Discount, Guid>(Address.DiscountController).Create<CreateDiscountCommand>(request, token);
|
||||||
|
|
||||||
|
_snackbar.Add($"ساخت تخفیف با موفقیت انجام شد", 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 SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (_discountId == default)
|
||||||
|
throw new Exception("بلاگ اشتباه است");
|
||||||
|
if (SelectedCategory == null)
|
||||||
|
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
PageDto.Id = _discountId;
|
||||||
|
var request = PageDto.Adapt<UpdateDiscountCommand>();
|
||||||
|
await _restWrapper.CrudApiRest<Discount, Guid>(Address.DiscountController).Create<UpdateDiscountCommand>(request, token);
|
||||||
|
_snackbar.Add($"ویرایش تخفیف با موفقیت انجام شد", 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>> SearchCategory(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<ProductSDto> _products = new List<ProductSDto>();
|
||||||
|
public ProductSDto? SelectedProduct;
|
||||||
|
public async Task<IEnumerable<ProductSDto>> SearchProduct(string product)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (product.IsNullOrEmpty())
|
||||||
|
_products = await _restWrapper.ProductRestApi.ReadAll(0);
|
||||||
|
else
|
||||||
|
_products = await _restWrapper.ProductRestApi.ReadAll(product);
|
||||||
|
return _products;
|
||||||
|
}
|
||||||
|
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 _products;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
return _products;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,10 +24,10 @@
|
||||||
<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.PageDto.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.PageDto.EnglishName" T="string" Label="نام انگلیسی محصول" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
|
|
||||||
|
@ -74,36 +74,36 @@
|
||||||
</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.PageDto.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.PageDto.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.PageDto.MaxOrderCount" 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.PageDto.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.PageDto.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.PageDto.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.PageDto.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.PageDto.Summery" T="string" Label="توضیحاتــ" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</div>
|
</div>
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem sm="12">
|
<MudItem sm="12">
|
||||||
<RadzenHtmlEditor @bind-Value="@ViewModel.ExpertCheck" class="min-h-[28rem]">
|
<RadzenHtmlEditor @bind-Value="@ViewModel.PageDto.ExpertCheck" class="min-h-[28rem]">
|
||||||
<RadzenHtmlEditorUndo />
|
<RadzenHtmlEditorUndo />
|
||||||
<RadzenHtmlEditorRedo />
|
<RadzenHtmlEditorRedo />
|
||||||
<RadzenHtmlEditorSeparator />
|
<RadzenHtmlEditorSeparator />
|
||||||
|
@ -240,6 +240,51 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
|
|
||||||
|
<MudTabPanel Text="پیشنهاد ویژه" Icon="@Icons.Material.Outlined.LocalOffer">
|
||||||
|
|
||||||
|
<div class="min-h-[33rem]">
|
||||||
|
<MudGrid>
|
||||||
|
|
||||||
|
<MudItem sm="12">
|
||||||
|
<MudSwitch @bind-Value="@ViewModel.IsSpecialOffer"
|
||||||
|
class="mt-2"
|
||||||
|
Size="Size.Large"
|
||||||
|
T="bool"
|
||||||
|
Label="آیا محصول در فروش ویژه میباشد ؟"
|
||||||
|
Color="Color.Info" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
|
||||||
|
<MudSelect Disabled="@ViewModel.IsSpecialOffer.Not()" T="DiscountAmountType" ValueChanged="@ViewModel.AmountTypeChanged" Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
|
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Percent" />
|
||||||
|
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Amount" />
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
<MudTextField Disabled="@ViewModel.IsPercentType.Not()" @bind-Value="@ViewModel.Discount.DiscountPercent" T="int" Label="درصد تخفیف" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem md="4">
|
||||||
|
<MudTextField Disabled="@ViewModel.IsAmountType.Not()" @bind-Value="@ViewModel.Discount.DiscountAmount" T="long" Label="مبلغ تخفیفــ" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
|
||||||
|
<MudItem sm="6">
|
||||||
|
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.StartDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ شروع تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
<MudItem sm="6">
|
||||||
|
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.ExpireDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ پایان تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||||
|
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
|
||||||
|
</MudGrid>
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
</MudTabs>
|
</MudTabs>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
using Mapster;
|
||||||
|
|
||||||
public class ProductActionDialogBoxViewModel : BaseViewModel
|
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||||
|
|
||||||
|
public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
||||||
{
|
{
|
||||||
private readonly ISnackbar _snackbar;
|
private readonly ISnackbar _snackbar;
|
||||||
private readonly IRestWrapper _restWrapper;
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
@ -48,17 +50,22 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
public void Cancel() => _mudDialog.Cancel();
|
public void Cancel() => _mudDialog.Cancel();
|
||||||
|
|
||||||
public bool IsEditing = false;
|
public bool IsEditing = false;
|
||||||
public string ExpertCheck = string.Empty;
|
private bool _isSpecialOffer;
|
||||||
public string Summery = string.Empty;
|
|
||||||
public bool BeDisplayed = true;
|
public bool IsSpecialOffer
|
||||||
public bool HasExpressDelivery = false;
|
{
|
||||||
public string PersianName = string.Empty;
|
get => _isSpecialOffer;
|
||||||
public string EnglishName = string.Empty;
|
set
|
||||||
public double Cost;
|
{
|
||||||
public double PackingCost;
|
_isSpecialOffer = value;
|
||||||
public int MaxOrder;
|
PageDto.IsSpecialOffer = value;
|
||||||
public string Warranty = string.Empty;
|
if(!value)
|
||||||
public string Tags = string.Empty;
|
{
|
||||||
|
IsAmountType = value;
|
||||||
|
IsPercentType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string SpecificationTitle = string.Empty;
|
public string SpecificationTitle = string.Empty;
|
||||||
public string SpecificationValue = string.Empty;
|
public string SpecificationValue = string.Empty;
|
||||||
|
@ -74,20 +81,40 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
IsProcessing = true;
|
IsProcessing = true;
|
||||||
var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
|
var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
|
||||||
ExpertCheck = productLDto.ExpertCheck;
|
PageDto.ExpertCheck = productLDto.ExpertCheck;
|
||||||
Summery = productLDto.Summery;
|
PageDto.Summery = productLDto.Summery;
|
||||||
BeDisplayed = productLDto.BeDisplayed;
|
PageDto.BeDisplayed = productLDto.BeDisplayed;
|
||||||
HasExpressDelivery = productLDto.HasExpressDelivery;
|
PageDto.HasExpressDelivery = productLDto.HasExpressDelivery;
|
||||||
PersianName = productLDto.PersianName;
|
PageDto.PersianName = productLDto.PersianName;
|
||||||
EnglishName = productLDto.EnglishName;
|
PageDto.EnglishName = productLDto.EnglishName;
|
||||||
Cost = productLDto.Cost;
|
PageDto.Cost = productLDto.Cost;
|
||||||
PackingCost = productLDto.PackingCost;
|
PageDto.PackingCost = productLDto.PackingCost;
|
||||||
MaxOrder = productLDto.MaxOrderCount;
|
PageDto.MaxOrderCount = productLDto.MaxOrderCount;
|
||||||
Warranty = productLDto.Warranty;
|
PageDto.Warranty = productLDto.Warranty;
|
||||||
productLDto.Specifications.ForEach(s => Specifications.Add(s));
|
productLDto.Specifications.ForEach(s => Specifications.Add(s));
|
||||||
productLDto.Files.ForEach(f => Files.Add(f));
|
productLDto.Files.ForEach(f => Files.Add(f));
|
||||||
SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
|
SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
|
||||||
SelectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
|
SelectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
|
||||||
|
PageDto.IsSpecialOffer = productLDto.IsSpecialOffer;
|
||||||
|
IsSpecialOffer = PageDto.IsSpecialOffer;
|
||||||
|
if (productLDto.SpecialOffer != null)
|
||||||
|
{
|
||||||
|
Discount = productLDto.SpecialOffer;
|
||||||
|
switch (Discount.AmountType)
|
||||||
|
{
|
||||||
|
case DiscountAmountType.Amount:
|
||||||
|
IsAmountType = true;
|
||||||
|
IsPercentType = false;
|
||||||
|
break;
|
||||||
|
case DiscountAmountType.Percent:
|
||||||
|
IsAmountType = false;
|
||||||
|
IsPercentType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpireDate = Discount.ExpireDate;
|
||||||
|
StartDate = Discount.StartDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
{
|
{
|
||||||
|
@ -122,9 +149,24 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
if (SelectedBrand == null)
|
if (SelectedBrand == null)
|
||||||
throw new Exception("لطفا یک برند انتخاب کنید");
|
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());
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
PageDto.Specifications = Specifications.ToList();
|
||||||
|
PageDto.Files = Files.ToList();
|
||||||
|
PageDto.Id = Product.Id;
|
||||||
|
PageDto.CategoryId = SelectedCategory?.Id ?? default;
|
||||||
|
PageDto.BrandId = SelectedBrand?.Id ?? default;
|
||||||
|
if (PageDto.IsSpecialOffer)
|
||||||
|
{
|
||||||
|
if (ExpireDate != null)
|
||||||
|
Discount.ExpireDate = ExpireDate.Value;
|
||||||
|
if (StartDate != null)
|
||||||
|
Discount.StartDate = StartDate.Value;
|
||||||
|
PageDto.SpecialOffer = Discount;
|
||||||
|
}
|
||||||
|
var request = PageDto.Adapt<UpdateProductCommand>();
|
||||||
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($"ویرایش محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||||
_mudDialog.Close();
|
_mudDialog.Close();
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
|
@ -156,10 +198,22 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
if (SelectedBrand == null)
|
if (SelectedBrand == null)
|
||||||
throw new Exception("لطفا یک برند انتخاب کنید");
|
throw new Exception("لطفا یک برند انتخاب کنید");
|
||||||
var token = await _userUtility.GetBearerTokenAsync();
|
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());
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
PageDto.Specifications = Specifications.ToList();
|
||||||
|
PageDto.Files = Files.ToList();
|
||||||
|
if (PageDto.IsSpecialOffer)
|
||||||
|
{
|
||||||
|
if (ExpireDate != null)
|
||||||
|
Discount.ExpireDate = ExpireDate.Value;
|
||||||
|
if (StartDate != null)
|
||||||
|
Discount.StartDate = StartDate.Value;
|
||||||
|
PageDto.SpecialOffer = Discount;
|
||||||
|
}
|
||||||
|
var request = PageDto.Adapt<CreateProductCommand>();
|
||||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
||||||
|
|
||||||
_snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
|
_snackbar.Add($"ساخت محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||||
_mudDialog.Close();
|
_mudDialog.Close();
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
|
@ -182,6 +236,25 @@ public class ProductActionDialogBoxViewModel : BaseViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsPercentType { get; set; } = true;
|
||||||
|
public bool IsAmountType { get; set; }
|
||||||
|
public DateTime? ExpireDate { get; set; }
|
||||||
|
public DateTime? StartDate { get; set; }
|
||||||
|
public DiscountSDto Discount { get; set; } = new DiscountSDto();
|
||||||
|
public void AmountTypeChanged(DiscountAmountType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DiscountAmountType.Amount:
|
||||||
|
IsAmountType = true;
|
||||||
|
IsPercentType = false;
|
||||||
|
break;
|
||||||
|
case DiscountAmountType.Percent:
|
||||||
|
IsAmountType = false;
|
||||||
|
IsPercentType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
|
||||||
public ProductCategorySDto? SelectedCategory;
|
public ProductCategorySDto? SelectedCategory;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Extensions;
|
||||||
|
|
||||||
|
public static class BoolExtension
|
||||||
|
{
|
||||||
|
public static bool Not( this bool value ) => !value;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Extensions;
|
||||||
|
|
||||||
|
public static class PersianCultureInfo
|
||||||
|
{
|
||||||
|
public static CultureInfo GetPersianCulture()
|
||||||
|
{
|
||||||
|
var culture = new CultureInfo("fa-IR");
|
||||||
|
DateTimeFormatInfo formatInfo = culture.DateTimeFormat;
|
||||||
|
formatInfo.AbbreviatedDayNames = new[] { "ی", "د", "س", "چ", "پ", "ج", "ش" };
|
||||||
|
formatInfo.DayNames = new[] { "یکشنبه", "دوشنبه", "سه شنبه", "چهار شنبه", "پنجشنبه", "جمعه", "شنبه" };
|
||||||
|
var monthNames = new[]
|
||||||
|
{
|
||||||
|
"فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن",
|
||||||
|
"اسفند",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
formatInfo.AbbreviatedMonthNames =
|
||||||
|
formatInfo.MonthNames =
|
||||||
|
formatInfo.MonthGenitiveNames = formatInfo.AbbreviatedMonthGenitiveNames = monthNames;
|
||||||
|
formatInfo.AMDesignator = "ق.ظ";
|
||||||
|
formatInfo.PMDesignator = "ب.ظ";
|
||||||
|
formatInfo.ShortDatePattern = "yyyy/MM/dd";
|
||||||
|
formatInfo.LongDatePattern = "dddd, dd MMMM,yyyy";
|
||||||
|
formatInfo.FirstDayOfWeek = DayOfWeek.Saturday;
|
||||||
|
System.Globalization.Calendar cal = new PersianCalendar();
|
||||||
|
FieldInfo fieldInfo = culture.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
if (fieldInfo != null)
|
||||||
|
fieldInfo.SetValue(culture, cal);
|
||||||
|
FieldInfo info = formatInfo.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
if (info != null)
|
||||||
|
info.SetValue(formatInfo, cal);
|
||||||
|
culture.NumberFormat.NumberDecimalSeparator = "/";
|
||||||
|
culture.NumberFormat.DigitSubstitution = DigitShapes.NativeNational;
|
||||||
|
culture.NumberFormat.NumberNegativePattern = 0;
|
||||||
|
return culture;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NetinaShop.AdminPanel.PWA.Extensions;
|
|
||||||
|
|
||||||
public class StringCipher
|
|
||||||
{
|
|
||||||
public string Encrypt(string data, RSAParameters key)
|
|
||||||
{
|
|
||||||
|
|
||||||
using (var rsa = new RSACryptoServiceProvider())
|
|
||||||
{
|
|
||||||
rsa.ImportParameters(key);
|
|
||||||
var byteData = Encoding.UTF8.GetBytes(data);
|
|
||||||
var encryptData = rsa.Encrypt(byteData, false);
|
|
||||||
return Convert.ToBase64String(encryptData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Decrypt(string cipherText, RSAParameters key)
|
|
||||||
{
|
|
||||||
|
|
||||||
using (var rsa = new RSACryptoServiceProvider())
|
|
||||||
{
|
|
||||||
var cipherByteData = Convert.FromBase64String(cipherText);
|
|
||||||
rsa.ImportParameters(key);
|
|
||||||
|
|
||||||
var encryptData = rsa.Decrypt(cipherByteData, false);
|
|
||||||
return Encoding.UTF8.GetString(encryptData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -32,7 +32,7 @@
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
<MudRTLProvider RightToLeft="true">
|
<MudRTLProvider RightToLeft="true">
|
||||||
<MudThemeProvider IsDarkMode="true" Theme="@MainTheme.MyCustomTheme" />
|
<MudThemeProvider IsDarkMode="false" Theme="@MainTheme.MyCustomTheme" />
|
||||||
<MudDialogProvider />
|
<MudDialogProvider />
|
||||||
<MudSnackbarProvider />
|
<MudSnackbarProvider />
|
||||||
<RadzenContextMenu />
|
<RadzenContextMenu />
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
public static class Address
|
public static class Address
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
//public static string BaseAddress = "http://localhost:32770/api";
|
public static string BaseAddress = "http://localhost:32770/api";
|
||||||
public static string BaseAddress = "https://api.vesmook.com/api";
|
//public static string BaseAddress = "https://api.vesmook.com/api";
|
||||||
#else
|
#else
|
||||||
public static string BaseAddress = "https://api.vesmook.com/api";
|
public static string BaseAddress = "https://api.vesmook.com/api";
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,4 +16,5 @@ public static class Address
|
||||||
public static string FileController => $"{BaseAddress}/file";
|
public static string FileController => $"{BaseAddress}/file";
|
||||||
public static string BlogController => $"{BaseAddress}/blog";
|
public static string BlogController => $"{BaseAddress}/blog";
|
||||||
public static string BlogCategoryController => $"{BaseAddress}/blog/category";
|
public static string BlogCategoryController => $"{BaseAddress}/blog/category";
|
||||||
|
public static string DiscountController => $"{BaseAddress}/discount";
|
||||||
}
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
@page "/discounts"
|
||||||
|
@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-[--mud-palette-background-grey]">
|
||||||
|
<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.AddAsync"
|
||||||
|
class="my-auto">افزودن تخفیفــ جدید</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
<MudPaper>
|
||||||
|
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||||
|
T="DiscountSDto" 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.Code" />
|
||||||
|
<PropertyColumn Title="تعداد" Property="arg => arg.Count" />
|
||||||
|
<PropertyColumn Title="تاریخ شروع" Property="arg => arg.StartDate" />
|
||||||
|
<PropertyColumn Title="تاریخ انقضا" Property="arg => arg.ExpireDate" />
|
||||||
|
<PropertyColumn Title="پیشنهاد ویژه" Property="arg => arg.IsSpecialOffer" />
|
||||||
|
<PropertyColumn Title="تعداد استفاده شده" Property="arg => arg.UseCount" />
|
||||||
|
<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.EditAsync(context.Item)" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
OnClick="async () => await ViewModel.DeleteAsync(context.Item.Id)"
|
||||||
|
Color="@Color.Error" />
|
||||||
|
</MudStack>
|
||||||
|
</CellTemplate>
|
||||||
|
</TemplateColumn>
|
||||||
|
</Columns>
|
||||||
|
<PagerContent>
|
||||||
|
<MudStack Row="true" class="w-full">
|
||||||
|
|
||||||
|
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||||
|
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto" />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
|
</MudDataGrid>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
public DiscountPageViewModel ViewModel { get; set; }
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
ViewModel = new DiscountPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
using NetinaShop.Domain.Entities.Discounts;
|
||||||
|
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class DiscountPageViewModel : BaseViewModel<ObservableCollection<DiscountSDto>>
|
||||||
|
{
|
||||||
|
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 DiscountPageViewModel(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 token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
var dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, token);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 15)
|
||||||
|
PageCount = 2;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
await base.InitializeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page - 1;
|
||||||
|
if (CurrentPage > PageCount - 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
List<DiscountSDto> dto = new List<DiscountSDto>();
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, Search, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count % 20 == 0)
|
||||||
|
PageCount = CurrentPage + 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddAsync()
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
await _dialogService.ShowAsync<DiscountActionDialogBox>("افزودن بلاگ جدید", maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EditAsync(DiscountSDto discount)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<DiscountActionDialogBox>();
|
||||||
|
parameters.Add(x => x.Discount, discount);
|
||||||
|
await _dialogService.ShowAsync<DiscountActionDialogBox>($"ویرایش تخفیف {discount.Code}", parameters, maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAsync(Guid selectedDiscountId)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
await _restWrapper.CrudDtoApiRest<Discount, DiscountSDto, Guid>(Address.BlogController)
|
||||||
|
.Delete(selectedDiscountId, 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("کد تخفیفــ برای جست جو وارد نشده است");
|
||||||
|
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
if (token == null)
|
||||||
|
throw new Exception("Token is null");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.DiscountRest.ReadAll(CurrentPage, Search, token);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,16 +29,55 @@
|
||||||
SortMode="@SortMode.None" Groupable="false">
|
SortMode="@SortMode.None" Groupable="false">
|
||||||
|
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
<MudGrid Row="true">
|
||||||
Clearable="true"
|
|
||||||
ValueChanged="@ViewModel.SearchChanged"
|
<MudItem sm="6">
|
||||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
Clearable="true"
|
||||||
|
ValueChanged="@ViewModel.SearchChanged"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||||
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
<MudItem sm="6">
|
||||||
|
<MudAutocomplete class="-mt-0.5" Required="true" ToStringFunc="dto => dto.Name"
|
||||||
|
T="BrandSDto"
|
||||||
|
Label="بر اساس دسته بندی"
|
||||||
|
Clearable="true">
|
||||||
|
<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>
|
||||||
|
</MudGrid>
|
||||||
</ToolBarContent>
|
</ToolBarContent>
|
||||||
<Columns>
|
<Columns>
|
||||||
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName"/>
|
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName"/>
|
||||||
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName"/>
|
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName"/>
|
||||||
<PropertyColumn Title="برند" Property="arg => arg.BrandNames"/>
|
<PropertyColumn Title="برند" Property="arg => arg.BrandNames" />
|
||||||
|
<TemplateColumn T="ProductSDto" Title="پیشنهاد ویژه است">
|
||||||
|
<CellTemplate>
|
||||||
|
@if (@context.Item.IsSpecial)
|
||||||
|
{
|
||||||
|
<p>بلی</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>خیر</p>
|
||||||
|
|
||||||
|
}
|
||||||
|
</CellTemplate>
|
||||||
|
</TemplateColumn>
|
||||||
<PropertyColumn Title="قیمتــ" Property="arg => arg.Cost"/>
|
<PropertyColumn Title="قیمتــ" Property="arg => arg.Cost"/>
|
||||||
<TemplateColumn CellClass="d-flex justify-end">
|
<TemplateColumn CellClass="d-flex justify-end">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IDiscountRestApi
|
||||||
|
{
|
||||||
|
|
||||||
|
[Get("")]
|
||||||
|
Task<List<DiscountSDto>> ReadAll([Header("Authorization")] string authorization);
|
||||||
|
|
||||||
|
[Get("/{id}")]
|
||||||
|
Task<DiscountLDto> ReadOne(Guid id,[Header("Authorization")] string authorization);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<DiscountSDto>> ReadAll([Query] int page, [Header("Authorization")] string authorization);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<DiscountSDto>> ReadAll([Query] int page, [Query] string discountCode, [Header("Authorization")] string authorization);
|
||||||
|
}
|
|
@ -9,4 +9,6 @@ public interface IProductRestApi
|
||||||
Task<List<ProductSDto>> ReadAll([Query] int page);
|
Task<List<ProductSDto>> ReadAll([Query] int page);
|
||||||
[Get("")]
|
[Get("")]
|
||||||
Task<List<ProductSDto>> ReadAll([Query] int page, [Query] string productName);
|
Task<List<ProductSDto>> ReadAll([Query] int page, [Query] string productName);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductSDto>> ReadAll([Query] string productName);
|
||||||
}
|
}
|
|
@ -13,5 +13,6 @@ public interface IRestWrapper
|
||||||
public IBrandRestApi BrandRestApi { get; }
|
public IBrandRestApi BrandRestApi { get; }
|
||||||
public IFileRestApi FileRestApi { get; }
|
public IFileRestApi FileRestApi { get; }
|
||||||
public IBlogRestApi BlogRestApi { get; }
|
public IBlogRestApi BlogRestApi { get; }
|
||||||
|
public IDiscountRestApi DiscountRest { get; }
|
||||||
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
|
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
|
||||||
}
|
}
|
|
@ -25,5 +25,6 @@ public class RestWrapper : IRestWrapper
|
||||||
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 IBlogRestApi BlogRestApi => RestService.For<IBlogRestApi>(Address.BlogController, setting);
|
||||||
|
public IDiscountRestApi DiscountRest => RestService.For<IDiscountRestApi>(Address.DiscountController, setting);
|
||||||
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For<IBlogCategoryRestApi>(Address.BlogCategoryController, setting);
|
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For<IBlogCategoryRestApi>(Address.BlogCategoryController, setting);
|
||||||
}
|
}
|
|
@ -1080,6 +1080,10 @@ input:checked + .toggle-bg {
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
.my-10 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
.my-4 {
|
.my-4 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -1097,6 +1101,12 @@ input:checked + .toggle-bg {
|
||||||
.-mr-2 {
|
.-mr-2 {
|
||||||
margin-right: -0.5rem;
|
margin-right: -0.5rem;
|
||||||
}
|
}
|
||||||
|
.-mt-0 {
|
||||||
|
margin-top: -0px;
|
||||||
|
}
|
||||||
|
.-mt-0\.5 {
|
||||||
|
margin-top: -0.125rem;
|
||||||
|
}
|
||||||
.-mt-1 {
|
.-mt-1 {
|
||||||
margin-top: -0.25rem;
|
margin-top: -0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1124,6 +1134,12 @@ input:checked + .toggle-bg {
|
||||||
.mr-2 {
|
.mr-2 {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.mt-1 {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
|
.mt-1\.5 {
|
||||||
|
margin-top: 0.375rem;
|
||||||
|
}
|
||||||
.mt-2 {
|
.mt-2 {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -1178,6 +1194,9 @@ input:checked + .toggle-bg {
|
||||||
.h-14 {
|
.h-14 {
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
}
|
}
|
||||||
|
.h-24 {
|
||||||
|
height: 6rem;
|
||||||
|
}
|
||||||
.h-28 {
|
.h-28 {
|
||||||
height: 7rem;
|
height: 7rem;
|
||||||
}
|
}
|
||||||
|
@ -1239,6 +1258,9 @@ input:checked + .toggle-bg {
|
||||||
.w-14 {
|
.w-14 {
|
||||||
width: 3.5rem;
|
width: 3.5rem;
|
||||||
}
|
}
|
||||||
|
.w-24 {
|
||||||
|
width: 6rem;
|
||||||
|
}
|
||||||
.w-28 {
|
.w-28 {
|
||||||
width: 7rem;
|
width: 7rem;
|
||||||
}
|
}
|
||||||
|
@ -1311,6 +1333,15 @@ input:checked + .toggle-bg {
|
||||||
.transform-none {
|
.transform-none {
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-spin {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
.cursor-default {
|
.cursor-default {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
@ -1367,6 +1398,9 @@ input:checked + .toggle-bg {
|
||||||
.overflow-hidden {
|
.overflow-hidden {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.overflow-y-scroll {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
.rounded-full {
|
.rounded-full {
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
}
|
}
|
||||||
|
@ -1401,6 +1435,12 @@ input:checked + .toggle-bg {
|
||||||
.border-4 {
|
.border-4 {
|
||||||
border-width: 4px;
|
border-width: 4px;
|
||||||
}
|
}
|
||||||
|
.border-b-8 {
|
||||||
|
border-bottom-width: 8px;
|
||||||
|
}
|
||||||
|
.border-t-8 {
|
||||||
|
border-top-width: 8px;
|
||||||
|
}
|
||||||
.border-solid {
|
.border-solid {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
@ -1420,10 +1460,18 @@ input:checked + .toggle-bg {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
||||||
}
|
}
|
||||||
|
.border-gray-200 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
.border-gray-300 {
|
.border-gray-300 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||||
}
|
}
|
||||||
|
.border-indigo-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(104 117 245 / 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));
|
||||||
|
@ -1555,6 +1603,9 @@ input:checked + .toggle-bg {
|
||||||
.text-justify {
|
.text-justify {
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
|
.text-5xl {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
.text-\[1\.8rem\] {
|
.text-\[1\.8rem\] {
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
}
|
}
|
||||||
|
@ -1988,6 +2039,10 @@ code {
|
||||||
height: 38rem;
|
height: 38rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lg\:max-h-\[35rem\] {
|
||||||
|
max-height: 35rem;
|
||||||
|
}
|
||||||
|
|
||||||
.lg\:w-96 {
|
.lg\:w-96 {
|
||||||
width: 24rem;
|
width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1160,6 +1160,11 @@ input:checked + .toggle-bg {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-10 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.my-4 {
|
.my-4 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -1182,6 +1187,14 @@ input:checked + .toggle-bg {
|
||||||
margin-right: -0.5rem;
|
margin-right: -0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-mt-0 {
|
||||||
|
margin-top: -0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-mt-0\.5 {
|
||||||
|
margin-top: -0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.-mt-1 {
|
.-mt-1 {
|
||||||
margin-top: -0.25rem;
|
margin-top: -0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1218,6 +1231,14 @@ input:checked + .toggle-bg {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-1 {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-1\.5 {
|
||||||
|
margin-top: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-2 {
|
.mt-2 {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -1289,6 +1310,10 @@ input:checked + .toggle-bg {
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-24 {
|
||||||
|
height: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-28 {
|
.h-28 {
|
||||||
height: 7rem;
|
height: 7rem;
|
||||||
}
|
}
|
||||||
|
@ -1370,6 +1395,10 @@ input:checked + .toggle-bg {
|
||||||
width: 3.5rem;
|
width: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-24 {
|
||||||
|
width: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-28 {
|
.w-28 {
|
||||||
width: 7rem;
|
width: 7rem;
|
||||||
}
|
}
|
||||||
|
@ -1464,6 +1493,16 @@ input:checked + .toggle-bg {
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-spin {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.cursor-default {
|
.cursor-default {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
@ -1538,6 +1577,10 @@ input:checked + .toggle-bg {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-y-scroll {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded-full {
|
.rounded-full {
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
}
|
}
|
||||||
|
@ -1582,6 +1625,14 @@ input:checked + .toggle-bg {
|
||||||
border-width: 4px;
|
border-width: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-b-8 {
|
||||||
|
border-bottom-width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-t-8 {
|
||||||
|
border-top-width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-solid {
|
.border-solid {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
@ -1606,11 +1657,21 @@ input:checked + .toggle-bg {
|
||||||
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-gray-200 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.border-gray-300 {
|
.border-gray-300 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-indigo-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(104 117 245 / 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));
|
||||||
|
@ -1779,6 +1840,10 @@ input:checked + .toggle-bg {
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-5xl {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-\[1\.8rem\] {
|
.text-\[1\.8rem\] {
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
}
|
}
|
||||||
|
@ -2272,6 +2337,10 @@ code {
|
||||||
height: 38rem;
|
height: 38rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lg\:max-h-\[35rem\] {
|
||||||
|
max-height: 35rem;
|
||||||
|
}
|
||||||
|
|
||||||
.lg\:w-96 {
|
.lg\:w-96 {
|
||||||
width: 24rem;
|
width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<link href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" rel="stylesheet">
|
<link href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" rel="stylesheet">
|
||||||
|
|
||||||
<link rel="stylesheet" href="css/app.min.css" />
|
<link rel="stylesheet" href="css/app.min.css" />
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
|
||||||
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
|
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
@ -26,12 +27,28 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<!--<div id="app">
|
||||||
<svg class="loading-progress">
|
<svg class="loading-progress">
|
||||||
<circle r="40%" cx="50%" cy="50%" />
|
<circle r="40%" cx="50%" cy="50%" />
|
||||||
<circle r="40%" cx="50%" cy="50%" />
|
<circle r="40%" cx="50%" cy="50%" />
|
||||||
</svg>
|
</svg>
|
||||||
<div class="loading-progress-text"></div>
|
<div class="loading-progress-text"></div>
|
||||||
|
</div>-->
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<div style="position:absolute; top:30vh; width:100%; text-align:center">
|
||||||
|
<h1 class="text-5xl"><b>پنـــــل ادمین فروشگاه</b></h1>
|
||||||
|
<div class="my-10" style="display:flex; gap:10px; justify-content:center; align-items:center">
|
||||||
|
<div class="relative">
|
||||||
|
<div class="h-24 w-24 rounded-full border-t-8 border-b-8 border-gray-200"></div>
|
||||||
|
<div class="absolute top-0 left-0 h-24 w-24 rounded-full border-t-8 border-b-8 border-indigo-500 animate-spin">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; gap:10px; justify-content:center; align-items:center">
|
||||||
|
... در حال لود کردن اپلیکیشن
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="blazor-error-ui">
|
<div id="blazor-error-ui">
|
||||||
|
@ -40,8 +57,8 @@
|
||||||
<a class="dismiss">🗙</a>
|
<a class="dismiss">🗙</a>
|
||||||
</div>
|
</div>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
<script src="aes-js-3.1.2.js"></script>
|
<script src="aes-js-3.1.2.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function encryptText(inputSrt, keyArray) {
|
function encryptText(inputSrt, keyArray) {
|
||||||
var textBytes = aesjs.utils.utf8.toBytes(inputSrt);
|
var textBytes = aesjs.utils.utf8.toBytes(inputSrt);
|
||||||
var aesCtr = new aesjs.ModeOfOperation.ctr(keyArray, new aesjs.Counter(5));
|
var aesCtr = new aesjs.ModeOfOperation.ctr(keyArray, new aesjs.Counter(5));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "NetinaShop.AdminPanel.PWA",
|
"name": "پنل مدیریتـــ فروشگاه وسمه",
|
||||||
"short_name": "NetinaShop.AdminPanel.PWA",
|
"short_name": "پنل مدیریت وسمه",
|
||||||
"id": "./",
|
"id": "./",
|
||||||
"start_url": "./",
|
"start_url": "./",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
|
|
Loading…
Reference in New Issue