@model FloorPlanEditorViewModel @{ ViewData["Title"] = Model.FloorPlan.FloorPlanID == 0 ? "New Floor Plan" : Model.FloorPlan.Name; ViewData["ProjectSection"] = "Floor Plans"; var activeFloor = Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name).FirstOrDefault(); var blocksByFloor = Model.Blocks.GroupBy(x => x.FloorPlanFloorID).ToDictionary(x => x.Key, x => x.ToList()); var transitionsByFloor = Model.Transitions.GroupBy(x => x.FloorPlanFloorID).ToDictionary(x => x.Key, x => x.ToList()); var selectedBlockId = int.TryParse(Context.Request.Query["selectedBlockId"], out var parsedSelectedBlockId) ? parsedSelectedBlockId : 0; string BlockClass(string blockType) => $"floor-plan-block floor-plan-block--{blockType.ToLowerInvariant()}"; string CssNumber(decimal value) => value.ToString("0.###", System.Globalization.CultureInfo.InvariantCulture); string TransitionDetails(FloorPlanTransitionEditViewModel transition) { var details = $"{transition.FromLocationName} -> {transition.ToLocationName}\n{transition.TransitionType}"; return string.IsNullOrWhiteSpace(transition.DisplayLabel) ? details : $"{details}\n{transition.DisplayLabel}"; } string TransitionMarkerType(string? transitionType) { var normalized = (transitionType ?? string.Empty) .Trim() .Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("-", string.Empty, StringComparison.OrdinalIgnoreCase) .ToLowerInvariant(); return normalized switch { "door" => "door", "doubledoor" => "double-door", "window" => "window", "archway" or "opening" => "archway", "secretdoor" => "secret-door", "blockeddoor" => "blocked-door", "exteriordoor" => "exterior-door", "stairs" or "stair" => "stairs", "passage" => "passage", _ => "other" }; } string TransitionMarkerSvg(string markerType) => markerType switch { "door" => @"", "double-door" => @"", "window" => @"", "archway" => @"", "secret-door" => @"", "blocked-door" => @"", "exterior-door" => @"", "stairs" => @"", "passage" => @"", _ => @"x" }; }

Location floor plan

@Model.FloorPlan.Name

Back to floor plans
@if (TempData["FloorPlanMessage"] is string message) {
@message
} @if (TempData["FloorPlanError"] is string error) {
@error
}

Linked Location: @(string.IsNullOrWhiteSpace(Model.FloorPlan.LocationPath) ? "A matching Location will be created or linked on save." : Model.FloorPlan.LocationPath)

@if (!Model.Floors.Any()) {

No floors yet

Add a floor to start arranging linked locations.

Add floor

} else {
Active floor @activeFloor?.Name
@foreach (var floor in Model.Floors.OrderBy(x => x.SortOrder).ThenBy(x => x.Name)) { var isActive = floor.FloorPlanFloorID == activeFloor?.FloorPlanFloorID; }
Saved Back to floor plans
@for (var i = 0; i < Model.Floors.Count; i++) { var floor = Model.Floors[i]; var isActive = floor.FloorPlanFloorID == activeFloor?.FloorPlanFloorID; var floorBlocks = blocksByFloor.GetValueOrDefault(floor.FloorPlanFloorID) ?? []; var floorTransitions = transitionsByFloor.GetValueOrDefault(floor.FloorPlanFloorID) ?? [];
@if (!string.IsNullOrWhiteSpace(floor.BackgroundImagePath)) { } @foreach (var block in floorBlocks) { var blockIndex = Model.Blocks.FindIndex(x => x.FloorPlanBlockID == block.FloorPlanBlockID); } @foreach (var transition in floorTransitions) { var transitionDetails = TransitionDetails(transition); var markerType = TransitionMarkerType(transition.TransitionType);
@Html.Raw(TransitionMarkerSvg(markerType))
}
}
@foreach (var floor in Model.Floors) {
} @foreach (var floor in Model.Floors) { var placedBlockCount = Model.Blocks.Count(x => x.FloorPlanFloorID == floor.FloorPlanFloorID); } @foreach (var floor in Model.Floors.Where(x => !string.IsNullOrWhiteSpace(x.BackgroundImagePath))) { } @foreach (var transition in Model.Transitions) { var transitionFloorBlocks = blocksByFloor.GetValueOrDefault(transition.FloorPlanFloorID) ?? []; var transitionLocationOptions = transitionFloorBlocks .Where(x => x.LocationID.HasValue) .GroupBy(x => x.LocationID!.Value) .Select(x => x.First()) .OrderBy(x => x.LocationName) .ToList(); } @foreach (var block in Model.Blocks) { } }
@section Scripts { }