3 Commits

Author SHA1 Message Date
JonathanMcCaffrey 2625992014 ... 2026-06-04 11:29:24 -04:00
JonathanMcCaffrey 377a041afa ... 2026-06-04 11:12:23 -04:00
JonathanMcCaffrey 6e58c63082 ... 2026-06-04 11:05:21 -04:00
93 changed files with 254 additions and 190 deletions
+1
View File
@@ -76,6 +76,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Components\Components.csproj"/> <ProjectReference Include="..\Components\Components.csproj"/>
<ProjectReference Include="..\Model\Model.csproj"/> <ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Pages\Pages.csproj"/>
<ProjectReference Include="..\Services\Services.csproj"/> <ProjectReference Include="..\Services\Services.csproj"/>
</ItemGroup> </ItemGroup>
+18 -1
View File
@@ -2,4 +2,21 @@
<MudDialogProvider/> <MudDialogProvider/>
<MudSnackbarProvider/> <MudSnackbarProvider/>
<HomePage/> <Router AppAssembly="@typeof(IGP.Pages.Home.HomePage).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
<EntityDialogPortal/>
<GlossaryDialogPortal/>
<ToastPortal/>
<SearchPortal/>
<ConfirmationDialogPortal/>
@@ -1,71 +0,0 @@
<a href="@Href" class="contentHighlight">
<div class="contentHighlightTitle">
@Title
</div>
<img width="268px" height="161px" src="@ImageHref" class="contentHighlightImage" alt="@Title"/>
<div class="contentHighlightCallToAction">
@Description
</div>
</a>
<style>
.contentHighlight {
background-color: var(--paper);
border: 1px solid var(--paper-border);
border-radius: 2px;
padding-left: 12px;
padding-right: 12px;
padding-top: 24px;
padding-bottom: 24px;
color: white;
display: flex;
flex-direction: column;
gap: 12px;
text-align: center;
margin-left: 12px;
margin-right: 12px;
}
.contentHighlight:hover {
background-color: var(--paper-hover);
border-color: var(--paper-border-hover);
text-decoration: none;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.6);
transform: translateY(-2px) scale(1.01);
}
.contentHighlightTitle {
font-weight: 800;
font-size: 1.3rem;
margin: auto;
}
.contentHighlightImage {
border: 1px solid rgba(0, 0, 0, 0.5);
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
width: calc(100% - 32px);
margin-left: auto;
margin-right: auto;
margin-top: 12px;
margin-bottom: 12px;
}
.contentHighlightCallToAction {
font-weight: 700;
font-size: 1.1rem;
margin: auto;
padding: 16px;
}
</style>
@code {
[Parameter] public string Href { get; set; } = default!;
[Parameter] public string Title { get; set; } = default!;
[Parameter] public string Description { get; set; } = default!;
[Parameter] public string ImageHref { get; set; } = default!;
}
-47
View File
@@ -1,47 +0,0 @@
<LayoutMediumContentComponent>
<PaperComponent>
<div class="mainContainer">
<div class="mainTitle">
IGP Fan Reference
</div>
<div>
Refer to various aspects of "IMMORTAL: Gates of Pyre" from this external reference!
</div>
</div>
</PaperComponent>
<ContentDividerComponent></ContentDividerComponent>
<PaperComponent>
<div class="heroesContainer">
<ContentHighlightComponent Title="Build Calculator"
Description="Make a build!"
Href="https://igpfanreference.ca/build-calculator"
ImageHref="image/hero/Build.png"/>
<ContentHighlightComponent Title="Database"
Description="Review the units!"
Href="https://igpfanreference.ca/database"
ImageHref="image/hero/Database.png"/>
</div>
</PaperComponent>
</LayoutMediumContentComponent>
<style>
.mainContainer {
padding-bottom: 32px;
}
.mainTitle {
font-size: 2.2rem;
font-weight: bold;
}
.heroesContainer {
display: grid;
gap: 64px;
justify-content: center;
margin: auto;
grid-template-columns: 1fr 1fr;
}
@@media only screen and (max-width: 1025px) {
.heroesContainer {
grid-template-columns: 1fr;
}
}
</style>
+16 -1
View File
@@ -5,7 +5,22 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using Device @using Device
@using Device.Pages @using IGP.Pages
@using IGP.Pages.Home
@using IGP.Pages.Home.Parts
@using IGP.Dialog
@using IGP.Pages.BuildCalculator
@using IGP.Pages.BuildCalculator.Parts
@using IGP.Pages.Database.Entity
@using IGP.Pages.Database.Entity.Parts
@using IGP.Pages.Database.Parts
@using IGP.Pages.EconomyComparison
@using IGP.Pages.EconomyComparison.Parts
@using IGP.Pages.MemoryTester.Parts
@using IGP.Pages.Notes
@using IGP.Pages.Notes.Parts
@using IGP.Portals
@using IGP.Utils
@using Components.Display @using Components.Display
@using Components.Feedback @using Components.Feedback
+14
View File
@@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "API\API.csproj", "{6
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device", "Device\Device.csproj", "{FF07C814-9757-48B5-8450-CFA4958EC42D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device", "Device\Device.csproj", "{FF07C814-9757-48B5-8450-CFA4958EC42D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pages", "Pages\Pages.csproj", "{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -125,6 +127,18 @@ Global
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x64.Build.0 = Release|Any CPU {FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x64.Build.0 = Release|Any CPU
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.ActiveCfg = Release|Any CPU {FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.ActiveCfg = Release|Any CPU
{FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.Build.0 = Release|Any CPU {FF07C814-9757-48B5-8450-CFA4958EC42D}.Release|x86.Build.0 = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x64.ActiveCfg = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x64.Build.0 = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x86.ActiveCfg = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Debug|x86.Build.0 = Debug|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|Any CPU.Build.0 = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x64.ActiveCfg = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x64.Build.0 = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x86.ActiveCfg = Release|Any CPU
{3BFCB341-D41D-4F23-B867-EB4A8F58BB14}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+1 -1
View File
@@ -9,7 +9,7 @@ public class WebsiteData
* Flag for content generated by the AI. Can contain UI that makes no sense, or more importantly, * Flag for content generated by the AI. Can contain UI that makes no sense, or more importantly,
* game data that is not real. Fun to look at, but needs to be thoroughly vetted before it can ever go live. * game data that is not real. Fun to look at, but needs to be thoroughly vetted before it can ever go live.
*/ */
public static bool allowSlopData { get; set; } = false; public static bool allowSlopData { get; set; } = true;
private static bool IsPageAllowed(WebPageModel page) private static bool IsPageAllowed(WebPageModel page)
{ {
+42
View File
@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>IGP</RootNamespace>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="1.1.1"/>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.5"/>
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.5"/>
<PackageReference Include="MudBlazor" Version="9.2.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Components\Components.csproj"/>
<ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Services\Services.csproj"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Localizations.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Localizations.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Localizations.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Localizations.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -35,7 +34,7 @@
The game hasn't even been released. Isn't it a bit early for publishing community tools? The game hasn't even been released. Isn't it a bit early for publishing community tools?
</InfoQuestionComponent> </InfoQuestionComponent>
<InfoAnswerComponent> <InfoAnswerComponent>
Maybe 🙂 Maybe ??
</InfoAnswerComponent> </InfoAnswerComponent>
</InfoBodyComponent> </InfoBodyComponent>
<InfoBodyComponent> <InfoBodyComponent>
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -1,4 +1,3 @@
@layout PageLayout
@inject IDataCollectionService DataCollectionService @inject IDataCollectionService DataCollectionService
@inherits BasePage @inherits BasePage
@@ -1,9 +1,8 @@
@page "/data-collection" @page "/data-collection"
@inject IDataCollectionService DataCollectionService @inject IDataCollectionService DataCollectionService
@inherits BasePage @inherits BasePage
@layout PageLayout
<LayoutMediumContentComponent> <LayoutMediumContentComponent>
@@ -1,4 +1,3 @@
@layout PageLayout
@using IGP.Pages.DataTables.Parts @using IGP.Pages.DataTables.Parts
@inherits BasePage @inherits BasePage
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@page "/database" @page "/database"
@using Model @using Model
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -1,10 +1,9 @@
@page "/economy-comparison" @page "/economy-comparison"
@inherits BasePage @inherits BasePage
@implements IDisposable @implements IDisposable
@inject IEconomyComparisonService EconomyComparisonService @inject IEconomyComparisonService EconomyComparisonService
@layout PageLayout
<LayoutMediumContentComponent> <LayoutMediumContentComponent>
<WebsiteTitleComponent>Economy Comparision</WebsiteTitleComponent> <WebsiteTitleComponent>Economy Comparision</WebsiteTitleComponent>
@@ -1,4 +1,3 @@
@layout PageLayout
@inject IGlossaryService glossaryService @inject IGlossaryService glossaryService
@inject IGlossaryDialogService glossaryDialogService @inject IGlossaryDialogService glossaryDialogService
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@inject IGlossaryService glossaryService @inject IGlossaryService glossaryService
@inject IGlossaryDialogService glossaryDialogService @inject IGlossaryDialogService glossaryDialogService
@@ -1,4 +1,3 @@
@layout PageLayout
@inject IDataCollectionService DataCollectionService @inject IDataCollectionService DataCollectionService
@using Model @using Model
@@ -168,12 +167,12 @@
<MathLoopSumComponent> <MathLoopSumComponent>
<LoopStart><i>x</i> =1</LoopStart> <LoopStart><i>x</i> =1</LoopStart>
<LoopEnd> <LoopEnd>
?
<MathDivisionComponent> <MathDivisionComponent>
<Dividee>m</Dividee> <Dividee>m</Dividee>
<Divider>a</Divider> <Divider>a</Divider>
</MathDivisionComponent> </MathDivisionComponent>
?
</LoopEnd> </LoopEnd>
<IndexSymbol> <IndexSymbol>
<i>x</i> <i>x</i>
@@ -1,7 +1,7 @@
@layout PageLayout;
@inherits BasePage @inherits BasePage
@page "/"
@page "/immortal-home" @page "/immortal-home"
<LayoutMediumContentComponent> <LayoutMediumContentComponent>
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@@ -1,7 +1,6 @@
@page "/permissions" @page "/permissions"
@inject IPermissionService PermissionService @inject IPermissionService PermissionService
@layout PageLayout
@inject IMyDialogService MyDialogService @inject IMyDialogService MyDialogService
@@ -1,11 +1,10 @@
@page "/storage" @page "/storage"
@inherits BasePage @inherits BasePage
@inject IStorageService StorageService @inject IStorageService StorageService
@using Services.Website @using Services.Website
@implements IDisposable @implements IDisposable
@layout PageLayout
<LayoutMediumContentComponent> <LayoutMediumContentComponent>
@if (!_enabledPermissions) @if (!_enabledPermissions)
@@ -1,8 +1,7 @@
@page "/streams" @page "/streams"
@inherits BasePage @inherits BasePage
@layout PageLayout
<LayoutMediumContentComponent> <LayoutMediumContentComponent>
<WebsiteTitleComponent>Streams</WebsiteTitleComponent> <WebsiteTitleComponent>Streams</WebsiteTitleComponent>
@@ -1,4 +1,3 @@
@layout PageLayout
@inherits BasePage @inherits BasePage
@inject TechTreeService techTreeService @inject TechTreeService techTreeService
@inject IEntityDialogService entityDialogService @inject IEntityDialogService entityDialogService
+58
View File
@@ -0,0 +1,58 @@
@using Components.Display
@using Components.Feedback
@using Components.TechTree
@using Components.Form
@using Components.Info
@using Components.Inputs
@using Components.Layout
@using Components.Navigation
@using Components.Shared
@using Markdig
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.Extensions.Localization
@using Microsoft.JSInterop
@using Model.Chart
@using Model.Economy
@using Model.Entity
@using Model.Entity.Data
@using Model.Entity.Parts
@using Model.Feedback
@using Model.Glossary
@using Model.Hotkeys
@using Model.MemoryTester
@using Model.Notes
@using Model.RoadMap
@using Model.RoadMap.Enums
@using Model.TechTree
@using Model.Types
@using Model.Website
@using Services
@using Services.Immortal
@using Services.Website
@using System.Globalization
@using System.Reflection
@using System.Timers
@using MudBlazor
@using IGP.Pages
@using IGP.Pages.BuildCalculator
@using IGP.Pages.BuildCalculator.Parts
@using IGP.Pages.BuildCalculator.Parts.Cosmetic
@using IGP.Pages.Database
@using IGP.Pages.Database.Entity
@using IGP.Pages.Database.Entity.Parts
@using IGP.Pages.Database.Parts
@using IGP.Pages.EconomyComparison
@using IGP.Pages.EconomyComparison.Parts
@using IGP.Pages.Home
@using IGP.Pages.Home.Parts
@using IGP.Pages.MemoryTester
@using IGP.Pages.MemoryTester.Parts
@using IGP.Pages.Notes
@using IGP.Pages.Notes.Parts
@using IGP.Dialog
@using IGP.Portals
@using IGP.Utils
+3 -2
View File
@@ -3,11 +3,12 @@
@inject IGlossaryDialogService GlossaryDialogService @inject IGlossaryDialogService GlossaryDialogService
@inject IJSRuntime JsRuntime @inject IJSRuntime JsRuntime
<Router AppAssembly="@typeof(App).Assembly"> <Router AppAssembly="@typeof(App).Assembly"
AdditionalAssemblies="@(new[] { typeof(HomePage).Assembly })">
<Found Context="routeData"> <Found Context="routeData">
@if (isLoaded) @if (isLoaded)
{ {
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/> <RouteView RouteData="@routeData" DefaultLayout="@typeof(PageLayout)"/>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/> <FocusOnNavigate RouteData="@routeData" Selector="h1"/>
} }
</Found> </Found>
-5
View File
@@ -1,5 +0,0 @@
@page "/"
@layout PageLayout
<HomePage/>
+1 -15
View File
@@ -37,26 +37,12 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Components\Components.csproj"/> <ProjectReference Include="..\Components\Components.csproj"/>
<ProjectReference Include="..\Model\Model.csproj"/> <ProjectReference Include="..\Model\Model.csproj"/>
<ProjectReference Include="..\Pages\Pages.csproj"/>
<ProjectReference Include="..\Services\Services.csproj"/> <ProjectReference Include="..\Services\Services.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Pages\DataTables\Parts\"/>
<Folder Include="wwwroot\generated"/> <Folder Include="wwwroot\generated"/>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Localizations.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Localizations.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Localizations.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Example.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project> </Project>
+7 -20
View File
@@ -42,30 +42,16 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "Helper Tutorial Info Improvements.md", "file": "Device MAUI Pages Setup.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "Helper Tutorial Info Improvements" "title": "Device MAUI Pages Setup"
}
},
{
"id": "b98a69cefb529fc8",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "Feature Proposals.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "Feature Proposals"
} }
} }
], ],
"currentTab": 3 "currentTab": 2
} }
], ],
"direction": "vertical" "direction": "vertical"
@@ -237,8 +223,11 @@
"bases:Create new base": false "bases:Create new base": false
} }
}, },
"active": "b98a69cefb529fc8", "active": "68e1ba2b54081b9a",
"lastOpenFiles": [ "lastOpenFiles": [
"Build Calculator CmdLine.md",
"Device MAUI Pages Setup.md",
"Feature Proposals.md",
"_Tasks Kanban.base", "_Tasks Kanban.base",
"Tasks/Worker Income UI and Tests.md", "Tasks/Worker Income UI and Tests.md",
"Tasks/Update the Reference Tables with Telerik.md", "Tasks/Update the Reference Tables with Telerik.md",
@@ -263,8 +252,6 @@
"Tasks/Get AI to Add easy Test Tasks.md", "Tasks/Get AI to Add easy Test Tasks.md",
"Tasks/Helper Tutorial Info Improvements.md", "Tasks/Helper Tutorial Info Improvements.md",
"Tasks/Fix Entity Recursion Error - Parent.md", "Tasks/Fix Entity Recursion Error - Parent.md",
"Tasks/Fully Test the Build Calculator.md",
"Tasks/Ensure build order gets greyed out past the attack time. Clicking the cancel button will wipe the entire greyed out timeline..md",
"Tasks", "Tasks",
"Images/Pasted image 20260601093510.png", "Images/Pasted image 20260601093510.png",
"Images/Pasted image 20260601083333.png", "Images/Pasted image 20260601083333.png",
+84
View File
@@ -0,0 +1,84 @@
# Device MAUI Pages Setup
Changes needed to get all shared pages rendering in the Device (MAUI Blazor) project.
## How pages render
`MainRazor.razor` has a `Router` pointing at the Pages assembly. When the URL matches a `@page` directive (e.g. `/database`), the Router renders that page component with `MainLayout`. All component references resolve from the Components or Pages project. All DI services are already registered in `MauiProgram.cs`.
Only two things block pages from rendering currently:
## 1. No route for `/`
The MAUI app starts at `/`, but `HomePage` only has `@page "/immortal-home"`. Nothing matches → NotFound.
**Fix:** Add `@page "/"` to `Pages/Pages/Home/HomePage.razor`:
```razor
@page "/"
@page "/immortal-home"
```
Then remove `Web/Index.razor` — its `@page "/"` wrapper is redundant since the Pages project now provides the route directly, and `App.razor` already uses `PageLayout` as the default layout.
## 2. Move dialog portals from Web to Pages
Pages like `BuildCalculatorPage` and `DatabasePage` trigger dialogs via `IEntityDialogService` etc. The portal components that render the dialog UI (`EntityDialogPortal`, `GlossaryDialogPortal`, `ToastPortal`, `SearchPortal`, `ConfirmationDialogPortal`) live in `Web/Portals/`. The dialog components themselves live in `Web/Dialog/`.
Since the Device project can't reference the Web project, these need to be moved into the Pages project so both Web and Device can use them:
- `Web/Portals/*``Pages/Portals/`
- `Web/Dialog/*``Pages/Dialog/`
Then add them to `Device/MainRazor.razor`:
```razor
<MudThemeProvider IsDarkMode="true"/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<EntityDialogPortal/>
<GlossaryDialogPortal/>
<ToastPortal/>
<SearchPortal/>
<ConfirmationDialogPortal/>
<Router AppAssembly="@typeof(IGP.Pages.Home.HomePage).Assembly">
...
</Router>
```
And add the same portal rendering to `Web/App.razor` (already present, but the types now come from Pages instead of Web).
## 3. Add storage loading gate (optional)
The Web project's `App.razor` gates rendering behind `isLoaded` (waits for `IStorageService.Load()`). Some pages may depend on stored data. Add to `MainRazor.razor`:
```razor
@inject IStorageService StorageService
@if (isLoaded)
{
<Router ...>
...
</Router>
}
@code {
private bool isLoaded;
protected override async Task OnInitializedAsync()
{
await StorageService.Load();
isLoaded = true;
}
}
```
## 4. Static assets
Images referenced by pages (e.g. `image/hero/Build.png`) are served from `wwwroot/`. These are already copied from `Web/wwwroot/image/hero/` to `Device/wwwroot/image/hero/`. Check for additional asset references as more pages are used.
## 5. HttpClient base address
`MauiProgram.cs` line 73 sets `BaseAddress = new Uri("https://0.0.0.0")`. Won't resolve real API calls (e.g. markdown content loading). Needs a valid API URL for the MAUI environment.