diff --git a/src/BackOffice/App.razor b/src/BackOffice/App.razor index c93d097..598cb71 100644 --- a/src/BackOffice/App.razor +++ b/src/BackOffice/App.razor @@ -17,7 +17,7 @@ } }); } - + @@ -27,4 +27,10 @@ - \ No newline at end of file + + +@code{ + + + +} \ No newline at end of file diff --git a/src/BackOffice/BackOffice.csproj b/src/BackOffice/BackOffice.csproj index 6e27229..d2c7337 100644 --- a/src/BackOffice/BackOffice.csproj +++ b/src/BackOffice/BackOffice.csproj @@ -21,10 +21,15 @@ + + + + + diff --git a/src/BackOffice/Common/BaseComponents/BasePageComponent.razor b/src/BackOffice/Common/BaseComponents/BasePageComponent.razor index 715341f..6519ddd 100644 --- a/src/BackOffice/Common/BaseComponents/BasePageComponent.razor +++ b/src/BackOffice/Common/BaseComponents/BasePageComponent.razor @@ -6,9 +6,9 @@ فیلتر ها - @if (IsFilterd) + @if (IsFiltered) { - خذف فیلتر + حذف فیلتر } @@ -32,4 +32,3 @@ - diff --git a/src/BackOffice/Common/BaseComponents/BasePageComponent.razor.cs b/src/BackOffice/Common/BaseComponents/BasePageComponent.razor.cs index d7086be..7d930e0 100644 --- a/src/BackOffice/Common/BaseComponents/BasePageComponent.razor.cs +++ b/src/BackOffice/Common/BaseComponents/BasePageComponent.razor.cs @@ -3,15 +3,9 @@ using Microsoft.AspNetCore.Components; namespace BackOffice.Common.BaseComponents; public partial class BasePageComponent { - [Parameter] public RenderFragment Filters { get; set; } - [Parameter] public RenderFragment Content { get; set; } - [Parameter] public bool IsFilterd { get; set; } + [Parameter] public RenderFragment Filters { get; set; } = default!; + [Parameter] public RenderFragment Content { get; set; } = default!; + [Parameter] public bool IsFiltered { get; set; } [Parameter] public EventCallback OnSubmitClick { get; set; } [Parameter] public EventCallback OnClearFilterClick { get; set; } - private bool _open = true; - - private void ToggleDrawer() - { - _open = !_open; - } -} \ No newline at end of file +} diff --git a/src/BackOffice/Common/BaseComponents/DateRangePicker.razor.cs b/src/BackOffice/Common/BaseComponents/DateRangePicker.razor.cs index 754b321..39cd928 100644 --- a/src/BackOffice/Common/BaseComponents/DateRangePicker.razor.cs +++ b/src/BackOffice/Common/BaseComponents/DateRangePicker.razor.cs @@ -55,12 +55,17 @@ public partial class DateRangePicker } private async Task OnClickOK() { - _picker.CloseAsync(); - await OnChanged.InvokeAsync(_picker.DateRange); + if (_picker.DateRange is not null) + { + await OnChanged.InvokeAsync(_picker.DateRange); + } + + await _picker.CloseAsync(); } private async Task OnClickClear() { - _picker.CloseAsync(); - await OnChanged.InvokeAsync(_picker.DateRange); + _dateRange = new DateRange(); + await OnChanged.InvokeAsync(_dateRange); + await _picker.CloseAsync(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Common/Configure/ConfigureService.cs b/src/BackOffice/Common/Configure/ConfigureService.cs index de8bd70..7a2f140 100644 --- a/src/BackOffice/Common/Configure/ConfigureService.cs +++ b/src/BackOffice/Common/Configure/ConfigureService.cs @@ -2,23 +2,22 @@ using BackOffice.BFF.Otp.Protobuf.Protos.Otp; using BackOffice.BFF.Package.Protobuf.Protos.Package; using BackOffice.BFF.Role.Protobuf.Protos.Role; +using BackOffice.BFF.Products.Protobuf.Protos.Products; using BackOffice.BFF.User.Protobuf.Protos.User; using BackOffice.BFF.UserAddress.Protobuf.Protos.UserAddress; using BackOffice.BFF.UserOrder.Protobuf.Protos.UserOrder; using BackOffice.BFF.UserRole.Protobuf.Protos.UserRole; +using BackOffice.BFF.Category.Protobuf.Protos.Category; using BackOffice.Common.Utilities; using Blazored.LocalStorage; -using Google.Protobuf.Reflection; using Grpc.Core; using Grpc.Core.Interceptors; using Grpc.Net.Client; using Grpc.Net.Client.Web; using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using MudBlazor.Services; using System.Text.Json; using System.Text.Json.Serialization; -using static MudBlazor.Colors; namespace Microsoft.Extensions.DependencyInjection; @@ -48,25 +47,35 @@ public static class ConfigureServices - public static IServiceCollection AddGrpcServices(this IServiceCollection services, IConfiguration configuration) // + public static IServiceCollection AddGrpcServices(this IServiceCollection services, IConfiguration configuration) { - var baseUri = configuration["GwUrl"]; - Console.WriteLine(); - Console.WriteLine(baseUri); - var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler())); - httpClient.Timeout = TimeSpan.FromMinutes(10); // TODO Check Timeout - var serviceProvider = services.BuildServiceProvider(); - var channel = CreateAuthenticatedChannel(baseUri, httpClient, serviceProvider); + services.AddSingleton(sp => + { + var config = sp.GetRequiredService(); + var baseUri = config["GwUrl"]; + if (string.IsNullOrWhiteSpace(baseUri)) + { + throw new InvalidOperationException("Configuration value 'GwUrl' is missing or empty."); + } + var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler())) + { + Timeout = TimeSpan.FromMinutes(10) + }; - services.AddTransient(sp => new OtpContract.OtpContractClient(channel)); - services.AddTransient(sp => new PackageContract.PackageContractClient(channel)); - services.AddTransient(sp => new RoleContract.RoleContractClient(channel)); - services.AddTransient(sp => new UserContract.UserContractClient(channel)); - services.AddTransient(sp => new UserAddressContract.UserAddressContractClient(channel)); - services.AddTransient(sp => new UserOrderContract.UserOrderContractClient(channel)); - services.AddTransient(sp => new UserRoleContract.UserRoleContractClient(channel)); + return CreateAuthenticatedChannel(baseUri, httpClient, sp); + }); + + services.AddTransient(sp => new OtpContract.OtpContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new PackageContract.PackageContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new ProductsContract.ProductsContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new RoleContract.RoleContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new UserContract.UserContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new UserAddressContract.UserAddressContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new UserOrderContract.UserOrderContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new UserRoleContract.UserRoleContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new CategoryContract.CategoryContractClient(sp.GetRequiredService())); return services; } @@ -98,7 +107,6 @@ public static class ConfigureServices MaxReceiveMessageSize = 1000 * 1024 * 1024, // 1 GB MaxSendMessageSize = 1000 * 1024 * 1024 // 1 GB }); - var invoker = channel.Intercept(new ErrorHandlerInterceptor()); - return invoker; + return channel.Intercept(new ErrorHandlerInterceptor()); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Common/Utilities/ErrorHandlerInterceptor.cs b/src/BackOffice/Common/Utilities/ErrorHandlerInterceptor.cs index a8aeb80..24dad33 100644 --- a/src/BackOffice/Common/Utilities/ErrorHandlerInterceptor.cs +++ b/src/BackOffice/Common/Utilities/ErrorHandlerInterceptor.cs @@ -1,14 +1,15 @@ -using Grpc.Core.Interceptors; -using Grpc.Core; +using Grpc.Core; +using Grpc.Core.Interceptors; +using MudBlazor; namespace BackOffice.Common.Utilities; public class ErrorHandlerInterceptor : Interceptor { public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) { var call = continuation(request, context); @@ -28,8 +29,9 @@ public class ErrorHandlerInterceptor : Interceptor } catch (Exception ex) { - GlobalConstants.ConstSnackbar.Add(ex.Message, severity: MudBlazor.Severity.Error); + var message = ex.Message.ExtractUserFriendlyMessage(); + GlobalConstants.ConstSnackbar?.Add(message, Severity.Error); throw; } } -} \ No newline at end of file +} diff --git a/src/BackOffice/Common/Utilities/GlobalConstants.cs b/src/BackOffice/Common/Utilities/GlobalConstants.cs index 7d48134..b2a4788 100644 --- a/src/BackOffice/Common/Utilities/GlobalConstants.cs +++ b/src/BackOffice/Common/Utilities/GlobalConstants.cs @@ -8,6 +8,5 @@ public static class GlobalConstants public const string DateTimeFormat = "MMM dd, yyyy - HH:mm"; public static string JwtTokenKey = "AuthToken"; public const string SuccessMsg = "با موفقیت انجام شد"; - public static ISnackbar ConstSnackbar; - -} \ No newline at end of file + public static ISnackbar? ConstSnackbar { get; set; } +} diff --git a/src/BackOffice/Common/Utilities/RouteConstance.cs b/src/BackOffice/Common/Utilities/RouteConstance.cs index 5906b3b..55b63ca 100644 --- a/src/BackOffice/Common/Utilities/RouteConstance.cs +++ b/src/BackOffice/Common/Utilities/RouteConstance.cs @@ -11,4 +11,6 @@ public static class RouteConstance public const string UserOrder = "/UserOrderPage/"; public const string UserRole = "/UserRolePage/"; public const string UserAddress = "/UserAddressPage/"; + public const string Products = "/ProductsPage/"; + public const string Category = "/CategoryPage/"; } diff --git a/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor b/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor new file mode 100644 index 0000000..87ca4de --- /dev/null +++ b/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor @@ -0,0 +1,15 @@ +@using BackOffice.BFF.Products.Protobuf.Protos.Products + + + diff --git a/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor.cs b/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor.cs new file mode 100644 index 0000000..f19ae7b --- /dev/null +++ b/src/BackOffice/Pages/AutoComplete/ProductsAutoComplete.razor.cs @@ -0,0 +1,79 @@ +using BackOffice.BFF.Products.Protobuf.Protos.Products; +using Microsoft.AspNetCore.Components; + +namespace BackOffice.Pages.AutoComplete; + +public partial class ProductsAutoComplete +{ + [Inject] public ProductsContract.ProductsContractClient ProductsService { get; set; } = default!; + + [Parameter] public long? Value { get; set; } + [Parameter] public string? Label { get; set; } = "محصول"; + [Parameter] public EventCallback ValueChanged { get; set; } + + private List _items = new(); + private GetAllProductsByFilterResponseModel? _item; + + protected override async void OnParametersSet() + { + await base.OnParametersSetAsync(); + + if (Value.HasValue && Value.Value > 0) + { + var getAll = await ProductsService.GetAllProductsByFilterAsync(new GetAllProductsByFilterRequest + { + Filter = new GetAllProductsByFilterFilter + { + Id = Value.Value + }, + PaginationState = new PaginationState + { + PageNumber = 1, + PageSize = 1 + } + }); + + if (getAll?.Models != null && getAll.Models.Any()) + { + _item = getAll.Models.First(); + StateHasChanged(); + } + } + } + + private async Task OnSelected(GetAllProductsByFilterResponseModel? model) + { + if (model == null) + { + _item = null; + await ValueChanged.InvokeAsync(null); + } + else + { + _item = model; + await ValueChanged.InvokeAsync(model.Id); + } + } + + private async Task> Search(string value, CancellationToken token) + { + var request = new GetAllProductsByFilterRequest + { + Filter = new GetAllProductsByFilterFilter + { + Title = string.IsNullOrWhiteSpace(value) ? null : value + }, + PaginationState = new PaginationState + { + PageNumber = 1, + PageSize = 9 + } + }; + + var getAll = await ProductsService.GetAllProductsByFilterAsync(request); + _items = getAll?.Models?.ToList() ?? new List(); + + return _items; + } +} + diff --git a/src/BackOffice/Pages/Category/CategoryMainPage.razor b/src/BackOffice/Pages/Category/CategoryMainPage.razor new file mode 100644 index 0000000..9a05073 --- /dev/null +++ b/src/BackOffice/Pages/Category/CategoryMainPage.razor @@ -0,0 +1,83 @@ +@attribute [Route(RouteConstance.Category)] + +@using BackOffice.BFF.Category.Protobuf.Protos.Category +@using BackOffice.Common.BaseComponents +@using DataModel = BackOffice.BFF.Category.Protobuf.Protos.Category.GetAllCategoryByFilterResponseModel + + + + + + + + + + + + + + + + + مدیریت دستهبندیها + + + + افزودن + + + + + + + + + + + + @(context.Item.IsActive ? "فعال" : "غیرفعال") + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BackOffice/Pages/Category/CategoryMainPage.razor.cs b/src/BackOffice/Pages/Category/CategoryMainPage.razor.cs new file mode 100644 index 0000000..7324188 --- /dev/null +++ b/src/BackOffice/Pages/Category/CategoryMainPage.razor.cs @@ -0,0 +1,120 @@ +using BackOffice.BFF.Category.Protobuf.Protos.Category; +using BackOffice.Common.BaseComponents; +using Mapster; +using Microsoft.AspNetCore.Components; +using MudBlazor; +using DataModel = BackOffice.BFF.Category.Protobuf.Protos.Category.GetAllCategoryByFilterResponseModel; + +namespace BackOffice.Pages.Category; + +public partial class CategoryMainPage +{ + [Inject] public CategoryContract.CategoryContractClient CategoryContract { get; set; } = default!; + + private BasePageComponent _basePage = default!; + private MudDataGrid _gridData = default!; + private GetAllCategoryByFilterRequest _request = new() { Filter = new() }; + + private async Task> ServerReload(GridState state) + { + _request.Filter ??= new(); + _request.PaginationState ??= new(); + _request.PaginationState.PageNumber = state.Page + 1; + _request.PaginationState.PageSize = state.PageSize; + + var result = await CategoryContract.GetAllCategoryByFilterAsync(_request); + if (result != null && result.Models != null && result.Models.Any()) + { + return new GridData + { + Items = result.Models.ToList(), + TotalItems = (int)result.MetaData.TotalCount + }; + } + + return new GridData(); + } + + public async Task CreateNew() + { + var dialog = await DialogService.ShowAsync( + "افزودن دستهبندی", + new DialogParameters + { + { x => x.Model, new CreateNewCategoryRequest { IsActive = true } } + }, + new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); + + var result = await dialog.Result; + if (!result.Canceled) + { + await ReloadData(); + Snackbar.Add("دستهبندی با موفقیت ایجاد شد.", Severity.Success); + } + } + + public async Task Update(DataModel model) + { + var getResponse = await CategoryContract.GetCategoryAsync(new GetCategoryRequest { Id = model.Id }); + + var editModel = getResponse.Adapt(); + + var dialog = await DialogService.ShowAsync( + "ویرایش دستهبندی", + new DialogParameters + { + { x => x.EditModel, editModel } + }, + new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); + + var result = await dialog.Result; + if (!result.Canceled) + { + await ReloadData(); + Snackbar.Add("دستهبندی با موفقیت ویرایش شد.", Severity.Success); + } + } + + private async Task OnDelete(DataModel model) + { + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small }; + bool? result = await DialogService.ShowMessageBox( + "اخطار", + "آیا از حذف این دستهبندی مطمئن هستید؟", + yesText: "حذف", + cancelText: "لغو", + options: options); + + if (result == true) + { + await CategoryContract.DeleteCategoryAsync(new DeleteCategoryRequest { Id = model.Id }); + await ReloadData(); + Snackbar.Add("دستهبندی با موفقیت حذف شد.", Severity.Success); + } + + StateHasChanged(); + } + + private async Task ReloadData() + { + if (_gridData != null) + { + await _gridData.ReloadServerData(); + } + } + + public async Task OnFilterSubmit() + { + _basePage.IsFiltered = true; + StateHasChanged(); + await ReloadData(); + } + + public async Task OnFilterCleared() + { + _basePage.IsFiltered = false; + StateHasChanged(); + _request = new GetAllCategoryByFilterRequest { Filter = new GetAllCategoryByFilterFilter() }; + await ReloadData(); + } +} diff --git a/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor b/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor new file mode 100644 index 0000000..7484e35 --- /dev/null +++ b/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor @@ -0,0 +1,48 @@ +@using BackOffice.BFF.Category.Protobuf.Protos.Category +@using Microsoft.AspNetCore.Components.Forms + + + + + + + + + + + + + + + + + + + لغو + ثبت + + diff --git a/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor.cs b/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor.cs new file mode 100644 index 0000000..aba60fd --- /dev/null +++ b/src/BackOffice/Pages/Category/CreateOrUpdateCategoryDialog.razor.cs @@ -0,0 +1,86 @@ +using BackOffice.BFF.Category.Protobuf.Protos.Category; +using Microsoft.AspNetCore.Components; +using MudBlazor; + +namespace BackOffice.Pages.Category; + +public partial class CreateOrUpdateCategoryDialog +{ + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!; + [Inject] public CategoryContract.CategoryContractClient CategoryContract { get; set; } = default!; + + [Parameter] public CreateNewCategoryRequest? Model { get; set; } + [Parameter] public UpdateCategoryRequest? EditModel { get; set; } + + private bool IsEdit => EditModel != null; + + private string Name { get; set; } = string.Empty; + private string Title { get; set; } = string.Empty; + private string? Description { get; set; } + private long? ParentId { get; set; } + private bool IsActive { get; set; } = true; + private int SortOrder { get; set; } + + protected override void OnInitialized() + { + if (IsEdit && EditModel != null) + { + Name = EditModel.Name; + Title = EditModel.Title; + Description = EditModel.Description; + ParentId = EditModel.ParentId; + IsActive = EditModel.IsActive; + SortOrder = EditModel.SortOrder; + } + else if (Model != null) + { + Name = Model.Name; + Title = Model.Title; + Description = Model.Description; + ParentId = Model.ParentId; + IsActive = Model.IsActive; + SortOrder = Model.SortOrder; + } + } + + private async Task Save() + { + if (IsEdit && EditModel != null) + { + var request = new UpdateCategoryRequest + { + Id = EditModel.Id, + Name = Name, + Title = Title, + Description = Description, + ParentId = ParentId, + IsActive = IsActive, + SortOrder = SortOrder + }; + + await CategoryContract.UpdateCategoryAsync(request); + } + else + { + var request = new CreateNewCategoryRequest + { + Name = Name, + Title = Title, + Description = Description, + ParentId = ParentId, + IsActive = IsActive, + SortOrder = SortOrder + }; + + await CategoryContract.CreateNewCategoryAsync(request); + } + + MudDialog.Close(DialogResult.Ok(true)); + } + + private void Cancel() + { + MudDialog.Cancel(); + } +} + diff --git a/src/BackOffice/Pages/Login/LoginPage.razor.cs b/src/BackOffice/Pages/Login/LoginPage.razor.cs index 6f7c8d0..d796916 100644 --- a/src/BackOffice/Pages/Login/LoginPage.razor.cs +++ b/src/BackOffice/Pages/Login/LoginPage.razor.cs @@ -15,7 +15,6 @@ public partial class LoginPage [Inject] public OtpContract.OtpContractClient OtpContract { get; set; } private async Task OnSubmitClick() { - Console.WriteLine(OtpContract == null); await _form.Validate(); if (!_form.IsValid) return; @@ -31,11 +30,12 @@ public partial class LoginPage } catch (Exception ex) { - Snackbar.Add(message: ex.Message, severity: Severity.Error, null); + var message = ex.Message.ExtractUserFriendlyMessage(); + Snackbar.Add(message: message, severity: Severity.Error); } _isLoading = false; StateHasChanged(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/Login/VerifyCodePage.razor.cs b/src/BackOffice/Pages/Login/VerifyCodePage.razor.cs index 2e78f39..975d015 100644 --- a/src/BackOffice/Pages/Login/VerifyCodePage.razor.cs +++ b/src/BackOffice/Pages/Login/VerifyCodePage.razor.cs @@ -45,7 +45,8 @@ public partial class VerifyCodePage } catch (Exception ex) { - Snackbar.Add(message: ex.Message, severity: Severity.Error, null); + var message = ex.Message.ExtractUserFriendlyMessage(); + Snackbar.Add(message: message, severity: Severity.Error); } _isLoading = false; @@ -68,7 +69,8 @@ public partial class VerifyCodePage } catch (Exception ex) { - Snackbar.Add(message: ex.Message, severity: Severity.Error, null); + var message = ex.Message.ExtractUserFriendlyMessage(); + Snackbar.Add(message: message, severity: Severity.Error); } _isLoading = false; @@ -94,4 +96,4 @@ public partial class VerifyCodePage } }), null, 1000, 1000); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/Package/Components/CreateDialog.razor.cs b/src/BackOffice/Pages/Package/Components/CreateDialog.razor.cs index 2e3612e..6a5a847 100644 --- a/src/BackOffice/Pages/Package/Components/CreateDialog.razor.cs +++ b/src/BackOffice/Pages/Package/Components/CreateDialog.razor.cs @@ -11,7 +11,7 @@ public partial class CreateDialog { [Inject] public PackageContract.PackageContractClient PackageContract { get; set; } [Parameter] public CreateNewPackageRequest Model { get; set; } = new(); - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } private bool _isLoading = false; private string _srcImage = "data:image/png;base64,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"; @@ -69,9 +69,8 @@ public partial class CreateDialog Submit(); } - catch (RpcException ex) + catch (RpcException) { - Console.WriteLine(ex); Snackbar.Add("خطای سرور", Severity.Error); } @@ -80,4 +79,4 @@ public partial class CreateDialog } void Submit() => MudDialog.Close(DialogResult.Ok(true)); void Cancel() => MudDialog.Cancel(); -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/Package/Components/UpdateDialog.razor.cs b/src/BackOffice/Pages/Package/Components/UpdateDialog.razor.cs index 31ce4f9..464d7d0 100644 --- a/src/BackOffice/Pages/Package/Components/UpdateDialog.razor.cs +++ b/src/BackOffice/Pages/Package/Components/UpdateDialog.razor.cs @@ -15,7 +15,7 @@ namespace BackOffice.Pages.Package.Components public UpdatePackageRequest Model { get; set; } = new(); [CascadingParameter] - MudDialogInstance MudDialog { get; set; } + IMudDialogInstance MudDialog { get; set; } private string _srcImage = "data:image/png;base64,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"; private IBrowserFile? _imageFile; private long _maxAllowedSize = (1024 * 1024) * 200; diff --git a/src/BackOffice/Pages/Package/PackageMainPage.razor b/src/BackOffice/Pages/Package/PackageMainPage.razor index e5e43ad..ea3741c 100644 --- a/src/BackOffice/Pages/Package/PackageMainPage.razor +++ b/src/BackOffice/Pages/Package/PackageMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.Package.Protobuf.Protos.Package.GetAllPackageByFilterResponseModel - + @@ -93,4 +93,3 @@ - diff --git a/src/BackOffice/Pages/Package/PackageMainPage.razor.cs b/src/BackOffice/Pages/Package/PackageMainPage.razor.cs index cf7cfc4..05496db 100644 --- a/src/BackOffice/Pages/Package/PackageMainPage.razor.cs +++ b/src/BackOffice/Pages/Package/PackageMainPage.razor.cs @@ -82,16 +82,16 @@ public partial class PackageMainPage public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/Products/Components/CreateDialog.razor b/src/BackOffice/Pages/Products/Components/CreateDialog.razor new file mode 100644 index 0000000..ea53519 --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/CreateDialog.razor @@ -0,0 +1,87 @@ +@using BackOffice.BFF.Products.Protobuf.Protos.Products +@using Microsoft.AspNetCore.Components.Forms +@using Tizzani.MudBlazor.HtmlEditor +@using BackOffice.Common.BaseComponents + + + + + + @if (!string.IsNullOrWhiteSpace(_mainImagePreview)) + { + + } + else + { + + تصویری انتخاب نشده است + + } + + + + + انتخاب تصویر اصلی + + + + @if (context != null) + { + + + @context.Name + + + } + else + { + فایلی انتخاب نشده + } + + + + + + + + + + + + + + + + + + + + + + + تصویر بندانگشتی + + + + انتخاب تصویر بندانگشتی (اختیاری) + + + + + + + + لغو + ثبت + + diff --git a/src/BackOffice/Pages/Products/Components/CreateDialog.razor.cs b/src/BackOffice/Pages/Products/Components/CreateDialog.razor.cs new file mode 100644 index 0000000..3080a9e --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/CreateDialog.razor.cs @@ -0,0 +1,91 @@ +using BackOffice.BFF.Products.Protobuf.Protos.Products; +using Google.Protobuf; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using MudBlazor; + +namespace BackOffice.Pages.Products.Components; + +public partial class CreateDialog +{ + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!; + [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!; + [Parameter] public CreateNewProductsRequest Model { get; set; } = default!; + + private IBrowserFile? _mainImageFile; + private IBrowserFile? _thumbnailImageFile; + private readonly long _maxAllowedSize = (1024 * 1024) * 5; + private bool _isLoading; + private string? _mainImagePreview; + + private async Task OnMainImageSelected(IBrowserFile? file) + { + _mainImageFile = file; + if (file != null) + { + var buffer = new byte[file.Size]; + await file.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + _mainImagePreview = $"data:{file.ContentType};base64," + Convert.ToBase64String(buffer); + StateHasChanged(); + } + } + + private async Task OnThumbnailSelected(IBrowserFile? file) + { + _thumbnailImageFile = file; + } + + public async void CallCreateMethod() + { + _isLoading = true; + StateHasChanged(); + + if (string.IsNullOrWhiteSpace(Model.Title)) + { + Snackbar.Add("لطفا عنوان را وارد کنید!", Severity.Warning); + _isLoading = false; + StateHasChanged(); + return; + } + + if (_mainImageFile != null) + { + var buffer = new byte[_mainImageFile.Size]; + await _mainImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + Model.ImageFile = new ImageFileModel + { + File = ByteString.CopyFrom(buffer), + Mime = _mainImageFile.ContentType, + FileName = Path.GetFileNameWithoutExtension(_mainImageFile.Name) + }; + } + + if (_thumbnailImageFile != null) + { + var buffer = new byte[_thumbnailImageFile.Size]; + await _thumbnailImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + Model.ThumbnailFile = new ImageFileModel + { + File = ByteString.CopyFrom(buffer), + Mime = _thumbnailImageFile.ContentType, + FileName = Path.GetFileNameWithoutExtension(_thumbnailImageFile.Name) + }; + } + + try + { + await ProductsContract.CreateNewProductsAsync(Model); + Submit(); + } + catch + { + Snackbar.Add("خطای سرور", Severity.Error); + } + + _isLoading = false; + StateHasChanged(); + } + + void Submit() => MudDialog.Close(DialogResult.Ok(true)); + void Cancel() => MudDialog.Cancel(); +} diff --git a/src/BackOffice/Pages/Products/Components/GalleryDialog.razor b/src/BackOffice/Pages/Products/Components/GalleryDialog.razor new file mode 100644 index 0000000..a821e9b --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/GalleryDialog.razor @@ -0,0 +1,83 @@ +@using BackOffice.BFF.Products.Protobuf.Protos.Products +@using Microsoft.AspNetCore.Components.Forms + + + + + گالری تصاویر - @ProductTitle + + + + + + + + + + انتخاب تصویر + + + + @if (context != null) + { + @context.Name + } + else + { + فایلی انتخاب نشده + } + + + + @if (!string.IsNullOrWhiteSpace(_previewImage)) + { + + + + } + + افزودن به گالری + + + + + @if (Items?.Count > 0) + { + + @foreach (var item in Items) + { + + + + @item.Title + + + + + + } + + } + else + { + هنوز تصویری برای این محصول ثبت نشده است. + } + + + + + + بستن + + diff --git a/src/BackOffice/Pages/Products/Components/GalleryDialog.razor.cs b/src/BackOffice/Pages/Products/Components/GalleryDialog.razor.cs new file mode 100644 index 0000000..186724e --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/GalleryDialog.razor.cs @@ -0,0 +1,129 @@ +using BackOffice.BFF.Products.Protobuf.Protos.Products; +using Google.Protobuf; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using MudBlazor; + +namespace BackOffice.Pages.Products.Components; + +public partial class GalleryDialog +{ + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!; + [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!; + + [Parameter] public long ProductId { get; set; } + [Parameter] public string ProductTitle { get; set; } = string.Empty; + + private List Items { get; set; } = new List(); + private IBrowserFile? _file; + private string? _title; + private readonly long _maxAllowedSize = (1024 * 1024) * 5; + private bool _isUploading; + private string? _previewImage; + private byte[]? _imageBuffer; + + protected override async Task OnInitializedAsync() + { + if (string.IsNullOrWhiteSpace(_title)) + _title = ProductTitle; + + await LoadGallery(); + } + + private async Task LoadGallery() + { + var response = await ProductsContract.GetProductGalleryAsync(new GetProductGalleryRequest + { + ProductId = ProductId + }); + + Items = response?.Items? + .Select(x => new GalleryItemViewModel + { + ProductGalleryId = x.ProductGalleryId, + ProductImageId = x.ProductImageId, + Title = x.Title, + ImagePath = x.ImagePath, + ImageThumbnailPath = x.ImageThumbnailPath + }) + .ToList() ?? new List(); + StateHasChanged(); + } + + private async Task OnImageSelected(IBrowserFile? file) + { + _file = file; + _previewImage = null; + _imageBuffer = null; + + if (file != null) + { + var buffer = new byte[file.Size]; + await file.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + _imageBuffer = buffer; + _previewImage = $"data:{file.ContentType};base64," + Convert.ToBase64String(buffer); + StateHasChanged(); + } + } + + private async Task AddImage() + { + if (_file == null) + return; + + _isUploading = true; + StateHasChanged(); + + if (_imageBuffer == null) + { + var buffer = new byte[_file.Size]; + await _file.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + _imageBuffer = buffer; + } + + var request = new AddProductImageRequest + { + ProductId = ProductId, + Title = _title ?? string.Empty, + ImageFile = new ImageFileModel + { + File = ByteString.CopyFrom(_imageBuffer), + Mime = _file.ContentType, + FileName = Path.GetFileNameWithoutExtension(_file.Name) + } + }; + + await ProductsContract.AddProductImageAsync(request); + + _file = null; + _title = string.Empty; + _previewImage = null; + _imageBuffer = null; + + await LoadGallery(); + + _isUploading = false; + StateHasChanged(); + } + + private async Task RemoveImage(GalleryItemViewModel item) + { + await ProductsContract.RemoveProductImageAsync(new RemoveProductImageRequest + { + ProductGalleryId = item.ProductGalleryId + }); + + await LoadGallery(); + } + + private void Close() => MudDialog.Close(); + + private class GalleryItemViewModel + { + public long ProductGalleryId { get; set; } + public long ProductImageId { get; set; } + public string Title { get; set; } + public string ImagePath { get; set; } + public string ImageThumbnailPath { get; set; } + } +} diff --git a/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor b/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor new file mode 100644 index 0000000..75b3577 --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor @@ -0,0 +1,25 @@ +@using BackOffice.Common.BaseComponents + + + + + @Title + @if (!string.IsNullOrWhiteSpace(ImageUrl)) + { + + } + else + { + تصویری برای نمایش وجود ندارد. + } + + + + بستن + + + diff --git a/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor.cs b/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor.cs new file mode 100644 index 0000000..fd4694c --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/ImagePreviewDialog.razor.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Components; +using MudBlazor; + +namespace BackOffice.Pages.Products.Components; + +public partial class ImagePreviewDialog +{ + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!; + + [Parameter] public string ImageUrl { get; set; } = string.Empty; + [Parameter] public string Title { get; set; } = string.Empty; + + private void Close() => MudDialog.Close(); +} + diff --git a/src/BackOffice/Pages/Products/Components/UpdateDialog.razor b/src/BackOffice/Pages/Products/Components/UpdateDialog.razor new file mode 100644 index 0000000..307542b --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/UpdateDialog.razor @@ -0,0 +1,73 @@ +@using BackOffice.BFF.Products.Protobuf.Protos.Products +@using Microsoft.AspNetCore.Components.Forms +@using Tizzani.MudBlazor.HtmlEditor +@using BackOffice.Common.BaseComponents + + + + + + @if (!string.IsNullOrWhiteSpace(_mainImagePreview)) + { + + } + else + { + + تصویری انتخاب نشده است + + } + + + + + تغییر تصویر اصلی + + + + + + + + + + + + + + + + + + + + + + + + تصویر بندانگشتی + + + + تغییر تصویر بندانگشتی (اختیاری) + + + + + + + + لغو + ویرایش + + diff --git a/src/BackOffice/Pages/Products/Components/UpdateDialog.razor.cs b/src/BackOffice/Pages/Products/Components/UpdateDialog.razor.cs new file mode 100644 index 0000000..231982b --- /dev/null +++ b/src/BackOffice/Pages/Products/Components/UpdateDialog.razor.cs @@ -0,0 +1,97 @@ +using BackOffice.BFF.Products.Protobuf.Protos.Products; +using Google.Protobuf; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using MudBlazor; + +namespace BackOffice.Pages.Products.Components; + +public partial class UpdateDialog +{ + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!; + [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!; + [Parameter] public UpdateProductsRequest Model { get; set; } = default!; + + private IBrowserFile? _mainImageFile; + private IBrowserFile? _thumbnailImageFile; + private readonly long _maxAllowedSize = (1024 * 1024) * 5; + private bool _isLoading; + private string? _mainImagePreview; + + private async Task OnMainImageSelected(IBrowserFile? file) + { + _mainImageFile = file; + if (file != null) + { + var buffer = new byte[file.Size]; + await file.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + _mainImagePreview = $"data:{file.ContentType};base64," + Convert.ToBase64String(buffer); + StateHasChanged(); + } + } + + private async Task OnThumbnailSelected(IBrowserFile? file) + { + _thumbnailImageFile = file; + } + + protected override Task OnInitializedAsync() + { + _mainImagePreview = Model.ImagePath; + return base.OnInitializedAsync(); + } + + public async void CallUpdateMethod() + { + _isLoading = true; + StateHasChanged(); + + if (string.IsNullOrWhiteSpace(Model.Title)) + { + Snackbar.Add("لطفا عنوان را وارد کنید!", Severity.Warning); + _isLoading = false; + StateHasChanged(); + return; + } + + if (_mainImageFile != null) + { + var buffer = new byte[_mainImageFile.Size]; + await _mainImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + Model.ImageFile = new ImageFileModel + { + File = ByteString.CopyFrom(buffer), + Mime = _mainImageFile.ContentType, + FileName = Path.GetFileNameWithoutExtension(_mainImageFile.Name) + }; + } + + if (_thumbnailImageFile != null) + { + var buffer = new byte[_thumbnailImageFile.Size]; + await _thumbnailImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer); + Model.ThumbnailFile = new ImageFileModel + { + File = ByteString.CopyFrom(buffer), + Mime = _thumbnailImageFile.ContentType, + FileName = Path.GetFileNameWithoutExtension(_thumbnailImageFile.Name) + }; + } + + try + { + await ProductsContract.UpdateProductsAsync(Model); + Submit(); + } + catch + { + Snackbar.Add("خطای سرور", Severity.Error); + } + + _isLoading = false; + StateHasChanged(); + } + + void Submit() => MudDialog.Close(DialogResult.Ok(true)); + void Cancel() => MudDialog.Cancel(); +} diff --git a/src/BackOffice/Pages/Products/ProductsMainPage.razor b/src/BackOffice/Pages/Products/ProductsMainPage.razor new file mode 100644 index 0000000..acdb396 --- /dev/null +++ b/src/BackOffice/Pages/Products/ProductsMainPage.razor @@ -0,0 +1,85 @@ +@attribute [Route(RouteConstance.Products)] + +@using BackOffice.BFF.Products.Protobuf.Protos.Products +@using BackOffice.Common.BaseComponents +@using BackOffice.Pages.Products.Components +@using DataModel = BackOffice.BFF.Products.Protobuf.Protos.Products.GetAllProductsByFilterResponseModel + + + + + + + + + + + + + + + مدیریت محصولات + + + افزودن + + + + + + + + + + OpenImagePreview(context.Item.ImagePath, context.Item.Title))"> + + + + @if (string.IsNullOrWhiteSpace(context.Item.Title)) + { + - + } + else + { + + + @(context.Item.Title.Truncate(20, true)) + + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BackOffice/Pages/Products/ProductsMainPage.razor.cs b/src/BackOffice/Pages/Products/ProductsMainPage.razor.cs new file mode 100644 index 0000000..8d4424e --- /dev/null +++ b/src/BackOffice/Pages/Products/ProductsMainPage.razor.cs @@ -0,0 +1,123 @@ +using BackOffice.BFF.Products.Protobuf.Protos.Products; +using BackOffice.Common.BaseComponents; +using BackOffice.Pages.Products.Components; +using Mapster; +using Microsoft.AspNetCore.Components; +using MudBlazor; +using DataModel = BackOffice.BFF.Products.Protobuf.Protos.Products.GetAllProductsByFilterResponseModel; + +namespace BackOffice.Pages.Products; + +public partial class ProductsMainPage +{ + [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!; + + private bool _isLoading = true; + private MudDataGrid _gridData; + private BasePageComponent _basePage; + private GetAllProductsByFilterRequest _request = new() { Filter = new() }; + + private async Task> ServerReload(GridState state) + { + _request.Filter ??= new(); + _request.PaginationState ??= new(); + _request.PaginationState.PageNumber = state.Page + 1; + _request.PaginationState.PageSize = state.PageSize; + + var result = await ProductsContract.GetAllProductsByFilterAsync(_request); + if (result != null && result.Models != null && result.Models.Any()) + { + return new GridData { Items = result.Models.ToList(), TotalItems = (int)result.MetaData.TotalCount }; + } + + return new GridData(); + } + + public async Task Update(DataModel model) + { + var parameters = new DialogParameters { { x => x.Model, model.Adapt() } }; + + var dialog = await DialogService.ShowAsync("ویرایش محصول", parameters, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); + var result = await dialog.Result; + + if (!result.Canceled) + { + ReLoadData(); + Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success); + } + } + + private async Task OnDelete(DataModel model) + { + var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small }; + bool? result = await DialogService.ShowMessageBox( + "اخطار", + "آیا از حذف این مورد مطمئن هستید؟", + yesText: "حذف", cancelText: "لغو", + options: options); + if (result == true) + { + await ProductsContract.DeleteProductsAsync(new DeleteProductsRequest { Id = model.Id }); + ReLoadData(); + } + StateHasChanged(); + } + + public async void ReLoadData() + { + if (_gridData != null) + await _gridData.ReloadServerData(); + } + + public async Task CreateNew() + { + var dialog = await DialogService.ShowAsync("افزودن محصول", new DialogParameters { { x => x.Model, new CreateNewProductsRequest() } }, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); + var result = await dialog.Result; + if (!result.Canceled) + { + ReLoadData(); + Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success); + } + } + + public async Task OnFilterSubmit() + { + _basePage.IsFiltered = true; + StateHasChanged(); + ReLoadData(); + } + + public async Task OnFilterCleared() + { + _basePage.IsFiltered = false; + StateHasChanged(); + _request = new GetAllProductsByFilterRequest { Filter = new() }; + ReLoadData(); + } + + public async Task OpenGallery(DataModel model) + { + var parameters = new DialogParameters + { + { x => x.ProductId, model.Id }, + { x => x.ProductTitle, model.Title } + }; + await DialogService.ShowAsync("گالری تصاویر", parameters, + new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium }); + } + + public async Task OpenImagePreview(string imagePath, string title) + { + if (string.IsNullOrWhiteSpace(imagePath)) + return; + + var parameters = new DialogParameters + { + { x => x.ImageUrl, imagePath }, + { x => x.Title, title } + }; + + await DialogService.ShowAsync("پیشنمایش تصویر محصول", parameters, + new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true }); + } +} diff --git a/src/BackOffice/Pages/Role/Components/CreateDialog.razor.cs b/src/BackOffice/Pages/Role/Components/CreateDialog.razor.cs index aa0aa4e..2c0c776 100644 --- a/src/BackOffice/Pages/Role/Components/CreateDialog.razor.cs +++ b/src/BackOffice/Pages/Role/Components/CreateDialog.razor.cs @@ -11,7 +11,7 @@ public partial class CreateDialog { [Inject] public RoleContract.RoleContractClient RoleContract { get; set; } [Parameter] public CreateNewRoleRequest Model { get; set; } = new(); - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } private bool _isLoading = false; private string _srcImage = "data:image/png;base64,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"; @@ -53,9 +53,8 @@ public partial class CreateDialog Submit(); } - catch (RpcException ex) + catch (RpcException) { - Console.WriteLine(ex); Snackbar.Add("خطای سرور", Severity.Error); } @@ -64,4 +63,4 @@ public partial class CreateDialog } void Submit() => MudDialog.Close(DialogResult.Ok(true)); void Cancel() => MudDialog.Cancel(); -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/Role/Components/UpdateDialog.razor.cs b/src/BackOffice/Pages/Role/Components/UpdateDialog.razor.cs index 152800c..82236e0 100644 --- a/src/BackOffice/Pages/Role/Components/UpdateDialog.razor.cs +++ b/src/BackOffice/Pages/Role/Components/UpdateDialog.razor.cs @@ -15,7 +15,7 @@ namespace BackOffice.Pages.Role.Components public UpdateRoleRequest Model { get; set; } = new(); [CascadingParameter] - MudDialogInstance MudDialog { get; set; } + IMudDialogInstance MudDialog { get; set; } public async void CallUpdateMethod() { diff --git a/src/BackOffice/Pages/Role/RoleMainPage.razor b/src/BackOffice/Pages/Role/RoleMainPage.razor index 7057408..a8b0f09 100644 --- a/src/BackOffice/Pages/Role/RoleMainPage.razor +++ b/src/BackOffice/Pages/Role/RoleMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.Role.Protobuf.Protos.Role.GetAllRoleByFilterResponseModel - + @@ -57,4 +57,3 @@ - diff --git a/src/BackOffice/Pages/Role/RoleMainPage.razor.cs b/src/BackOffice/Pages/Role/RoleMainPage.razor.cs index 0fdb165..506af20 100644 --- a/src/BackOffice/Pages/Role/RoleMainPage.razor.cs +++ b/src/BackOffice/Pages/Role/RoleMainPage.razor.cs @@ -81,16 +81,16 @@ public partial class RoleMainPage } public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/User/Components/UserRoleDialog.razor.cs b/src/BackOffice/Pages/User/Components/UserRoleDialog.razor.cs index e212b36..7fc56cf 100644 --- a/src/BackOffice/Pages/User/Components/UserRoleDialog.razor.cs +++ b/src/BackOffice/Pages/User/Components/UserRoleDialog.razor.cs @@ -8,7 +8,7 @@ namespace BackOffice.Pages.User.Components; public partial class UserRoleDialog { [Parameter] public long UserId { get; set; } - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } MudForm _form; private bool _isLoading; private bool _isFirstLoad = true; diff --git a/src/BackOffice/Pages/User/UserMainPage.razor b/src/BackOffice/Pages/User/UserMainPage.razor index b8ea98e..aec662d 100644 --- a/src/BackOffice/Pages/User/UserMainPage.razor +++ b/src/BackOffice/Pages/User/UserMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.User.Protobuf.Protos.User.GetAllUserByFilterResponseModel - + @@ -64,4 +64,3 @@ - diff --git a/src/BackOffice/Pages/User/UserMainPage.razor.cs b/src/BackOffice/Pages/User/UserMainPage.razor.cs index 9dda340..53ec385 100644 --- a/src/BackOffice/Pages/User/UserMainPage.razor.cs +++ b/src/BackOffice/Pages/User/UserMainPage.razor.cs @@ -51,30 +51,6 @@ public partial class UserMainPage if (_gridData != null) await _gridData.ReloadServerData(); } - private async Task Searchfirstname(string? firstname) - { - _request.Filter ??= new(); - _request.Filter.FirstName = string.IsNullOrWhiteSpace(firstname) ? default : firstname; - ReLoadData(); - } - private async Task Searchlastname(string? lastname) - { - _request.Filter ??= new(); - _request.Filter.LastName = string.IsNullOrWhiteSpace(lastname) ? default : lastname; - ReLoadData(); - } - private async Task SearchNationalCode(string? nationalcode) - { - _request.Filter ??= new(); - _request.Filter.NationalCode = string.IsNullOrWhiteSpace(nationalcode) ? default : nationalcode; - ReLoadData(); - } - private async Task SearchMobile(string? mobile) - { - _request.Filter ??= new(); - _request.Filter.Mobile = string.IsNullOrWhiteSpace(mobile) ? default : mobile; - ReLoadData(); - } public async Task OnclickUserRoleDialog(long userid) { var dialog = await DialogService.ShowAsync($"نقش های کاربر", new DialogParameters() { { x => x.UserId, userid } }, new DialogOptions() { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); @@ -87,16 +63,16 @@ public partial class UserMainPage } public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/UserAddress/Components/CreateDialog.razor.cs b/src/BackOffice/Pages/UserAddress/Components/CreateDialog.razor.cs index d2142c7..ae95782 100644 --- a/src/BackOffice/Pages/UserAddress/Components/CreateDialog.razor.cs +++ b/src/BackOffice/Pages/UserAddress/Components/CreateDialog.razor.cs @@ -11,7 +11,7 @@ public partial class CreateDialog { [Inject] public UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } [Parameter] public CreateNewUserAddressRequest Model { get; set; } = new(); - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } private bool _isLoading = false; @@ -49,9 +49,8 @@ public partial class CreateDialog Submit(); } - catch (RpcException ex) + catch (RpcException) { - Console.WriteLine(ex); Snackbar.Add("خطای سرور", Severity.Error); } @@ -60,4 +59,4 @@ public partial class CreateDialog } void Submit() => MudDialog.Close(DialogResult.Ok(true)); void Cancel() => MudDialog.Cancel(); -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/UserAddress/Components/UpdateDialog.razor.cs b/src/BackOffice/Pages/UserAddress/Components/UpdateDialog.razor.cs index 212edaa..0c884a4 100644 --- a/src/BackOffice/Pages/UserAddress/Components/UpdateDialog.razor.cs +++ b/src/BackOffice/Pages/UserAddress/Components/UpdateDialog.razor.cs @@ -15,7 +15,7 @@ namespace BackOffice.Pages.UserAddress.Components public UpdateUserAddressRequest Model { get; set; } = new(); [CascadingParameter] - MudDialogInstance MudDialog { get; set; } + IMudDialogInstance MudDialog { get; set; } public async void CallUpdateMethod() { _isLoading = true; diff --git a/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor b/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor index ecb2f13..2a34c45 100644 --- a/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor +++ b/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.UserAddress.Protobuf.Protos.UserAddress.GetAllUserAddressByFilterResponseModel - + @@ -54,4 +54,3 @@ - diff --git a/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor.cs b/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor.cs index 4525371..d2e4d53 100644 --- a/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor.cs +++ b/src/BackOffice/Pages/UserAddress/UserAddressMainPage.razor.cs @@ -83,16 +83,16 @@ public partial class UserAddressMainPage } public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor b/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor index c8a477d..60cd716 100644 --- a/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor +++ b/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.UserOrder.Protobuf.Protos.UserOrder.GetAllUserOrderByFilterResponseModel - + @@ -65,4 +65,3 @@ - diff --git a/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor.cs b/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor.cs index 26c7ad9..dc6108a 100644 --- a/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor.cs +++ b/src/BackOffice/Pages/UserOrder/UserOrderMainPage.razor.cs @@ -56,16 +56,16 @@ public partial class UserOrderMainPage } public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Pages/UserRole/Components/CreateDialog.razor.cs b/src/BackOffice/Pages/UserRole/Components/CreateDialog.razor.cs index 4bd7a3d..5b3e918 100644 --- a/src/BackOffice/Pages/UserRole/Components/CreateDialog.razor.cs +++ b/src/BackOffice/Pages/UserRole/Components/CreateDialog.razor.cs @@ -11,7 +11,7 @@ public partial class CreateDialog { [Inject] public UserRoleContract.UserRoleContractClient UserRoleContract { get; set; } [Parameter] public CreateNewUserRoleRequest Model { get; set; } = new(); - [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } private bool _isLoading = false; diff --git a/src/BackOffice/Pages/UserRole/Components/UpdateDialog.razor.cs b/src/BackOffice/Pages/UserRole/Components/UpdateDialog.razor.cs index baebcdd..9b40628 100644 --- a/src/BackOffice/Pages/UserRole/Components/UpdateDialog.razor.cs +++ b/src/BackOffice/Pages/UserRole/Components/UpdateDialog.razor.cs @@ -15,7 +15,7 @@ namespace BackOffice.Pages.UserRole.Components public UpdateUserRoleRequest Model { get; set; } = new(); [CascadingParameter] - MudDialogInstance MudDialog { get; set; } + IMudDialogInstance MudDialog { get; set; } public async void CallUpdateMethod() { diff --git a/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor b/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor index dbfe885..f6ad58d 100644 --- a/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor +++ b/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor @@ -5,7 +5,7 @@ @using BackOffice.Common.BaseComponents @using DataModel = BackOffice.BFF.UserRole.Protobuf.Protos.UserRole.GetAllUserRoleByFilterResponseModel - + @@ -53,4 +53,3 @@ - diff --git a/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor.cs b/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor.cs index b397833..1026c09 100644 --- a/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor.cs +++ b/src/BackOffice/Pages/UserRole/UserRoleMainPage.razor.cs @@ -83,16 +83,16 @@ public partial class UserRoleMainPage } public async Task OnFilterSubmit() { - _basePage.IsFilterd = true; + _basePage.IsFiltered = true; StateHasChanged(); ReLoadData(); } - public async Task OnFilterCleard() + public async Task OnFilterCleared() { - _basePage.IsFilterd = false; + _basePage.IsFiltered = false; StateHasChanged(); _request = new() { Filter = new() { } }; ReLoadData(); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Shared/CustomMudTheme.cs b/src/BackOffice/Shared/CustomMudTheme.cs new file mode 100644 index 0000000..31a1efa --- /dev/null +++ b/src/BackOffice/Shared/CustomMudTheme.cs @@ -0,0 +1,104 @@ +using MudBlazor; + +namespace BackOffice.Shared; + +public static class CustomMudTheme +{ + public static MudTheme CustomMudBlazorTheme { get; set; } = new() + { + PaletteLight = new PaletteLight() + { + Primary = "#0380C0", + Secondary = "#5E4DF9", + PrimaryContrastText = "#FFFFFF", + AppbarText = Colors.Gray.Darken4, + Background = "#F5F5F5", + AppbarBackground = "#F5F5F5", + TextPrimary = Colors.Gray.Darken3, + Surface = "#FFFFFF", + Divider = "#B2BFCB", + DrawerBackground = "#FFFFFF", + DrawerText = Colors.Gray.Darken3, + DrawerIcon = Colors.Gray.Darken2, + }, + LayoutProperties = new LayoutProperties + { + DefaultBorderRadius = "12px", + AppbarHeight = "56px", + DrawerWidthLeft = "260px", + DrawerWidthRight = "260px" + }, + Typography = new Typography + { + Default = new DefaultTypography() + { + FontFamily = new[] { "Vazir", "Tahoma", "Segoe UI", "Arial", "sans-serif" } + }, + H1 = new H1Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "2rem", LineHeight = "1.70", FontWeight = "800", + LetterSpacing = "normal" + }, + H2 = new H2Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1.875rem", LineHeight = "1.65", FontWeight = "800", + LetterSpacing = "normal" + }, + H3 = new H3Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1.5rem", LineHeight = "1.60", FontWeight = "800", + LetterSpacing = "normal" + }, + H4 = new H4Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1.25rem", LineHeight = "1.55", FontWeight = "800", + LetterSpacing = "normal" + }, + H5 = new H5Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1.125rem", LineHeight = "1.50", FontWeight = "800", + LetterSpacing = "normal" + }, + H6 = new H6Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1rem", LineHeight = "1.45", FontWeight = "800", + LetterSpacing = "normal" + }, + Subtitle1 = new Subtitle1Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1rem", LineHeight = "1.62", FontWeight = "500", + LetterSpacing = "normal" + }, + Subtitle2 = new Subtitle2Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "0.875rem", LineHeight = "1.60", FontWeight = "500", + LetterSpacing = "normal" + }, + Body1 = new Body1Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "1rem", LineHeight = "1.85", FontWeight = "400", + LetterSpacing = "normal" + }, + Body2 = new Body2Typography() + { + FontFamily = new[] { "Vazir" }, FontSize = "0.875rem", LineHeight = "1.80", FontWeight = "400", + LetterSpacing = "normal" + }, + Caption = new CaptionTypography() + { + FontFamily = new[] { "Vazir" }, FontSize = "0.75rem", LineHeight = "1.60", FontWeight = "400", + LetterSpacing = "normal" + }, + Overline = new OverlineTypography() + { + FontFamily = new[] { "Vazir" }, FontSize = "0.75rem", LineHeight = "1.60", FontWeight = "500", + LetterSpacing = "normal" + }, + Button = new ButtonTypography() + { + FontFamily = new[] { "Vazir" }, FontSize = "0.875rem", LineHeight = "1.60", FontWeight = "600", + LetterSpacing = "normal", TextTransform = "none" + } + } + }; +} diff --git a/src/BackOffice/Shared/EmptyLayout.razor b/src/BackOffice/Shared/EmptyLayout.razor index 6c9e2bb..ca0e3bc 100644 --- a/src/BackOffice/Shared/EmptyLayout.razor +++ b/src/BackOffice/Shared/EmptyLayout.razor @@ -1,7 +1,7 @@ @inherits LayoutComponentBase - + @@ -13,24 +13,3 @@ - - -@code { - - - MudTheme CustomTheme = new MudTheme() - { - Typography = new Typography() - { - Default = new Default() - { - FontFamily = new[] { "IRANSans" } - - } - }, - LayoutProperties = new() - { - DrawerWidthRight = "250px" - }, - }; -} \ No newline at end of file diff --git a/src/BackOffice/Shared/MainLayout.razor b/src/BackOffice/Shared/MainLayout.razor index 541ea1d..dca9a7c 100644 --- a/src/BackOffice/Shared/MainLayout.razor +++ b/src/BackOffice/Shared/MainLayout.razor @@ -4,14 +4,14 @@ @attribute [AllowAnonymous] - + - + - مدیریت + پنل مدیریت فرصت @@ -33,4 +33,3 @@ - diff --git a/src/BackOffice/Shared/MainLayout.razor.cs b/src/BackOffice/Shared/MainLayout.razor.cs index 6aa7911..fa1153e 100644 --- a/src/BackOffice/Shared/MainLayout.razor.cs +++ b/src/BackOffice/Shared/MainLayout.razor.cs @@ -1,27 +1,24 @@ +using BackOffice.Common.Utilities; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using MudBlazor; namespace BackOffice.Shared; + public partial class MainLayout { - bool _drawerOpen = false; - private string Details { get; set; } - + private bool _drawerOpen; + + protected override void OnInitialized() + { + base.OnInitialized(); + GlobalConstants.ConstSnackbar = Snackbar; + } + void DrawerToggle() { _drawerOpen = !_drawerOpen; } - MudTheme CustomTheme = new MudTheme() - { - Typography = new Typography() - { - Default = new Default() - { - FontFamily = new[] { "IRANSans" } - - } - } - }; -} \ No newline at end of file + +} diff --git a/src/BackOffice/Shared/NavMenu.razor b/src/BackOffice/Shared/NavMenu.razor index a89e1eb..4409b79 100644 --- a/src/BackOffice/Shared/NavMenu.razor +++ b/src/BackOffice/Shared/NavMenu.razor @@ -1,19 +1,57 @@ -@using BackOffice.BFF.Package.Protobuf.Protos.Package -@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Authorization + + + منوی اصلی + + + + داشبورد + - - داشبورد - مدیریت پکیج - مدیریت کاربر - مدیریت نقش - + + مدیریت پکیج + + + + مدیریت محصول + + + + مدیریت دستهبندی + + + + مدیریت کاربر + + + + مدیریت نقش + - - - خروج از حساب + + + + + خروج از حساب + @@ -24,4 +62,4 @@ await LocalStorageService.RemoveItemAsync("AuthToken"); Navigation.NavigateTo("/Login"); } -} \ No newline at end of file +} diff --git a/src/BackOffice/Shared/NavMenu.razor.css b/src/BackOffice/Shared/NavMenu.razor.css index e69de29..893825d 100644 --- a/src/BackOffice/Shared/NavMenu.razor.css +++ b/src/BackOffice/Shared/NavMenu.razor.css @@ -0,0 +1,33 @@ +.nav-menu { + padding: 1.5rem 0.5rem 1.5rem 0.5rem; +} + +.nav-menu__title { + padding: 0 0.75rem 0.25rem 0.75rem; + color: rgba(0, 0, 0, 0.6); +} + +.nav-menu .mud-divider { + opacity: 0.7; +} + +.nav-menu .mud-nav-link { + margin: 0.15rem 0.4rem; + border-radius: 999px; + padding-inline: 0.75rem 1rem; + font-weight: 500; +} + +.nav-menu .mud-nav-link .mud-nav-link-text { + margin-right: 0.5rem; +} + +.nav-menu .mud-nav-link.mud-nav-link-active { + background-color: rgba(3, 128, 192, 0.12); + color: #0380C0; + font-weight: 600; +} + +.nav-menu .mud-nav-link.mud-nav-link-active .mud-nav-link-icon { + color: #0380C0; +} diff --git a/src/BackOffice/_Imports.razor b/src/BackOffice/_Imports.razor index acf87fb..9bc8f09 100644 --- a/src/BackOffice/_Imports.razor +++ b/src/BackOffice/_Imports.razor @@ -11,6 +11,7 @@ @using MudBlazor @using Mapster @using DateTimeConverterCL +@using Microsoft.AspNetCore.Components.Authorization @attribute [Authorize(Roles = "Administrator, Admin, Author")] @@ -20,3 +21,4 @@ @inject IJSRuntime jsRuntime @inject NavigationManager Navigation @inject ILocalStorageService LocalStorageService +@inject AuthenticationStateProvider AuthenticationStateProvider diff --git a/src/BackOffice/wwwroot/css/app.css b/src/BackOffice/wwwroot/css/app.css index 46042f4..01a6133 100644 --- a/src/BackOffice/wwwroot/css/app.css +++ b/src/BackOffice/wwwroot/css/app.css @@ -9,6 +9,17 @@ url('../fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf') format('truetype'); } +html, body { + margin: 0; + padding: 0; + height: 100%; + background-color: #f5f5f5; +} + +body { + font-family: "Vazir", "IRANSans", Tahoma, "Segoe UI", Arial, sans-serif; +} + .loading-progress { position: relative; display: block; @@ -79,4 +90,4 @@ h1:focus { .blazor-error-boundary::after { content: "An error has occurred." - } \ No newline at end of file + }