Skip to content

Commit 880e125

Browse files
committed
Fixed incorrect PortfolioEntryRow attributes starting letters.
Implemented dynamic parts of the PortfolioEntryDetail.razor page.
1 parent 1d27200 commit 880e125

File tree

2 files changed

+140
-62
lines changed

2 files changed

+140
-62
lines changed

WebFrontend/Pages/PortfolioDetail.razor

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@
8383
<th>Holdings</th>
8484
</MatTableHeader>
8585
<MatTableRow>
86-
<td>@context.symbol.ToUpper()</td>
87-
<td>@(CurrencyUtils.Format(context.currentPrice, ActivePortfolio.Currency))</td>
88-
<td style='color: @(context.relativeChange >= 0 ? "#17a104" : "#FF0000")'>@DecimalUtils.FormatTwoDecimalPlaces(context.relativeChange)%</td>
89-
<td>@context.percentage%</td>
86+
<td>@context.Symbol.ToUpper()</td>
87+
<td>@(CurrencyUtils.Format(context.CurrentPrice, ActivePortfolio.Currency))</td>
88+
<td style='color: @(context.RelativeChange >= 0 ? "#17a104" : "#FF0000")'>@DecimalUtils.FormatTwoDecimalPlaces(context.RelativeChange)%</td>
89+
<td>@context.Percentage%</td>
9090
</MatTableRow>
9191
</MatTable>
9292
}
@@ -119,7 +119,7 @@
119119

120120
protected List<PortfolioEntryRow> PortfolioEntryRows;
121121

122-
protected record PortfolioEntryRow(string symbol, decimal currentPrice, decimal relativeChange, decimal percentage);
122+
protected record PortfolioEntryRow(string Symbol, decimal CurrentPrice, decimal RelativeChange, decimal Percentage, int EntryId);
123123

124124
protected override void OnInitialized()
125125
{
@@ -132,7 +132,10 @@
132132
private async void _loadEntryInfo()
133133
{
134134
// resolve names of all portfolio entries
135-
var portfolioEntriesNames = await Task.WhenAll(ActivePortfolioEntries.Select(async entry => (await CryptoNameResolver.Resolve(entry.Symbol)).ToLower()));
135+
var portfolioEntriesNames = await Task.WhenAll(
136+
ActivePortfolioEntries.Select(
137+
async entry => (await CryptoNameResolver.Resolve(entry.Symbol)).ToLower())
138+
);
136139

137140
// fetch market entries of all entries of the portfolio
138141
var marketEntries = await CryptoStatsSource.GetMarketEntries(
@@ -186,7 +189,10 @@
186189
// asset's price change since the last 24h
187190
new decimal(symbolsToMarketEntries[tuple.Second.Symbol].PriceChangePercentage24H),
188191
// percentage within the portfolio
189-
portfolioTotalMarketValue > 0 ? (tuple.First.MarketValue / portfolioTotalMarketValue) * 100 : 0)
192+
portfolioTotalMarketValue > 0 ? (tuple.First.MarketValue / portfolioTotalMarketValue) * 100 : 0,
193+
// pass the entry id
194+
tuple.Second.Id
195+
)
190196
).ToList();
191197

192198
StateHasChanged();
@@ -196,7 +202,7 @@
196202
{
197203
if (row != null)
198204
{
199-
NavigationManager.NavigateTo($"entrydetail");
205+
NavigationManager.NavigateTo($"entrydetail/{((PortfolioEntryRow) row).EntryId}");
200206
}
201207
}
202208

WebFrontend/Pages/PortfolioEntryDetail.razor

Lines changed: 126 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
@page "/entrydetail"
1+
@page "/entrydetail/{entryId:int}"
22
@using Model
33
@using Services
44
@using Utils
5+
@using CryptoStatsSource
6+
@using CryptoStatsSource.model
57
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
68
@inject IMatDialogService MatDialogService
9+
@inject IPortfolioService PortfolioService
10+
@inject IPortfolioEntryService PortfolioEntryService
11+
@inject IMarketOrderService MarketOrderService
12+
@inject ICryptoNameResolver CryptoNameResolver
13+
@inject ICryptoStatsSource CryptoStatsSource
14+
@inject ISummaryService SummaryService
715

