Skip to content

Commit 6fbce01

Browse files
New UI (#263)
* Change date format in signature request to dd/MM/yyyy * Hide number input spin buttons for a cleaner UI * Clean code * Fix chronological validation for project stages * Add error handling for JSON deserialization in NetworkService * Refactor confirmation modal for improved styling and layout * Remove added codes * Add robust error handling and validation for signature recovery request deserialization * Improve layout for signatures page * Enhance password input layout by adding margin to input group * Format date display for signature timestamps to "dd/MM/yyyy HH:mm" * Revert back to only using the SignRecoveryRequest class when fetching messages --------- Co-authored-by: dangershony <dan.gershony@gmail.com>
1 parent c8bb5d4 commit 6fbce01

File tree

6 files changed

+240
-217
lines changed

6 files changed

+240
-217
lines changed

src/Angor/Client/Pages/Create.razor

Lines changed: 132 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -477,29 +477,7 @@
477477
</div>
478478
</div>
479479

480-
@code {
481-
private IEnumerable<(string IconName, string Label, string Value)> GetProjectInfoData()
482-
{
483-
return new List<(string, string, string)>
484-
{
485-
("name", "Project Name", project.Metadata.Name),
486-
("about", "Project About", ((MarkupString)project.Metadata.About).ToString()),
487-
("identifier", "Project Identifier", project.ProjectInfo.ProjectIdentifier),
488-
("key", "Founder Key", project.ProjectInfo.FounderKey)
489-
};
490-
}
491480

492-
private IEnumerable<(string IconName, string Label, string Value, string color)> GetAdditionalProjectInfo()
493-
{
494-
return new List<(string, string, string, string)>
495-
{
496-
("balance", "Target amount", $"{targetAmountInBTC} {network.CoinTicker}","text-success"),
497-
("calendar", "Start date", $"{project.ProjectInfo.StartDate:dd/MM/yyyy} in {(project.ProjectInfo.StartDate - DateTime.Now).Days} days","text-warning"),
498-
("calendar", "Expiry date", $"{project.ProjectInfo.ExpiryDate:dd/MM/yyyy} in {(project.ProjectInfo.ExpiryDate - DateTime.Now).Days} days","text-warning"),
499-
("sad-circle", "Penalty days", $"{project.ProjectInfo.PenaltyDays} days","text-warning")
500-
};
501-
}
502-
}
503481
}
504482

505483

@@ -520,95 +498,104 @@
520498
</div>
521499

522500

523-
<div class="modal-body modal-body-scroll">
524-
<p class="mb-1">
525-
<strong>Project Identifier:</strong> @project.ProjectInfo.ProjectIdentifier
526-
</p>
527-
<p class="mb-1"><strong>Founder Key:</strong> @project.ProjectInfo.FounderKey.Substring(0, 10)...</p> <!-- Display only the first 10 characters -->
501+
<div class="modal-body modal-body-scroll">
502+
<p class="mb-1">
503+
<strong>Project Identifier:</strong> @project.ProjectInfo.ProjectIdentifier
504+
</p>
505+
<p class="mb-1"><strong>Founder Key:</strong> @project.ProjectInfo.FounderKey.Substring(0, 10)...</p> <!-- Display only the first 10 characters -->
528506

529-
<p class="mb-1">
530-
<strong>Target amount:</strong> @project.ProjectInfo.TargetAmount.ToUnitBtc() @network.CoinTicker
531-
</p>
507+
<p class="mb-1">
508+
<strong>Target amount:</strong> @project.ProjectInfo.TargetAmount.ToUnitBtc() @network.CoinTicker
509+
</p>
532510

533-
<p class="mb-1"><strong>Start date:</strong> @project.ProjectInfo.StartDate.ToString("dd/MM/yyyy") in @((project.ProjectInfo.StartDate - DateTime.Now).Days) days</p>
534-
<p class="mb-1"><strong>Expiry date:</strong> @project.ProjectInfo.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ProjectInfo.ExpiryDate - DateTime.Now).Days) days</p>
535-
<p class="mb-1"><strong>Penalty days:</strong> @project.ProjectInfo.PenaltyDays days</p>
511+
<p class="mb-1"><strong>Start date:</strong> @project.ProjectInfo.StartDate.ToString("dd/MM/yyyy") in @((project.ProjectInfo.StartDate - DateTime.Now).Days) days</p>
512+
<p class="mb-1"><strong>Expiry date:</strong> @project.ProjectInfo.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ProjectInfo.ExpiryDate - DateTime.Now).Days) days</p>
513+
<p class="mb-1"><strong>Penalty days:</strong> @project.ProjectInfo.PenaltyDays days</p>
536514

