using OpenTheBox.Core; using OpenTheBox.Core.Crafting; using OpenTheBox.Data; using OpenTheBox.Localization; using Spectre.Console; using Spectre.Console.Rendering; namespace OpenTheBox.Rendering.Panels; /// /// Renders active crafting workstations showing progress bars and completion status. /// public static class CraftingPanel { /// /// Builds a renderable panel showing all active crafting jobs with their progress. /// public static IRenderable Render(GameState state, ContentRegistry? registry = null, LocalizationManager? loc = null) { var rows = new List(); foreach (var job in state.ActiveCraftingJobs.OrderBy(j => j.StartedAt)) { string name = job.RecipeId; if (registry is not null && registry.Recipes.TryGetValue(job.RecipeId, out var recipe)) { name = loc is not null ? loc.Get(recipe.NameKey) : recipe.NameKey; } string station = job.Workstation.ToString(); if (job.IsComplete) { // Completed: show checkmark rows.Add(new Markup($" [bold green]✓[/] [yellow]{Markup.Escape(station)}[/]: {Markup.Escape(name)} — [bold green]{Markup.Escape(loc?.Get("craft.done") ?? "Done")}[/]")); } else { // In progress: show progress bar int pct = (int)job.ProgressPercent; int barWidth = 20; int filled = barWidth * pct / 100; string bar = new string('#', filled) + new string('-', barWidth - filled); rows.Add(new Markup($" [yellow]{Markup.Escape(station)}[/]: {Markup.Escape(name)} [[{bar}]] {pct}%")); } } if (rows.Count == 0) { rows.Add(new Markup($"[dim]{Markup.Escape(loc?.Get("craft.panel.empty") ?? "No active workshops.")}[/]")); } return new Panel(new Rows(rows)) .Header($"[bold orange1]{Markup.Escape(loc?.Get("craft.panel.title") ?? "Workshops")}[/]") .Border(BoxBorder.Rounded); } }