Skip to content

Commit

Permalink
Make some UI changes to the investor page (also called portfolio) and…
Browse files Browse the repository at this point in the history
… load a project if it is not found in the view page also show some more stats
  • Loading branch information
dangershony committed Jan 17, 2024
1 parent 17abd5b commit 973ae7e
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 62 deletions.
11 changes: 1 addition & 10 deletions src/Angor/Client/Pages/Browse.razor
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,11 @@
StateHasChanged();
},
new[] { findProject.NostrPubKey });

//_RelayService.LookupProjectsInfoByPubKeys<ProjectInfo>(_ =>
//{
// if (!SessionStorage.IsProjectInStorageById(_.ProjectIdentifier))
// SessionStorage.StoreProjectInfo(_);
//},
//OnEndOfStreamAction: () =>
//{
//},
//nostrPubKey: new[] { findProject.NostrPubKey });
}

findInProgress = false;
}

private async Task SearchProjects()
{
searchInProgress = true;
Expand Down
18 changes: 15 additions & 3 deletions src/Angor/Client/Pages/Invest.razor
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,6 @@
unSignedTransaction = _InvestorTransactionActions.CreateInvestmentTransaction(project, investorKey, Money.Coins(Investment.InvestmentAmount).Satoshi);

signedTransaction = _WalletOperations.AddInputsAndSignTransaction(accountInfo.GetNextChangeReceiveAddress(), unSignedTransaction, _walletStorage.GetWallet(), accountInfo, feeData.SelectedFeeEstimation);

storage.AddInvestmentProject(project); //TODO David need to verify that this is the correct place to change state in storage

return new OperationResult { Success = true };

Expand Down Expand Up @@ -467,6 +465,7 @@
InvestorNostrPrivateKey = nostrPrivateKeyHex
});

storage.AddInvestmentProject(project); //TODO David need to verify that this is the correct place to change state in storage
storage.AddOrUpdateSignatures(recoverySigs);