537-
<p class="mb-1">
538-
<strong>Miner fee:</strong> @Money.Satoshis(signedTransaction?.TransactionFee ?? 0).ToUnit(MoneyUnit.BTC) @network.CoinTicker
539-
</p>
540-
<p class="mb-1">
541-
<strong>Angor fee:</strong> @signedTransaction?.Transaction.Outputs.First().Value.ToUnit(MoneyUnit.BTC) @network.CoinTicker
542-
</p>
515+
<p class="mb-1">
516+
<strong>Miner fee:</strong> @Money.Satoshis(signedTransaction?.TransactionFee ?? 0).ToUnit(MoneyUnit.BTC) @network.CoinTicker
517+
</p>
518+
<p class="mb-1">
519+
<strong>Angor fee:</strong> @signedTransaction?.Transaction.Outputs.First().Value.ToUnit(MoneyUnit.BTC) @network.CoinTicker
520+
</p>
543521

544-
<hr>
522+
<hr>
545523

546-
<div class="mb-3">
547-
<label for="feeRange" class="form-label">Feerate for @feeData.SelectedFeeEstimation.Confirmations blocks is @feeData.SelectedFeeEstimation.FeeRate sats</label>
548-
<input type="range" class="form-range" id="feeRange" @bind="feeData.FeePosition" @oninput="FeeRangeChanged" min="@feeData.FeeMin" max="@feeData.FeeMax">
549-
</div>
524+
<div class="mb-3">
525+
<label for="feeRange" class="form-label">Feerate for @feeData.SelectedFeeEstimation.Confirmations blocks is @feeData.SelectedFeeEstimation.FeeRate sats</label>
526+
<input type="range" class="form-range" id="feeRange" @bind="feeData.FeePosition" @oninput="FeeRangeChanged" min="@feeData.FeeMin" max="@feeData.FeeMax">
527+
</div>
550528

551-
<hr>
529+
<hr>
552530

553-
<h6 class="mt-3 mb-2">Stages</h6>
554-
@foreach (var stage in project.ProjectInfo.Stages)
555-
{
556-
<div style="border-top: 1px solid #dee2e6; padding-top: 10px; margin-top: 10px; font-size: 0.85em;">
557-
<p class="mb-1"><strong>Stage percent:</strong> @stage.AmountToRelease % </p>
558-
<p class="mb-1"><strong>Stage date:</strong> @stage.ReleaseDate.ToString("dd/MM/yyyy") - @((stage.ReleaseDate - project.ProjectInfo.StartDate).Days) days after project starts </p>
559-
</div>
560-
}
531+
<h6 class="mt-3 mb-2">Stages</h6>
532+
@foreach (var stage in project.ProjectInfo.Stages)
533+
{
534+
<div style="border-top: 1px solid #dee2e6; padding-top: 10px; margin-top: 10px; font-size: 0.85em;">
535+
<p class="mb-1"><strong>Stage percent:</strong> @stage.AmountToRelease % </p>
536+
<p class="mb-1"><strong>Stage date:</strong> @stage.ReleaseDate.ToString("dd/MM/yyyy") - @((stage.ReleaseDate - project.ProjectInfo.StartDate).Days) days after project starts </p>
537+
</div>
538+
}
561539

562-
<hr>
540+
<hr>
563541

564-
<p class="mt-3">Are you sure you want to continue?</p>
542+
<p class="mt-3">Are you sure you want to continue?</p>
565543

