diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor
index 1adf0f15..42f67de2 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor
@@ -3,10 +3,12 @@
@inherits AdminBase
@inject WebClientTpos.Client.Services.AuthStateService AuthState
@inject WebClientTpos.Client.Services.PosDataService DataService
+@inject IJSRuntime JS
+@inject NavigationManager Nav
@*
- EN: Admin settings page — account info, shop overview, general settings.
- VI: Trang cài đặt admin — thông tin tài khoản, tổng quan cửa hàng, cài đặt chung.
+ EN: Admin settings page — account, security, subscription, notifications, system overview.
+ VI: Trang cài đặt admin — tài khoản, bảo mật, gói dịch vụ, thông báo, tổng quan hệ thống.
*@
Cài đặt — GoodGo Admin
@@ -21,26 +23,455 @@
@* ═══ TABS ═══ *@
- @if (_tab == "general")
+ @* ════════════════════════════════════════════════════════════════════
+ TAB: TÀI KHOẢN — Profile + Merchant Info
+ ════════════════════════════════════════════════════════════════════ *@
+ @if (_tab == "account")
+ {
+ @* ── Profile Info ── *@
+
+
+
+ @if (_loadingAccount)
+ {
+
+ }
+ else
+ {
+
+
+ @(string.IsNullOrEmpty(_firstName) ? (AuthState.UserEmail?[..1].ToUpper() ?? "U") : _firstName[..1].ToUpper())
+
+
+
+ @(string.IsNullOrEmpty(_firstName) && string.IsNullOrEmpty(_lastName)
+ ? (AuthState.UserEmail ?? "—")
+ : $"{_firstName} {_lastName}".Trim())
+
+
@(AuthState.UserEmail ?? "—")
+
+ Chủ doanh nghiệp
+
+
+
+
+
+
+
+
+
+
+ @if (_editingProfile)
+ {
+
+
+
+
+ }
+
+ @if (!string.IsNullOrEmpty(_profileMsg))
+ {
+
+ @_profileMsg
+
+ }
+ }
+
+
+
+ @* ── Merchant Info ── *@
+
+
+
+
+
+ @if (_editingMerchant)
+ {
+
+
+
+
+ }
+
+ @if (!string.IsNullOrEmpty(_merchantMsg))
+ {
+
+ @_merchantMsg
+
+ }
+
+
+ }
+
+ @* ════════════════════════════════════════════════════════════════════
+ TAB: BẢO MẬT — Password, 2FA, Sessions
+ ════════════════════════════════════════════════════════════════════ *@
+ else if (_tab == "security")
+ {
+ @* ── Change Password ── *@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @if (!string.IsNullOrEmpty(_pwMsg))
+ {
+
@_pwMsg
+ }
+
+
+
+ @* ── 2FA ── *@
+
+
+
+
+
+
Trạng thái 2FA
+
Bảo mật tài khoản bằng mã OTP từ ứng dụng Authenticator
+
+ @if (_twoFactorEnabled)
+ {
+
+ }
+ else
+ {
+
+ }
+
+
+ @if (_show2FASetup)
+ {
+
+
Quét mã QR bằng Google Authenticator hoặc Authy:
+ @if (!string.IsNullOrEmpty(_qrCodeBase64))
+ {
+
+

+
+ }
+ @if (!string.IsNullOrEmpty(_manualKey))
+ {
+
+ Mã thủ công: @_manualKey
+
+ }
+
+
+
+
+
+
+
+
+
+ }
+
+ @if (_showDisable2FA)
+ {
+
+
Nhập mã OTP hiện tại để tắt 2FA:
+
+
+
+
+
+
+
+
+ }
+
+ @if (!string.IsNullOrEmpty(_tfaMsg))
+ {
+
@_tfaMsg
+ }
+
+
+
+ @* ── Linked Accounts ── *@
+
+
+
+
+
+
@(_linkedGoogle ? "Đã liên kết" : "Chưa liên kết")
+
+
+
+
@(_linkedFacebook ? "Đã liên kết" : "Chưa liên kết")
+
+
+
+
+ @* ── Danger Zone ── *@
+
+
+
+
+
+
Xóa tài khoản
+
Xóa vĩnh viễn tài khoản và toàn bộ dữ liệu
+
+
+
+
+
+ }
+
+ @* ════════════════════════════════════════════════════════════════════
+ TAB: GÓI DỊCH VỤ — Subscription plans
+ ════════════════════════════════════════════════════════════════════ *@
+ else if (_tab == "subscription")
+ {
+ @* ── Current Plan ── *@
+
+
+
+
+
+
@_usageShops/@(FormatLimit(_limitShops))
+
Cửa hàng
+
+
+
@_usageStaff/@(FormatLimit(_limitStaff))
+
Nhân viên/shop
+
+
+
@_usageVerticals/@(FormatLimit(_limitVerticals))
+
Ngành nghề
+
+
+
@_usageProducts/@(FormatLimit(_limitProducts))
+
Sản phẩm
+
+
+
+
+
+ @* ── Plan Comparison ── *@
+
+ @foreach (var plan in _plans)
+ {
+ var isCurrent = plan.Id == _currentPlanId;
+
+
+
+ @foreach (var f in plan.Features)
+ {
+
+
+ @f.Label
+
+ }
+
+ @if (isCurrent)
+ {
+
+ }
+ else if (plan.Id > _currentPlanId)
+ {
+
+ }
+
+
+
+ }
+
+ }
+
+ @* ════════════════════════════════════════════════════════════════════
+ TAB: THÔNG BÁO
+ ════════════════════════════════════════════════════════════════════ *@
+ else if (_tab == "notifications")
+ {
+
+
+
+ @foreach (var notif in _notifSettings)
+ {
+
+
+ @notif.Label
+ @notif.Desc
+
+
+
+ }
+
+
+ }
+
+ @* ════════════════════════════════════════════════════════════════════
+ TAB: HỆ THỐNG
+ ════════════════════════════════════════════════════════════════════ *@
+ else if (_tab == "general")
{
- @* ── System Info ── *@
- @* ── Service Health ── *@
}
- else if (_tab == "account")
- {
-
- }
- else if (_tab == "notifications")
- {
-
-
-
- @foreach (var notif in _notifSettings)
- {
-
-
- @notif.Label
- @notif.Desc
-
-
-
- }
-
-
- }
- else if (_tab == "security")
- {
-
-
-
-
-
-
Đổi mật khẩu
-
Thay đổi mật khẩu đăng nhập
-
-
-
-
-
-
Xác thực 2 bước (2FA)
-
Bảo mật tài khoản bằng mã OTP
-
-
-
-
-
-
Phiên đăng nhập
-
Quản lý các phiên đang hoạt động
-
-
-
-
-
-
- @* ─── DANGER ZONE ─── *@
-
-
-
-
-
-
Xóa tài khoản
-
Xóa vĩnh viễn tài khoản và toàn bộ dữ liệu
-
-
-
-
-
- }
@code {
- private string _tab = "general";
+ private string _tab = "account";
private int _shopCount = 0;
+ private bool _loadingAccount = true;
+ private bool _saving = false;
+
+ // ═══ Account/Profile state ═══
+ private string _firstName = "";
+ private string _lastName = "";
+ private string _bio = "";
+ private string _timezone = "Asia/Ho_Chi_Minh";
+ private bool _editingProfile = false;
+ private string? _profileMsg;
+ private bool _profileMsgOk;
+
+ // ═══ Merchant state ═══
+ private string _businessName = "";
+ private string _merchantType = "Individual";
+ private string _taxId = "";
+ private string _verificationStatus = "Unverified";
+ private string _merchantCreatedAt = "—";
+ private bool _editingMerchant = false;
+ private string? _merchantMsg;
+ private bool _merchantMsgOk;
+
+ // ═══ Security state ═══
+ private string _currentPassword = "";
+ private string _newPassword = "";
+ private string _confirmPassword = "";
+ private string? _pwMsg;
+ private bool _pwMsgOk;
+ private bool _twoFactorEnabled = false;
+ private bool _show2FASetup = false;
+ private bool _showDisable2FA = false;
+ private string? _qrCodeBase64;
+ private string? _manualKey;
+ private string _totpCode = "";
+ private string? _tfaMsg;
+ private bool _tfaMsgOk;
+ private bool _linkedGoogle = false;
+ private bool _linkedFacebook = false;
+
+ // ═══ Subscription state ═══
+ private int _currentPlanId = 0;
+ private string _currentPlanName = "Starter";
+ private int _usageShops = 0, _limitShops = 1;
+ private int _usageStaff = 0, _limitStaff = 3;
+ private int _usageVerticals = 0, _limitVerticals = 1;
+ private int _usageProducts = 0, _limitProducts = 50;
+
+ ///