Files
pos-system/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Auth/Register.razor

171 lines
6.8 KiB
Plaintext

@page "/register"
@layout AuthLayout
@using WebClientTpos.Shared.DTOs
@using WebClientTpos.Shared
@using WebClientTpos.Client.Services
@inject AuthService AuthService
@inject NavigationManager Navigation
@inject IStringLocalizer<Register> L
@inject IJSRuntime JS
@*
EN: User registration page — connected to IAM Service API.
VI: Trang đăng ký người dùng — kết nối API IAM Service.
*@
<PageTitle>@L["Auth_Register_Title"]</PageTitle>
<div class="auth-container">
<section class="auth-card">
<h1 class="auth-title">@L["Auth_Register_Title"]</h1>
<p class="auth-subtitle">@L["Auth_Register_Subtitle"]</p>
<EditForm Model="@registerModel" OnValidSubmit="HandleRegister" FormName="RegisterForm">
<DataAnnotationsValidator />
<div class="form-row">
<div class="form-group">
<label for="reg-lastname">@L["Auth_Register_LastName"] *</label>
<InputText id="reg-lastname"
@bind-Value="registerModel.LastName"
class="form-input"
placeholder="Nguyễn"
autocomplete="family-name" />
<ValidationMessage For="() => registerModel.LastName" class="validation-message" />
</div>
<div class="form-group">
<label for="reg-firstname">@L["Auth_Register_FirstName"] *</label>
<InputText id="reg-firstname"
@bind-Value="registerModel.FirstName"
class="form-input"
placeholder="Văn A"
autocomplete="given-name" />
<ValidationMessage For="() => registerModel.FirstName" class="validation-message" />
</div>
</div>
<div class="form-group">
<label for="reg-email">@L["Auth_Register_Email"] *</label>
<InputText id="reg-email"
@bind-Value="registerModel.Email"
class="form-input"
placeholder="email@example.com"
autocomplete="email" />
<ValidationMessage For="() => registerModel.Email" class="validation-message" />
</div>
<div class="form-group">
<label for="reg-password">@L["Auth_Register_Password"] *</label>
<div style="position:relative;">
<InputText id="reg-password"
@bind-Value="registerModel.Password"
type="@(_showPassword ? "text" : "password")"
class="form-input"
placeholder="••••••••"
autocomplete="new-password" />
<button type="button" class="toggle-password-btn" @onclick="() => _showPassword = !_showPassword">
<i data-lucide="@(_showPassword ? "eye-off" : "eye")"></i>
</button>
</div>
<small class="form-hint">@L["Auth_Register_PasswordHint"]</small>
<ValidationMessage For="() => registerModel.Password" class="validation-message" />
</div>
<div class="form-group">
<label for="reg-confirm">@L["Auth_Register_ConfirmPassword"] *</label>
<div style="position:relative;">
<InputText id="reg-confirm"
@bind-Value="registerModel.ConfirmPassword"
type="@(_showConfirmPassword ? "text" : "password")"
class="form-input"
placeholder="••••••••"
autocomplete="new-password" />
<button type="button" class="toggle-password-btn" @onclick="() => _showConfirmPassword = !_showConfirmPassword">
<i data-lucide="@(_showConfirmPassword ? "eye-off" : "eye")"></i>
</button>
</div>
<ValidationMessage For="() => registerModel.ConfirmPassword" class="validation-message" />
</div>
<div class="checkbox-group mb-6">
<InputCheckbox id="accept-terms"
@bind-Value="registerModel.AcceptTerms"
class="form-checkbox" />
<label for="accept-terms" class="checkbox-label">@L["Auth_Register_Terms"]</label>
</div>
<button type="submit" class="btn-primary btn-full" disabled="@isSubmitting">
@if (isSubmitting)
{
<span class="spinner-small"></span>
<span>@L["Common_Loading"]</span>
}
else
{
@L["Auth_Register_Submit"]
}
</button>
</EditForm>
@if (!string.IsNullOrEmpty(message))
{
<div class="alert @(success ? "alert-success" : "alert-error")">
@message
</div>
}
<div class="auth-footer">
<span>@L["Auth_Register_HaveAccount"]</span>
<a href="/auth/login" class="link-primary">@L["Auth_Register_LoginLink"]</a>
</div>
</section>
</div>
@code {
private RegisterDto registerModel = new();
private bool isSubmitting = false;
private string message = "";
private bool success = false;
private bool _showPassword = false;
private bool _showConfirmPassword = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
try { await JS.InvokeVoidAsync("lucide.createIcons"); } catch { }
}
}
/// <summary>
/// EN: Handle registration form submission — calls IAM Service API.
/// VI: Xử lý submit form đăng ký — gọi API IAM Service.
/// </summary>
private async Task HandleRegister()
{
isSubmitting = true;
message = "";
var (ok, error) = await AuthService.RegisterAsync(registerModel);
if (ok)
{
success = true;
message = L["Auth_Register_Success"];
StateHasChanged();
// EN: Redirect to login after 2 seconds
// VI: Chuyển hướng đến đăng nhập sau 2 giây
await Task.Delay(2000);
Navigation.NavigateTo("/login");
}
else
{
success = false;
message = error ?? L["Auth_Register_Error"];
}
isSubmitting = false;
}
}