feat : ProductPage and CategoryPage
complete category edit and creation , complete search for category and products pagerelease
parent
a8af53c9d9
commit
639d858476
|
@ -0,0 +1,55 @@
|
||||||
|
<MudButton Variant="@Variant"
|
||||||
|
Color="@Color"
|
||||||
|
@onclick="OnClickCallback"
|
||||||
|
@attributes="CapturedAttributes"
|
||||||
|
Disabled="IsProcessing"
|
||||||
|
DisableElevation="true"
|
||||||
|
>
|
||||||
|
@if (IsProcessing)
|
||||||
|
{
|
||||||
|
<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-extrabold my-1 mx-auto text-lg">منتظر بمانید</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="flex flex-row w-full">
|
||||||
|
@if (Variant == Variant.Filled)
|
||||||
|
{
|
||||||
|
<div class="-mr-2 -ml-6 w-10 h-10 items-center bg-[#000000] bg-opacity-20 rounded-md">
|
||||||
|
<MudIcon Icon="@Icon" class="w-5 h-5 mt-2.5"></MudIcon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="-mr-2 -ml-6 w-12 h-12 items-center rounded-md">
|
||||||
|
<MudIcon Icon="@Icon" class="w-7 h-7 mt-2"></MudIcon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<p class="my-auto mx-auto font-extrabold">@Content</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public Variant Variant { get; set; }
|
||||||
|
[Parameter]
|
||||||
|
public Color Color { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Icon { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool IsProcessing { get; set; } = false;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback OnClickCallback { get; set; }
|
||||||
|
|
||||||
|
[Parameter(CaptureUnmatchedValues = true)]
|
||||||
|
public Dictionary<string, object> CapturedAttributes { get; set; } = new();
|
||||||
|
}
|
|
@ -61,13 +61,13 @@
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
TreeItems.Add(new TreeItemData("داشبورد", Icons.Material.Outlined.Dashboard, "HomePage"));
|
TreeItems.Add(new TreeItemData("داشبورد", Icons.Material.Outlined.Dashboard, ""));
|
||||||
TreeItems.Add(new TreeItemData("فروش", Icons.Material.Outlined.ShoppingCart, "ProductsPage"));
|
TreeItems.Add(new TreeItemData("فروش", Icons.Material.Outlined.ShoppingCart, "products"));
|
||||||
TreeItems.Add(new TreeItemData("محصولات", Icons.Material.Outlined.CenterFocusStrong, "ProductsPage"));
|
TreeItems.Add(new TreeItemData("محصولات", Icons.Material.Outlined.CenterFocusStrong, "products"));
|
||||||
TreeItems.Add(new TreeItemData("دسته بندی ها", Icons.Material.Outlined.AllInbox, "CategoriesPage"));
|
TreeItems.Add(new TreeItemData("دسته بندی ها", Icons.Material.Outlined.AllInbox, "categories"));
|
||||||
TreeItems.Add(new TreeItemData("برند ها", Icons.Custom.Brands.Facebook, "BrandsPage"));
|
TreeItems.Add(new TreeItemData("برند ها", Icons.Custom.Brands.Facebook, "brands"));
|
||||||
TreeItems.Add(new TreeItemData("مشترکین", Icons.Material.Outlined.People, "ProductsPage"));
|
TreeItems.Add(new TreeItemData("مشترکین", Icons.Material.Outlined.People, "products"));
|
||||||
TreeItems.Add(new TreeItemData("وبلاگ", Icons.Material.Outlined.Web, "ProductsPage"));
|
TreeItems.Add(new TreeItemData("وبلاگ", Icons.Material.Outlined.Web, "products"));
|
||||||
TreeItems.Add(new TreeItemData("تنظیمات", Icons.Material.Outlined.Settings, "ProductsPage"));
|
TreeItems.Add(new TreeItemData("تنظیمات", Icons.Material.Outlined.Settings, "products"));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,86 @@
|
||||||
<h3>BrandActionDialogBox</h3>
|
@using NetinaShop.Common.Models.Exception
|
||||||
|
@using NetinaShop.Domain.CommandQueries.Commands
|
||||||
|
@using NetinaShop.Domain.Entities.Brands
|
||||||
|
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
|
||||||
|
<MudDialog class="mx-auto">
|
||||||
|
<DialogContent>
|
||||||
|
<MudStack>
|
||||||
|
<MudDivider class="-mt-3" />
|
||||||
|
<MudStack Spacing="0">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||||
|
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem lg="6" md="6">
|
||||||
|
<MudTextField T="string" Label="نام برند" @bind-Value="@_name" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="6" md="6">
|
||||||
|
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@_isMain" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||||
|
<MudSelectItem T="bool" Value="true"></MudSelectItem>
|
||||||
|
<MudSelectItem T="bool" Value="false" />
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem lg="12" md="12">
|
||||||
|
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
||||||
|
</MudItem>
|
||||||
|
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
@* <MudStack>
|
||||||
|
<BaseButtonUi Icon="@Icons.Material.Outlined.Check" Variant="Variant.Filled" Color="Color.Success" Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||||
|
|
||||||
|
</MudStack> *@
|
||||||
|
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||||
|
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing" Icon="@Icons.Material.Outlined.Check" Variant="Variant.Filled" Color="Color.Success" Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
@code {
|
@code {
|
||||||
|
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
private bool _isProcessing = false;
|
||||||
|
private string _name = string.Empty;
|
||||||
|
private string _description = string.Empty;
|
||||||
|
private bool _isMain;
|
||||||
|
|
||||||
|
private async Task SubmitCreateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام برند را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
|
var request = new CreateBrandCommand(_name, _description, _isMain, string.Empty, new List<StorageFileSDto>());
|
||||||
|
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||||
|
MudDialog.Close(DialogResult.Ok(true));
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -37,21 +37,28 @@
|
||||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="12" md="12">
|
||||||
<RadzenHtmlEditor>
|
<RadzenHtmlEditor class="min-h-[10rem]">
|
||||||
<RadzenHtmlEditorUndo/>
|
<RadzenHtmlEditorUndo />
|
||||||
<RadzenHtmlEditorRedo/>
|
<RadzenHtmlEditorRedo />
|
||||||
<RadzenHtmlEditorSeparator/>
|
<RadzenHtmlEditorSeparator />
|
||||||
<RadzenHtmlEditorAlignLeft/>
|
|
||||||
<RadzenHtmlEditorAlignCenter/>
|
<RadzenHtmlEditorFormatBlock />
|
||||||
<RadzenHtmlEditorAlignRight/>
|
<RadzenHtmlEditorSeparator />
|
||||||
<RadzenHtmlEditorJustify/>
|
|
||||||
<RadzenHtmlEditorSeparator/>
|
<RadzenHtmlEditorAlignLeft />
|
||||||
<RadzenHtmlEditorBold/>
|
<RadzenHtmlEditorAlignCenter />
|
||||||
<RadzenHtmlEditorItalic/>
|
<RadzenHtmlEditorAlignRight />
|
||||||
<RadzenHtmlEditorUnderline/>
|
<RadzenHtmlEditorJustify />
|
||||||
<RadzenHtmlEditorStrikeThrough/>
|
<RadzenHtmlEditorSeparator />
|
||||||
<RadzenHtmlEditorSeparator/>
|
|
||||||
<RadzenHtmlEditorRemoveFormat/>
|
<RadzenHtmlEditorSource />
|
||||||
|
<RadzenHtmlEditorBold />
|
||||||
|
<RadzenHtmlEditorItalic />
|
||||||
|
<RadzenHtmlEditorUnderline />
|
||||||
|
<RadzenHtmlEditorStrikeThrough />
|
||||||
|
<RadzenHtmlEditorRemoveFormat />
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
</RadzenHtmlEditor>
|
</RadzenHtmlEditor>
|
||||||
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
@ -77,4 +84,22 @@
|
||||||
|
|
||||||
void Submit() => MudDialog.Close(DialogResult.Ok(true));
|
void Submit() => MudDialog.Close(DialogResult.Ok(true));
|
||||||
void Cancel() => MudDialog.Cancel();
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
|
||||||
|
private bool _isEditing = false;
|
||||||
|
private bool _isProcessing = false;
|
||||||
|
|
||||||
|
private ProductSDto? _product = null;
|
||||||
|
[Parameter]
|
||||||
|
public ProductSDto? Product
|
||||||
|
{
|
||||||
|
get => _product;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_product = value;
|
||||||
|
if (_product != null)
|
||||||
|
{
|
||||||
|
_isEditing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
@using NetinaShop.Common.Models.Exception
|
@using NetinaShop.Common.Models.Exception
|
||||||
@using NetinaShop.Domain.CommandQueries.Commands
|
@using NetinaShop.Domain.CommandQueries.Commands
|
||||||
|
@using Radzen.Blazor
|
||||||
|
|
||||||
@inject ISnackbar Snackbar
|
@inject ISnackbar Snackbar
|
||||||
@inject IRestWrapper RestWrapper
|
@inject IRestWrapper RestWrapper
|
||||||
@inject IUserUtility UserUtility
|
@inject IUserUtility UserUtility
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||||
|
</head>
|
||||||
<MudDialog class="mx-auto">
|
<MudDialog class="mx-auto">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<MudStack>
|
<MudStack>
|
||||||
|
@ -16,10 +19,10 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudTextField T="string" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
<MudTextField T="string" @bind-Value="@_name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="4" md="6">
|
<MudItem lg="4" md="6">
|
||||||
<MudSelect T="bool" 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>
|
||||||
<MudSelectItem T="bool" Value="false" />
|
<MudSelectItem T="bool" Value="false" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
|
@ -46,29 +49,91 @@
|
||||||
</MudAutocomplete>
|
</MudAutocomplete>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem lg="12" md="12">
|
<MudItem lg="12" md="12">
|
||||||
<MudTextField T="string" Label="توضیحاتــ" Variant="Variant.Outlined"></MudTextField>
|
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||||
|
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<RadzenHtmlEditor @bind-Value="@_description" class="min-h-[10rem]">
|
||||||
|
<RadzenHtmlEditorUndo/>
|
||||||
|
<RadzenHtmlEditorRedo/>
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorFormatBlock/>
|
||||||
|
<RadzenHtmlEditorSeparator />
|
||||||
|
|
||||||
|
<RadzenHtmlEditorAlignLeft/>
|
||||||
|
<RadzenHtmlEditorAlignCenter/>
|
||||||
|
<RadzenHtmlEditorAlignRight/>
|
||||||
|
<RadzenHtmlEditorJustify/>
|
||||||
|
<RadzenHtmlEditorSeparator/>
|
||||||
|
|
||||||
|
<RadzenHtmlEditorSource />
|
||||||
|
<RadzenHtmlEditorBold/>
|
||||||
|
<RadzenHtmlEditorItalic/>
|
||||||
|
<RadzenHtmlEditorUnderline/>
|
||||||
|
<RadzenHtmlEditorStrikeThrough />
|
||||||
|
<RadzenHtmlEditorRemoveFormat />
|
||||||
|
<RadzenHtmlEditorSeparator/>
|
||||||
|
|
||||||
|
</RadzenHtmlEditor>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudStack class="w-full mx-4" Row="true">
|
|
||||||
<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 Row="true" class="w-full mx-4 mb-2">
|
||||||
|
|
||||||
|
@if (_isEditing)
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||||
|
Icon="@Icons.Material.Outlined.Check"
|
||||||
|
Variant="Variant.Filled" Color="Color.Success"
|
||||||
|
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||||
|
}
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||||
</MudStack>
|
</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();
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
|
||||||
private string _name;
|
private string _name = string.Empty;
|
||||||
private string _description;
|
private string _description = string.Empty;
|
||||||
private bool _isMain;
|
private bool _isMain;
|
||||||
|
private bool _isEditing = false;
|
||||||
|
private bool _isProcessing = false;
|
||||||
|
|
||||||
|
private ProductCategorySDto? _category = null;
|
||||||
|
[Parameter]
|
||||||
|
public ProductCategorySDto? Category
|
||||||
|
{
|
||||||
|
get => _category;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_category = value;
|
||||||
|
if (_category != null)
|
||||||
|
{
|
||||||
|
_name = _category.Name;
|
||||||
|
_description = _category.Description;
|
||||||
|
_isEditing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SubmitCreateAsync()
|
private async Task SubmitCreateAsync()
|
||||||
{
|
{
|
||||||
|
@ -76,9 +141,11 @@
|
||||||
{
|
{
|
||||||
if (_name.IsNullOrEmpty())
|
if (_name.IsNullOrEmpty())
|
||||||
throw new AppException("لطفا نام دسته را وارد کنید");
|
throw new AppException("لطفا نام دسته را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
var token = await UserUtility.GetBearerTokenAsync();
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
var request = new ProductCreateCategoryCommand(_name, _description, _selectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
var request = new CreateProductCategoryCommand(_name, _description,_isMain, _selectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
||||||
await RestWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<ProductCreateCategoryCommand>(request, token);
|
await RestWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(request, token);
|
||||||
|
MudDialog.Close();
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
{
|
{
|
||||||
|
@ -86,10 +153,52 @@
|
||||||
if (exe != null)
|
if (exe != null)
|
||||||
Snackbar.Add(exe.Message, Severity.Error);
|
Snackbar.Add(exe.Message, Severity.Error);
|
||||||
Snackbar.Add(ex.Content, Severity.Error);
|
Snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Snackbar.Add(e.Message, Severity.Error);
|
Snackbar.Add(e.Message, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
_isProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitEditAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Category == null)
|
||||||
|
throw new AppException("دسته به درستی ارسال نشده است");
|
||||||
|
if (_name.IsNullOrEmpty())
|
||||||
|
throw new AppException("لطفا نام دسته را وارد کنید");
|
||||||
|
_isProcessing = true;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
var token = await UserUtility.GetBearerTokenAsync();
|
||||||
|
var request = new UpdateProductCategoryCommand(Category.Id, _name, _description,_isMain, _selectedCategory?.Id ?? default, new List<StorageFileSDto>());
|
||||||
|
await RestWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(request, token);
|
||||||
|
MudDialog.Close();
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
if (exe != null)
|
||||||
|
Snackbar.Add(exe.Message, Severity.Error);
|
||||||
|
Snackbar.Add(ex.Content, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Snackbar.Add(e.Message, Severity.Error);
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
_isProcessing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +210,7 @@
|
||||||
{
|
{
|
||||||
if (_productCategories.Count == 0)
|
if (_productCategories.Count == 0)
|
||||||
{
|
{
|
||||||
_productCategories = await RestWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController).ReadAll();
|
_productCategories = await RestWrapper.ProductCategoryRestApi.ReadAll();
|
||||||
}
|
}
|
||||||
if (city.IsNullOrEmpty())
|
if (city.IsNullOrEmpty())
|
||||||
return _productCategories;
|
return _productCategories;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
@inherits LayoutComponentBase
|
@using NetinaShop.AdminPanel.PWA.Pages
|
||||||
|
@using Radzen.Blazor
|
||||||
|
@inherits LayoutComponentBase
|
||||||
@inject IPWAUpdaterService PwaUpdaterService
|
@inject IPWAUpdaterService PwaUpdaterService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
<style>
|
<style>
|
||||||
body .pwa-updater[b-pwa-updater] {
|
body .pwa-updater[b-pwa-updater] {
|
||||||
--pwa-updater-bar-height: 40px;
|
--pwa-updater-bar-height: 40px;
|
||||||
|
@ -45,7 +49,7 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudSpacer />
|
<MudSpacer />
|
||||||
<MudIconButton Size="Size.Medium" Color="Color.Inherit" Icon="@Icons.Material.Outlined.Settings"/>
|
<MudIconButton Size="Size.Medium" Color="Color.Inherit" Icon="@Icons.Material.Outlined.Settings"/>
|
||||||
<MudIconButton Size="Size.Medium" Color="Color.Error" Icon="@Icons.Material.Outlined.ExitToApp" />
|
<MudIconButton Size="Size.Medium" Color="Color.Error" OnClick="LogoutAsync" Icon="@Icons.Material.Outlined.ExitToApp" />
|
||||||
</MudAppBar>
|
</MudAppBar>
|
||||||
|
|
||||||
<MudGrid Spacing="0">
|
<MudGrid Spacing="0">
|
||||||
|
@ -77,7 +81,7 @@
|
||||||
|
|
||||||
<MudLayout>
|
<MudLayout>
|
||||||
<div>
|
<div>
|
||||||
@Body
|
<LoginPage/>
|
||||||
<div dir="ltr">
|
<div dir="ltr">
|
||||||
<PWAUpdater Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
<PWAUpdater Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,6 +115,12 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
private string _updateText = "! نسخه جدید پنل ادمین رسید";
|
private string _updateText = "! نسخه جدید پنل ادمین رسید";
|
||||||
|
|
||||||
|
private async Task LogoutAsync()
|
||||||
|
{
|
||||||
|
await UserUtility.LogoutAsync();
|
||||||
|
NavigationManager.NavigateTo("login",true,true);
|
||||||
|
}
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
string? version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
|
string? version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
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://apinetinashop.visabartar.com/api";
|
//public static string BaseAddress = "https://apinetinashop.visabartar.com/api";
|
||||||
#else
|
#else
|
||||||
public static string BaseAddress = "https://apinetinashop.visabartar.com/api";
|
public static string BaseAddress = "https://apinetinashop.visabartar.com/api";
|
||||||
#endif
|
#endif
|
||||||
public static string AuthController = $"{BaseAddress}/auth";
|
public static string AuthController = $"{BaseAddress}/auth";
|
||||||
public static string UserController = $"{BaseAddress}/user";
|
public static string UserController = $"{BaseAddress}/user";
|
||||||
public static string ProductCategoryController = $"{BaseAddress}/product/category";
|
public static string ProductCategoryController = $"{BaseAddress}/product/category";
|
||||||
|
public static string ProductController = $"{BaseAddress}/product";
|
||||||
public static string BrandController = $"{BaseAddress}/brand";
|
public static string BrandController = $"{BaseAddress}/brand";
|
||||||
}
|
}
|
|
@ -37,12 +37,12 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Utilities\" />
|
<Folder Include="Utilities\" />
|
||||||
<Folder Include="Services\RestServices\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="Blazored.LocalStorage" />
|
<Using Include="Blazored.LocalStorage" />
|
||||||
<Using Include="Microsoft.AspNetCore.Components" />
|
<Using Include="Microsoft.AspNetCore.Components" />
|
||||||
|
<Using Include="Microsoft.IdentityModel.Tokens" />
|
||||||
<Using Include="Microsoft.JSInterop" />
|
<Using Include="Microsoft.JSInterop" />
|
||||||
<Using Include="MudBlazor" />
|
<Using Include="MudBlazor" />
|
||||||
<Using Include="NetinaShop.AdminPanel.PWA.Dialogs" />
|
<Using Include="NetinaShop.AdminPanel.PWA.Dialogs" />
|
||||||
|
@ -52,12 +52,15 @@
|
||||||
<Using Include="NetinaShop.AdminPanel.PWA.Services.RestServices" />
|
<Using Include="NetinaShop.AdminPanel.PWA.Services.RestServices" />
|
||||||
<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.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" />
|
||||||
|
<Using Include="NetinaShop.Domain.Entities.Products" />
|
||||||
<Using Include="NetinaShop.Domain.Enums" />
|
<Using Include="NetinaShop.Domain.Enums" />
|
||||||
<Using Include="Newtonsoft.Json" />
|
<Using Include="Newtonsoft.Json" />
|
||||||
<Using Include="Refit" />
|
<Using Include="Refit" />
|
||||||
|
<Using Include="System.Collections.ObjectModel" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@page "/BrandsPage"
|
@page "/brands"
|
||||||
|
|
||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class BrandsPageViewModel : BaseViewModel<List<BrandSDto>>
|
||||||
await _restWrapper.CrudDtoApiRest<Brand, BrandSDto, Guid>(Address.BrandController)
|
await _restWrapper.CrudDtoApiRest<Brand, BrandSDto, Guid>(Address.BrandController)
|
||||||
.Delete(selectedCategoryId, token);
|
.Delete(selectedCategoryId, token);
|
||||||
_snackbar.Add("حذف برند با موفقیت انجام شد", Severity.Success);
|
_snackbar.Add("حذف برند با موفقیت انجام شد", Severity.Success);
|
||||||
|
await InitializeAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@page "/CategoriesPage"
|
@using Radzen.Blazor
|
||||||
|
@page "/categories"
|
||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IRestWrapper RestWrapper
|
@inject IRestWrapper RestWrapper
|
||||||
|
@ -13,25 +14,35 @@
|
||||||
<MudText Typo="Typo.h4">دسته بندی ها</MudText>
|
<MudText Typo="Typo.h4">دسته بندی ها</MudText>
|
||||||
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
|
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
|
||||||
|
|
||||||
<MudSpacer />
|
<MudSpacer/>
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
DisableElevation="true"
|
DisableElevation="true"
|
||||||
StartIcon="@Icons.Material.Outlined.Add"
|
StartIcon="@Icons.Material.Outlined.Add"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
OnClick="ViewModel.AddProductClicked"
|
OnClick="ViewModel.AddProductCategoryClicked"
|
||||||
class="my-auto">افزودن دسته بندی</MudButton>
|
class="my-auto">افزودن دسته بندی</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudPaper>
|
<MudPaper>
|
||||||
<MudDataGrid Striped="true" T="ProductCategorySDto" Items="@ViewModel.PageDto" Filterable="false" Loading="@ViewModel.IsProcessing"
|
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||||
|
T="ProductCategorySDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||||
|
RowsPerPage="15" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||||
SortMode="@SortMode.None" Groupable="false">
|
SortMode="@SortMode.None" Groupable="false">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"></MudTextField>
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||||
|
@bind-Value="@ViewModel.Search"
|
||||||
|
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||||
</ToolBarContent>
|
</ToolBarContent>
|
||||||
|
|
||||||
<Columns>
|
<Columns>
|
||||||
<PropertyColumn Title="نام دسته" Property="arg => arg.Name"/>
|
<HierarchyColumn T="ProductCategorySDto" ButtonDisabledFunc="@(x => x.Description.IsNullOrEmpty())" />
|
||||||
<PropertyColumn Title="توضیحاتــ" Property="arg => arg.Description"/>
|
<PropertyColumn Title="نام دسته" Resizable="false" Property="arg => arg.Name"/>
|
||||||
<TemplateColumn Title="دسته اصلی" T="ProductCategorySDto">
|
@* <TemplateColumn Title="توضیحاتــ" Resizable="false" T="ProductCategorySDto">
|
||||||
|
<CellTemplate>
|
||||||
|
<p class="line-clamp-1">@context.Item.Description</p>
|
||||||
|
</CellTemplate>
|
||||||
|
</TemplateColumn> *@
|
||||||
|
<TemplateColumn Resizable="false" Title="دسته اصلی" T="ProductCategorySDto">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
@if (@context.Item.IsMain)
|
@if (@context.Item.IsMain)
|
||||||
{
|
{
|
||||||
|
@ -44,19 +55,46 @@
|
||||||
}
|
}
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
|
<PropertyColumn Title="دسته پدر" Resizable="false" Property="arg => arg.ParentName" />
|
||||||
<TemplateColumn CellClass="d-flex justify-end">
|
<TemplateColumn CellClass="d-flex justify-end">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="@Size.Small" Variant="@Variant.Outlined" Color="@Color.Info"></MudIconButton>
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
OnClick="async () => await ViewModel.EditProductCategoryClicked(context.Item)"
|
||||||
|
Color="@Color.Info"/>
|
||||||
|
|
||||||
<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.DeleteProductCategoryAsync(context.Item.Id)"
|
OnClick="async () => await ViewModel.DeleteProductCategoryAsync(context.Item.Id)"
|
||||||
Color="@Color.Error"></MudIconButton>
|
Color="@Color.Error"/>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
|
||||||
|
<ChildRowContent>
|
||||||
|
<MudCard>
|
||||||
|
<MudCardHeader>
|
||||||
|
<CardHeaderContent>
|
||||||
|
<MudText Typo="Typo.h6">توضیحاتــ</MudText>
|
||||||
|
</CardHeaderContent>
|
||||||
|
</MudCardHeader>
|
||||||
|
<MudCardContent>
|
||||||
|
<MudText>@context.Item.Description</MudText>
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
|
</ChildRowContent>
|
||||||
|
<PagerContent>
|
||||||
|
<MudStack Row="true" class="w-full">
|
||||||
|
|
||||||
|
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||||
|
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto"/>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
using System.Collections.ObjectModel;
|
||||||
|
using NetinaShop.Common.Models.Exception;
|
||||||
|
|
||||||
public class CategoriesPageViewModel : BaseViewModel<List<ProductCategorySDto>>
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<ProductCategorySDto>>
|
||||||
{
|
{
|
||||||
private readonly NavigationManager _navigationManager;
|
private readonly NavigationManager _navigationManager;
|
||||||
private readonly ISnackbar _snackbar;
|
private readonly ISnackbar _snackbar;
|
||||||
|
@ -8,6 +11,10 @@ public class CategoriesPageViewModel : BaseViewModel<List<ProductCategorySDto>>
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly IRestWrapper _restWrapper;
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
|
||||||
|
public string Search = string.Empty;
|
||||||
|
public int CurrentPage = 0;
|
||||||
|
public int PageCount = 1;
|
||||||
|
|
||||||
public CategoriesPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
public CategoriesPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||||
{
|
{
|
||||||
_navigationManager = navigationManager;
|
_navigationManager = navigationManager;
|
||||||
|
@ -22,9 +29,12 @@ public class CategoriesPageViewModel : BaseViewModel<List<ProductCategorySDto>>
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IsProcessing = true;
|
IsProcessing = true;
|
||||||
|
PageDto.Clear();
|
||||||
var dto = await _restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
|
var dto = await _restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
|
||||||
.ReadAll();
|
.ReadAll(CurrentPage);
|
||||||
PageDto = dto;
|
dto.ForEach(d=>PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 15)
|
||||||
|
PageCount = 2;
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (ApiException ex)
|
||||||
{
|
{
|
||||||
|
@ -43,12 +53,53 @@ public class CategoriesPageViewModel : BaseViewModel<List<ProductCategorySDto>>
|
||||||
await base.InitializeAsync();
|
await base.InitializeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddProductClicked()
|
public async Task ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page-1;
|
||||||
|
if (CurrentPage > PageCount-2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
var dto = await _restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if(PageDto.Count % 15==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 AddProductCategoryClicked()
|
||||||
{
|
{
|
||||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
await _dialogService.ShowAsync<ProductCategoryActionDialogBox>("افزودن دسته جدید", maxWidth);
|
await _dialogService.ShowAsync<ProductCategoryActionDialogBox>("افزودن دسته جدید", maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task EditProductCategoryClicked(ProductCategorySDto category)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<ProductCategoryActionDialogBox>();
|
||||||
|
parameters.Add(x=>x.Category,category);
|
||||||
|
await _dialogService.ShowAsync<ProductCategoryActionDialogBox>($"ویرایش دسته {category.Name}", parameters, maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteProductCategoryAsync(Guid selectedCategoryId)
|
public async Task DeleteProductCategoryAsync(Guid selectedCategoryId)
|
||||||
{
|
{
|
||||||
var options = new DialogOptions { CloseOnEscapeKey = true };
|
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||||
|
@ -85,4 +136,35 @@ public class CategoriesPageViewModel : BaseViewModel<List<ProductCategorySDto>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("دسته بندی برای جست جو وارد نشده است");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.ProductCategoryRestApi.ReadAll(Search);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
|
@page "/"
|
||||||
@page "/"
|
@page "/home"
|
||||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||||
|
|
||||||
<MudStack class="w-screen h-screen bg-[--color-background]">
|
<MudStack class="w-screen h-screen bg-[--color-background]">
|
||||||
|
|
|
@ -1,6 +1,90 @@
|
||||||
@page "/LoginPage"
|
@using Microsoft.AspNetCore.Authorization
|
||||||
<h3>LoginPage</h3>
|
@attribute [AllowAnonymous]
|
||||||
|
@page "/login"
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
|
||||||
|
|
||||||
|
@* <style>
|
||||||
|
.mud-input-label {
|
||||||
|
background-color: #356859;
|
||||||
|
color: #eee !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-border > .mud-input-control-input-container > .mud-input.mud-input-outlined > input:focus ~ .mud-input-outlined-border {
|
||||||
|
border-color: rgba(253, 85, 35, 1);
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
inpute {
|
||||||
|
color: white !important
|
||||||
|
}
|
||||||
|
</style> *@
|
||||||
|
<div class="w-screen h-screen bg-[#EEEEEE] p-0 flex flex-col-reverse md:flex-row overflow-hidden">
|
||||||
|
<div class="bg-white h-full basis-full md:basis-1/2 md:rounded-tr-none md:rounded-bl-xl md:rounded-tl-xl flex md:px-10 lg:px-20 py-8 px-4">
|
||||||
|
<MudStack class="my-auto mx-auto">
|
||||||
|
<div>
|
||||||
|
<MudText Typo="Typo.h5" class="text-lg text-center"><b>ورود با شماره تلفن همراه</b></MudText>
|
||||||
|
<MudText Typo="Typo.caption" Align="Align.Center">برای ورود به پنل ادمین شماره تلفن همراه خود را وارد کنید ، میتوانید با رمز عبور نیز وارد شوید</MudText>
|
||||||
|
</div>
|
||||||
|
@*<p class="text-lg sm:mt-6 mb-3 font-extrabold">شماره تلفن شما</p>
|
||||||
|
|
||||||
|
<input class="bg-transparent text-[1.8rem] sm:py-3 font-extrabold text-center border rounded-md shadow-sm focus:border-teal-500 focus:ring-teal-500"
|
||||||
|
type="text"
|
||||||
|
maxlength="11"
|
||||||
|
pattern="[0-9]"
|
||||||
|
inputmode="numeric"
|
||||||
|
autocomplete="one-time-code" required> *@
|
||||||
|
|
||||||
|
@if (@ViewModel.PhoneNumberConfirmed)
|
||||||
|
{
|
||||||
|
<MudTextField T="string" @bind-value="@ViewModel.VerifyCode" Label="کد ارسال شده" Variant="Variant.Outlined" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudTextField T="string" @bind-Value="@ViewModel.PhoneNumber" Label="شماره تلفن همراه" Variant="Variant.Outlined" />
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<BaseButtonUi Variant="Variant.Filled"
|
||||||
|
Icon="@Icons.Material.Outlined.Login"
|
||||||
|
OnClickCallback="@ViewModel.SubmitAsync"
|
||||||
|
Color="Color.Info"
|
||||||
|
IsProcessing="@ViewModel.IsProcessing"
|
||||||
|
class="text-xl py-3"
|
||||||
|
Content="تایید و ادامه"></BaseButtonUi>
|
||||||
|
<p class="mx-3 text-justify">
|
||||||
|
با تایید شماره تلفن همراه با همه شرایط <a class="text-blue-500">
|
||||||
|
حریم
|
||||||
|
خصوصی
|
||||||
|
</a> اپلیکیشن داکیومد موافقت می کنم
|
||||||
|
</p>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="h-full basis-full md:basis-1/2 md:rounded-tr-none md:rounded-bl-xl md:rounded-tl-xl flex md:px-10 lg:px-20 py-8 px-4">
|
||||||
|
|
||||||
|
<div class="mx-auto my-auto">
|
||||||
|
<dotlottie-player src="https://lottie.host/235bcb2d-0f2c-4f06-9c36-7e6677b82e00/9tGECPkU5J.json"
|
||||||
|
background="transparent" speed="1" class="mx-auto w-64 h-64 lg:w-96 lg:h-96" loop autoplay />
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h5" Align="Align.Center"><b>داشبورد تخصصی نتینا</b></MudText>
|
||||||
|
<MudText Align="Align.Center">شما میتوانید با ورود به داشبورد تخصصی نتینا فروشگاه خود را مدیریت کنید </MudText>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
|
public LoginPageViewModel ViewModel { get; set; }
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
ViewModel = new LoginPageViewModel(Snackbar,RestWrapper,NavigationManager,UserUtility);
|
||||||
|
await ViewModel.InitializeAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class LoginPageViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly IRestWrapper _restWrapper;
|
||||||
|
private readonly NavigationManager _navigationManager;
|
||||||
|
private readonly IUserUtility _userUtility;
|
||||||
|
private readonly ISnackbar _snackbar;
|
||||||
|
public LoginPageViewModel(ISnackbar snackbar, IRestWrapper restWrapper,NavigationManager navigationManager,IUserUtility userUtility)
|
||||||
|
{
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_navigationManager = navigationManager;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
}
|
||||||
|
public bool PhoneNumberConfirmed { get; set; }
|
||||||
|
public string PhoneNumber { get; set; } = string.Empty;
|
||||||
|
public string VerifyCode { get; set; } = string.Empty;
|
||||||
|
public async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
if (!PhoneNumberConfirmed)
|
||||||
|
{
|
||||||
|
await _restWrapper.AuthRestApi.GetVerifyCodeAsync(PhoneNumber);
|
||||||
|
PhoneNumberConfirmed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dto = await _restWrapper.AuthRestApi.LoginWithVerifyCodeAsync(new LoginRequestDto
|
||||||
|
{ UserName = PhoneNumber, VerifyCode = VerifyCode });
|
||||||
|
await _userUtility.SetUserAsync(dto.User);
|
||||||
|
await _userUtility.SetBearerTokenAsync(dto.BearerToken);
|
||||||
|
_navigationManager.NavigateTo("home",true,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,11 @@
|
||||||
@page "/ProductsPage"
|
@page "/products"
|
||||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||||
|
|
||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IUserUtility UserUtility
|
||||||
|
@inject IRestWrapper RestWrapper
|
||||||
|
|
||||||
<MudStack class="w-full p-8 h-screen bg-[--color-background]">
|
<MudStack class="w-full p-8 h-screen bg-[--color-background]">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
|
@ -14,25 +18,52 @@
|
||||||
DisableElevation="true"
|
DisableElevation="true"
|
||||||
StartIcon="@Icons.Material.Outlined.Add"
|
StartIcon="@Icons.Material.Outlined.Add"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
OnClick="AddProductClicked"
|
OnClick="@ViewModel.AddProductClicked"
|
||||||
class="my-auto">افزودن محصول</MudButton>
|
class="my-auto">افزودن محصول</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudPaper>
|
<MudPaper>
|
||||||
<MudDataGrid T="ProductSDto" Items="@Products" Filterable="false" SortMode="@SortMode.None" Groupable="false">
|
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||||
|
T="ProductSDto" 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>
|
<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"/>
|
||||||
<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>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="@Size.Small" Variant="@Variant.Outlined" Color="@Color.Info"></MudIconButton>
|
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="@Size.Small" Variant="@Variant.Outlined" Color="@Color.Error"></MudIconButton>
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
Color="@Color.Info"></MudIconButton>
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||||
|
Size="@Size.Small"
|
||||||
|
Variant="@Variant.Outlined"
|
||||||
|
OnClick="async () => await ViewModel.DeleteProductAsync(context.Item.Id)"
|
||||||
|
Color="@Color.Error"></MudIconButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
<PagerContent>
|
||||||
|
<MudStack Row="true" class="w-full">
|
||||||
|
|
||||||
|
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||||
|
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto"/>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
</PagerContent>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
@ -41,56 +72,11 @@
|
||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
List<ProductSDto> Products { get; set; } = new List<ProductSDto>();
|
public ProductsPageViewModel ViewModel { get; set; }
|
||||||
protected override Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
Products.Add(new ProductSDto
|
ViewModel = new ProductsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||||
{
|
await ViewModel.InitializeAsync();
|
||||||
PersianName = "شامپو ضدشوره هد اند شولدرز (Head & Shoulders) مدل Lemon 2in1 arada حجم 350 میلی لیتر",
|
await base.OnInitializedAsync();
|
||||||
BrandNames = "شوریدر",
|
|
||||||
CategoryName = "شوینده سر",
|
|
||||||
Cost = 1200000,
|
|
||||||
|
|
||||||
});
|
|
||||||
Products.Add(new ProductSDto
|
|
||||||
{
|
|
||||||
PersianName = "شامپو ضدشوره هد اند شولدرز (Head & Shoulders) مدل Lemon 2in1 arada حجم 350 میلی لیتر",
|
|
||||||
BrandNames = "شوریدر",
|
|
||||||
CategoryName = "شوینده سر",
|
|
||||||
Cost = 1200000,
|
|
||||||
|
|
||||||
});
|
|
||||||
Products.Add(new ProductSDto
|
|
||||||
{
|
|
||||||
PersianName = "شامپو ضدشوره هد اند شولدرز (Head & Shoulders) مدل Lemon 2in1 arada حجم 350 میلی لیتر",
|
|
||||||
BrandNames = "شوریدر",
|
|
||||||
CategoryName = "شوینده سر",
|
|
||||||
Cost = 1200000,
|
|
||||||
|
|
||||||
});
|
|
||||||
Products.Add(new ProductSDto
|
|
||||||
{
|
|
||||||
PersianName = "شامپو ضدشوره هد اند شولدرز (Head & Shoulders) مدل Lemon 2in1 arada حجم 350 میلی لیتر",
|
|
||||||
BrandNames = "شوریدر",
|
|
||||||
CategoryName = "شوینده سر",
|
|
||||||
Cost = 1200000,
|
|
||||||
|
|
||||||
});
|
|
||||||
Products.Add(new ProductSDto
|
|
||||||
{
|
|
||||||
PersianName = "شامپو ضدشوره هد اند شولدرز (Head & Shoulders) مدل Lemon 2in1 arada حجم 350 میلی لیتر",
|
|
||||||
BrandNames = "شوریدر",
|
|
||||||
CategoryName = "شوینده سر",
|
|
||||||
Cost = 1200000,
|
|
||||||
|
|
||||||
});
|
|
||||||
return base.OnInitializedAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddProductClicked()
|
|
||||||
{
|
|
||||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true };
|
|
||||||
var options = new DialogOptions { CloseOnEscapeKey = true , Position = DialogPosition.Center, MaxWidth = MaxWidth.Large , DisableBackdropClick = true};
|
|
||||||
await DialogService.ShowAsync<ProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||||
|
|
||||||
|
public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductSDto>>
|
||||||
|
{
|
||||||
|
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 ProductsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||||
|
{
|
||||||
|
_navigationManager = navigationManager;
|
||||||
|
_snackbar = snackbar;
|
||||||
|
_userUtility = userUtility;
|
||||||
|
_restWrapper = restWrapper;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
PageCount = 2;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
await base.InitializeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ChangePageAsync(int page)
|
||||||
|
{
|
||||||
|
CurrentPage = page - 1;
|
||||||
|
if (CurrentPage > PageCount - 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsProcessing = true;
|
||||||
|
|
||||||
|
List<ProductSDto> dto = new List<ProductSDto>();
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||||
|
.ReadAll(CurrentPage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count % 20 == 0)
|
||||||
|
PageCount = CurrentPage + 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddProductClicked()
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
await _dialogService.ShowAsync<ProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EditProductClicked(ProductSDto product)
|
||||||
|
{
|
||||||
|
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||||
|
var parameters = new DialogParameters<ProductActionDialogBox>();
|
||||||
|
parameters.Add(x => x.Product, product);
|
||||||
|
await _dialogService.ShowAsync<ProductActionDialogBox>($"ویرایش محصول {product.PersianName}", parameters, maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteProductAsync(Guid selectedCategoryId)
|
||||||
|
{
|
||||||
|
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||||
|
var parameters = new DialogParameters<QuestionDialog>();
|
||||||
|
parameters.Add(x => x.ContentText, "آیا از حذف محصول اطمینان دارید ?");
|
||||||
|
var dialogReference = await _dialogService.ShowAsync<QuestionDialog>("حذف شرح حال", parameters, options);
|
||||||
|
var result = await dialogReference.Result;
|
||||||
|
if (!result.Canceled)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = true;
|
||||||
|
var token = await _userUtility.GetBearerTokenAsync();
|
||||||
|
await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||||
|
.Delete(selectedCategoryId, token);
|
||||||
|
_snackbar.Add("حذف محصول با موفقیت انجام شد", Severity.Success);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SearchChanged(string search)
|
||||||
|
{
|
||||||
|
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||||
|
await InitializeAsync();
|
||||||
|
Search = search;
|
||||||
|
}
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Search.IsNullOrEmpty())
|
||||||
|
throw new AppException("دسته بندی برای جست جو وارد نشده است");
|
||||||
|
IsProcessing = true;
|
||||||
|
CurrentPage = 0;
|
||||||
|
PageCount = 1;
|
||||||
|
PageDto.Clear();
|
||||||
|
var dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage, Search);
|
||||||
|
dto.ForEach(d => PageDto.Add(d));
|
||||||
|
if (PageDto.Count == 20)
|
||||||
|
PageCount = 2;
|
||||||
|
}
|
||||||
|
catch (ApiException ex)
|
||||||
|
{
|
||||||
|
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||||
|
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_snackbar.Add(e.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
|
||||||
|
IsProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,5 +31,7 @@ builder.Services.AddMudServices(config =>
|
||||||
builder.Services.AddScoped<IRestWrapper, RestWrapper>();
|
builder.Services.AddScoped<IRestWrapper, RestWrapper>();
|
||||||
builder.Services.AddScoped<IUserUtility, UserUtility>();
|
builder.Services.AddScoped<IUserUtility, UserUtility>();
|
||||||
builder.Services.AddBlazoredLocalStorage();
|
builder.Services.AddBlazoredLocalStorage();
|
||||||
|
builder.Services.AddScoped<Radzen.ContextMenuService>();
|
||||||
|
builder.Services.AddScoped<Radzen.DialogService>();
|
||||||
builder.Services.AddPWAUpdater();
|
builder.Services.AddPWAUpdater();
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Blazorise.Extensions;
|
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
|
||||||
namespace NetinaShop.AdminPanel.PWA.Services;
|
namespace NetinaShop.AdminPanel.PWA.Services;
|
||||||
|
@ -19,14 +18,17 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
||||||
{
|
{
|
||||||
return new AuthenticationState(new());
|
return new AuthenticationState(new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var user = await _userUtility.GetUserAsync();
|
||||||
var identity = new ClaimsIdentity(new[]
|
var identity = new ClaimsIdentity(new[]
|
||||||
{
|
{
|
||||||
new Claim(ClaimTypes.Name, "mrfibuli"),
|
new Claim(ClaimTypes.Name, user.FirstName + " " + user.LastName),
|
||||||
}, "Custom Authentication");
|
new Claim(ClaimTypes.MobilePhone , user.PhoneNumber)
|
||||||
|
}, "Bearer");
|
||||||
|
|
||||||
var user = new ClaimsPrincipal(identity);
|
var claimUser = new ClaimsPrincipal(identity);
|
||||||
|
|
||||||
|
|
||||||
return new AuthenticationState(user);
|
return new AuthenticationState(claimUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
public interface IAuthRestApi
|
public interface IAuthRestApi
|
||||||
{
|
{
|
||||||
[Get("/verifycode")]
|
[Get("/verifycode")]
|
||||||
public Task<SignUpStatus> GetVerifyCodeAsync([Query] string phoneNumber);
|
public Task GetVerifyCodeAsync([Query] string phoneNumber);
|
||||||
|
|
||||||
[Post("/login/code")]
|
[Post("/login/code")]
|
||||||
public Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync([Body] LoginRequestDto request);
|
public Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync([Body] LoginRequestDto request);
|
||||||
|
|
|
@ -14,7 +14,7 @@ public interface ICrudApiRest<T, in TKey> where T : class
|
||||||
Task<T> ReadOne(TKey key, [Header("Authorization")] string authorization);
|
Task<T> ReadOne(TKey key, [Header("Authorization")] string authorization);
|
||||||
|
|
||||||
[Put("")]
|
[Put("")]
|
||||||
Task Update([Body] T payload, [Header("Authorization")] string authorization);
|
Task Update<TUpdateCommand>([Body] TUpdateCommand payload, [Header("Authorization")] string authorization);
|
||||||
|
|
||||||
[Delete("/{key}")]
|
[Delete("/{key}")]
|
||||||
Task Delete(TKey key, [Header("Authorization")] string authorization);
|
Task Delete(TKey key, [Header("Authorization")] string authorization);
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IProductCategoryRestApi
|
||||||
|
{
|
||||||
|
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductCategorySDto>> ReadAll();
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductCategorySDto>> ReadAll([Query] int page);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductCategorySDto>> ReadAll([Query] int page,[Query]string categoryName);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductCategorySDto>> ReadAll([Query] string categoryName);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||||
|
|
||||||
|
public interface IProductRestApi
|
||||||
|
{
|
||||||
|
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductSDto>> ReadAll();
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductSDto>> ReadAll([Query] int page);
|
||||||
|
[Get("")]
|
||||||
|
Task<List<ProductSDto>> ReadAll([Query] int page, [Query] string productName);
|
||||||
|
}
|
|
@ -8,4 +8,6 @@ public interface IRestWrapper
|
||||||
|
|
||||||
public IAuthRestApi AuthRestApi { get; }
|
public IAuthRestApi AuthRestApi { get; }
|
||||||
public IUserRestApi UserRestApi { get; }
|
public IUserRestApi UserRestApi { get; }
|
||||||
|
public IProductCategoryRestApi ProductCategoryRestApi { get; }
|
||||||
|
public IProductRestApi ProductRestApi { get; }
|
||||||
}
|
}
|
|
@ -20,4 +20,6 @@ public class RestWrapper : IRestWrapper
|
||||||
}
|
}
|
||||||
public IAuthRestApi AuthRestApi => RestService.For<IAuthRestApi>(Address.AuthController, setting);
|
public IAuthRestApi AuthRestApi => RestService.For<IAuthRestApi>(Address.AuthController, setting);
|
||||||
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 IProductRestApi ProductRestApi => RestService.For<IProductRestApi>(Address.ProductController, setting);
|
||||||
}
|
}
|
|
@ -501,6 +501,10 @@ video {
|
||||||
--tw-backdrop-saturate: ;
|
--tw-backdrop-saturate: ;
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
.mx-3 {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
.mx-4 {
|
.mx-4 {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
@ -513,6 +517,10 @@ video {
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
.my-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
.my-auto {
|
.my-auto {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
|
@ -520,12 +528,24 @@ video {
|
||||||
.-ml-4 {
|
.-ml-4 {
|
||||||
margin-left: -1rem;
|
margin-left: -1rem;
|
||||||
}
|
}
|
||||||
|
.-ml-6 {
|
||||||
|
margin-left: -1.5rem;
|
||||||
|
}
|
||||||
|
.-mr-2 {
|
||||||
|
margin-right: -0.5rem;
|
||||||
|
}
|
||||||
.-mt-3 {
|
.-mt-3 {
|
||||||
margin-top: -0.75rem;
|
margin-top: -0.75rem;
|
||||||
}
|
}
|
||||||
.mb-10 {
|
.mb-10 {
|
||||||
margin-bottom: 2.5rem;
|
margin-bottom: 2.5rem;
|
||||||
}
|
}
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
.mb-5 {
|
.mb-5 {
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
}
|
}
|
||||||
|
@ -535,6 +555,12 @@ video {
|
||||||
.mr-2 {
|
.mr-2 {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
.mt-2\.5 {
|
||||||
|
margin-top: 0.625rem;
|
||||||
|
}
|
||||||
.mt-3 {
|
.mt-3 {
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -544,37 +570,115 @@ video {
|
||||||
.mt-5 {
|
.mt-5 {
|
||||||
margin-top: 1.25rem;
|
margin-top: 1.25rem;
|
||||||
}
|
}
|
||||||
|
.line-clamp-1 {
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.h-10 {
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
.h-12 {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
.h-64 {
|
||||||
|
height: 16rem;
|
||||||
|
}
|
||||||
|
.h-7 {
|
||||||
|
height: 1.75rem;
|
||||||
|
}
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.h-screen {
|
.h-screen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
.min-h-\[10rem\] {
|
||||||
|
min-height: 10rem;
|
||||||
|
}
|
||||||
|
.w-10 {
|
||||||
|
width: 2.5rem;
|
||||||
|
}
|
||||||
|
.w-12 {
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
.w-5 {
|
||||||
|
width: 1.25rem;
|
||||||
|
}
|
||||||
|
.w-64 {
|
||||||
|
width: 16rem;
|
||||||
|
}
|
||||||
|
.w-7 {
|
||||||
|
width: 1.75rem;
|
||||||
|
}
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.w-screen {
|
.w-screen {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
.basis-full {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
.flex-col-reverse {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.justify-end {
|
.justify-end {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.rounded-md {
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
}
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
.bg-\[\#000000\] {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.bg-\[\#EEEEEE\] {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(238 238 238 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
.bg-\[--color-background\] {
|
.bg-\[--color-background\] {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
.bg-transparent {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
.bg-white {
|
.bg-white {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
.bg-opacity-20 {
|
||||||
|
--tw-bg-opacity: 0.2;
|
||||||
|
}
|
||||||
|
.p-0 {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
.p-8 {
|
.p-8 {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
.px-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
.py-2 {
|
.py-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
@ -583,12 +687,43 @@ video {
|
||||||
padding-top: 0.75rem;
|
padding-top: 0.75rem;
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
.py-8 {
|
||||||
|
padding-top: 2rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
}
|
||||||
.pt-8 {
|
.pt-8 {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.text-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
.text-\[1\.8rem\] {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
.text-lg {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
.text-xl {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
.font-bold {
|
.font-bold {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
.font-extrabold {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
.text-blue-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.shadow-sm {
|
||||||
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: iranyekan;
|
font-family: iranyekan;
|
||||||
|
@ -774,3 +909,69 @@ a, .btn-link {
|
||||||
code {
|
code {
|
||||||
color: #c02d76;
|
color: #c02d76;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.focus\:border-teal-500:focus {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(20 184 166 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:ring-teal-500:focus {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(20 184 166 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
|
||||||
|
.sm\:mt-6 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:py-3 {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
|
||||||
|
.md\:basis-1\/2 {
|
||||||
|
flex-basis: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-bl-xl {
|
||||||
|
border-bottom-left-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-tl-xl {
|
||||||
|
border-top-left-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-tr-none {
|
||||||
|
border-top-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:px-10 {
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
|
||||||
|
.lg\:h-96 {
|
||||||
|
height: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:w-96 {
|
||||||
|
width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:px-20 {
|
||||||
|
padding-left: 5rem;
|
||||||
|
padding-right: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -554,6 +554,11 @@ video {
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx-3 {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mx-4 {
|
.mx-4 {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
@ -569,6 +574,11 @@ video {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.my-auto {
|
.my-auto {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
|
@ -578,6 +588,14 @@ video {
|
||||||
margin-left: -1rem;
|
margin-left: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-ml-6 {
|
||||||
|
margin-left: -1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-mr-2 {
|
||||||
|
margin-right: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.-mt-3 {
|
.-mt-3 {
|
||||||
margin-top: -0.75rem;
|
margin-top: -0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -586,6 +604,14 @@ video {
|
||||||
margin-bottom: 2.5rem;
|
margin-bottom: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mb-5 {
|
.mb-5 {
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
}
|
}
|
||||||
|
@ -598,6 +624,14 @@ video {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2\.5 {
|
||||||
|
margin-top: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-3 {
|
.mt-3 {
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -610,14 +644,69 @@ video {
|
||||||
margin-top: 1.25rem;
|
margin-top: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line-clamp-1 {
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-10 {
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-12 {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-64 {
|
||||||
|
height: 16rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-7 {
|
||||||
|
height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.h-screen {
|
.h-screen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.min-h-\[10rem\] {
|
||||||
|
min-height: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-10 {
|
||||||
|
width: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-12 {
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-5 {
|
||||||
|
width: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-64 {
|
||||||
|
width: 16rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-7 {
|
||||||
|
width: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -626,31 +715,78 @@ video {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.basis-full {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-col-reverse {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.justify-end {
|
.justify-end {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-md {
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-\[\#000000\] {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-\[\#EEEEEE\] {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(238 238 238 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-\[--color-background\] {
|
.bg-\[--color-background\] {
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-transparent {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.bg-white {
|
.bg-white {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-opacity-20 {
|
||||||
|
--tw-bg-opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-0 {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.p-8 {
|
.p-8 {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.px-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.py-2 {
|
.py-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
@ -661,14 +797,54 @@ video {
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.py-8 {
|
||||||
|
padding-top: 2rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pt-8 {
|
.pt-8 {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[1\.8rem\] {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-lg {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-xl {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.font-bold {
|
.font-bold {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-extrabold {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-blue-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-sm {
|
||||||
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: iranyekan;
|
font-family: iranyekan;
|
||||||
|
|
||||||
|
@ -884,3 +1060,66 @@ a, .btn-link {
|
||||||
code {
|
code {
|
||||||
color: #c02d76;
|
color: #c02d76;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.focus\:border-teal-500:focus {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(20 184 166 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:ring-teal-500:focus {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(20 184 166 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:mt-6 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:py-3 {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:basis-1\/2 {
|
||||||
|
flex-basis: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-bl-xl {
|
||||||
|
border-bottom-left-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-tl-xl {
|
||||||
|
border-top-left-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:rounded-tr-none {
|
||||||
|
border-top-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:px-10 {
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:h-96 {
|
||||||
|
height: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:w-96 {
|
||||||
|
width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:px-20 {
|
||||||
|
padding-left: 5rem;
|
||||||
|
padding-right: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -22,6 +22,19 @@
|
||||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Main Quill library -->
|
||||||
|
<script src="//cdn.quilljs.com/1.3.6/quill.js"></script>
|
||||||
|
<script src="//cdn.quilljs.com/1.3.6/quill.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Theme included stylesheets -->
|
||||||
|
<link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
||||||
|
<link href="//cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Core build with no theme, formatting, non-essential modules -->
|
||||||
|
<link href="//cdn.quilljs.com/1.3.6/quill.core.css" rel="stylesheet">
|
||||||
|
<script src="//cdn.quilljs.com/1.3.6/quill.core.js"></script>
|
||||||
|
|
||||||
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
Loading…
Reference in New Issue