Skip to content

Commit

Permalink
Add purchase datagrid and fetch purchases from db (#44)
Browse files Browse the repository at this point in the history
* Add purchase datagrid and fetch purchases from db

* Revert appsettings

* Oops i reverted the wrong appsettings

* PR comments

* Update apihost

* Remove cosole writeline
  • Loading branch information
fredpetersen authored Oct 22, 2024
1 parent 36ac002 commit 181b0bb
Show file tree
Hide file tree
Showing 11 changed files with 464 additions and 101 deletions.
199 changes: 101 additions & 98 deletions Shifty.App/Components/ProductManager.razor
Original file line number Diff line number Diff line change
Expand Up @@ -26,109 +26,112 @@
<LoadingIndicator Height="400px" />
</MudContainer>
}
<MudDataGrid
@ref="_dataGrid"
T="Product"
Items="@_products"
EditMode="DataGridEditMode.Form"
ReadOnly="false"
StartedEditingItem="@StartedEditingItem"
CanceledEditingItem="@CanceledEditingItem"
CommittedItemChanges="@CommittedItemChanges"
EditTrigger="DataGridEditTrigger.Manual"
QuickFilter="e => _showNonvisible || e.Visible"
RowStyleFunc="@RowStyleFunc"
FixedHeader="true"
Height="calc(100vh - 250px)"
Dense="true"
SortMode="MudBlazor.SortMode.None">
<Columns>
<TemplateColumn Title="Edit">
<CellTemplate>
<MudIconButton
Size="@Size.Medium"
Icon="@Icons.Material.Outlined.Edit"
Color="Color.Primary"
OnClick="@context.Actions.StartEditingItemAsync" />
</CellTemplate>
</TemplateColumn>
<PropertyColumn Property="x => x.Visible" Title="" InitialDirection="SortDirection.Descending">
<CellTemplate>
@{
if (context.Item.Visible)
{
<MudIcon Size="@Size.Small" Color="Color.Dark"
Icon="@Icons.Material.Filled.Visibility" />
}
else
{
<MudIcon Size="@Size.Small" Style="@($"color:{Colors.Grey.Default};")"
Icon="@Icons.Material.Filled.VisibilityOff" />
}
}
</CellTemplate>
<EditTemplate>
<MudSwitch id="first-edit-element" Label="Visible" Color="Color.Primary" @bind-Checked="context.Item.Visible" />
</EditTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.Id" Title="Id" IsEditable="false" />
<PropertyColumn Property="x => x.Name" Title="Name" IsEditable="true" />
<PropertyColumn Property="x => x.NumberOfTickets" Title="Tickets" IsEditable="true" />
<PropertyColumn Property="x => x.Price" Title="Price" IsEditable="true" />
<PropertyColumn Property='x => string.Join(", ", x.AllowedUserGroups.Select(e => e.ToString()))'
Title="User groups" IsEditable="true">
<EditTemplate>
<MudText Typo="Typo.subtitle1">Visible to:</MudText>
@foreach (var group in Enum.GetValues<UserGroup>())
{
<MudCheckBox Dense="true" Color="Color.Primary" @bind-Checked="UserGroupDict[group]" Value="@group">
@group</MudCheckBox>
}
</EditTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.IsPerk" Title="Perk?" IsEditable="false">
<CellTemplate>
@{
if (context.Item.IsPerk)
{
<MudIcon Style="color:gold;" Icon="@Icons.Material.Filled.Star" Title="IsPerk" />
else
{
<MudDataGrid
@ref="_dataGrid"
T="Product"
Items="@_products"
EditMode="DataGridEditMode.Form"
ReadOnly="false"
StartedEditingItem="@StartedEditingItem"
CanceledEditingItem="@CanceledEditingItem"
CommittedItemChanges="@CommittedItemChanges"
EditTrigger="DataGridEditTrigger.Manual"
QuickFilter="e => _showNonvisible || e.Visible"
RowStyleFunc="@RowStyleFunc"
FixedHeader="true"
Height="calc(100vh - 250px)"
Dense="true"
SortMode="MudBlazor.SortMode.None">
<Columns>
<TemplateColumn Title="Edit">
<CellTemplate>
<MudIconButton
Size="@Size.Medium"
Icon="@Icons.Material.Outlined.Edit"
Color="Color.Primary"
OnClick="@context.Actions.StartEditingItemAsync" />
</CellTemplate>
</TemplateColumn>
<PropertyColumn Property="x => x.Visible" Title="" InitialDirection="SortDirection.Descending">
<CellTemplate>
@{
if (context.Item.Visible)
{
<MudIcon Size="@Size.Small" Color="Color.Dark"
Icon="@Icons.Material.Filled.Visibility" />
}
else
{
<MudIcon Size="@Size.Small" Style="@($"color:{Colors.Grey.Default};")"
Icon="@Icons.Material.Filled.VisibilityOff" />
}
}
else
</CellTemplate>
<EditTemplate>
<MudSwitch id="first-edit-element" Label="Visible" Color="Color.Primary" @bind-Checked="context.Item.Visible" />
</EditTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.Id" Title="Id" IsEditable="false" />
<PropertyColumn Property="x => x.Name" Title="Name" IsEditable="true" />
<PropertyColumn Property="x => x.NumberOfTickets" Title="Tickets" IsEditable="true" />
<PropertyColumn Property="x => x.Price" Title="Price" IsEditable="true" />
<PropertyColumn Property='x => string.Join(", ", x.AllowedUserGroups.Select(e => e.ToString()))'
Title="User groups" IsEditable="true">
<EditTemplate>
<MudText Typo="Typo.subtitle1">Visible to:</MudText>
@foreach (var group in Enum.GetValues<UserGroup>())
{
<MudIcon Icon="@Icons.Material.Filled.StarOutline" Title="IsPerk" />
<MudCheckBox Dense="true" Color="Color.Primary" @bind-Checked="UserGroupDict[group]" Value="@group">
@group</MudCheckBox>
}
}
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.Description" Title="Description" IsEditable="true" />
<PropertyColumn Property="x => x.EligibleMenuItems" Title="Eligible menu items" IsEditable="true" Hidden>
<EditTemplate>
<MudComboBox
T="MenuItem"
Label="Eligible menu items"
MultiSelection="true"
Editable="true"
@bind-SelectedValues="context.Item.EligibleMenuItems">
@foreach (var mi in _allMenuItems)
{
<MudComboBoxItem Text="@mi.Name" Value="@mi">@mi.Name</MudComboBoxItem>
</EditTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.IsPerk" Title="Perk?" IsEditable="false">
<CellTemplate>
@{
if (context.Item.IsPerk)
{
<MudIcon Style="color:gold;" Icon="@Icons.Material.Filled.Star" Title="IsPerk" />
}
else
{
<MudIcon Icon="@Icons.Material.Filled.StarOutline" Title="IsPerk" />
}
}
</MudComboBox>
</EditTemplate>
</PropertyColumn>
</Columns>
</MudDataGrid>
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.Description" Title="Description" IsEditable="true" />
<PropertyColumn Property="x => x.EligibleMenuItems" Title="Eligible menu items" IsEditable="true" Hidden>
<EditTemplate>
<MudComboBox
T="MenuItem"
Label="Eligible menu items"
MultiSelection="true"
Editable="true"
@bind-SelectedValues="context.Item.EligibleMenuItems">
@foreach (var mi in _allMenuItems)
{
<MudComboBoxItem Text="@mi.Name" Value="@mi">@mi.Name</MudComboBoxItem>
}
</MudComboBox>
</EditTemplate>
</PropertyColumn>
</Columns>
</MudDataGrid>

<MudToolBar>
<MudSpacer />
<MudButton
Color="Color.Primary"
Variant="Variant.Filled"
EndIcon="@Icons.Material.Outlined.Add"
OnClick="@AddItemToDataGrid">
Add Product
</MudButton>
</MudToolBar>
<MudToolBar>
<MudSpacer />
<MudButton
Color="Color.Primary"
Variant="Variant.Filled"
EndIcon="@Icons.Material.Outlined.Add"
OnClick="@AddItemToDataGrid">
Add Product
</MudButton>
</MudToolBar>
}
</MudPaper>
@code
{
Expand Down
103 changes: 103 additions & 0 deletions Shifty.App/Components/Refunds.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
@namespace Components
@using System.ComponentModel.DataAnnotations
@using MudExtensions
@using Shifty.App.Services
@using Shifty.Api.Generated.AnalogCoreV1
@using Shifty.Api.Generated.AnalogCoreV2
@using Shared
@using LanguageExt.UnsafeValueAccess
@using Components
@using Shifty.App.DomainModels
@using System.Collections.ObjectModel
@inject IPurchaseService PurchaseService
@inject ISnackbar Snackbar

<MudPaper Elevation="15" Style="border-radius: 5px; width:fit-content; min-width: 500px; margin:2rem auto">
@if(_purchasesFetched)
{
<MudIconButton Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Primary" OnClick="@(() => _purchasesFetched = false)" />
<MudDataGrid
T="Purchase"
Items="@_purchases"
ReadOnly="true"
FixedHeader="true"
Height="calc(100vh - 250px)"
SortMode="MudBlazor.SortMode.None"
Style="width: 70vw;padding: 1rem"
>
<Columns>
<PropertyColumn Property="x => x.Id" Title="Id" />
<PropertyColumn Property="x => x.DateCreated" Title="Date" />
<PropertyColumn Property="x => x.ProductName" Title="Name" />
<PropertyColumn Property="x => x.NumberOfTickets" Title="Tickets" />
<PropertyColumn Property="x => x.Price" Title="Price" />
<PropertyColumn Property="x => x.PurchaseStatus" Title="Status" >
<CellTemplate>
@{
if(@context.Item.PurchaseStatus == PurchaseStatus.Completed)
{
<MudButton Size="@Size.Small" Color="Color.Primary" Variant="Variant.Filled" OnClick="@(() => RefundPurchase(context.Item))">
Refund
</MudButton>
}
else
{
<MudText>@context.Item.PurchaseStatus</MudText>
}
}
</CellTemplate>
</PropertyColumn>
</Columns>
</MudDataGrid>
}
else
{
<MudContainer Style="padding: 2rem; display: flex; flex-direction: column; justify-content: center;">
<MudText Style="padding: 0.5rem;">Find purchases for user</MudText>
<MudTextField Immediate="true" OnKeyDown="OnKeyDown" @bind-Value="UserId" Label="User ID" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Secondary"></MudTextField>
</MudContainer>
}
</MudPaper>

@code {
private int UserId;
private bool _loading = true;

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / dev-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / dev-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / dev-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / prd-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / prd-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used

Check warning on line 64 in Shifty.App/Components/Refunds.razor

View workflow job for this annotation

GitHub Actions / prd-deploy / Build codebase / Build webapp / Build and test Webapp

The field 'Refunds._loading' is assigned but its value is never used
private bool _purchasesFetched = false;
private List<Purchase> _purchases;

private async Task GetPurchases()
{
var result = await PurchaseService.GetPurchases(UserId);
result.Match(
purchases =>
{
_purchases = purchases.OrderByDescending(x => x.DateCreated).ToList();
_purchasesFetched = true;
},
error => Snackbar.Add(error.Message, Severity.Error)
);
_loading = false;
}

async void OnKeyDown(KeyboardEventArgs args)
{
if (args.Key=="Enter")
{
_loading = true;
await GetPurchases();
StateHasChanged();
}

}

private async Task RefundPurchase(Purchase purchase)
{
var result = await PurchaseService.RefundPurchase(purchase.Id);
result.Match(
_ => Snackbar.Add("Purchase refunded", Severity.Success),
error => Snackbar.Add(error.Message, Severity.Error)
);
_loading = true;
await GetPurchases();
}
}
33 changes: 33 additions & 0 deletions Shifty.App/DomainModels/Purchase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using Microsoft.VisualBasic;
using Shifty.Api.Generated.AnalogCoreV1;
using Shifty.Api.Generated.AnalogCoreV2;

namespace Shifty.App.DomainModels
{
public record Purchase {
public int Id { get; init; }
public int NumberOfTickets { get; set; }
public int Price { get; set; }
public string ProductName { get; set; }
public int ProductId { get; set; }
public PurchaseStatus PurchaseStatus { get; set; }

public DateTimeOffset DateCreated { get; set; }

public static Purchase FromDto(SimplePurchaseResponse dto)
{
return new Purchase()
{
Id = dto.Id,
DateCreated = dto.DateCreated,
NumberOfTickets = dto.NumberOfTickets,
Price = dto.TotalAmount,
PurchaseStatus = dto.PurchaseStatus,
ProductName = dto.ProductName,
ProductId = dto.ProductId
};
}

}
}
24 changes: 24 additions & 0 deletions Shifty.App/Pages/Refund.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@page "/Refunds"
@using Components
@inject NavigationManager NavManager

@if (_user is not null && _user.IsInRole("Board"))
{
<Refunds />
}

@code {
[CascadingParameter] public Task<AuthenticationState> AuthTask { get; set; }
private System.Security.Claims.ClaimsPrincipal _user;

protected override async Task OnInitializedAsync()
{
var authState = await AuthTask;
_user = authState.User;

if (_user is null || !_user.IsInRole("Board"))
{
NavManager.NavigateTo("/");
}
}
}
2 changes: 2 additions & 0 deletions Shifty.App/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ public static void ConfigureServices(IServiceCollection services, IConfiguration
services.AddScoped<IAccountRepository, AccountRepository>();
services.AddScoped<IVoucherRepository, VoucherRepository>();
services.AddScoped<IProductRepository, ProductRepository>();
services.AddScoped<IPurchaseRepository, PurchaseRepository>();
services.AddScoped<IMenuItemRepository, MenuItemRepository>();
services.AddScoped<IUnusedTicketRepository, UnusedTicketRepository>();
services.AddScoped<CustomAuthStateProvider>();
services.AddScoped<AuthenticationStateProvider>(s => s.GetService<CustomAuthStateProvider>());
services.AddScoped<IAuthenticationService, AuthenticationService>();
services.AddScoped<IVoucherService, VoucherService>();
services.AddScoped<IProductService, ProductService>();
services.AddScoped<IPurchaseService, PurchaseService>();
services.AddScoped<IMenuItemService, MenuItemService>();
services.AddScoped<IUserService, UserService>();
services.AddScoped<IMenuItemService, MenuItemService>();
Expand Down
Loading

0 comments on commit 181b0bb

Please sign in to comment.