_SignService.LookupSignatureForInvestmentRequest(
Expand All @@ -479,6 +478,12 @@

if (operationResult.Success)
{
var metadata = SessionStorage.GetProjectMetadataByPubkey(project.NostrPubKey);
if (metadata != null)
{
storage.AddInvestmentProjectMetadata(project.NostrPubKey, metadata);
}

notificationComponent.ShowNotificationMessage("Signature request sent", 5);
}
else
Expand Down Expand Up @@ -531,7 +536,8 @@
// link the trx to the signatures
recoverySigs.TransactionId = signedTransaction.GetHash().ToString();
recoverySigs.SignedTransactionHex = null;

recoverySigs.AmountInvested = signedTransaction.Outputs.Skip(2).Take(project.Stages.Count).Sum(s => s.Value);

storage.AddOrUpdateSignatures(recoverySigs);

var accountInfo = storage.GetAccountInfo(network.Name);
Expand All @@ -547,6 +553,12 @@

if (operationResult.Success)
{
var metadata = SessionStorage.GetProjectMetadataByPubkey(project.NostrPubKey);
if (metadata != null)
{
storage.AddInvestmentProjectMetadata(project.NostrPubKey, metadata);
}

notificationComponent.ShowNotificationMessage("Invested in project", 5);

NavigationManager.NavigateTo($"/view/{project.ProjectIdentifier}");
Expand Down
133 changes: 110 additions & 23 deletions src/Angor/Client/Pages/Investor.razor
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
@page "/investor"
@using Angor.Client.Storage
@using Angor.Shared.Models
@using Angor.Shared.Services
@using Blockcore.NBitcoin

@inject IClientStorage storage;
@inject NavigationManager NavigationManager
@inject IWalletStorage _walletStorage;
@inject ICacheStorage SessionStorage;

@inherits BaseComponent

Expand All @@ -22,69 +25,153 @@
<NotificationComponent @ref="notificationComponent"/>

<!-- Summary Statistics -->
<div class="row row-cols-1 row-cols-md-3 g-4 mb-4">
<div class="row row-cols-1 row-cols-md-4 g-4 mb-4">
<div class="col">
<div class="card text-white bg-primary">
<div class="card-body">
<h5 class="card-title">Total Projects</h5>
<p class="card-text">@projects.Count</p>
<h5 class="card-title">Funded Projects</h5>
<p class="card-text">@TotalFundedProjects</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-white bg-success">
<div class="card-body">
<h5 class="card-title">Total invested</h5>
<p class="card-text"> @projects.Sum(s => s.TargetAmount) @network.CoinTicker</p>
<p class="card-text"> @Money.Satoshis(TotalInvested).ToUnit(MoneyUnit.BTC) @network.CoinTicker</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-white bg-info">
<div class="card-body">
<h5 class="card-title">Total Stages</h5>
<p class="card-text">@projects.Sum(s => s.Stages.Count)</p>
<h5 class="card-title">Wallet</h5>
<p class="card-text">@Money.Satoshis(TotalWallet).ToUnit(MoneyUnit.BTC) @network.CoinTicker</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-white bg-secondary">
<div class="card-body">
<h5 class="card-title">In Recovery</h5>
<p class="card-text">@Money.Satoshis(TotalInRecovery).ToUnit(MoneyUnit.BTC) @network.CoinTicker</p>
</div>
</div>
</div>
</div>

<!-- List of Projects -->
<h2 class="mb-4">Your Projects</h2>
<div class="row row-cols-1 row-cols-md-3 g-4">
@foreach(var project in projects)
{
<div class="col">
<div class="card">
<img src="https://via.placeholder.com/150" class="card-img-top" alt="Project Image">
<div class="card-body">
<h5 class="card-title">Project Title</h5>
<p class="card-text">@project.ProjectIdentifier</p>
<p class="card-text">Short project description...</p>
<NavLink href=@($"/view/{project.ProjectIdentifier}") class="btn btn-primary">View Project</NavLink>
</div>
</div>
</div>
}
<div class="row">
<div class="col">
<table class="table table-bordered">
<thead>
<tr >
<th></th>
<th></th>
<th>Funding Target (@network.CoinTicker)</th>
<th>Raised (@network.CoinTicker)</th>
<th>Raised (% Target)</th>
<th>Project Status</th>
<th>My Investment (@network.CoinTicker)</th>
<th>Spent by Founder</th>
<th>Available to Founder</th>
<th>In Recovery</th>
</tr>
</thead>
<tbody>
@foreach(var project in projects)
{
<tr>
<td>
<a href=@($"/view/{project.ProjectInfo.ProjectIdentifier}") class="btn btn-link"> @TrimString(@project.ProjectInfo.ProjectIdentifier)</a>
</td>
<td> @project.ProjectMetadata?.Name</td>
<td>@project.ProjectInfo.TargetAmount @network.CoinTicker</td>
<td>0</td>
<td>0%</td>
<td>
@if (project.ProjectInfo.StartDate < DateTime.UtcNow)
{
<p class="text-info">Funding</p>
}
else
{
<p class="text-success">Live</p>
}
</td>
<td>@Money.Satoshis(project.SignatureInfo?.AmountInvested ?? 0).ToUnit(MoneyUnit.BTC) @network.CoinTicker @(!project.SignatureInfo?.Signatures?.Any() ?? false ? "(pending)" : string.Empty)</td>
<td>-</td>
<td>-</td>
<td>@Money.Satoshis(project.SignatureInfo?.AmountInRecovery ?? 0).ToUnit(MoneyUnit.BTC) @network.CoinTicker</td>
</tr>
}
</tbody>
</table>
</div>
</div>

</div>

@code {

private List<ProjectInfo> projects;
private List<ProjectData> projects = new();

long TotalInvested = 0;
long TotalWallet = 0;
int TotalFundedProjects = 0;
long TotalInRecovery = 0;

public class ProjectData
{
public ProjectInfo ProjectInfo;
public ProjectMetadata? ProjectMetadata;
public SignatureInfo? SignatureInfo;
}

protected override Task OnInitializedAsync()
{
hasWallet = _walletStorage.HasWallet();

if (hasWallet)
{
projects = storage.GetInvestmentProjects();
var accountInfo = storage.GetAccountInfo(network.Name);
var unconfirmedInfo = SessionStorage.GetUnconfirmedInboundFunds();

var investedProjects = storage.GetInvestmentProjects();
var recoveries = storage.GetSignatures();

foreach (var projectInfo in investedProjects)
{
var data = new ProjectData { ProjectInfo = projectInfo };
projects.Add(data);
storage.GetInvestmentProjectsMetadata().TryGetValue(projectInfo.NostrPubKey, out data.ProjectMetadata);
data.SignatureInfo = recoveries.FirstOrDefault(s => s.ProjectIdentifier == projectInfo.ProjectIdentifier);
}

var abi = new AccountBalanceInfo();
abi.UpdateAccountBalanceInfo(accountInfo, unconfirmedInfo);

TotalFundedProjects = projects.Count;
TotalInvested = projects.Sum(s => s.SignatureInfo?.AmountInvested ?? 0);
TotalWallet = abi.TotalBalance;
TotalInRecovery = projects.Sum(s => s.SignatureInfo?.AmountInRecovery ?? 0);

}

return Task.CompletedTask;
}

public string TrimString(string input)
{
if (input.Length > 20)
{
return input.Substring(0, 10) + "..." + input.Substring(input.Length - 10);
}

return input;
}

private void NavigateToPenalties()
{
NavigationManager.NavigateTo("/penalties");
Expand Down
1 change: 1 addition & 0 deletions src/Angor/Client/Pages/Recover.razor
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@
recoveryTransaction = _WalletOperations.AddFeeAndSignTransaction(accountInfo.GetNextChangeReceiveAddress(), unsignedRecoveryTransaction, _walletStorage.GetWallet(), accountInfo, feeData.SelectedFeeEstimation);

recoverySigs.RecoveryTransactionId = recoveryTransaction.GetHash().ToString();
recoverySigs.AmountInRecovery = unsignedRecoveryTransaction.TotalOut;

Logger.LogInformation($"recoveryTransaction={recoverySigs.RecoveryTransactionId}");

Expand Down
Loading

0 comments on commit 973ae7e

Please sign in to comment.