566-
</div>
567-
<div class="modal-footer">
568-
<button type="button" class="btn btn-border" @onclick="Send" disabled="@publishProjectSpinner">
569-
@if (publishProjectSpinner)
570-
{
571-
<span class=" spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
572-
<span>Confirming...</span>
573-
}
574-
else
575-
{
576-
<span>Confirm</span>
577-
}
578-
</button>
544+
</div>
545+
<div class="modal-footer">
546+
<button type="button" class="btn btn-border" @onclick="Send" disabled="@publishProjectSpinner">
547+
@if (publishProjectSpinner)
548+
{
549+
<span class=" spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
550+
<span>Confirming...</span>
551+
}
552+
else
553+
{
554+
<span>Confirm</span>
555+
}
556+
</button>
579557

580558

559+
</div>
560+
</div>
581561
</div>
582562
</div>
583-
</div>
584-
</div>
585-
}
563+
}
586564

587-
@if (showConfirmationModal)
588-
{
589-
<div class="modal fade show d-block" tabindex="-1" style="background: rgba(0, 0, 0, 0.5)">
590-
<div class="modal-dialog">
591-
<div class="modal-content">
592-
<div class="modal-header">
593-
<h5 class="modal-title">Confirmation</h5>
594-
<button type="button" class="btn-close" @onclick="CloseConfirmationModal" aria-label="Close"></button>
595-
</div>
596-
<div class="modal-body">
597-
<p>@confirmationMessage</p>
598-
</div>
599-
<div class="modal-footer">
600-
<button type="button" class="btn btn-secondary" @onclick="CloseConfirmationModal">Cancel</button>
601-
<button type="button" class="btn btn-primary" @onclick="PerformFinalizeAction">Confirm</button>
565+
566+
567+
</div>
568+
}
569+
@if (showConfirmationModal)
570+
{
571+
<div class="modal-wrapper">
572+
<div class="modal fade show d-block" tabindex="-1">
573+
<div class="modal-dialog modal-dialog-centered">
574+
<div class="modal-content modern-modal">
575+
<div class="modal-header border-0 pb-0">
576+
<div class="d-flex align-items-center">
577+
<Icon IconName="alert-circle" Height="32" Width="32" class="me-2" />
578+
<h5 class="modal-title">Confirmation</h5>
579+
</div>
580+
<button class="btn-close-custom" @onclick="CloseConfirmationModal">
581+
<Icon IconName="close-circle" Height="24" Width="24" />
582+
</button>
583+
</div>
584+
585+
<div class="modal-body modal-body-scroll">
586+
<p class="mb-1">@confirmationMessage</p>
587+
</div>
588+
589+
<div class="modal-footer">
590+
<button type="button" class="btn btn-border-warning" @onclick="CloseConfirmationModal">Cancel</button>
591+
<button type="button" class="btn btn-border-success" @onclick="PerformFinalizeAction">Confirm</button>
592+
</div>
593+
</div>
602594
</div>
603595
</div>
604596
</div>
605-
</div>
606-
}
607-
608-
609597

610-
</div>
611-
}
598+
}
612599
</div>
613600
@code {
614601

@@ -1181,19 +1168,30 @@
11811168
return false;
11821169
}
11831170

1184-
var prev = DateTime.UtcNow;
1185-
foreach (var stage in project.ProjectInfo.Stages)
1171+
if (project.ProjectInfo.Stages.Any())
11861172
{
1187-
if ((stage.ReleaseDate - prev).Days < 0)
1173+
// First check if first stage is after project start
1174+
if (project.ProjectInfo.Stages.First().ReleaseDate < project.ProjectInfo.StartDate)
11881175
{
1189-
notificationComponent.ShowErrorMessage("Stages must be chronological");
1176+
notificationComponent.ShowErrorMessage("First stage must be after project start date");
11901177
return false;
11911178
}
11921179

1193-
prev = stage.ReleaseDate;
1180+
// Then check stages are in order
1181+
var sortedStages = project.ProjectInfo.Stages.OrderBy(s => s.ReleaseDate).ToList();
1182+
for (int i = 0; i < sortedStages.Count - 1; i++)
1183+
{
1184+
if (sortedStages[i].ReleaseDate >= sortedStages[i + 1].ReleaseDate)
1185+
{
1186+
notificationComponent.ShowErrorMessage($"Stage {i + 2} must be after stage {i + 1}");
1187+
return false;
1188+
}
1189+
}
1190+
1191+
// Keep stages sorted
1192+
project.ProjectInfo.Stages = sortedStages;
11941193
}
11951194

