Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add purchase datagrid and fetch purchases from db #44

Merged
merged 6 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 All @@ -144,7 +147,7 @@
{
UserGroupDict.Add(group, item.AllowedUserGroups.Contains(group));
}
FocusFirst();

Check warning on line 150 in Shifty.App/Components/ProductManager.razor

View workflow job for this annotation

GitHub Actions / build / Build webapp / Build and test Webapp

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 150 in Shifty.App/Components/ProductManager.razor

View workflow job for this annotation

GitHub Actions / build / Build webapp / Build and test Webapp

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

Check warning on line 150 in Shifty.App/Components/ProductManager.razor

View workflow job for this annotation

GitHub Actions / build / Build webapp / Build and test Webapp

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
}

private bool _loading = true;
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>
fredpetersen marked this conversation as resolved.
Show resolved Hide resolved
</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 / build / 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 / build / 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 / build / 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
Loading