diff --git a/Netina.AdminPanel.PWA/Layout/MainLayout.razor b/Netina.AdminPanel.PWA/Layout/MainLayout.razor index 8a2d743..b9d25d8 100644 --- a/Netina.AdminPanel.PWA/Layout/MainLayout.razor +++ b/Netina.AdminPanel.PWA/Layout/MainLayout.razor @@ -63,12 +63,12 @@ - + - +
@Body diff --git a/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor b/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor index cf62358..b8e07f4 100644 --- a/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor +++ b/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor @@ -5,43 +5,142 @@ @inject ISnackbar Snackbar @inject IUserUtility UserUtility +@* *@ + - - - + + - دسته بندی ها - @* 124 عدد *@ - - - - افزودن دسته بندی + دسته های اصلی + + - + @if (ViewModel.OriginalCategoryVisibility) + { + + } + @foreach (var item in ViewModel.PageDto) + { + + + + @item.Name + + + + + + + + + + + } + + + + @foreach (var item in ViewModel.SelectedCategories) + { + + + @item.Name + + + + + @if (item.AddNewCatVisibility) + { + + } + @foreach (var child in item.Children) + { + + + + @child.Name + + + + + + + + + + + } + + } + + + + + +@code +{ + public CategoriesPageViewModel ViewModel { get; set; } + protected override async Task OnInitializedAsync() + { + ViewModel = new CategoriesPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService); + await ViewModel.InitializeAsync(); + await base.OnInitializedAsync(); + } + +} + + + @* - + - @* +

@context.Item.Description

