Skip to content

Commit 5134c72

Browse files
committed
Extracted the New Portfolio form and made a reusable Form component from it.
Added Edit Portfolio page. Small various improvements and code formatting changes across other pages.
1 parent 0d59b38 commit 5134c72

File tree

8 files changed

+208
-171
lines changed

8 files changed

+208
-171
lines changed

WebFrontend/Pages/EditMarketOrder.razor

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555

5656
private void OnCreateOrderFormSubmit(EntryForm.NewOrderModel formModel)
5757
{
58-
// TODO enable adding sells
5958
MarketOrderService.UpdateMarketOrder(ActiveMarketOrder with {
6059
FilledPrice = formModel.FilledPrice,
6160
Fee = formModel.Fee,

WebFrontend/Pages/EditPortfolio.razor

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
@page "/editportfolio/{portfolioId:int}"
2+
@using Model
3+
@using Services
4+
@using Utils
5+
@inject IPortfolioService PortfolioService
6+
@inject IMatDialogService MatDialogService
7+
@inject IMatToaster Toaster
8+
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
9+
10+
11+
<style>
12+
.demo-mat-card {
13+
max-width: 400px;
14+
margin-bottom: 2em;
15+
}
16+
17+
.demo-mat-card-content {
18+
padding: 1rem;
19+
}
20+
21+
.clear-margin {
22+
margin: 0px;
23+
}
24+
</style>
25+
26+
<div class="mat-layout-grid">
27+
<div class="mat-layout-grid-inner">
28+
<div class="mat-layout-grid-cell">
29+
<MatButton Outlined="true" Icon="keyboard_arrow_left" Style="margin-bottom:1em; margin-right: 1rem;" OnClick='() => { NavigationManager.NavigateTo($""); }'>Back</MatButton>
30+
<MatCard>
31+
<MatCardContent class="demo-mat-card-content">
32+
<h2>Edit portfolio</h2>
33+
<PortfolioForm
34+
DefaultCurrency="@Currency.Usd"
35+
AvailableCurrencies="@(EnumUtils.GetEnumList<Currency>())"
36+
FormModel="FormModel"
37+
Edit="true"
38+
OnSubmitEventHandler="@OnCreateFormSubmitted">
39+
</PortfolioForm>
40+
</MatCardContent>
41+
</MatCard>
42+
</div>
43+
</div>
44+
</div>
45+
46+
47+
@code
48+
{
49+
[Parameter] public int PortfolioId { get; set; }
50+
51+
public PortfolioForm.NewPortfolioModel FormModel = new(Currency.Usd);
52+
53+
public Portfolio ActivePortfolio;
54+
55+
protected override void OnInitialized()
56+
{
57+
ActivePortfolio = PortfolioService.GetPortfolio(PortfolioId);
58+
FormModel.Name = ActivePortfolio.Name;
59+
FormModel.Description = ActivePortfolio.Description;
60+
}
61+
62+
private void OnCreateFormSubmitted(PortfolioForm.NewPortfolioModel formModel)
63+
{
64+
PortfolioService.UpdatePortfolio(ActivePortfolio with {
65+
Name = formModel.Name,
66+
Description = formModel.Description
67+
});
68+
formModel.Reset();
69+
Toaster.Add("Portfolio successfully edited", MatToastType.Success, "", "");
70+
NavigationManager.NavigateTo($"/portfolios/{ActivePortfolio.Id}");
71+
}
72+
}

WebFrontend/Pages/Index.razor

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@inject IPortfolioService PortfolioService
77
@inject IPortfolioEntryService PortfolioEntryService
88
@inject IMatDialogService MatDialogService
9+
@inject IMatToaster Toaster
910

1011
<style>
1112
.demo-mat-card {
@@ -33,9 +34,9 @@
3334
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-3"></div>
3435
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6">
3536
<MatH5>Portfolios</MatH5>
36-
@if (Portfolios != null)
37+
@if (PortfoliosWithEntries != null)
3738
{
38-
@foreach (var activePortfolio in Portfolios)
39+
@foreach (var portfolioWithEntries in PortfoliosWithEntries)
3940
{
4041
<MatCard class="demo-mat-card" OnCli>
4142
<MatCardContent>
@@ -45,30 +46,30 @@
4546
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6">
4647
<MatHeadline6 class="clear-margin">
4748
<MatChipSet Style="align-items: center">
48-
<MatH5 Class="clear-margin">@activePortfolio.Item1.Name</MatH5>
49-
<MatChip Style="vertical-align: center" Label="@CurrencyUtils.GetCurrencyLabel(activePortfolio.Item1.Currency)"/>
49+
<MatH5 Class="clear-margin">@portfolioWithEntries.Item1.Name</MatH5>
50+
<MatChip Style="vertical-align: center" Label="@CurrencyUtils.GetCurrencyLabel(portfolioWithEntries.Item1.Currency)"/>
5051
</MatChipSet>
5152
</MatHeadline6>
5253
</div>
5354
<div class="mat-layout-grid-cell mat-layout-grid-cell-span-6" style="text-align: right;">
54-
<MatIconButton Icon="edit" OnClick="() => EditPortfolio(activePortfolio.Item1)"></MatIconButton>
55-
<MatIconButton Icon="delete" OnClick="() => DeletePortfolio(activePortfolio.Item1)"></MatIconButton>
55+
<MatIconButton Icon="edit" OnClick="() => EditPortfolio(portfolioWithEntries.Item1)"></MatIconButton>
56+
<MatIconButton Icon="delete" OnClick="() => DeletePortfolio(portfolioWithEntries.Item1)"></MatIconButton>
5657
</div>
5758
</div>
5859
</div>
5960
</div>
6061
<div style="padding: 1rem">
61-
<MatButton Label="View" Style="margin-right: 1rem;" OnClick="() => ViewPortfolio(activePortfolio.Item1)"></MatButton>
62-
@if (activePortfolio.Item2.Count > 0)
62+
<MatButton Label="View" Style="margin-right: 1rem;" OnClick="() => ViewPortfolio(portfolioWithEntries.Item1)"></MatButton>
63+
@if (portfolioWithEntries.Item2.Count > 0)
6364
{
64-
@foreach (var entry in activePortfolio.Item2)
65+
@foreach (var entry in portfolioWithEntries.Item2)
6566
{
6667
<MatButton Outlined="true" Style="margin-right: 1em;" Label="@entry.Symbol.ToUpper()" OnClick='() => NavigationManager.NavigateTo($"/entries/{entry.Id}")'></MatButton>
6768
}
6869
}
6970
else
7071
{
71-
<MatButton Icon="add" Outlined="true" OnClick="() => AddNewEntryToPortfolio(activePortfolio.Item1)" Label="Add entry"></MatButton>
72+
<MatButton Icon="add" Outlined="true" OnClick="() => AddNewEntryToPortfolio(portfolioWithEntries.Item1)" Label="Add entry"></MatButton>
7273
}
7374
</div>
7475
</MatCardContent>
@@ -88,36 +89,7 @@
8889

8990
@code
9091
{
91-
protected List<Tuple<Portfolio, List<PortfolioEntry>>> Portfolios;
92-
93-
protected ISummaryService.Summary portfolioSummary = new(1341m, 1.8m, 9982.489m, 1000m);
94-
95-
protected List<PortfolioEntry> activePortfolioEntries = new List<PortfolioEntry>()
96-
{
97-
new("btc", 1, 1),
98-
new("ada", 1, 2),
99-
new("eth", 1, 3),
100-
new("ltc", 1, 4),
101-
new("link", 1, 5),
102-
};
103-
104-
protected List<decimal> portfolioHoldings = new()
105-
{
106-
44.8886m,
107-
28.18m,
108-
10.116m,
109-
9.38m,
110-
2.70m,
111-
};
112-
113-
protected List<PortfolioEntryRow> portfolioEntryRows = new()
114-
{
115-
new("btc", 57644.42m, 1.35m, 44.76m),
116-
new("ada", 1.36m, 0.58m, 28.18m),
117-
new("eth", 3279.64m, 10.95m, 27.11m),
118-
new("ltc", 291.55m, 7.20m, 9.38m),
119-
new("link", 42.20m, -5.19m, 2.70m)
120-
};
92+
protected List<Tuple<Portfolio, List<PortfolioEntry>>> PortfoliosWithEntries;
12193

12294
protected record PortfolioEntryRow(string symbol, decimal currentPrice, decimal relativeChange, decimal percentage);
12395

@@ -128,34 +100,17 @@
128100

129101
private void LoadPortfolios()
130102
{
131-
Portfolios = PortfolioService.GetPortfolios().Select(
103+
PortfoliosWithEntries = PortfolioService.GetPortfolios().Select(
132104
portfolio => new Tuple<Portfolio, List<PortfolioEntry>>(
133105
portfolio,
134106
PortfolioEntryService.GetPortfolioEntries(portfolio.Id)
135107
)
136108
).ToList();
137109
}
138110

139-
140-
protected override async Task OnInitializedAsync()
141-
{
142-
//_existingPortfolios = PortfolioService.GetPortfolios();
143-
}
144-
145-
public void SelectionChangedEvent(object row)
146-
{
147-
if (row == null)
148-
{
149-
}
150-
else
151-
{
152-
NavigationManager.NavigateTo($"entries");
153-
}
154-
}
155-
156111
private void EditPortfolio(Portfolio activePortfolioItem1)
157112
{
158-
Console.WriteLine($"About to edit {activePortfolioItem1.Name}");
113+
NavigationManager.NavigateTo($"/editportfolio/{activePortfolioItem1.Id}");
159114
}
160115

161116
private async void DeletePortfolio(Portfolio portfolio)
@@ -166,6 +121,7 @@
166121
PortfolioService.DeletePortfolio(portfolio);
167122
LoadPortfolios();
168123
StateHasChanged();
124+
Toaster.Add($"Portfolio \"{portfolio.Name}\" sucessfully deleted", MatToastType.Info, "", "");
169125
}
170126
}
171127

WebFrontend/Pages/NewPortfolio.razor

Lines changed: 8 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,16 @@
22
@using Model
33
@using Services
44
@using Utils
5-
@using System.ComponentModel.DataAnnotations
65
@inject IPortfolioService PortfolioService
76
@inject IMatDialogService MatDialogService
87
@inject IMatToaster Toaster
98
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
109

1110

1211
<style>
13-
.demo-mat-card {
14-
max-width: 400px;
15-
margin-bottom: 2em;
16-
}
17-
1812
.demo-mat-card-content {
1913
padding: 1rem;
2014
}
21-
22-
.clear-margin {
23-
margin: 0px;
24-
}
2515
</style>
2616

2717
<div class="mat-layout-grid">
@@ -31,35 +21,11 @@
3121
<MatCard>
3222
<MatCardContent class="demo-mat-card-content">
3323
<h2>New portfolio</h2>
34-
<EditForm Model="FormModel" OnValidSubmit="SaveButtonClicked">
35-
<DataAnnotationsValidator/>
36-
<p>
37-
<MatTextField FullWidth="true" @bind-Value="@FormModel.Name" Label="Portfolio name"></MatTextField>
38-
<ValidationMessage For="@(() => FormModel.Name)"/>
39-
</p>
40-
41-
<p>
42-
<MatTextField FullWidth="true" @bind-Value="@FormModel.Description" Label="Description"></MatTextField>
43-
<ValidationMessage For="@(() => FormModel.Description)"/>
44-
</p>
45-
<MatRadioGroup @bind-Value="@FormModel.SelectedCurrency" Items="@AvailableCurrencies">
46-
<ItemTemplate Context="currencyContext">
47-
<div>
48-
<MatRadioButton Value="@currencyContext">@GetCurrencyLabel(@currencyContext)</MatRadioButton>
49-
</div>
50-
</ItemTemplate>
51-
</MatRadioGroup>
52-
<ValidationMessage For="@(() => FormModel.SelectedCurrency)"/>
53-
<MatCardActions>
54-
<MatCardActionButtons>
55-
<MatButton Type="submit">Create</MatButton>
56-
</MatCardActionButtons>
57-
58-
<MatCardActionIcons>
59-
<MatIconButton Icon="@MatIconNames.Refresh" OnClick="(_) => FormModel.Reset()"></MatIconButton>
60-
</MatCardActionIcons>
61-
</MatCardActions>
62-
</EditForm>
24+
<PortfolioForm
25+
DefaultCurrency="@Currency.Usd"
26+
AvailableCurrencies="@(EnumUtils.GetEnumList<Currency>())"
27+
OnSubmitEventHandler="@OnCreateFormSubmitted">
28+
</PortfolioForm>
6329
</MatCardContent>
6430
</MatCard>
6531
</div>
@@ -69,68 +35,10 @@
6935

7036
@code
7137
{
72-
protected Currency[] AvailableCurrencies = EnumUtils.GetEnumList<Currency>().ToArray();
73-
protected const Currency DefaultCurerncy = Currency.Usd;
74-
75-
protected CreateFormModel FormModel = new();
76-
List<Portfolio> _existingPortfolios;
77-
78-
public class CreateFormModel
38+
private void OnCreateFormSubmitted(PortfolioForm.NewPortfolioModel formModel)
7939
{
80-
[Required]
81-
[MinLength(1)]
82-
public string Name { get; set; }
83-
84-
[Required]
85-
[MinLength(1)]
86-
public string Description { get; set; }
87-
88-
[Required] public Currency SelectedCurrency = DefaultCurerncy;
89-
90-
public void Reset()
91-
{
92-
Name = "";
93-
Description = "";
94-
SelectedCurrency = DefaultCurerncy;
95-
}
96-
}
97-
98-
protected override async Task OnInitializedAsync()
99-
{
100-
_existingPortfolios = PortfolioService.GetPortfolios();
101-
}
102-
103-
protected string GetCurrencyLabel(Currency currency)
104-
{
105-
switch (currency)
106-
{
107-
case Currency.Czk:
108-
return "CZK";
109-
case Currency.Eur:
110-
return "EUR";
111-
case Currency.Usd:
112-
return "USD";
113-
}
114-
return "UNDEFINED";
115-
}
116-
117-
void SaveButtonClicked()
118-
{
119-
PortfolioService.CreatePortfolio(FormModel.Name, FormModel.Description, FormModel.SelectedCurrency);
120-
FormModel.Reset();
121-
_existingPortfolios = PortfolioService.GetPortfolios();
40+
PortfolioService.CreatePortfolio(formModel.Name, formModel.Description, formModel.SelectedCurrency);
41+
formModel.Reset();
12242
Toaster.Add("New portfolio successfully added", MatToastType.Success, "", "");
12343
}
124-
125-
async void DeletePortfolio(Portfolio portfolio)
126-
{
127-
var result = await MatDialogService.ConfirmAsync("Do you really wish to delete this portfolio including all of it's portfolio entries and market orders?");
128-
if (result)
129-
{
130-
PortfolioService.DeletePortfolio(portfolio);
131-
_existingPortfolios = PortfolioService.GetPortfolios();
132-
StateHasChanged();
133-
Toaster.Add($"Portfolio \"{portfolio.Name}\" sucessfully deleted", MatToastType.Info, "", "");
134-
}
135-
}
13644
}

0 commit comments

Comments
 (0)