Onboarding
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
@inject IJSRuntime JS
|
||||
|
||||
@if (_active)
|
||||
{
|
||||
@* Dark Backdrop Overlay *@
|
||||
<div class="onboarding-backdrop"></div>
|
||||
|
||||
@* Onboarding Instruction Card *@
|
||||
<div class="onboarding-card-container">
|
||||
<MudCard Class="onboarding-info-card pa-5 rounded-xl shadow-2xl">
|
||||
<MudCardContent Class="pa-0">
|
||||
<MudStack Spacing="3">
|
||||
@* Header / Title *@
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudIcon Icon="@Icons.Material.Filled.AutoAwesome" Style="color: #0EA5E9;" />
|
||||
<MudText Typo="Typo.h6" Style="font-weight: 700; color: white;">
|
||||
@_steps[_currentStep].Title
|
||||
</MudText>
|
||||
</MudStack>
|
||||
|
||||
@* Explanation Text *@
|
||||
<MudText Typo="Typo.body2" Style="color: #CBD5E1; line-height: 1.6; min-height: 60px;">
|
||||
@_steps[_currentStep].Content
|
||||
</MudText>
|
||||
|
||||
@* Footer / Progress & Buttons *@
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Class="mt-2">
|
||||
@* Step Count *@
|
||||
<MudText Typo="Typo.caption" Style="color: #94A3B8; font-weight: 600;">
|
||||
Schritt @(_currentStep + 1) von @_steps.Count
|
||||
</MudText>
|
||||
|
||||
@* Navigation Button Stack *@
|
||||
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
|
||||
@if (_currentStep > 0)
|
||||
{
|
||||
<MudButton Variant="Variant.Text"
|
||||
Style="color: #94A3B8; text-transform: none; border-radius: 12px;"
|
||||
OnClick="PrevStep"
|
||||
Size="Size.Small">
|
||||
Zurück
|
||||
</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton Variant="Variant.Text"
|
||||
Style="color: #94A3B8; text-transform: none; border-radius: 12px;"
|
||||
OnClick="CompleteTour"
|
||||
Size="Size.Small">
|
||||
Überspringen
|
||||
</MudButton>
|
||||
}
|
||||
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Secondary"
|
||||
Style="text-transform: none; border-radius: 12px; font-weight: 700; min-width: 80px;"
|
||||
OnClick="NextStep"
|
||||
Size="Size.Small">
|
||||
@(_currentStep == _steps.Count - 1 ? "Fertig" : "Weiter")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</div>
|
||||
}
|
||||
|
||||
<style>
|
||||
/* Backdrop behind cards but below the spotlight highlight */
|
||||
.onboarding-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(15, 23, 42, 0.4);
|
||||
backdrop-filter: blur(2px);
|
||||
z-index: 9999;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
/* Fixed positioned instruction box at the bottom center */
|
||||
.onboarding-card-container {
|
||||
position: fixed;
|
||||
bottom: 32px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 90%;
|
||||
max-width: 480px;
|
||||
z-index: 10001;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Dark theme styling for the instruction card */
|
||||
.onboarding-info-card {
|
||||
background: rgba(15, 23, 42, 0.9) !important;
|
||||
backdrop-filter: blur(16px) !important;
|
||||
-webkit-backdrop-filter: blur(16px) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08) !important;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.4) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
[Parameter] public EventCallback OnFinished { get; set; }
|
||||
|
||||
private bool _active = true;
|
||||
private int _currentStep = 0;
|
||||
|
||||
private readonly List<OnboardingStep> _steps =
|
||||
[
|
||||
new(".onboarding-nav-menu", "Die Navigation", "Hier auf der linken Seite findest du das Hauptmenü. Du kannst ganz einfach zwischen der Wochen- und Monatsübersicht wechseln oder deine Statistiken einsehen."),
|
||||
new(".onboarding-week-header", "Kalenderwoche blättern", "Hier siehst du die aktuell ausgewählte Woche. Verwende die Pfeiltasten links und rechts, um in vergangenen oder zukünftigen Wochen deine Zeiten zu erfassen."),
|
||||
new(".onboarding-day-card", "Zeiterfassung pro Tag", "Das Herzstück des Timetrackers. Trage hier deine täglichen Start- und Endzeiten sowie deine Pausen ein. Das System errechnet die Zeiten und Überstunden in Echtzeit."),
|
||||
new(".onboarding-week-summary", "Wochenzusammenfassung", "Hier siehst du auf einen Blick, wie viele Stunden du in dieser Woche gearbeitet hast, wie viel Pause du gemacht hast und wie sich dein Stundensaldo verändert hat."),
|
||||
new(".onboarding-overtime-balance", "Gleitzeitkonto", "Hier wird dein gesamtes Gleitzeitkonto über das Jahr hinweg zusammengerechnet. So weißt du immer genau, wie viele Überstunden du angesammelt hast.")
|
||||
];
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await HighlightStep();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HighlightStep()
|
||||
{
|
||||
if (_active && _steps.Count > 0)
|
||||
{
|
||||
var step = _steps[_currentStep];
|
||||
await JS.InvokeVoidAsync("window.onboarding.highlight", step.TargetSelector);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task NextStep()
|
||||
{
|
||||
if (_currentStep < _steps.Count - 1)
|
||||
{
|
||||
_currentStep++;
|
||||
await HighlightStep();
|
||||
}
|
||||
else
|
||||
{
|
||||
await CompleteTour();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PrevStep()
|
||||
{
|
||||
if (_currentStep > 0)
|
||||
{
|
||||
_currentStep--;
|
||||
await HighlightStep();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CompleteTour()
|
||||
{
|
||||
_active = false;
|
||||
await JS.InvokeVoidAsync("window.onboarding.clear");
|
||||
await OnFinished.InvokeAsync();
|
||||
}
|
||||
|
||||
private class OnboardingStep
|
||||
{
|
||||
public string TargetSelector { get; }
|
||||
public string Title { get; }
|
||||
public string Content { get; }
|
||||
|
||||
public OnboardingStep(string targetSelector, string title, string content)
|
||||
{
|
||||
TargetSelector = targetSelector;
|
||||
Title = title;
|
||||
Content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user