176 lines
7.1 KiB
Plaintext
176 lines
7.1 KiB
Plaintext
@page "/"
|
|
@rendermode InteractiveServer
|
|
@inject IRadiusService RadiusService
|
|
@inject IJSRuntime JS
|
|
|
|
<div class="portal-wrapper">
|
|
<div class="portal-header">
|
|
<div class="brand-icon" style="margin: 0 auto 1rem auto; width: 60px; height: 60px; font-size: 1.8rem;">
|
|
<i class="bi bi-wifi"></i>
|
|
</div>
|
|
<h1 class="portal-title">Guest Wi-Fi Access</h1>
|
|
<p class="portal-subtitle">Enter your name to generate your instant high-speed network credentials</p>
|
|
</div>
|
|
|
|
<div class="glass-card">
|
|
@if (config != null)
|
|
{
|
|
<div style="display: flex; gap: 1rem; background: rgba(255,255,255,0.03); border: 1px solid var(--bg-card-border); padding: 0.85rem 1rem; border-radius: var(--radius-sm); margin-bottom: 1.5rem; font-size: 0.875rem;">
|
|
<div>
|
|
<i class="bi bi-clock-history text-primary" style="color: var(--primary);"></i>
|
|
<span style="color: var(--text-muted); margin-left: 0.35rem;">Session Limit:</span> <strong>@config.DefaultSessionTimeMinutes mins</strong>
|
|
</div>
|
|
<div>
|
|
<i class="bi bi-database text-teal" style="color: var(--accent-teal);"></i>
|
|
<span style="color: var(--text-muted); margin-left: 0.35rem;">Data Cap:</span> <strong>@config.DefaultDataLimitMb MB</strong>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<EditForm Model="this" OnValidSubmit="HandleRegistration">
|
|
<div class="form-group">
|
|
<label class="form-label" for="guestNameInput">Full Name or Guest Identifier</label>
|
|
<input id="guestNameInput"
|
|
type="text"
|
|
class="form-control-glass"
|
|
placeholder="e.g. Alex Taylor"
|
|
@bind="guestName"
|
|
required
|
|
disabled="@isSubmitting" />
|
|
</div>
|
|
|
|
@if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
<div style="color: var(--accent-rose); font-size: 0.875rem; margin-bottom: 1rem;">
|
|
<i class="bi bi-exclamation-circle-fill"></i> @errorMessage
|
|
</div>
|
|
}
|
|
|
|
<button type="submit" class="btn-gradient-primary" disabled="@(isSubmitting || string.IsNullOrWhiteSpace(guestName))">
|
|
@if (isSubmitting)
|
|
{
|
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
<span>Generating Access...</span>
|
|
}
|
|
else
|
|
{
|
|
<i class="bi bi-key-fill"></i>
|
|
<span>Get Wi-Fi Password</span>
|
|
}
|
|
</button>
|
|
</EditForm>
|
|
|
|
@if (result != null)
|
|
{
|
|
<div class="credentials-box">
|
|
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;">
|
|
<h3 style="font-size: 1.1rem; font-weight: 700; color: white;">
|
|
<i class="bi bi-check-circle-fill" style="color: var(--accent-teal);"></i> Access Granted!
|
|
</h3>
|
|
<span class="badge badge-emerald">Ready to Connect</span>
|
|
</div>
|
|
|
|
<p style="font-size: 0.875rem; color: var(--text-muted); margin-bottom: 1rem;">
|
|
Connect to the <strong>Guest-WiFi</strong> network on your device and enter the credentials below:
|
|
</p>
|
|
|
|
<div class="cred-row">
|
|
<div>
|
|
<div class="cred-label">Username</div>
|
|
<div class="cred-value">@result.Username</div>
|
|
</div>
|
|
<button class="copy-btn" @onclick='() => CopyToClipboard(result.Username, "Username")'>
|
|
<i class="bi bi-clipboard"></i> Copy
|
|
</button>
|
|
</div>
|
|
|
|
<div class="cred-row">
|
|
<div>
|
|
<div class="cred-label">Password</div>
|
|
<div class="cred-value" style="color: var(--accent-purple);">@result.Password</div>
|
|
</div>
|
|
<button class="copy-btn" @onclick='() => CopyToClipboard(result.Password, "Password")'>
|
|
<i class="bi bi-clipboard"></i> Copy
|
|
</button>
|
|
</div>
|
|
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 1rem; font-size: 0.8rem; color: var(--text-muted);">
|
|
<div style="background: rgba(11,15,25,0.4); padding: 0.6rem; border-radius: var(--radius-sm);">
|
|
<i class="bi bi-hourglass-split" style="color: var(--accent-amber);"></i> Session: <strong>@result.SessionTimeMinutes Mins</strong>
|
|
</div>
|
|
<div style="background: rgba(11,15,25,0.4); padding: 0.6rem; border-radius: var(--radius-sm);">
|
|
<i class="bi bi-wifi-off" style="color: var(--accent-rose);"></i> Data Cap: <strong>@result.DataLimitMb MB</strong>
|
|
</div>
|
|
</div>
|
|
|
|
@if (!string.IsNullOrEmpty(copyNotification))
|
|
{
|
|
<div style="text-align: center; color: var(--accent-teal); font-size: 0.8rem; font-weight: 600; margin-top: 0.75rem; animation: fadeIn 0.2s;">
|
|
<i class="bi bi-check2"></i> @copyNotification
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private string guestName = string.Empty;
|
|
private bool isSubmitting = false;
|
|
private string errorMessage = string.Empty;
|
|
private RegistrationResultDto? result;
|
|
private SystemConfigDto? config;
|
|
private string copyNotification = string.Empty;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
try
|
|
{
|
|
config = await RadiusService.GetSystemConfigAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = "Database connection offline or initializing: " + ex.Message;
|
|
}
|
|
}
|
|
|
|
private async Task HandleRegistration()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(guestName)) return;
|
|
|
|
isSubmitting = true;
|
|
errorMessage = string.Empty;
|
|
copyNotification = string.Empty;
|
|
|
|
try
|
|
{
|
|
result = await RadiusService.RegisterGuestAsync(guestName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = "Failed to create credentials: " + ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
isSubmitting = false;
|
|
}
|
|
}
|
|
|
|
private async Task CopyToClipboard(string text, string label)
|
|
{
|
|
try
|
|
{
|
|
await JS.InvokeVoidAsync("navigator.clipboard.writeText", text);
|
|
copyNotification = $"{label} copied to clipboard!";
|
|
StateHasChanged();
|
|
await Task.Delay(2500);
|
|
copyNotification = string.Empty;
|
|
StateHasChanged();
|
|
}
|
|
catch
|
|
{
|
|
copyNotification = $"Failed to copy {label} automatically.";
|
|
}
|
|
}
|
|
}
|