FRONT-I-01: Extract Auth components to Razor Class Library packages/blazor-ui/
- Created GoodGo.BlazorUi RCL (net10.0, MudBlazor 8.15) at packages/blazor-ui/
- Moved AuthButton, AuthCard, AuthInput, OtpInput, BrandPanel, SocialLogin, LanguageSwitcher
- Referenced RCL from WebClientTpos.Client via ProjectReference
- Added GoodGo.BlazorUi.Components.Auth/Common namespaces to _Imports.razor
FRONT-I-02: Add ARIA/accessibility attributes (WCAG 2.1 AA)
- AuthButton: aria-label, aria-busy, aria-disabled, aria-hidden on decorative icons
- OtpInput: role=group, aria-label per digit, autocomplete=one-time-code
- PosLayout: aria-expanded + aria-controls on sidebar/order toggles, aria-label on all icon buttons
FRONT-I-03: Implement Style Dictionary design token pipeline
- Created packages/design-tokens/ with token JSON (color, spacing, typography, border)
- Style Dictionary config outputs: CSS custom properties → wwwroot/css/tokens.generated.css
- Second output: C# constants → packages/blazor-ui/DesignTokens/DesignTokens.g.cs
- Added tokens:build script to root package.json
- Added tokens.generated.css link to index.html (before app.css for cascade correctness)
FRONT-I-04: Replace eval() in OtpInput with safe JS interop
- Created wwwroot/js/otp-input.js with window.focusOtpInput(index) helper
- Replaced JS.InvokeVoidAsync("eval", ...) with JS.InvokeVoidAsync("focusOtpInput", index)
- Eliminates CSP-violating eval(), improves security and debuggability
Co-Authored-By: Paperclip <noreply@paperclip.ing>
96 lines
2.9 KiB
Plaintext
96 lines
2.9 KiB
Plaintext
@*
|
|
EN: Brand panel for split auth layouts — shows logo, title, description, and trust stats.
|
|
VI: Panel thương hiệu cho layout chia đôi — hiển thị logo, tiêu đề, mô tả, thống kê.
|
|
*@
|
|
|
|
<div class="auth-brand-panel @PanelClass">
|
|
<div class="auth-brand-logo">@LogoText</div>
|
|
<h2 class="auth-brand-title">@Title</h2>
|
|
<p class="auth-brand-desc">@Description</p>
|
|
|
|
@if (ShowStats)
|
|
{
|
|
<div class="auth-brand-stats">
|
|
@foreach (var stat in Stats)
|
|
{
|
|
<div class="auth-brand-stat">
|
|
<span class="auth-brand-stat-value">@stat.Value</span>
|
|
<span class="auth-brand-stat-label">@stat.Label</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@if (Features != null && Features.Count > 0)
|
|
{
|
|
<div class="auth-brand-features">
|
|
@foreach (var feature in Features)
|
|
{
|
|
<div class="auth-brand-feature">
|
|
<i data-lucide="check"></i>
|
|
<span>@feature</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@ChildContent
|
|
</div>
|
|
|
|
@code {
|
|
/// <summary>
|
|
/// EN: Panel variant class (auth-brand-panel--orange or auth-brand-panel--dark).
|
|
/// VI: Class biến thể panel (auth-brand-panel--orange hoặc auth-brand-panel--dark).
|
|
/// </summary>
|
|
[Parameter] public string PanelClass { get; set; } = "auth-brand-panel--orange";
|
|
|
|
/// <summary>
|
|
/// EN: Logo character/text displayed in the brand panel.
|
|
/// VI: Ký tự/text logo hiển thị trong brand panel.
|
|
/// </summary>
|
|
[Parameter] public string LogoText { get; set; } = "a";
|
|
|
|
/// <summary>
|
|
/// EN: Brand panel title.
|
|
/// VI: Tiêu đề brand panel.
|
|
/// </summary>
|
|
[Parameter] public string Title { get; set; } = "aPOS Branch";
|
|
|
|
/// <summary>
|
|
/// EN: Description text.
|
|
/// VI: Text mô tả.
|
|
/// </summary>
|
|
[Parameter] public string Description { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// EN: Whether to show trust stats.
|
|
/// VI: Có hiển thị thống kê tin cậy không.
|
|
/// </summary>
|
|
[Parameter] public bool ShowStats { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// EN: Trust statistics data.
|
|
/// VI: Dữ liệu thống kê tin cậy.
|
|
/// </summary>
|
|
[Parameter] public List<BrandStat> Stats { get; set; } = new()
|
|
{
|
|
new("1,200+", "Cửa hàng"),
|
|
new("50K+", "Giao dịch/ngày"),
|
|
new("99.9%", "Uptime")
|
|
};
|
|
|
|
/// <summary>
|
|
/// EN: Feature list items.
|
|
/// VI: Danh sách tính năng.
|
|
/// </summary>
|
|
[Parameter] public List<string>? Features { get; set; }
|
|
|
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
|
|
|
/// <summary>
|
|
/// EN: Brand stat record.
|
|
/// VI: Record thống kê thương hiệu.
|
|
/// </summary>
|
|
public record BrandStat(string Value, string Label);
|
|
}
|