diff --git a/Moonlight/App/Models/Forms/Store/AddCouponForm.cs b/Moonlight/App/Models/Forms/Admin/Store/AddCouponForm.cs similarity index 91% rename from Moonlight/App/Models/Forms/Store/AddCouponForm.cs rename to Moonlight/App/Models/Forms/Admin/Store/AddCouponForm.cs index 4242e767..ad363695 100644 --- a/Moonlight/App/Models/Forms/Store/AddCouponForm.cs +++ b/Moonlight/App/Models/Forms/Admin/Store/AddCouponForm.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Moonlight.App.Models.Forms.Store; +namespace Moonlight.App.Models.Forms.Admin.Store; public class AddCouponForm { diff --git a/Moonlight/App/Models/Forms/Admin/Store/AddGiftCodeForm.cs b/Moonlight/App/Models/Forms/Admin/Store/AddGiftCodeForm.cs new file mode 100644 index 00000000..29de4cd9 --- /dev/null +++ b/Moonlight/App/Models/Forms/Admin/Store/AddGiftCodeForm.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms.Admin.Store; + +public class AddGiftCodeForm +{ + [MinLength(5, ErrorMessage = "The code needs to be longer than 4")] + [MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")] + public string Code { get; set; } = ""; + + [Range(0, int.MaxValue, ErrorMessage = "The value needs to be equals or greater than 0")] + public double Value { get; set; } + + [Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")] + public int Amount { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/Admin/Store/EditCouponForm.cs b/Moonlight/App/Models/Forms/Admin/Store/EditCouponForm.cs new file mode 100644 index 00000000..89517f9f --- /dev/null +++ b/Moonlight/App/Models/Forms/Admin/Store/EditCouponForm.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms.Admin.Store; + +public class EditCouponForm +{ + [MinLength(5, ErrorMessage = "The code needs to be longer than 4")] + [MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")] + public string Code { get; set; } = ""; + + [Range(1, 99, ErrorMessage = "The percent needs to be between 1 and 99")] + public int Percent { get; set; } + + [Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")] + public int Amount { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/Admin/Store/EditGiftCodeForm.cs b/Moonlight/App/Models/Forms/Admin/Store/EditGiftCodeForm.cs new file mode 100644 index 00000000..93bdb843 --- /dev/null +++ b/Moonlight/App/Models/Forms/Admin/Store/EditGiftCodeForm.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms.Admin.Store; + +public class EditGiftCodeForm +{ + [MinLength(5, ErrorMessage = "The code needs to be longer than 4")] + [MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")] + public string Code { get; set; } = ""; + + [Range(0, int.MaxValue, ErrorMessage = "The value needs to be equals or greater than 0")] + public double Value { get; set; } + + [Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")] + public int Amount { get; set; } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Forms/AutoCrud.razor b/Moonlight/Shared/Components/Forms/AutoCrud.razor index 6ab4b548..15e4dd13 100644 --- a/Moonlight/Shared/Components/Forms/AutoCrud.razor +++ b/Moonlight/Shared/Components/Forms/AutoCrud.razor @@ -1,61 +1,147 @@ @using BlazorTable @using Moonlight.App.Repositories +@using System.Linq.Expressions +@using Mappy.Net @typeparam TItem where TItem : class +@typeparam TCreateForm +@typeparam TUpdateForm @inject Repository ItemRepository +@inject ToastService ToastService

@(Title)

-
- + @ChildContent + + +
+ + + + + + + + + + + + + + + + + + + + + + @code { [Parameter] public string Title { get; set; } = ""; - [Parameter] - public Type CreateForm { get; set; } - - [Parameter] - public Type UpdateForm { get; set; } - [Parameter] public Func, TItem[]> Load { get; set; } - + [Parameter] public RenderFragment ChildContent { get; set; } + + [Parameter] + public Func? ValidateAdd { get; set; } + + [Parameter] + public Func? ValidateUpdate { get; set; } + + [Parameter] + public Func? ValidateDelete { get; set; } private TItem[] Items; + private TCreateForm CreateForm; + private TUpdateForm UpdateForm; + private TItem ItemToUpdate; + private TItem ItemToDelete; + + private SmartModal CreateModal; + private SmartModal UpdateModal; + private SmartModal DeleteModal; + + private Expression> IdExpression; + private LazyLoader LazyLoader; protected override void OnInitialized() { - if (CreateForm == null) - throw new ArgumentNullException(nameof(CreateForm)); - - if (UpdateForm == null) - throw new ArgumentNullException(nameof(UpdateForm)); - if (Load == null) throw new ArgumentNullException(nameof(Load)); + + CreateForm = Activator.CreateInstance()!; + UpdateForm = Activator.CreateInstance()!; + + IdExpression = CreateExpression(); } private Task LoadItems(LazyLoader _) @@ -64,4 +150,86 @@ return Task.CompletedTask; } + + private async Task StartUpdate(TItem item) + { + UpdateForm = Mapper.Map(item); + ItemToUpdate = item; + await UpdateModal.Show(); + } + + private async Task FinishUpdate() + { + var item = Mapper.Map(ItemToUpdate, UpdateForm!); + + if (ValidateUpdate != null) // Optional additional validation + await ValidateUpdate.Invoke(item); + + ItemRepository.Update(item); + + // Reset + await UpdateModal.Hide(); + await LazyLoader.Reload(); + await ToastService.Success("Successfully updated item"); + } + + private async Task StartCreate() + { + CreateForm = Activator.CreateInstance()!; + await CreateModal.Show(); + } + + private async Task FinishCreate() + { + var item = Mapper.Map(CreateForm!); + + if (ValidateAdd != null) // Optional additional validation + await ValidateAdd.Invoke(item); + + ItemRepository.Add(item); + + // Reset + await CreateModal.Hide(); + await LazyLoader.Reload(); + await ToastService.Success("Successfully added item"); + } + + private async Task StartDelete(TItem item) + { + ItemToDelete = item; + await DeleteModal.Show(); + } + + private async Task FinishDelete() + { + if (ValidateDelete != null) // Optional additional validation + await ValidateDelete.Invoke(ItemToDelete); + + ItemRepository.Delete(ItemToDelete); + + // Reset + await DeleteModal.Hide(); + await LazyLoader.Reload(); + await ToastService.Success("Successfully deleted item"); + } + + private Expression> CreateExpression() + { + // Parameter expression for the input object + var inputParam = Expression.Parameter(typeof(TItem), "input"); + + // Convert the input object to the actual model type (MyModel in this example) + var castedInput = Expression.Convert(inputParam, typeof(TItem)); + + // Create a property access expression using the property name + var propertyAccess = Expression.Property(castedInput, "Id"); + + // Convert the property value to an object + var castedResult = Expression.Convert(propertyAccess, typeof(object)); + + // Create a lambda expression + var lambda = Expression.Lambda>(castedResult, inputParam); + + return lambda; + } } \ No newline at end of file diff --git a/Moonlight/Shared/Components/Modals/Store/AddCouponModal.razor b/Moonlight/Shared/Components/Modals/Store/AddCouponModal.razor index f1c0ca34..69b280ad 100644 --- a/Moonlight/Shared/Components/Modals/Store/AddCouponModal.razor +++ b/Moonlight/Shared/Components/Modals/Store/AddCouponModal.razor @@ -2,6 +2,7 @@ @using Moonlight.App.Repositories @using Moonlight.App.Database.Entities.Store @using Mappy.Net +@using Moonlight.App.Models.Forms.Admin.Store @inject Repository CouponRepository @inject ToastService ToastService diff --git a/Moonlight/Shared/Views/Account/Payments.razor b/Moonlight/Shared/Views/Account/Payments.razor index 73facb35..ba008779 100644 --- a/Moonlight/Shared/Views/Account/Payments.razor +++ b/Moonlight/Shared/Views/Account/Payments.razor @@ -117,7 +117,10 @@ await StoreService.Gift.Redeem(IdentityService.CurrentUser, GiftCode); + // Reset GiftCode = ""; + await InvokeAsync(StateHasChanged); + await ToastService.Success("Successfully applied gift code"); await LazyLoader.Reload(); } diff --git a/Moonlight/Shared/Views/Admin/Store/Coupons.razor b/Moonlight/Shared/Views/Admin/Store/Coupons.razor index 27d2bb58..aebcee81 100644 --- a/Moonlight/Shared/Views/Admin/Store/Coupons.razor +++ b/Moonlight/Shared/Views/Admin/Store/Coupons.razor @@ -1,70 +1,43 @@ @page "/admin/store/coupons" -@using BlazorTable @using Moonlight.App.Database.Entities.Store @using Moonlight.App.Repositories -@using Moonlight.Shared.Components.Modals.Store +@using BlazorTable +@using Moonlight.App.Models.Forms.Admin.Store @inject Repository CouponRepository -@inject Repository CouponUseRepository -@inject ToastService ToastService - + -
-
-

Coupons

-
- -
-
-
- - - - - - - - - -
-
-
+
+ + + + + +
- - @code { - private Coupon[] AllCoupons; - - private LazyLoader LazyLoader; - private AddCouponModal AddCouponModal; - - private Task Load(LazyLoader _) + private Coupon[] LoadData(Repository repository) { - AllCoupons = CouponRepository + return repository .Get() .ToArray(); - + } + + private Task Validate(Coupon coupon) + { + if (CouponRepository.Get().Any(x => x.Code == coupon.Code && x.Id != coupon.Id)) + throw new DisplayException("A coupon with that code does already exist"); + return Task.CompletedTask; } - - private async Task Remove(Coupon coupon) - { - if (CouponUseRepository.Get().Any(x => x.Coupon.Id == coupon.Id)) - throw new DisplayException("The coupon has been used so it cannot be deleted"); - - CouponRepository.Delete(coupon); - - await ToastService.Success("Successfully deleted coupon"); - await LazyLoader.Reload(); - } -} +} \ No newline at end of file diff --git a/Moonlight/Shared/Views/Admin/Store/Gifts.razor b/Moonlight/Shared/Views/Admin/Store/Gifts.razor index 9cdb986c..288823dd 100644 --- a/Moonlight/Shared/Views/Admin/Store/Gifts.razor +++ b/Moonlight/Shared/Views/Admin/Store/Gifts.razor @@ -1,3 +1,41 @@ @page "/admin/store/gifts" - \ No newline at end of file +@using Moonlight.App.Database.Entities.Store +@using Moonlight.App.Models.Forms.Admin.Store +@using Moonlight.App.Repositories +@using BlazorTable + +@inject Repository GiftCodeRepository + + + +
+ + + + + +
+ +@code +{ + private GiftCode[] LoadData(Repository repository) + { + return repository + .Get() + .ToArray(); + } + + private Task Validate(GiftCode giftCode) + { + if (GiftCodeRepository.Get().Any(x => x.Code == giftCode.Code && x.Id != giftCode.Id)) + throw new DisplayException("A gift code with that code does already exist"); + + return Task.CompletedTask; + } +} \ No newline at end of file