Skip to content

Commit 414325f

Browse files
committed
Improved the design of PortfolioEntryDetail.razor page
Added and improved formatting methods in CurrencyUtils.cs and DecimalUtils.cs
1 parent bd7c697 commit 414325f

File tree

4 files changed

+93
-20
lines changed

4 files changed

+93
-20
lines changed

Utils/CurrencyUtils.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static string GetCurrencyLabel(Currency currency)
2424

2525
public static string Format(decimal value, Currency currency)
2626
{
27-
var valueStr = String.Format("{0:0.00}", Math.Abs(value));
27+
var valueStr = DecimalUtils.FormatTwoDecimalPlaces(Math.Abs(value));
2828
var output = "";
2929
switch (currency)
3030
{
@@ -49,5 +49,8 @@ public static string Format(decimal value, Currency currency)
4949

5050
return output;
5151
}
52+
53+
public static string FormatWithPlusSign(decimal value, Currency currency) =>
54+
(value > 0 ? "+" : "") + Format(value, currency);
5255
}
5356
}

Utils/DecimalUtils.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
using System;
2+
using System.Globalization;
23

34
namespace Utils
45
{
56
public static class DecimalUtils
67
{
7-
public static string FormatTwoDecimalPlaces(decimal value) => String.Format("{0:0.00}", Math.Abs(value));
8+
private static NumberFormatInfo whitespaceSeparatorNfi = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
9+
static DecimalUtils()
10+
{
11+
whitespaceSeparatorNfi.NumberGroupSeparator = " ";
12+
}
13+
14+
public static string FormatTrimZeros(decimal value) => value.ToString("#,0.#############", whitespaceSeparatorNfi);
15+
16+
public static string FormatTwoDecimalPlaces(decimal value) => value.ToString("#,0.00", whitespaceSeparatorNfi);
17+
18+
public static string FormatFiveDecimalPlaces(decimal value) => value.ToString("#,0.00000", whitespaceSeparatorNfi);
19+
20+
public static string FormatTwoDecimalPlacesWithPlusSign(decimal value) =>
21+
(value > 0 ? "+" : "") + FormatTwoDecimalPlaces(value);
822
}
923
}

WebFrontend/Pages/PortfolioEntryDetail.razor

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@using CryptoStatsSource.model
77
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
88
@inject IMatDialogService MatDialogService
9+
@inject IMatToaster Toaster
910
@inject IPortfolioService PortfolioService
1011
@inject IPortfolioEntryService PortfolioEntryService
1112
@inject IMarketOrderService MarketOrderService
@@ -71,23 +72,40 @@
7172
</div>
7273

7374
<MatBody2 class="demo-mat-card-content clear-margin">
74-
<div class="mat-layout-grid">
75-
<div class="mat-layout-grid-inner" style="align-items: center">
76-
@if (entrySummary != null)
77-
{
78-
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6">
79-
<MatH4 Class="clear-margin">@(CurrencyUtils.Format(entrySummary.MarketValue, ActivePortfolio.Currency))</MatH4>
75+
@if (EntrySummary != null)
76+
{
77+
<div class="mat-layout-grid">
78+
<div class="mat-layout-grid-inner" style="align-items: center">
79+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4">
80+
<LabelDecimalValue Value="@(CurrencyUtils.Format(EntrySummary.MarketValue, ActivePortfolio.Currency))" Label="Market Value"></LabelDecimalValue>
8081
</div>
81-
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6" style="text-align: end">
82-
@(entrySummary.RelativeChange * 100m) %
82+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4">
83+
<LabelDecimalValue Value="@(DecimalUtils.FormatTrimZeros(TotalHoldings))" Label="Holdings"></LabelDecimalValue>
8384
</div>
84-
}
85-
else
86-
{
87-
<MatProgressCircle Indeterminate="true"/>
88-
}
85+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4" style="text-align: end">
86+
<LabelDecimalValue Positive="@(EntrySummary.AbsoluteChange >= 0)" ValueColorBasedOnValue="true" Value="@(CurrencyUtils.FormatWithPlusSign(EntrySummary.AbsoluteChange, ActivePortfolio.Currency))" Label="Profit/Loss"></LabelDecimalValue>
87+
</div>
88+
</div>
8989
</div>
90-
</div>
90+
<div class="mat-layout-grid">
91+
<div class="mat-layout-grid-inner" style="align-items: center">
92+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4">
93+
<LabelDecimalValue Value="@(CurrencyUtils.Format(EntrySummary.Cost, ActivePortfolio.Currency))" Label="Net Cost"></LabelDecimalValue>
94+
</div>
95+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4">
96+
<LabelDecimalValue Value="@(CurrencyUtils.Format(TotalHoldings > 0 ? (EntrySummary.Cost / TotalHoldings) : 0, ActivePortfolio.Currency))" Label="Avg Net Cost"></LabelDecimalValue>
97+
</div>
98+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-4" style="text-align: end">
99+
<LabelDecimalValue Positive="@(EntrySummary.RelativeChange >= 0)" ValueColorBasedOnValue="true" Value="@(DecimalUtils.FormatTwoDecimalPlacesWithPlusSign(EntrySummary.RelativeChange * 100) + "%")" Label="Percent Change"></LabelDecimalValue>
100+
</div>
101+
</div>
102+
</div>
103+
}
104+
else
105+
{
106+
<MatProgressCircle Indeterminate="true"/>
107+
}
108+
91109
</MatBody2>
92110
}
93111
else
@@ -125,7 +143,7 @@
125143
</td>
126144
<td>@CurrencyUtils.Format(context.Item2.MarketValue, ActivePortfolio.Currency)</td>
127145
<td style='color: @(context.Item2.RelativeChange >= 0 ? "#17a104" : "#FF0000")'>
128-
<div style="min-width: 9rem">@CurrencyUtils.Format(context.Item2.AbsoluteChange, ActivePortfolio.Currency) (@(context.Item2.RelativeChange * 100)%)</div>
146+
<div style="min-width: 9rem">@CurrencyUtils.Format(context.Item2.AbsoluteChange, ActivePortfolio.Currency) (@(DecimalUtils.FormatTwoDecimalPlaces(context.Item2.RelativeChange * 100))%)</div>
129147
</td>
130148
<td>@CurrencyUtils.Format(context.Item2.Cost, ActivePortfolio.Currency)</td>
131149
<td>@CurrencyUtils.Format(context.Item1.Fee, ActivePortfolio.Currency)</td>
@@ -152,7 +170,8 @@
152170
protected PortfolioEntry ActivePortfolioEntry;
153171
protected MarketEntry CurrentEntryAssetMarketEntry;
154172
protected string portfolioEntryName = "Bitcoin";
155-
protected ISummaryService.Summary entrySummary = new(523m, 0.719m, 1268.89m, 745.58m);
173+
protected ISummaryService.Summary EntrySummary = new(523m, 0.719m, 1268.89m, 745.58m);
174+
protected decimal TotalHoldings = 0;
156175