1196-
// If all checks pass, return true
11971195
return true;
11981196
}
11991197

@@ -1277,21 +1275,21 @@
12771275
private FounderProject CreateDefaultProject(FounderKeys projectsKeys)
12781276
{
12791277
return new FounderProject
1280-
{
1281-
ProjectIndex = projectsKeys.Index,
1282-
Metadata = new ProjectMetadata(),
1283-
ProjectInfo = new ProjectInfo
12841278
{
1285-
FounderKey = projectsKeys.FounderKey,
1286-
FounderRecoveryKey = projectsKeys.FounderRecoveryKey,
1287-
ProjectIdentifier = projectsKeys.ProjectIdentifier,
1288-
NostrPubKey = projectsKeys.NostrPubKey,
1289-
StartDate = DateTime.UtcNow.AddMinutes(2), // to allow testing and spending immediately
1290-
PenaltyDays = 90,
1291-
ExpiryDate = DateTime.UtcNow.AddDays(120),
1292-
TargetAmount = Money.Coins(50).Satoshi
1279+
ProjectIndex = projectsKeys.Index,
1280+
Metadata = new ProjectMetadata(),
1281+
ProjectInfo = new ProjectInfo
1282+
{
1283+
FounderKey = projectsKeys.FounderKey,
1284+
FounderRecoveryKey = projectsKeys.FounderRecoveryKey,
1285+
ProjectIdentifier = projectsKeys.ProjectIdentifier,
1286+
NostrPubKey = projectsKeys.NostrPubKey,
1287+
StartDate = DateTime.UtcNow.AddMinutes(2), // to allow testing and spending immediately
1288+
PenaltyDays = 90,
1289+
ExpiryDate = DateTime.UtcNow.AddDays(120),
1290+
TargetAmount = Money.Coins(50).Satoshi
12931291
}
1294-
};
1292+
};
12951293
}
12961294
private void PopulateTestnetData(FounderProject project)
12971295
{
@@ -1326,4 +1324,27 @@
13261324
("key", "Founder Key", project.ProjectInfo.FounderKey)
13271325
};
13281326
}
1327+
1328+
private IEnumerable<(string IconName, string Label, string Value)> GetProjectInfoData()
1329+
{
1330+
return new List<(string, string, string)>
1331+
{
1332+
("name", "Project Name", project.Metadata.Name),
1333+
("about", "Project About", ((MarkupString)project.Metadata.About).ToString()),
1334+
("identifier", "Project Identifier", project.ProjectInfo.ProjectIdentifier),
1335+
("key", "Founder Key", project.ProjectInfo.FounderKey)
1336+
};
1337+
}
1338+
1339+
private IEnumerable<(string IconName, string Label, string Value, string color)> GetAdditionalProjectInfo()
1340+
{
1341+
return new List<(string, string, string, string)>
1342+
{
1343+
("balance", "Target amount", $"{targetAmountInBTC} {network.CoinTicker}","text-success"),
1344+
("calendar", "Start date", $"{project.ProjectInfo.StartDate:dd/MM/yyyy} in {(project.ProjectInfo.StartDate - DateTime.Now).Days} days","text-warning"),
1345+
("calendar", "Expiry date", $"{project.ProjectInfo.ExpiryDate:dd/MM/yyyy} in {(project.ProjectInfo.ExpiryDate - DateTime.Now).Days} days","text-warning"),
1346+
("sad-circle", "Penalty days", $"{project.ProjectInfo.PenaltyDays} days","text-warning")
1347+
};
1348+
}
1349+
13291350
}

src/Angor/Client/Pages/Invest.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ else
481481
</div>
482482
<div>
483483
<strong>Date:</strong>
484-
<p>@investorProject?.SignaturesInfo?.TimeOfSignatureRequest?.ToString("MM/dd/yyyy HH:mm")</p>
484+
<p>@investorProject?.SignaturesInfo?.TimeOfSignatureRequest?.ToString("dd/MM/yyyy HH:mm")</p>
485485
</div>
486486
</div>
487487
<div>

0 commit comments

Comments
 (0)