816
<style>
917
.demo-mat-card {
@@ -33,62 +41,94 @@
3341
<div class="mat-layout-grid-inner center">
3442
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-2"></div>
3543
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-8">
36-
<MatButton Outlined="true" Icon="keyboard_arrow_left" Style="margin-bottom: 1rem;" OnClick='() => { NavigationManager.NavigateTo($"/portfolios/{activePortfolio.Id}"); }'>Back</MatButton>
44+
<MatButton Outlined="true" Icon="keyboard_arrow_left" Style="margin-bottom: 1rem;" OnClick='() => { NavigationManager.NavigateTo($"/portfolios/{ActivePortfolio.Id}"); }'>Back</MatButton>
3745
<MatCard class="demo-mat-card">
3846
<MatCardContent>
39-
<div class="demo-mat-card-content">
40-
<MatHeadline6 class="clear-margin">
41-
<MatChipSet Style="align-items: center">
42-
<MatH5 Class="clear-margin-vertical">@portfolioEntryName</MatH5>
43-
<MatChip Style="vertical-align: center" Label="@(activePortfolioEntry.Symbol.ToUpper())"/>
44-
<MatH6 Class="clear-margin-vertical" Style="text-align: end;float: end;">1 BTC = $30 000</MatH6>
45-
</MatChipSet>
46-
</MatHeadline6>
47-
</div>
47+
@if(ActivePortfolioEntry != null)
48+
{
49+
<div class="demo-mat-card-content">
50+
<MatHeadline6 class="clear-margin">
51+
<MatChipSet Style="align-items: center">
52+
@if (portfolioEntryName != null)
53+
{
54+
<MatH5 Class="clear-margin-vertical">@portfolioEntryName</MatH5>
55+
}
56+
else
57+
{
58+
<MatProgressCircle Indeterminate="true"/>
59+
}
60+
<MatChip Style="vertical-align: center" Label="@(CurrencyUtils.GetCurrencyLabel(ActivePortfolio.Currency))"/>
61+
@if (CurrentEntryAssetMarketEntry != null)
62+
{
63+
<MatH6 Class="clear-margin-vertical" Style="text-align: end;float: end;">1 @ActivePortfolioEntry.Symbol.ToUpper() = @CurrencyUtils.Format(CurrentEntryAssetMarketEntry.CurrentPrice, ActivePortfolio.Currency)</MatH6>
64+
}
65+
else
66+
{
67+
<MatProgressCircle Indeterminate="true"></MatProgressCircle>
68+
}
69+
</MatChipSet>
70+
</MatHeadline6>
71+
</div>
4872

49-
<MatBody2 class="demo-mat-card-content clear-margin">
50-
<div class="mat-layout-grid">
51-
<div class="mat-layout-grid-inner" style="align-items: center">
52-
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6">
53-
<MatH4 Class="clear-margin">@(CurrencyUtils.Format(entrySummary.MarketValue, activePortfolio.Currency))</MatH4>
54-
</div>
55-
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6" style="text-align: end">
56-
@(entrySummary.RelativeChange * 100m) %
73+
<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+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6">
77+
<MatH4 Class="clear-margin">@(CurrencyUtils.Format(entrySummary.MarketValue, ActivePortfolio.Currency))</MatH4>
78+
</div>
79+
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6" style="text-align: end">
80+
@(entrySummary.RelativeChange * 100m) %
81+
</div>
5782
</div>
5883
</div>
59-
</div>
60-
</MatBody2>
84+
</MatBody2>
85+
}
86+
else
87+
{
88+
<MatProgressBar Indeterminate="true"/>
89+
}
6190
</MatCardContent>
6291
</MatCard>
63-
<MatTable Items="@tableRowsItems" Striped="true" AllowSelection="true" RowClass="tester" class="mat-elevation-z5" ShowPaging="false" PageSize="9999">
64-
<MatTableHeader>
65-
<th>Date</th>
66-
<th>Size</th>
67-
<th>Market Value</th>
68-
<th>Change</th>
69-
<th>Cost</th>
70-
<th>Fee</th>
71-
<th>Actions</th>
72-
</MatTableHeader>
73-
<MatTableRow>
74-
<td>
75-
<div style="min-width: 9rem">@(String.Format("{0:d.M.yyyy HH:mm:ss}", context.Item1.Date))</div>
76-
</td>
77-
<td>
78-
<div style="min-width: 9rem">@context.Item1.Size @activePortfolioEntry.Symbol.ToUpper()</div>
79-
</td>
80-
<td>@CurrencyUtils.Format(context.Item2.MarketValue, activePortfolio.Currency)</td>
81-
<td style='color: @(context.Item2.RelativeChange >= 0 ? "#17a104" : "#FF0000")'>
82-
<div style="min-width: 9rem">@CurrencyUtils.Format(context.Item2.AbsoluteChange, activePortfolio.Currency) (@(context.Item2.RelativeChange * 100)%)</div>
83-
</td>
84-
<td>@CurrencyUtils.Format(context.Item2.Cost, activePortfolio.Currency)</td>
85-
<td>@CurrencyUtils.Format(context.Item1.Fee, activePortfolio.Currency)</td>
86-
<td>
87-
<MatIconButton Icon="edit" OnClick="EditMarketOrder"></MatIconButton>
88-
<MatIconButton Icon="delete" OnClick="DeletePortfolio"></MatIconButton>
89-
</td>
90-
</MatTableRow>
91-
</MatTable>
92+
@if (tableRowsItems == null)
93+
{
94+
<MatProgressBar Indeterminate="true"></MatProgressBar>
95+
}
96+
else if (tableRowsItems.Count == 0)
97+
{
98+
<MatH6>No entries found...</MatH6>
99+
}
100+
else
101+
{
102+
<MatTable Items="@tableRowsItems" Striped="true" AllowSelection="true" RowClass="tester" class="mat-elevation-z5" ShowPaging="false" PageSize="9999">
103+
<MatTableHeader>
104+
<th>Date</th>
105+
<th>Size</th>
106+
<th>Market Value</th>
107+
<th>Change</th>
108+
<th>Cost</th>
109+
<th>Fee</th>
110+
<th>Actions</th>
111+
</MatTableHeader>
112+
<MatTableRow>
113+
<td>
114+
<div style="min-width: 9rem">@(String.Format("{0:d.M.yyyy HH:mm:ss}", context.Item1.Date))</div>
115+
</td>
116+
<td>
117+
<div style="min-width: 9rem">@context.Item1.Size @ActivePortfolioEntry.Symbol.ToUpper()</div>
118+
</td>
119+
<td>@CurrencyUtils.Format(context.Item2.MarketValue, ActivePortfolio.Currency)</td>
120+
<td style='color: @(context.Item2.RelativeChange >= 0 ? "#17a104" : "#FF0000")'>
121+
<div style="min-width: 9rem">@CurrencyUtils.Format(context.Item2.AbsoluteChange, ActivePortfolio.Currency) (@(context.Item2.RelativeChange * 100)%)</div>
122+
</td>
123+
<td>@CurrencyUtils.Format(context.Item2.Cost, ActivePortfolio.Currency)</td>
124+
<td>@CurrencyUtils.Format(context.Item1.Fee, ActivePortfolio.Currency)</td>
125+
<td>
126+
<MatIconButton Icon="edit" OnClick="EditMarketOrder"></MatIconButton>
127+
<MatIconButton Icon="delete" OnClick="DeletePortfolio"></MatIconButton>
128+
</td>
129+
</MatTableRow>
130+
</MatTable>
131+
}
92132
</div>
93133
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-2"></div>
94134
</div>
@@ -98,8 +138,12 @@
98138

99139
@code
100140
{
101-
protected Portfolio activePortfolio = new Portfolio("Main Portfolio", "My main portfolio to be used", Currency.Usd);
102-
protected PortfolioEntry activePortfolioEntry = new("btc");
141+
[Parameter]
142+
public int EntryId { get; set; }
143+
144+
protected Portfolio ActivePortfolio;
145+
protected PortfolioEntry ActivePortfolioEntry;
146+
protected MarketEntry CurrentEntryAssetMarketEntry;
103147
protected string portfolioEntryName = "Bitcoin";
104148
protected ISummaryService.Summary entrySummary = new(523m, 0.719m, 1268.89m, 745.58m);
105149

@@ -111,11 +155,39 @@
111155
new Tuple<MarketOrder, ISummaryService.Summary>(new(18300m, 0.1m, 0.003266m, DateTime.Now.AddMonths(-6), false), new(-60m, -0.6m, 40.00m, 100m)),
112156
};
113157

114-
protected record PortfolioEntryRow(string symbol, decimal currentPrice, decimal relativeChange, decimal percentage);
158+
159+
protected override void OnInitialized()
160+
{
161+
// get the portfolio entry
162+
ActivePortfolioEntry = PortfolioEntryService.GetPortfolioEntry(EntryId);
163+
164+
// get the entry's portfolio
165+
ActivePortfolio = PortfolioService.GetPortfolio(ActivePortfolioEntry.PortfolioId);
166+
}
115167

116168
protected override async Task OnInitializedAsync()
117169
{
118-
//_existingPortfolios = PortfolioService.GetPortfolios();
170+
// resolve the name of the cryptocurrency (using the symbol)
171+
portfolioEntryName = await CryptoNameResolver.Resolve(ActivePortfolioEntry.Symbol);
172+
173+
// fetch the price of the entry's asset
174+
// TODO null?
175+
CurrentEntryAssetMarketEntry = (await CryptoStatsSource.GetMarketEntries(
176+
CurrencyUtils.GetCurrencyLabel(ActivePortfolio.Currency).ToLower(),
177+
portfolioEntryName.ToLower()
178+
))[0];
179+
180+
// get all orders of the portfolio entry
181+
var entryOrders = MarketOrderService.GetPortfolioEntryOrders(ActivePortfolioEntry.Id);
182+
183+
// compute summaries of all orders in the entry
184+
var entrySummaries = entryOrders.Select(order => SummaryService.GetMarketOrderSummary(order, CurrentEntryAssetMarketEntry.CurrentPrice));
185+
186+
// zip entry orders and summaries into a table rows
187+
tableRowsItems = entryOrders.Zip(entrySummaries).Select(tuple => new Tuple<MarketOrder, ISummaryService.Summary>(tuple.First, tuple.Second)).ToList();
188+
189+
// compute suummary of this entry
190+
entrySummary = SummaryService.GetPortfolioEntrySummary(entryOrders, CurrentEntryAssetMarketEntry.CurrentPrice);
119191
}
120192

121193
public void EditMarketOrder(MouseEventArgs e)

0 commit comments

Comments
 (0)