157176
protected List<Tuple<MarketOrder, ISummaryService.Summary>> tableRowsItems = new()
158177
{
@@ -184,7 +203,7 @@
184203
{
185204
CurrentEntryAssetMarketEntry = null;
186205
tableRowsItems = null;
187-
entrySummary = null;
206+
EntrySummary = null;
188207
StateHasChanged();
189208
}
190209

@@ -205,12 +224,14 @@
205224
var entrySummaries = entryOrders.Select(order =>
206225
SummaryService.GetMarketOrderSummary(order, CurrentEntryAssetMarketEntry.CurrentPrice));
207226

227+
TotalHoldings = entryOrders.Sum(order => order.Size * (order.Buy ? 1 : -1));
228+
208229
// zip entry orders and summaries into a table rows
209230
tableRowsItems = entryOrders.Zip(entrySummaries)
210231
.Select(tuple => new Tuple<MarketOrder, ISummaryService.Summary>(tuple.First, tuple.Second)).ToList();
211232

212233
// compute suummary of this entry
213-
entrySummary = SummaryService.GetPortfolioEntrySummary(entryOrders, CurrentEntryAssetMarketEntry.CurrentPrice);
234+
EntrySummary = SummaryService.GetPortfolioEntrySummary(entryOrders, CurrentEntryAssetMarketEntry.CurrentPrice);
214235
}
215236

216237
public void EditMarketOrder(MouseEventArgs e)
@@ -227,6 +248,7 @@
227248
SetEntryLoading();
228249
await UpdateEntrySummary();
229250
StateHasChanged();
251+
Toaster.Add("Order successfully deleted", MatToastType.Success, "", "");
230252
}
231253
}
232254
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<style>
2+
.no-margin {
3+
margin: 0;
4+
}
5+
6+
.label {
7+
color: #6f6f6f;
8+
letter-spacing: 0.1rem;
9+
font-size: 1.1em;
10+
text-transform: uppercase;
11+
}
12+
13+
.value {
14+
margin-top: 1rem;
15+
}
16+
</style>
17+
<span Class="no-margin label">@Label</span>
18+
<MatH4 Class="no-margin value" style="@(ValueColorBasedOnValue ? !Positive ? "color:red" : "color: #17a104" : "")">@Value</MatH4>
19+
20+
@code {
21+
22+
[Parameter]
23+
public String Value { get; set; }
24+
25+
[Parameter]
26+
public String Label { get; set; }
27+
28+
[Parameter]
29+
public bool ValueColorBasedOnValue { get; set; } = false;
30+
31+
[Parameter]
32+
public bool Positive { get; set; } = true;
33+
34+
}

0 commit comments

Comments
 (0)