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
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
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
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 {
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}
0 commit comments