-
*@ +
@if (@context.Item.IsMain) @@ -74,7 +173,7 @@
- + @@ -91,24 +190,9 @@ + SelectedChanged="@ViewModel.ChangePageAsync" class="mx-auto my-4"/>
-
- - - - -@code -{ - public CategoriesPageViewModel ViewModel { get; set; } - protected override async Task OnInitializedAsync() - { - ViewModel = new CategoriesPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService); - await ViewModel.InitializeAsync(); - await base.OnInitializedAsync(); - } - -} + *@ \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor.cs b/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor.cs index 3ebeeb6..9f12444 100644 --- a/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor.cs +++ b/Netina.AdminPanel.PWA/Pages/CategoriesPage.razor.cs @@ -9,9 +9,7 @@ public class CategoriesPageViewModel : BaseViewModel(Address.ProductCategoryController) - .ReadAll(CurrentPage); - dto.ForEach(d=>PageDto.Add(d)); - if (PageDto.Count == 15) - PageCount = 2; + var dto = await _restWrapper.ProductCategoryRestApi.ReadAll(true); + dto.ForEach(d => PageDto.Add(d)); + } catch (ApiException ex) { @@ -51,38 +46,6 @@ public class CategoriesPageViewModel : BaseViewModel PageCount-2) - { - - try - { - IsProcessing = true; - var dto = await _restWrapper.CrudDtoApiRest(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(); - _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() { @@ -99,7 +62,7 @@ public class CategoriesPageViewModel : BaseViewModel(); - parameters.Add(x=>x.Category,category); + parameters.Add(x => x.Category, category); var dialogResult = await _dialogService.ShowAsync($"ویرایش دسته {category.Name}", parameters, maxWidth); var result = await dialogResult.Result; if (!result.Canceled && result.Data is bool and true) @@ -150,13 +113,9 @@ public class CategoriesPageViewModel : BaseViewModel PageDto.Add(d)); - if (PageDto.Count == 15) - PageCount = 2; } catch (ApiException ex) { @@ -173,4 +132,90 @@ public class CategoriesPageViewModel : BaseViewModel SelectedCategories = new(); + public void SelectCategory(ProductCategorySDto category) + { + var selected = SelectedCategories.FirstOrDefault(c => c.Id == category.Id); + if (selected != null) + { + UnSelectCategory(selected); + return; + } + var parent = FindParent(category.ParentId, PageDto.ToList()); + if (parent != null) + category.Index = parent.Index + 1; + category.IsSelected = true; + + var currentSelectedIndex = SelectedCategories.FirstOrDefault(c => c.Index == category.Index); + if (currentSelectedIndex != null) + UnSelectCategory(currentSelectedIndex); + + SelectedCategories.Add(category); + } + + public bool OriginalCategoryVisibility = false; + public bool ChangeOriginalCategoryVisibility() => OriginalCategoryVisibility = !OriginalCategoryVisibility; + public void AddFastProductCategory(string categoryName, Guid? parentId = null) + { + if(categoryName.IsNullOrEmpty()) + return; + ProductCategorySDto category = new ProductCategorySDto { Name = categoryName, IsMain = true}; + if (parentId != null) + { + category.IsMain = false; + category.ParentId = parentId.Value; + } + var command = category.Adapt() with{Files = new()}; + + Task.Run(async () => + { + var token = await _userUtility.GetBearerTokenAsync(); + if (token == null) + return; + var response = await _restWrapper.CrudApiRest(Address.ProductCategoryController) + .Create(command, token); + category.Id = response; + }); + if (parentId == null) + { + category.IsMain = true; + PageDto.Add(category); + } + else + { + var parent = FindParent(parentId.Value, PageDto.ToList()); + if (parent != null) + { + category.Index = parent.Index + 1; + parent.Children.Add(category); + } + } + + categoryName = string.Empty; + } + + + private void UnSelectCategory(ProductCategorySDto category) + { + category.IsSelected = false; + foreach (var selected in SelectedCategories.Where(c => c.ParentId == category.Id).ToList()) + UnSelectCategory(selected); + + SelectedCategories.Remove(category); + } + private ProductCategorySDto? FindParent(Guid parentId, List categories) + { + var parent = categories.FirstOrDefault(c => c.Id == parentId); + if (parent != null) + return parent; + foreach (var category in categories) + { + var founded = FindParent(parentId, category.Children); + if (founded != null) + return founded; + } + + return null; + } } \ No newline at end of file diff --git a/Netina.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs b/Netina.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs index f3e768a..bc944c8 100644 --- a/Netina.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs +++ b/Netina.AdminPanel.PWA/Services/RestServices/ICrudApiRest.cs @@ -1,9 +1,9 @@ namespace Netina.AdminPanel.PWA.Services.RestServices; -public interface ICrudApiRest where T : class +public interface ICrudApiRest where T : class { [Post("")] - Task Create([Body] TCreateCommand payload, [Header("Authorization")] string authorization); + Task Create([Body] TCreateCommand payload, [Header("Authorization")] string authorization); [Get("")] Task> ReadAll([Query] int page,[Header("Authorization")] string authorization); diff --git a/Netina.AdminPanel.PWA/Services/RestServices/IProductCategoryRestApi.cs b/Netina.AdminPanel.PWA/Services/RestServices/IProductCategoryRestApi.cs index c4a639b..6aafad4 100644 --- a/Netina.AdminPanel.PWA/Services/RestServices/IProductCategoryRestApi.cs +++ b/Netina.AdminPanel.PWA/Services/RestServices/IProductCategoryRestApi.cs @@ -8,6 +8,8 @@ public interface IProductCategoryRestApi [Get("")] Task> ReadAll([Query] int page); [Get("")] + Task> ReadAll([Query] bool sortByMain); + [Get("")] Task> ReadAll([Query] int page,[Query]string categoryName); [Get("")] Task> ReadAll([Query] string categoryName); diff --git a/Netina.AdminPanel.PWA/tailwind.config.js b/Netina.AdminPanel.PWA/tailwind.config.js index 958e212..b1ecdef 100644 --- a/Netina.AdminPanel.PWA/tailwind.config.js +++ b/Netina.AdminPanel.PWA/tailwind.config.js @@ -8,6 +8,14 @@ module.exports = { "./node_modules/flowbite/**/*.js" ], theme: { + screens: { + 'xs': '380px', + 'sm': '600px', + 'md': '960px', + 'lg': '1280px', + 'xl': '1920px', + '2xl': '2560px', + }, fontSize: { xs: '.75rem', sm: '.875rem', diff --git a/Netina.AdminPanel.PWA/wwwroot/css/app.min.css b/Netina.AdminPanel.PWA/wwwroot/css/app.min.css index 2777857..114675a 100644 --- a/Netina.AdminPanel.PWA/wwwroot/css/app.min.css +++ b/Netina.AdminPanel.PWA/wwwroot/css/app.min.css @@ -977,22 +977,22 @@ input:checked + .toggle-bg { .container { width: 100%; } -@media (min-width: 640px) { +@media (min-width: 380px) { .container { - max-width: 640px; + max-width: 380px; } } -@media (min-width: 768px) { +@media (min-width: 600px) { .container { - max-width: 768px; + max-width: 600px; } } -@media (min-width: 1024px) { +@media (min-width: 960px) { .container { - max-width: 1024px; + max-width: 960px; } } @media (min-width: 1280px) { @@ -1001,10 +1001,16 @@ input:checked + .toggle-bg { max-width: 1280px; } } -@media (min-width: 1536px) { +@media (min-width: 1920px) { .container { - max-width: 1536px; + max-width: 1920px; + } +} +@media (min-width: 2560px) { + + .container { + max-width: 2560px; } } .visible { @@ -1150,6 +1156,9 @@ input:checked + .toggle-bg { .-mt-1 { margin-top: -0.25rem; } +.-mt-2 { + margin-top: -0.5rem; +} .-mt-3 { margin-top: -0.75rem; } @@ -1353,6 +1362,9 @@ input:checked + .toggle-bg { .w-screen { width: 100vw; } +.min-w-\[340px\] { + min-width: 340px; +} .flex-1 { flex: 1 1 0%; } @@ -1466,6 +1478,9 @@ input:checked + .toggle-bg { .overflow-hidden { overflow: hidden; } +.overflow-x-auto { + overflow-x: auto; +} .overflow-x-hidden { overflow-x: hidden; } @@ -1565,6 +1580,10 @@ input:checked + .toggle-bg { --tw-border-opacity: 1; border-color: rgb(167 139 250 / var(--tw-border-opacity)); } +.border-yellow-400 { + --tw-border-opacity: 1; + border-color: rgb(227 160 8 / var(--tw-border-opacity)); +} .bg-\[\#000000\] { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); @@ -1704,6 +1723,9 @@ input:checked + .toggle-bg { padding-top: 2rem; padding-bottom: 2rem; } +.pb-3 { + padding-bottom: 0.75rem; +} .pt-2 { padding-top: 0.5rem; } @@ -2218,7 +2240,7 @@ code { color: rgb(255 255 255 / var(--tw-text-opacity)); } -@media (min-width: 640px) { +@media (min-width: 600px) { .sm\:mr-3 { margin-right: 0.75rem; @@ -2238,7 +2260,7 @@ code { } } -@media (min-width: 768px) { +@media (min-width: 960px) { .md\:visible { visibility: visible; @@ -2277,13 +2299,17 @@ code { padding: 1.25rem; } + .md\:p-8 { + padding: 2rem; + } + .md\:px-10 { padding-left: 2.5rem; padding-right: 2.5rem; } } -@media (min-width: 1024px) { +@media (min-width: 1280px) { .lg\:h-60 { height: 15rem; diff --git a/Netina.AdminPanel.PWA/wwwroot/css/app.output.css b/Netina.AdminPanel.PWA/wwwroot/css/app.output.css index b51dbc1..0b02fbf 100644 --- a/Netina.AdminPanel.PWA/wwwroot/css/app.output.css +++ b/Netina.AdminPanel.PWA/wwwroot/css/app.output.css @@ -1031,21 +1031,21 @@ input:checked + .toggle-bg { width: 100%; } -@media (min-width: 640px) { +@media (min-width: 380px) { .container { - max-width: 640px; + max-width: 380px; } } -@media (min-width: 768px) { +@media (min-width: 600px) { .container { - max-width: 768px; + max-width: 600px; } } -@media (min-width: 1024px) { +@media (min-width: 960px) { .container { - max-width: 1024px; + max-width: 960px; } } @@ -1055,9 +1055,15 @@ input:checked + .toggle-bg { } } -@media (min-width: 1536px) { +@media (min-width: 1920px) { .container { - max-width: 1536px; + max-width: 1920px; + } +} + +@media (min-width: 2560px) { + .container { + max-width: 2560px; } } @@ -1247,6 +1253,10 @@ input:checked + .toggle-bg { margin-top: -0.25rem; } +.-mt-2 { + margin-top: -0.5rem; +} + .-mt-3 { margin-top: -0.75rem; } @@ -1451,6 +1461,14 @@ input:checked + .toggle-bg { min-height: 33rem; } +.min-h-full { + min-height: 100%; +} + +.\!min-h-full { + min-height: 100% !important; +} + .w-1\/2 { width: 50%; } @@ -1516,6 +1534,10 @@ input:checked + .toggle-bg { width: 100vw; } +.min-w-\[340px\] { + min-width: 340px; +} + .flex-1 { flex: 1 1 0%; } @@ -1662,6 +1684,10 @@ input:checked + .toggle-bg { overflow: hidden; } +.overflow-x-auto { + overflow-x: auto; +} + .overflow-x-hidden { overflow-x: hidden; } @@ -1790,6 +1816,11 @@ input:checked + .toggle-bg { border-color: rgb(167 139 250 / var(--tw-border-opacity)); } +.border-yellow-400 { + --tw-border-opacity: 1; + border-color: rgb(227 160 8 / var(--tw-border-opacity)); +} + .bg-\[\#000000\] { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); @@ -1979,6 +2010,10 @@ input:checked + .toggle-bg { padding-top: 2rem; } +.pb-3 { + padding-bottom: 0.75rem; +} + .text-center { text-align: center; } @@ -2557,7 +2592,7 @@ code { color: rgb(255 255 255 / var(--tw-text-opacity)); } -@media (min-width: 640px) { +@media (min-width: 600px) { .sm\:mr-3 { margin-right: 0.75rem; } @@ -2576,7 +2611,7 @@ code { } } -@media (min-width: 768px) { +@media (min-width: 960px) { .md\:visible { visibility: visible; } @@ -2614,13 +2649,17 @@ code { padding: 1.25rem; } + .md\:p-8 { + padding: 2rem; + } + .md\:px-10 { padding-left: 2.5rem; padding-right: 2.5rem; } } -@media (min-width: 1024px) { +@media (min-width: 1280px) { .lg\:h-60 { height: 15rem; }