diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
index 41924fd..236cfd6 100644
--- a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor
@@ -1,105 +1,270 @@
@using Radzen.Blazor
+@using NetinaShop.AdminPanel.PWA.Extensions
+
+@inject ISnackbar Snackbar
+@inject IRestWrapper RestWrapper
+@inject IUserUtility UserUtility
+@inject IDialogService DialogService
+
+
+
+
+
-
-
+
+
+
- اطلاعات کلی
- اطلاعات کلی محصول را به دقت وارد کنید
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ اطلاعات کلی
+ اطلاعات کلی محصول را به دقت وارد کنید
+
+
- توضیحات تکمیلی
- می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+ @e.Name
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ @e.Name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
+ ویژگی های کلی
+ می توانید ویگی های تکمیلی محصول را کامل وارد کنید
+
+
-
-
-
+
+
+
- تصاویر محصول
- می توانید برای محصول چند تصویر اپلود کنید
-
-
+
+
+
+
+
+ افزودن
+
+
+
+
+
+
+
+
+
+
+ حذف
+
+
+
+
+
+
+
+
+
+
+
+
+ توضیحات تکمیلی
+ می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ تصاویر محصول
+ می توانید برای محصول چند تصویر اپلود کنید
+
+
+
+
+ @foreach (var item in ViewModel.Files)
+ {
+
+
+
+
+
+ }
+
+
+
+
+
-
- تایید
- بستن
+
-
+ @if (ViewModel.IsEditing)
+ {
+
+ }
+ else
+ {
+
+ }
+
+ بستن
+
@code {
- [CascadingParameter] MudDialogInstance MudDialog { get; set; }
+ [CascadingParameter]
+ MudDialogInstance MudDialog { get; set; }
- void Submit() => MudDialog.Close(DialogResult.Ok(true));
- void Cancel() => MudDialog.Cancel();
-
- private bool _isEditing = false;
- private bool _isProcessing = false;
-
- private ProductSDto? _product = null;
[Parameter]
- public ProductSDto? Product
+ public ProductSDto? Product { get; set; }
+
+ public ProductActionDialogBoxViewModel ViewModel { get; set; }
+ protected override async Task OnInitializedAsync()
{
- get => _product;
- set
- {
- _product = value;
- if (_product != null)
- {
- _isEditing = true;
- }
- }
+ if (Product == null)
+ ViewModel = new ProductActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
+ else
+ ViewModel = new ProductActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Product);
+ await ViewModel.InitializeAsync();
+ await base.OnInitializedAsync();
}
+
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
new file mode 100644
index 0000000..52ea191
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/ProductActionDialogBox.razor.cs
@@ -0,0 +1,272 @@
+namespace NetinaShop.AdminPanel.PWA.Dialogs;
+
+public class ProductActionDialogBoxViewModel : BaseViewModel
+{
+ private readonly ISnackbar _snackbar;
+ private readonly IRestWrapper _restWrapper;
+ private readonly IUserUtility _userUtility;
+ private readonly IDialogService _dialogService;
+ private readonly MudDialogInstance _mudDialog;
+
+ public ProductActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _userUtility = userUtility;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ }
+ public ProductActionDialogBoxViewModel(ISnackbar snackbar,
+ IRestWrapper restWrapper,
+ IUserUtility userUtility,
+ IDialogService dialogService,
+ MudDialogInstance mudDialog,
+ ProductSDto product)
+ {
+ _snackbar = snackbar;
+ _restWrapper = restWrapper;
+ _userUtility = userUtility;
+ _dialogService = dialogService;
+ _mudDialog = mudDialog;
+ Product = product;
+ }
+
+ private ProductSDto? _product = null;
+ public ProductSDto? Product
+ {
+ get => _product;
+ set
+ {
+ _product = value;
+ if (_product != null)
+ {
+ IsEditing = true;
+ }
+ }
+ }
+
+ public void Cancel() => _mudDialog.Cancel();
+
+ public bool IsEditing = false;
+ public string ExpertCheck = string.Empty;
+ public string Summery = string.Empty;
+ public bool BeDisplayed = true;
+ public bool HasExpressDelivery = false;
+ public string PersianName = string.Empty;
+ public string EnglishName = string.Empty;
+ public double Cost;
+ public double PackingCost;
+ public int MaxOrder;
+ public string Warranty = string.Empty;
+ public string Tags = string.Empty;
+
+ public string SpecificationTitle = string.Empty;
+ public string SpecificationValue = string.Empty;
+ public readonly ObservableCollection Specifications = new ObservableCollection();
+ public readonly ObservableCollection Files = new ObservableCollection();
+
+
+
+ public async Task SubmitEditAsync()
+ {
+ try
+ {
+ IsProcessing = true;
+ if (Product == null || Product.Id == default)
+ throw new Exception("محصول اشتباه است");
+ var token = await _userUtility.GetBearerTokenAsync();
+ var request = new UpdateProductCommand(Product.Id, PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, _selectedBrand?.Id ?? default, _selectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
+ await _restWrapper.CrudApiRest(Address.ProductController).Update(request, token);
+ _snackbar.Add($"ویرایش محصول {PersianName} با موفقیت انجام شد", Severity.Success);
+ _mudDialog.Close();
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+
+ public void AddSpecification()
+ {
+ try
+ {
+ if (SpecificationTitle.IsNullOrEmpty())
+ throw new AppException("عنوان ویژگی مورد نظر را وارد کنید");
+ if (SpecificationValue.IsNullOrEmpty())
+ throw new AppException("مقدار ویژگی مورد نظر را وارد کنید");
+ Specifications.Add(new SpecificationSDto { Title = SpecificationTitle.ToString(), Value = SpecificationValue.ToString() });
+
+ SpecificationTitle = string.Empty;
+ SpecificationValue = string.Empty;
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ }
+ }
+
+ public void RemoveSpecification(SpecificationSDto specification)
+ {
+ var spec = Specifications.FirstOrDefault(s => s.Value == specification.Value && s.Title == specification.Title);
+ if (spec != null)
+ Specifications.Remove(spec);
+ }
+ public async Task SubmitCreateAsync()
+ {
+ try
+ {
+ IsProcessing = true;
+ var token = await _userUtility.GetBearerTokenAsync();
+ var request = new CreateProductCommand(PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, _selectedBrand?.Id ?? default, _selectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
+ await _restWrapper.CrudApiRest(Address.ProductController).Create(request, token);
+
+ _snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
+ _mudDialog.Close();
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ }
+ public override async Task InitializeAsync()
+ {
+ if (IsEditing && _product != null)
+ {
+ try
+ {
+ IsProcessing = true;
+ var productLDto = await _restWrapper.CrudDtoApiRest(Address.ProductController).ReadOne(_product.Id);
+ ExpertCheck = productLDto.ExpertCheck;
+ Summery = productLDto.Summery;
+ BeDisplayed = productLDto.BeDisplayed;
+ HasExpressDelivery = productLDto.HasExpressDelivery;
+ PersianName = productLDto.PersianName;
+ EnglishName = productLDto.EnglishName;
+ Cost = productLDto.Cost;
+ PackingCost = productLDto.PackingCost;
+ MaxOrder = productLDto.MaxOrderCount;
+ Warranty = productLDto.Warranty;
+ productLDto.Specifications.ForEach(s => Specifications.Add(s));
+ productLDto.Files.ForEach(f => Files.Add(f));
+ _selectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
+ _selectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ _mudDialog.Cancel();
+ }
+ finally
+ {
+
+ IsProcessing = false;
+ }
+ };
+ }
+
+
+ public List _productCategories = new List();
+ public ProductCategorySDto? _selectedCategory;
+ public async Task> SearchProductCategory(string category)
+ {
+ try
+ {
+ if (category.IsNullOrEmpty())
+ _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
+ else
+ _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
+ return _productCategories;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ return _productCategories;
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ return _productCategories;
+ }
+ }
+
+ public List _brands = new List();
+ public BrandSDto? _selectedBrand;
+ public async Task> SearchBrand(string brand)
+ {
+ try
+ {
+ if (brand.IsNullOrEmpty())
+ _brands = await _restWrapper.BrandRestApi.ReadAll(0);
+ else
+ _brands = await _restWrapper.BrandRestApi.ReadAll(brand);
+ return _brands;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ _snackbar.Add(exe.Message, Severity.Error);
+ _snackbar.Add(ex.Content, Severity.Error);
+ return _brands;
+ }
+ catch (Exception e)
+ {
+ _snackbar.Add(e.Message, Severity.Error);
+ return _brands;
+ }
+ }
+
+ public async Task SelectFileAsync()
+ {
+ DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
+ var dialog = await _dialogService.ShowAsync("انتخاب عکس", maxWidth);
+ var result = await dialog.Result;
+ var file = result.Data;
+ if (file is StorageFileSDto storageFile)
+ Files.Add(storageFile);
+ }
+
+ public void RemoveFile(StorageFileSDto file)
+ {
+ Files.Remove(file);
+ }
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor b/NetinaShop.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor
index 7477667..0325e03 100644
--- a/NetinaShop.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/ProductCategoryActionDialogBox.razor
@@ -23,7 +23,7 @@
-
+
diff --git a/NetinaShop.AdminPanel.PWA/Dialogs/StorageDialogBox.razor b/NetinaShop.AdminPanel.PWA/Dialogs/StorageDialogBox.razor
new file mode 100644
index 0000000..9ea5362
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Dialogs/StorageDialogBox.razor
@@ -0,0 +1,192 @@
+@using NetinaShop.AdminPanel.PWA.Extensions
+
+@inject IRestWrapper RestWrapper
+@inject IUserUtility UserUtility
+@inject ISnackbar Snackbar
+
+
+
+
+
+ انتخاب یا اپلود عکس جدید
+ میتوانید از بین عکس های اپلود شده یکی را انتخاب کرده یا عکس جدیدی اپلود کنید
+
+
+
+
+
+
+ اپلود فایل جدید
+
+
+
+
+
+
+
+
+ @foreach (var item in _files)
+ {
+ @if (item.Selected)
+ {
+ UnSelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2 border-solid border-4 border-blue-500" Src="@item.GetLink()" Elevation="25" />
+ }
+ else
+ {
+ SelectFile(item)" class="cursor-pointer rounded-lg mx-1 w-52 h-52 mt-2" Src="@item.GetLink()" Elevation="25" />
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ بستن
+
+
+
+@code
+{
+
+
+ private void SelectFile(StorageFileSDto item)
+ {
+ var pastSelect = _files.FirstOrDefault(f => f.Selected);
+ if (pastSelect != null)
+ pastSelect.Selected = false;
+ item.Selected = true;
+ }
+
+ private void UnSelectFile(StorageFileSDto item) => item.Selected = false;
+
+ public void SearchChanged(string search)
+ {
+ if (search.IsNullOrEmpty() && !_search.IsNullOrEmpty())
+ {
+ _files.Clear();
+ _originalFiles.ForEach(f=>_files.Add(f));
+ }
+ _search = search;
+ }
+ public void SearchAsync()
+ {
+ try
+ {
+ if (_search.IsNullOrEmpty())
+ throw new AppException("دسته بندی برای جست جو وارد نشده است");
+ _files.Clear();
+ foreach (var storageFileSDto in _originalFiles.Where(f => f.FileName.ToLower().Trim().Contains(_search.ToLower().Trim())))
+ _files.Add(storageFileSDto);
+ }
+ catch (Exception e)
+ {
+ Snackbar.Add(e.Message, Severity.Error);
+ }
+ }
+
+ public void SelectFile()
+ {
+ var selected = _files.FirstOrDefault(f => f.Selected);
+ if (selected == null)
+ throw new Exception("یک فایل را انتخاب کنید");
+ MudDialog.Close(selected);
+ }
+ [CascadingParameter]
+ MudDialogInstance MudDialog { get; set; }
+ void Cancel() => MudDialog.Cancel();
+ private readonly ObservableCollection _files = new ObservableCollection();
+ private List _originalFiles = new List();
+ private bool _isProcessing = false;
+ private string _search = string.Empty;
+ protected override async Task OnInitializedAsync()
+ {
+ try
+ {
+ _isProcessing = true;
+ _files.Clear();
+ var token = await UserUtility.GetBearerTokenAsync();
+ var files = await RestWrapper.FileRestApi.GetFilesAsync(token);
+ files.ForEach(f => _files.Add(f));
+ _originalFiles = files;
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ if (exe != null)
+ Snackbar.Add(exe.Message, Severity.Error);
+ Snackbar.Add(ex.Content, Severity.Error);
+ }
+ catch (Exception e)
+ {
+ Snackbar.Add(e.Message, Severity.Error);
+ }
+ finally
+ {
+ _isProcessing = false;
+ }
+
+ await base.OnInitializedAsync();
+ }
+
+ private async Task FileChangeForUpload(InputFileChangeEventArgs obj)
+ {
+ try
+ {
+ _isProcessing = true;
+ using var memoryStream = new MemoryStream();
+ var file = obj.File;
+ var stream = file.OpenReadStream();
+ await stream.CopyToAsync(memoryStream);
+
+ var fileUpload = new FileUploadRequest
+ {
+ ContentType = file.ContentType,
+ FileName = file.Name,
+ FileUploadType = FileUploadType.Image,
+ StringBaseFile = Convert.ToBase64String(memoryStream.ToArray())
+ };
+ var token = await UserUtility.GetBearerTokenAsync();
+ var rest = await RestWrapper.FileRestApi.UploadFileAsync(fileUpload, token);
+ _files.Insert(0, new StorageFileSDto
+ {
+ FileLocation = rest.FileLocation,
+ FileName = rest.FileName,
+ FileType = StorageFileType.Image
+ });
+ }
+ catch (ApiException ex)
+ {
+ var exe = await ex.GetContentAsAsync();
+ 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;
+ }
+ }
+}
diff --git a/NetinaShop.AdminPanel.PWA/Extensions/StorageFileExtension.cs b/NetinaShop.AdminPanel.PWA/Extensions/StorageFileExtension.cs
new file mode 100644
index 0000000..9f55872
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Extensions/StorageFileExtension.cs
@@ -0,0 +1,12 @@
+using NetinaShop.Common.Extensions;
+
+namespace NetinaShop.AdminPanel.PWA.Extensions;
+
+public static class StorageFileExtension
+{
+ public static string GetLink(this StorageFileSDto file)
+ {
+ var link = $"https://storage.vesmook.com/{file.FileLocation}";
+ return link;
+ }
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Models/Address.cs b/NetinaShop.AdminPanel.PWA/Models/Address.cs
index a2bdea2..5034ac0 100644
--- a/NetinaShop.AdminPanel.PWA/Models/Address.cs
+++ b/NetinaShop.AdminPanel.PWA/Models/Address.cs
@@ -13,4 +13,5 @@ public static class Address
public static string ProductCategoryController = $"{BaseAddress}/product/category";
public static string ProductController = $"{BaseAddress}/product";
public static string BrandController = $"{BaseAddress}/brand";
+ public static string FileController => $"{BaseAddress}/file";
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/NetinaShop.AdminPanel.PWA.csproj b/NetinaShop.AdminPanel.PWA/NetinaShop.AdminPanel.PWA.csproj
index db17d6e..6beefb3 100644
--- a/NetinaShop.AdminPanel.PWA/NetinaShop.AdminPanel.PWA.csproj
+++ b/NetinaShop.AdminPanel.PWA/NetinaShop.AdminPanel.PWA.csproj
@@ -53,6 +53,8 @@
+
+
diff --git a/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor b/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
index 83e94e7..2796cd4 100644
--- a/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
+++ b/NetinaShop.AdminPanel.PWA/Pages/ProductsPage.razor
@@ -46,12 +46,13 @@
+ Color="@Color.Info"
+ OnClick="async()=>await ViewModel.EditProductClicked(context.Item)"/>
+ Color="@Color.Error"/>
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IBrandRestApi.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IBrandRestApi.cs
new file mode 100644
index 0000000..c9096d6
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IBrandRestApi.cs
@@ -0,0 +1,14 @@
+namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
+
+public interface IBrandRestApi
+{
+
+ [Get("")]
+ Task> ReadAll();
+ [Get("")]
+ Task> ReadAll([Query] int page);
+ [Get("")]
+ Task> ReadAll([Query] int page, [Query] string brandName);
+ [Get("")]
+ Task> ReadAll([Query] string brandName);
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs
index 441bb9e..118bfb6 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs
@@ -34,7 +34,7 @@ public interface ICrudDtoApiRest where T : class where TDto :
Task> ReadAll();
[Get("/{key}")]
- Task ReadOne(TKey key, [Header("Authorization")] string authorization);
+ Task ReadOne(TKey key);
[Put("")]
Task Update([Body] T payload, [Header("Authorization")] string authorization);
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IFileRestApi.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IFileRestApi.cs
new file mode 100644
index 0000000..baeba34
--- /dev/null
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IFileRestApi.cs
@@ -0,0 +1,9 @@
+namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
+
+public interface IFileRestApi
+{
+ [Get("")]
+ Task> GetFilesAsync([Header("Authorization")] string authorization);
+ [Post("")]
+ Task UploadFileAsync([Body] FileUploadRequest request, [Header("Authorization")] string authorization);
+}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
index e6bcedd..2cb0bbd 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/IRestWrapper.cs
@@ -10,4 +10,6 @@ public interface IRestWrapper
public IUserRestApi UserRestApi { get; }
public IProductCategoryRestApi ProductCategoryRestApi { get; }
public IProductRestApi ProductRestApi { get; }
+ public IBrandRestApi BrandRestApi { get; }
+ public IFileRestApi FileRestApi { get; }
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs b/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
index 6edcf56..6c8ac7c 100644
--- a/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
+++ b/NetinaShop.AdminPanel.PWA/Services/RestServices/RestWrapper.cs
@@ -22,4 +22,6 @@ public class RestWrapper : IRestWrapper
public IUserRestApi UserRestApi => RestService.For(Address.UserController, setting);
public IProductCategoryRestApi ProductCategoryRestApi => RestService.For(Address.ProductCategoryController, setting);
public IProductRestApi ProductRestApi => RestService.For(Address.ProductController, setting);
+ public IBrandRestApi BrandRestApi => RestService.For(Address.BrandController, setting);
+ public IFileRestApi FileRestApi => RestService.For(Address.FileController, setting);
}
\ No newline at end of file
diff --git a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
index 0590746..c8c40aa 100644
--- a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
+++ b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.min.css
@@ -501,6 +501,19 @@ video {
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
+.absolute {
+ position: absolute;
+}
+.m-1 {
+ margin: 0.25rem;
+}
+.m-1\.5 {
+ margin: 0.375rem;
+}
+.mx-1 {
+ margin-left: 0.25rem;
+ margin-right: 0.25rem;
+}
.mx-3 {
margin-left: 0.75rem;
margin-right: 0.75rem;
@@ -537,9 +550,6 @@ video {
.-mt-3 {
margin-top: -0.75rem;
}
-.mb-10 {
- margin-bottom: 2.5rem;
-}
.mb-2 {
margin-bottom: 0.5rem;
}
@@ -585,9 +595,15 @@ video {
.h-12 {
height: 3rem;
}
+.h-28 {
+ height: 7rem;
+}
.h-5 {
height: 1.25rem;
}
+.h-52 {
+ height: 13rem;
+}
.h-64 {
height: 16rem;
}
@@ -600,6 +616,9 @@ video {
.h-screen {
height: 100vh;
}
+.max-h-\[30rem\] {
+ max-height: 30rem;
+}
.min-h-\[10rem\] {
min-height: 10rem;
}
@@ -609,9 +628,15 @@ video {
.w-12 {
width: 3rem;
}
+.w-28 {
+ width: 7rem;
+}
.w-5 {
width: 1.25rem;
}
+.w-52 {
+ width: 13rem;
+}
.w-64 {
width: 16rem;
}
@@ -624,30 +649,58 @@ video {
.w-screen {
width: 100vw;
}
+.flex-none {
+ flex: none;
+}
+.grow {
+ flex-grow: 1;
+}
.basis-full {
flex-basis: 100%;
}
+.cursor-pointer {
+ cursor: pointer;
+}
.flex-row {
flex-direction: row;
}
.flex-col-reverse {
flex-direction: column-reverse;
}
+.flex-wrap {
+ flex-wrap: wrap;
+}
.items-center {
align-items: center;
}
.justify-end {
justify-content: flex-end;
}
+.justify-center {
+ justify-content: center;
+}
.overflow-hidden {
overflow: hidden;
}
+.rounded-lg {
+ border-radius: 0.5rem;
+}
.rounded-md {
border-radius: 0.375rem;
}
.border {
border-width: 1px;
}
+.border-4 {
+ border-width: 4px;
+}
+.border-solid {
+ border-style: solid;
+}
+.border-blue-500 {
+ --tw-border-opacity: 1;
+ border-color: rgb(59 130 246 / var(--tw-border-opacity));
+}
.bg-\[\#000000\] {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
diff --git a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
index 03cb8ef..8ba49f1 100644
--- a/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
+++ b/NetinaShop.AdminPanel.PWA/wwwroot/css/app.output.css
@@ -554,6 +554,23 @@ video {
--tw-backdrop-sepia: ;
}
+.absolute {
+ position: absolute;
+}
+
+.m-1 {
+ margin: 0.25rem;
+}
+
+.m-1\.5 {
+ margin: 0.375rem;
+}
+
+.mx-1 {
+ margin-left: 0.25rem;
+ margin-right: 0.25rem;
+}
+
.mx-3 {
margin-left: 0.75rem;
margin-right: 0.75rem;
@@ -600,10 +617,6 @@ video {
margin-top: -0.75rem;
}
-.mb-10 {
- margin-bottom: 2.5rem;
-}
-
.mb-2 {
margin-bottom: 0.5rem;
}
@@ -663,10 +676,18 @@ video {
height: 3rem;
}
+.h-28 {
+ height: 7rem;
+}
+
.h-5 {
height: 1.25rem;
}
+.h-52 {
+ height: 13rem;
+}
+
.h-64 {
height: 16rem;
}
@@ -683,6 +704,10 @@ video {
height: 100vh;
}
+.max-h-\[30rem\] {
+ max-height: 30rem;
+}
+
.min-h-\[10rem\] {
min-height: 10rem;
}
@@ -695,10 +720,18 @@ video {
width: 3rem;
}
+.w-28 {
+ width: 7rem;
+}
+
.w-5 {
width: 1.25rem;
}
+.w-52 {
+ width: 13rem;
+}
+
.w-64 {
width: 16rem;
}
@@ -715,10 +748,22 @@ video {
width: 100vw;
}
+.flex-none {
+ flex: none;
+}
+
+.grow {
+ flex-grow: 1;
+}
+
.basis-full {
flex-basis: 100%;
}
+.cursor-pointer {
+ cursor: pointer;
+}
+
.flex-row {
flex-direction: row;
}
@@ -727,6 +772,10 @@ video {
flex-direction: column-reverse;
}
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
.items-center {
align-items: center;
}
@@ -735,10 +784,18 @@ video {
justify-content: flex-end;
}
+.justify-center {
+ justify-content: center;
+}
+
.overflow-hidden {
overflow: hidden;
}
+.rounded-lg {
+ border-radius: 0.5rem;
+}
+
.rounded-md {
border-radius: 0.375rem;
}
@@ -747,6 +804,19 @@ video {
border-width: 1px;
}
+.border-4 {
+ border-width: 4px;
+}
+
+.border-solid {
+ border-style: solid;
+}
+
+.border-blue-500 {
+ --tw-border-opacity: 1;
+ border-color: rgb(59 130 246 / var(--tw-border-opacity));
+}
+
.bg-\[\#000000\] {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));