Improve loading UX with spinner and wider filter fields

Replaced plain loading text with a centered Bootstrap spinner in CatalogsGrid and MassDataGrid. Introduced hasLoaded flag for more accurate loading state handling. Increased min-width of filter input fields for better usability. Added .loading-container CSS for consistent spinner placement.
This commit is contained in:
OlgunR
2026-02-09 16:40:09 +01:00
parent 8387b71676
commit 74504c583e
4 changed files with 64 additions and 16 deletions

View File

@@ -86,8 +86,14 @@
flex: 0 0 52px; flex: 0 0 52px;
} }
.filter-value { .filter-value {
min-width: 140px; min-width: 160px;
flex: 1 1 140px; flex: 1 1 160px;
}
.loading-container {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
} }
</style> </style>
@@ -100,9 +106,13 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
<div class="alert alert-success" role="alert">@infoMessage</div> <div class="alert alert-success" role="alert">@infoMessage</div>
} }
@if (isLoading) @if (!hasLoaded || isLoading)
{ {
<p><em>Lade Daten...</em></p> <div class="loading-container">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Lade...</span>
</div>
</div>
} }
else if (items.Count == 0) else if (items.Count == 0)
{ {
@@ -196,6 +206,7 @@ else
@code { @code {
private List<CatalogReadDto> items = new(); private List<CatalogReadDto> items = new();
private bool isLoading; private bool isLoading;
private bool hasLoaded;
private string? errorMessage; private string? errorMessage;
private string? infoMessage; private string? infoMessage;
private EditContext? editContext; private EditContext? editContext;
@@ -342,6 +353,7 @@ else
finally finally
{ {
isLoading = false; isLoading = false;
hasLoaded = true;
StateHasChanged(); StateHasChanged();
} }
} }

View File

@@ -113,8 +113,14 @@
flex: 1 1 140px; flex: 1 1 140px;
} }
.filter-value-amount { .filter-value-amount {
min-width: 110px; min-width: 140px;
flex-basis: 110px; flex-basis: 140px;
}
.loading-container {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
} }
</style> </style>
@@ -127,9 +133,13 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
<div class="alert alert-success" role="alert">@infoMessage</div> <div class="alert alert-success" role="alert">@infoMessage</div>
} }
@if (isLoading) @if (!hasLoaded || isLoading)
{ {
<p><em>Lade Daten...</em></p> <div class="loading-container">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Lade...</span>
</div>
</div>
} }
else if (items.Count == 0) else if (items.Count == 0)
{ {
@@ -248,6 +258,7 @@ else
@code { @code {
private List<MassDataReadDto> items = new(); private List<MassDataReadDto> items = new();
private bool isLoading; private bool isLoading;
private bool hasLoaded;
private string? errorMessage; private string? errorMessage;
private string? infoMessage; private string? infoMessage;
private int pageIndex; private int pageIndex;
@@ -346,6 +357,7 @@ else
finally finally
{ {
isLoading = false; isLoading = false;
hasLoaded = true;
StateHasChanged(); StateHasChanged();
} }
} }

View File

@@ -45,8 +45,14 @@
flex: 0 0 52px; flex: 0 0 52px;
} }
.filter-value { .filter-value {
min-width: 140px; min-width: 160px;
flex: 1 1 140px; flex: 1 1 160px;
}
.loading-container {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
} }
</style> </style>
@@ -59,9 +65,13 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
<div class="alert alert-success" role="alert">@infoMessage</div> <div class="alert alert-success" role="alert">@infoMessage</div>
} }
@if (isLoading) @if (!hasLoaded || isLoading)
{ {
<p><em>Lade Daten...</em></p> <div class="loading-container">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Lade...</span>
</div>
</div>
} }
else if (items.Count == 0) else if (items.Count == 0)
{ {
@@ -155,6 +165,7 @@ else
@code { @code {
private List<CatalogReadDto> items = new(); private List<CatalogReadDto> items = new();
private bool isLoading; private bool isLoading;
private bool hasLoaded;
private string? errorMessage; private string? errorMessage;
private string? infoMessage; private string? infoMessage;
private EditContext? editContext; private EditContext? editContext;
@@ -301,6 +312,7 @@ else
finally finally
{ {
isLoading = false; isLoading = false;
hasLoaded = true;
StateHasChanged(); StateHasChanged();
} }
} }

View File

@@ -113,8 +113,14 @@
flex: 1 1 140px; flex: 1 1 140px;
} }
.filter-value-amount { .filter-value-amount {
min-width: 110px; min-width: 140px;
flex-basis: 110px; flex-basis: 140px;
}
.loading-container {
min-height: 160px;
display: flex;
align-items: center;
justify-content: center;
} }
</style> </style>
@@ -127,9 +133,13 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
<div class="alert alert-success" role="alert">@infoMessage</div> <div class="alert alert-success" role="alert">@infoMessage</div>
} }
@if (isLoading) @if (!hasLoaded || isLoading)
{ {
<p><em>Lade Daten...</em></p> <div class="loading-container">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Lade...</span>
</div>
</div>
} }
else if (items.Count == 0) else if (items.Count == 0)
{ {
@@ -248,6 +258,7 @@ else
@code { @code {
private List<MassDataReadDto> items = new(); private List<MassDataReadDto> items = new();
private bool isLoading; private bool isLoading;
private bool hasLoaded;
private string? errorMessage; private string? errorMessage;
private string? infoMessage; private string? infoMessage;
private int pageIndex; private int pageIndex;
@@ -346,6 +357,7 @@ else
finally finally
{ {
isLoading = false; isLoading = false;
hasLoaded = true;
StateHasChanged(); StateHasChanged();
} }
} }