diff --git a/.gitignore b/.gitignore
index b0fba1d..e81653c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
*.userosscache
*.sln.docstates
+
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
@@ -406,3 +407,6 @@ FodyWeavers.xsd
*.sln.iml
.containers/
+
+.secret.json
+secret.json
diff --git a/src/Application/Screens/MenuSelection.cs b/src/Application/Screens/MenuSelection.cs
index 580fc80..c61a82e 100644
--- a/src/Application/Screens/MenuSelection.cs
+++ b/src/Application/Screens/MenuSelection.cs
@@ -5,8 +5,8 @@ public enum MenuSelection
{
/// Login
Login,
- /// Register
- Register,
/// Exit
- Exit
+ Exit,
+ /// Dashboard
+ Dashboard
}
diff --git a/src/Domain/Elevators/ElevatorItem.cs b/src/Domain/Elevators/ElevatorItem.cs
index c83efcb..4e4cb5a 100644
--- a/src/Domain/Elevators/ElevatorItem.cs
+++ b/src/Domain/Elevators/ElevatorItem.cs
@@ -13,6 +13,9 @@ public class ElevatorItem
/// Get or set the current floor the elevator is on.
public int CurrentFloor { get; set; }
+
+ /// Get or set the destination floor the elevator is moving to.
+ public int DestinationFloor { get; set; }
/// Get or set the direction the elevator is moving.
[JsonConverter(typeof(JsonStringEnumConverter))]
diff --git a/src/Infrastructure/Migrations/20241209122830_TypoFix.Designer.cs b/src/Infrastructure/Migrations/20241209122830_TypoFix.Designer.cs
new file mode 100644
index 0000000..5cab85a
--- /dev/null
+++ b/src/Infrastructure/Migrations/20241209122830_TypoFix.Designer.cs
@@ -0,0 +1,327 @@
+//
+using System;
+using Infrastructure.Persistence.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Infrastructure.Migrations
+{
+ [DbContext(typeof(ApplicationDbContext))]
+ [Migration("20241209122830_TypoFix")]
+ partial class TypoFix
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasDefaultSchema("dbo")
+ .HasAnnotation("ProductVersion", "8.0.11");
+
+ modelBuilder.Entity("Domain.Buildings.Building", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("id");
+
+ b.Property("CreatedByUserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("created_by_user_id");
+
+ b.Property("CreatedDateTimeUtc")
+ .HasColumnType("TEXT")
+ .HasColumnName("created_date_time_utc");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("TEXT")
+ .HasColumnName("name");
+
+ b.Property("NumberOfFloors")
+ .HasColumnType("INTEGER")
+ .HasColumnName("number_of_floors");
+
+ b.Property("UpdatedByUserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("updated_by_user_id");
+
+ b.Property("UpdatedDateTimeUtc")
+ .HasColumnType("TEXT")
+ .HasColumnName("updated_date_time_utc");
+
+ b.HasKey("Id")
+ .HasName("pk_buildings");
+
+ b.HasIndex("CreatedByUserId")
+ .HasDatabaseName("ix_buildings_created_by_user_id");
+
+ b.HasIndex("Name")
+ .IsUnique()
+ .HasDatabaseName("ix_buildings_name");
+
+ b.HasIndex("UpdatedByUserId")
+ .HasDatabaseName("ix_buildings_updated_by_user_id");
+
+ b.ToTable("buildings", "dbo");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ Name = "Joe's Building",
+ NumberOfFloors = 10
+ });
+ });
+
+ modelBuilder.Entity("Domain.Elevators.Elevator", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("id");
+
+ b.Property("BuildingId")
+ .HasColumnType("TEXT")
+ .HasColumnName("building_id");
+
+ b.Property("Capacity")
+ .HasColumnType("INTEGER")
+ .HasColumnName("capacity");
+
+ b.Property("CreatedByUserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("created_by_user_id");
+
+ b.Property("CreatedDateTimeUtc")
+ .HasColumnType("TEXT")
+ .HasColumnName("created_date_time_utc");
+
+ b.Property("CurrentFloor")
+ .HasColumnType("INTEGER")
+ .HasColumnName("current_floor");
+
+ b.Property("ElevatorDirection")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("elevator_direction");
+
+ b.Property("ElevatorStatus")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("elevator_status");
+
+ b.Property("ElevatorType")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("elevator_type");
+
+ b.Property("Number")
+ .HasColumnType("INTEGER")
+ .HasColumnName("number");
+
+ b.Property("Speed")
+ .HasColumnType("REAL")
+ .HasColumnName("speed");
+
+ b.Property("UpdatedByUserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("updated_by_user_id");
+
+ b.Property("UpdatedDateTimeUtc")
+ .HasColumnType("TEXT")
+ .HasColumnName("updated_date_time_utc");
+
+ b.HasKey("Id")
+ .HasName("pk_elevators");
+
+ b.HasIndex("CreatedByUserId")
+ .HasDatabaseName("ix_elevators_created_by_user_id");
+
+ b.HasIndex("UpdatedByUserId")
+ .HasDatabaseName("ix_elevators_updated_by_user_id");
+
+ b.HasIndex("BuildingId", "Number")
+ .IsUnique()
+ .HasDatabaseName("ix_elevators_building_id_number");
+
+ b.ToTable("elevators", "dbo");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("852bb6fa-1831-49ef-a0d9-5bfa5f567841"),
+ BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ Capacity = 10,
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ CurrentFloor = 1,
+ ElevatorDirection = "None",
+ ElevatorStatus = "Active",
+ ElevatorType = "Passenger",
+ Number = 1,
+ Speed = 0.5
+ },
+ new
+ {
+ Id = new Guid("14ef29a8-001e-4b70-93b6-bfdb00237d46"),
+ BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ Capacity = 10,
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ CurrentFloor = 1,
+ ElevatorDirection = "None",
+ ElevatorStatus = "Active",
+ ElevatorType = "Passenger",
+ Number = 2,
+ Speed = 0.5
+ },
+ new
+ {
+ Id = new Guid("966b1041-ff39-432b-917c-b0a14ddce0bd"),
+ BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ Capacity = 10,
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ CurrentFloor = 1,
+ ElevatorDirection = "None",
+ ElevatorStatus = "Active",
+ ElevatorType = "Passenger",
+ Number = 3,
+ Speed = 0.5
+ },
+ new
+ {
+ Id = new Guid("b8557436-6472-4ad7-b111-09c8a023c463"),
+ BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ Capacity = 10,
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ CurrentFloor = 1,
+ ElevatorDirection = "None",
+ ElevatorStatus = "Active",
+ ElevatorType = "Passenger",
+ Number = 4,
+ Speed = 0.5
+ },
+ new
+ {
+ Id = new Guid("bbfbdffa-f7cd-4241-a222-85a733098782"),
+ BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
+ Capacity = 10,
+ CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+ CurrentFloor = 1,
+ ElevatorDirection = "None",
+ ElevatorStatus = "Active",
+ ElevatorType = "Passenger",
+ Number = 5,
+ Speed = 0.5
+ });
+ });
+
+ modelBuilder.Entity("Domain.Users.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("id");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("email");
+
+ b.Property("FirstName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("first_name");
+
+ b.Property("LastName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("last_name");
+
+ b.Property("PasswordHash")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("password_hash");
+
+ b.HasKey("Id")
+ .HasName("pk_users");
+
+ b.HasIndex("Email")
+ .IsUnique()
+ .HasDatabaseName("ix_users_email");
+
+ b.ToTable("users", "dbo");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ Email = "admin@building.com",
+ FirstName = "Admin",
+ LastName = "Joe",
+ PasswordHash = "55BC042899399B562DD4A363FD250A9014C045B900716FCDC074861EB69C344A-B44367BE2D0B037E31AEEE2649199100"
+ });
+ });
+
+ modelBuilder.Entity("Domain.Buildings.Building", b =>
+ {
+ b.HasOne("Domain.Users.User", "CreatedByUser")
+ .WithMany()
+ .HasForeignKey("CreatedByUserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired()
+ .HasConstraintName("fk_buildings_users_created_by_user_id");
+
+ b.HasOne("Domain.Users.User", "UpdatedByUser")
+ .WithMany()
+ .HasForeignKey("UpdatedByUserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .HasConstraintName("fk_buildings_users_updated_by_user_id");
+
+ b.Navigation("CreatedByUser");
+
+ b.Navigation("UpdatedByUser");
+ });
+
+ modelBuilder.Entity("Domain.Elevators.Elevator", b =>
+ {
+ b.HasOne("Domain.Buildings.Building", "Building")
+ .WithMany()
+ .HasForeignKey("BuildingId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired()
+ .HasConstraintName("fk_elevators_buildings_building_id");
+
+ b.HasOne("Domain.Users.User", "CreatedByUser")
+ .WithMany()
+ .HasForeignKey("CreatedByUserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_elevators_users_created_by_user_id");
+
+ b.HasOne("Domain.Users.User", "UpdatedByUser")
+ .WithMany()
+ .HasForeignKey("UpdatedByUserId")
+ .HasConstraintName("fk_elevators_users_updated_by_user_id");
+
+ b.Navigation("Building");
+
+ b.Navigation("CreatedByUser");
+
+ b.Navigation("UpdatedByUser");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Infrastructure/Migrations/20241209122830_TypoFix.cs b/src/Infrastructure/Migrations/20241209122830_TypoFix.cs
new file mode 100644
index 0000000..1654b46
--- /dev/null
+++ b/src/Infrastructure/Migrations/20241209122830_TypoFix.cs
@@ -0,0 +1,63 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Infrastructure.Migrations
+{
+ ///
+ public partial class TypoFix : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DeleteData(
+ schema: "dbo",
+ table: "elevators",
+ keyColumn: "id",
+ keyValue: new Guid("82d562f7-f7d5-4088-b735-9a7b085968d3"));
+
+ migrationBuilder.UpdateData(
+ schema: "dbo",
+ table: "elevators",
+ keyColumn: "id",
+ keyValue: new Guid("bbfbdffa-f7cd-4241-a222-85a733098782"),
+ column: "elevator_type",
+ value: "Passenger");
+
+ migrationBuilder.UpdateData(
+ schema: "dbo",
+ table: "users",
+ keyColumn: "id",
+ keyValue: new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ column: "email",
+ value: "admin@building.com");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.UpdateData(
+ schema: "dbo",
+ table: "elevators",
+ keyColumn: "id",
+ keyValue: new Guid("bbfbdffa-f7cd-4241-a222-85a733098782"),
+ column: "elevator_type",
+ value: "Service");
+
+ migrationBuilder.InsertData(
+ schema: "dbo",
+ table: "elevators",
+ columns: new[] { "id", "building_id", "capacity", "created_by_user_id", "created_date_time_utc", "current_floor", "elevator_direction", "elevator_status", "elevator_type", "number", "speed", "updated_by_user_id", "updated_date_time_utc" },
+ values: new object[] { new Guid("82d562f7-f7d5-4088-b735-9a7b085968d3"), new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"), 5, new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"), new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), 1, "None", "Active", "HighSpeed", 6, 1.0, null, null });
+
+ migrationBuilder.UpdateData(
+ schema: "dbo",
+ table: "users",
+ keyColumn: "id",
+ keyValue: new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
+ column: "email",
+ value: "admin@buiding.com");
+ }
+ }
+}
diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
index 3de2ca6..1e5d1f5 100644
--- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -218,23 +218,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
CurrentFloor = 1,
ElevatorDirection = "None",
ElevatorStatus = "Active",
- ElevatorType = "Service",
+ ElevatorType = "Passenger",
Number = 5,
Speed = 0.5
- },
- new
- {
- Id = new Guid("82d562f7-f7d5-4088-b735-9a7b085968d3"),
- BuildingId = new Guid("e16e32e7-8db0-4536-b86e-f53e53cd7a0d"),
- Capacity = 5,
- CreatedByUserId = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
- CreatedDateTimeUtc = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
- CurrentFloor = 1,
- ElevatorDirection = "None",
- ElevatorStatus = "Active",
- ElevatorType = "HighSpeed",
- Number = 6,
- Speed = 1.0
});
});
@@ -278,7 +264,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
new
{
Id = new Guid("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
- Email = "admin@buiding.com",
+ Email = "admin@building.com",
FirstName = "Admin",
LastName = "Joe",
PasswordHash = "55BC042899399B562DD4A363FD250A9014C045B900716FCDC074861EB69C344A-B44367BE2D0B037E31AEEE2649199100"
diff --git a/src/Infrastructure/Persistence/SeedData/ApplicationDbContextSeedData.cs b/src/Infrastructure/Persistence/SeedData/ApplicationDbContextSeedData.cs
index 28512eb..7d8fd79 100644
--- a/src/Infrastructure/Persistence/SeedData/ApplicationDbContextSeedData.cs
+++ b/src/Infrastructure/Persistence/SeedData/ApplicationDbContextSeedData.cs
@@ -21,7 +21,7 @@ public static List GetSeedUsers()
Id = Guid.Parse("31a9cff7-dc59-4135-a762-6e814bab6f9a"),
FirstName = "Admin",
LastName = "Joe",
- Email = "admin@buiding.com",
+ Email = "admin@building.com",
PasswordHash =
"55BC042899399B562DD4A363FD250A9014C045B900716FCDC074861EB69C344A-B44367BE2D0B037E31AEEE2649199100", //Admin123
}
diff --git a/src/Presentation/App.cs b/src/Presentation/App.cs
index 09dcdd8..c400d7c 100644
--- a/src/Presentation/App.cs
+++ b/src/Presentation/App.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Presentation.Screens;
+using Presentation.Screens.Dashboard;
using Spectre.Console;
namespace Presentation;
@@ -19,13 +20,14 @@ public async Task StartAsync(CancellationToken cancellationToken)
var menuScreen = serviceProvider.GetRequiredService();
var menuSelection = await menuScreen.ShowAsync(cancellationToken);
+
while (menuSelection.Value != MenuSelection.Exit)
{
switch (menuSelection.Value)
{
- case MenuSelection.Register:
- var registerScreen = serviceProvider.GetRequiredService();
- await registerScreen.ShowAsync(cancellationToken);
+ case MenuSelection.Dashboard:
+ var dashboardScreen = serviceProvider.GetRequiredService();
+ await dashboardScreen.ShowAsync(cancellationToken);
break;
case MenuSelection.Login:
var loginScreen = serviceProvider.GetRequiredService();
@@ -41,9 +43,9 @@ public async Task StartAsync(CancellationToken cancellationToken)
break;
}
- menuSelection = await menuScreen.ShowAsync(cancellationToken);
AnsiConsole.Clear();
DisplayHeader();
+ menuSelection = await menuScreen.ShowAsync(cancellationToken);
}
await StopAsync(cancellationToken);
}
diff --git a/src/Presentation/DependencyInjections.cs b/src/Presentation/DependencyInjections.cs
index d9a0e71..fcb7b1d 100644
--- a/src/Presentation/DependencyInjections.cs
+++ b/src/Presentation/DependencyInjections.cs
@@ -6,6 +6,7 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Presentation.Screens;
+using Presentation.Screens.Dashboard;
namespace Presentation;
@@ -20,6 +21,7 @@ public static IServiceCollection AddScreens(
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
return services;
}
diff --git a/src/Presentation/Screens/Dashboard/DashboardScreen.cs b/src/Presentation/Screens/Dashboard/DashboardScreen.cs
new file mode 100644
index 0000000..c929a64
--- /dev/null
+++ b/src/Presentation/Screens/Dashboard/DashboardScreen.cs
@@ -0,0 +1,119 @@
+using Application.Abstractions.Screen;
+using Application.Abstractions.Services;
+using Application.Services;
+using Domain.Common;
+using Domain.Elevators;
+using Infrastructure.Migrations;
+using Infrastructure.Persistence.SeedData;
+using Microsoft.Extensions.DependencyInjection;
+using Presentation.Extensions;
+using Spectre.Console;
+
+namespace Presentation.Screens.Dashboard;
+
+/// Dashboard screen which displays the current status of the elevators in the building.
+public class DashboardScreen(IServiceProvider serviceProvider) : IScreen
+{
+ public async Task> ShowAsync(CancellationToken token)
+ {
+ AnsiConsole.Clear();
+
+ var cts = new CancellationTokenSource();
+ var exitTask = Task.Run(() =>
+ {
+ while (!cts.Token.IsCancellationRequested)
+ {
+ if (Console.KeyAvailable)
+ {
+ var key = Console.ReadKey(intercept: true).Key;
+ if (key == ConsoleKey.C)
+ {
+ cts.Cancel();
+ }
+ }
+ }
+ });
+
+ try
+ {
+ while (!cts.Token.IsCancellationRequested)
+ {
+ AnsiConsole.Write(
+ new FigletText(" Dashboard")
+ .LeftJustified()
+ .Color(Color.Blue)
+ );
+
+ var reload = true;
+ var buildingId = ApplicationDbContextSeedData.GetSeedBuildings().First()!.Id;
+ Result> result = null;
+ await AnsiConsole.Status()
+ .StartAsync("Retrieving configured elevators...", async ctx =>
+ {
+ var elevatorPoolService = serviceProvider.GetRequiredService();
+ result =
+ await elevatorPoolService.GetAllElevatorsAsync(buildingId, token);
+ });
+
+ _ = result?.Match(
+ onSuccess: elevators =>
+ {
+ var table = new Table();
+ table.AddColumn("Elevator Number");
+ table.AddColumn("Current Floor");
+ table.AddColumn("Direction");
+ table.AddColumn("Status");
+ table.AddColumn("Type");
+ table.AddColumn("Speed");
+ table.AddColumn("Capacity");
+ foreach (var elevator in elevators.OrderBy(a => a.Number))
+ {
+ table.AddRow(
+ elevator.Number.ToString(),
+ elevator.CurrentFloor.ToString(),
+ elevator.ElevatorDirection.ToString(),
+ elevator.ElevatorStatus.ToString(),
+ elevator.ElevatorType.ToString(),
+ elevator.Speed.ToString(),
+ elevator.Capacity.ToString());
+ }
+
+ AnsiConsole.Render(table);
+ return true;
+ },
+ onFailure: error =>
+ {
+ var friendlyError = error.Error switch
+ {
+ ValidationError validationError => string.Join(", ",
+ validationError.Errors.Select(e => e.Description)),
+ _ => "An error occurred while retrieving the elevators."
+ };
+ AnsiConsole.MarkupLine($"[red]{friendlyError}[/]");
+ return false;
+ }) ?? false;
+
+ AnsiConsole.WriteLine("Press [green]C[/] to exit or press any key to pause the counter...");
+ await AnsiConsole.Status()
+ .StartAsync($"Refreshing elevators in 1 second.... {DateTime.UtcNow.ToLocalTime()}", async ctx =>
+ {
+ await Task.Delay(1000, cts.Token);
+ });
+
+ AnsiConsole.Console.Clear();
+ }
+ }
+ catch (TaskCanceledException ex)
+ {
+ //we are ignoring this one as this is the user initiated exit
+ }
+ finally
+ {
+ AnsiConsole.WriteLine("Exiting dashboard...");
+ await cts.CancelAsync();
+ await exitTask; // Ensure the background task completes
+ }
+
+ return true;
+ }
+}
diff --git a/src/Presentation/Screens/LoginScreen.cs b/src/Presentation/Screens/LoginScreen.cs
index cb24a0e..c0a733d 100644
--- a/src/Presentation/Screens/LoginScreen.cs
+++ b/src/Presentation/Screens/LoginScreen.cs
@@ -3,6 +3,8 @@
using MediatR;
using Presentation.Extensions;
using Domain.Common;
+using Infrastructure.Migrations;
+using Infrastructure.Persistence.SeedData;
using Spectre.Console;
namespace Presentation.Screens;
@@ -17,7 +19,16 @@ public async Task> ShowAsync(CancellationToken token)
while (tryAgain)
{
AnsiConsole.Clear();
- AnsiConsole.MarkupLine("[bold]User Login[/]");
+ AnsiConsole.Write(
+ new FigletText("User Login")
+ .LeftJustified()
+ .Color(Color.Blue)
+ );
+
+ var admin = ApplicationDbContextSeedData.GetSeedUsers().First();
+ var tempMessage = $"Administrator User: Email: {admin.Email}, Password: Admin123";
+ AnsiConsole.MarkupLine($"[bold]{tempMessage}[/]");
+
var email = AnsiConsole.Prompt(
new TextPrompt("What's your email?"));
var password = AnsiConsole.Prompt(
@@ -25,7 +36,7 @@ public async Task> ShowAsync(CancellationToken token)
.Secret());
await AnsiConsole.Status()
- .StartAsync("Thinking...", async ctx =>
+ .StartAsync("Loading...", async ctx =>
{
var loginCommand = new LoginUserCommand(email, password);
loginResult = await mediator.Send(loginCommand, token);
diff --git a/src/Presentation/Screens/MenuScreen.cs b/src/Presentation/Screens/MenuScreen.cs
index a711a12..06e6869 100644
--- a/src/Presentation/Screens/MenuScreen.cs
+++ b/src/Presentation/Screens/MenuScreen.cs
@@ -11,8 +11,9 @@ public class MenuScreen : IScreen
private static readonly Dictionary MenuOptions = new()
{
["Login"] = MenuSelection.Login,
- ["Register"] = MenuSelection.Register,
+ ["Dashboard"] = MenuSelection.Dashboard,
["Exit"] = MenuSelection.Exit
+
};
public async Task> ShowAsync(CancellationToken token)
@@ -20,7 +21,7 @@ public async Task> ShowAsync(CancellationToken token)
var selection = AnsiConsole.Prompt(
new SelectionPrompt()
.Title("Welcome to the Elevator Management Simulator")
- .PageSize(3)
+ .PageSize(10)
.AddChoices(MenuOptions.Keys));
if (MenuOptions.TryGetValue(selection, out var result))