관리자 시작 화면이 정상 렌더링되면 부트스트랩 자체는 동작합니다.
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Pages/ClientLogs.razor b/src/TaxBaik.Web.Client/Components/Admin/Pages/ClientLogs.razor
index 0f8327c..e9811e4 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Pages/ClientLogs.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Pages/ClientLogs.razor
@@ -7,12 +7,10 @@
-
@if (_summary is not null)
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Pages/Dashboard.razor b/src/TaxBaik.Web.Client/Components/Admin/Pages/Dashboard.razor
index ac7264a..48169e1 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Pages/Dashboard.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Pages/Dashboard.razor
@@ -3,4 +3,133 @@
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@attribute [Authorize]
-
+
대시보드
+
+
+
+
+
+
+
+
+
+ 오류 진단
+
+ 브라우저 오류와 JS interop 실패는 클라이언트 로그에서 바로 추적합니다.
+
+
+ 클라이언트 로그 보기 →
+
+
+
+
+
+
+
+
+ 운영 메뉴
+
+ CRM, 홈페이지, 문의 관리 화면을 표준 템플릿으로 확장합니다.
+
+
+ 문의 관리로 이동 →
+
+
+
+
+
+
+
+
+ 배포 확인
+
+ 하위 경로 배포와 렌더러 분리를 유지하도록 라우트 린트를 적용합니다.
+
+
+ 최근 에러 확인 →
+
+
+
+
+
+
+
+
+ 원인 규명
+
+ 중복되는 오류는 최근 로그 요약에서 source와 route 기준으로 묶어 봅니다.
+
+
+ 오류 검색 →
+
+
+
+
+
+
+
+
+ 관측성
+
+ Top sources / routes를 확인해서 어떤 모듈이 재발하는지 빠르게 좁힙니다.
+
+
+ 요약 리포트 보기 →
+
+
+
+
+
+
+
+ 📊 빠른 통계
+
+
+
+ 전체 문의: API에서 조회
+
+
+
+
+ 오류 건수: 클라이언트 로그 참조
+
+
+
+
+ 배포 상태: 최신 버전 실행 중
+
+
+
+
+ 로그 범위: 최근 7일
+
+
+
+
+
+
+
+
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Pages/DashboardOverview.razor b/src/TaxBaik.Web.Client/Components/Admin/Pages/DashboardOverview.razor
index b2b5324..1c63c03 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Pages/DashboardOverview.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Pages/DashboardOverview.razor
@@ -1,37 +1,135 @@
+@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
+@attribute [Authorize]
+
+
+
대시보드
-
-
+
+
-
-
- 오류 진단
- 브라우저 오류와 JS interop 실패는 클라이언트 로그에서 바로 추적합니다.
- 클라이언트 로그 보기
-
-
- 운영 메뉴
- 대시보드 복원 후 CRM, 홈페이지, 문의 관리 화면을 표준 템플릿으로 확장합니다.
- 문의 관리로 이동
-
-
- 배포 확인
- 하위 경로 배포와 렌더러 분리를 유지하도록 라우트 린트를 적용합니다.
- 최근 에러 확인
-
-
- 원인 규명
- 중복되는 오류는 최근 로그 요약에서 source와 route 기준으로 묶어 봅니다.
- 오류 검색
-
-
- 관측성
- Top sources / routes를 확인해서 어떤 모듈이 재발하는지 빠르게 좁힙니다.
- 요약 리포트 보기
-
-
-
+
+
+
+
+
+ 오류 진단
+
+ 브라우저 오류와 JS interop 실패는 클라이언트 로그에서 바로 추적합니다.
+
+
+ 클라이언트 로그 보기 →
+
+
+
+
+
+
+
+
+ 운영 메뉴
+
+ CRM, 홈페이지, 문의 관리 화면을 표준 템플릿으로 확장합니다.
+
+
+ 문의 관리로 이동 →
+
+
+
+
+
+
+
+
+ 배포 확인
+
+ 하위 경로 배포와 렌더러 분리를 유지하도록 라우트 린트를 적용합니다.
+
+
+ 최근 에러 확인 →
+
+
+
+
+
+
+
+
+ 원인 규명
+
+ 중복되는 오류는 최근 로그 요약에서 source와 route 기준으로 묶어 봅니다.
+
+
+ 오류 검색 →
+
+
+
+
+
+
+
+
+ 관측성
+
+ Top sources / routes를 확인해서 어떤 모듈이 재발하는지 빠르게 좁힙니다.
+
+
+ 요약 리포트 보기 →
+
+
+
+
+
+
+
+ 📊 빠른 통계
+
+
+
+ 전체 문의: API에서 조회
+
+
+
+
+ 오류 건수: 클라이언트 로그 참조
+
+
+
+
+ 배포 상태: 최신 버전 실행 중
+
+
+
+
+ 로그 범위: 최근 7일
+
+
+
+
+
+
+
+
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Pages/TaxProfiles.razor b/src/TaxBaik.Web.Client/Components/Admin/Pages/TaxProfiles.razor
index bc8f052..436910e 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Pages/TaxProfiles.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Pages/TaxProfiles.razor
@@ -75,20 +75,12 @@ else
}
-
-
-
-
+
+ @foreach (var client in clients)
+ {
+ @GetClientDisplayName(client)
+ }
+
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminLoginForm.razor b/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminLoginForm.razor
index 70fc5cd..2f06d23 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminLoginForm.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminLoginForm.razor
@@ -1,32 +1,131 @@
+@inject IJSRuntime JS
+
관리자 로그인
-
@code {
+ private string username = "";
+ private string password = "";
+ private bool rememberMe = false;
+ private string errorMessage = "";
+
+ protected override async Task OnInitializedAsync()
+ {
+ // 저장된 아이디 복원
+ try
+ {
+ var savedUsername = await JS.InvokeAsync("localStorage.getItem", "admin_username_remembered");
+ if (!string.IsNullOrEmpty(savedUsername))
+ {
+ username = savedUsername;
+ rememberMe = true;
+ }
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"localStorage 읽기 실패: {ex.Message}");
+ }
+ }
+
+ private async Task HandleLogin()
+ {
+ errorMessage = "";
+
+ if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
+ {
+ errorMessage = "사용자명과 비밀번호를 입력하세요.";
+ return;
+ }
+
+ try
+ {
+ // 아이디 기억하기 처리
+ if (rememberMe)
+ {
+ await JS.InvokeVoidAsync("localStorage.setItem", "admin_username_remembered", username);
+ }
+ else
+ {
+ await JS.InvokeVoidAsync("localStorage.removeItem", "admin_username_remembered");
+ }
+
+ // 로그인 폼 제출 (기존 HTML 폼으로 처리)
+ var form = await JS.InvokeAsync("document.getElementById", "admin-login-form");
+ if (form != null)
+ {
+ // 숨겨진 필드에 값 설정
+ await JS.InvokeVoidAsync("eval", @"
+ (function() {
+ const form = document.getElementById('admin-login-form');
+ const usernameInput = form.querySelector('input[name=""username""]') || form.querySelector('input[autocomplete=""username""]');
+ const passwordInput = form.querySelector('input[name=""password""]') || form.querySelector('input[autocomplete=""current-password""]');
+
+ if (usernameInput) usernameInput.value = '" + username + @"';
+ if (passwordInput) passwordInput.value = '" + password + @"';
+
+ // Razor Pages에서 처리하도록 폼 제출
+ const action = form.getAttribute('action') || '/taxbaik/admin/login';
+ form.action = action;
+ form.method = 'POST';
+ form.submit();
+ })();
+ ");
+ }
+ }
+ catch (Exception ex)
+ {
+ errorMessage = $"로그인 처리 중 오류: {ex.Message}";
+ System.Diagnostics.Debug.WriteLine($"로그인 오류: {ex}");
+ }
+ }
}
diff --git a/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminSidebar.razor b/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminSidebar.razor
index 9a92bfe..7d9da97 100644
--- a/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminSidebar.razor
+++ b/src/TaxBaik.Web.Client/Components/Admin/Shared/AdminSidebar.razor
@@ -11,10 +11,10 @@