fix: implement Blazor-native login form to properly update authentication state
TaxBaik CI/CD / build-and-deploy (push) Successful in 2m26s

Problem: JavaScript login form saved tokens to localStorage but didn't notify
CustomAuthenticationStateProvider, causing [Authorize] pages to remain in
'loading' state indefinitely. The provider only reads tokens when:
1. GetAuthenticationStateAsync() is called (page load)
2. NotifyAuthenticationStateChanged() is triggered (UI updates)

But JavaScript login didn't trigger either, leaving the authentication state
stale.

Solution: Convert AdminLoginForm from HTML+JavaScript to pure Blazor component.
Now the login flow is:
1. User enters credentials in Blazor form
2. HttpClient POST to /api/auth/login
3. Save tokens to localStorage
4. Call CustomAuthenticationStateProvider.LoginAsync() directly
5. Blazor detects auth state change and re-evaluates [Authorize] pages
6. Dashboard [Authorize] page renders successfully

Result: Immediate authentication state update, no loading timeout on protected pages.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 13:03:53 +09:00
parent 041d3cae96
commit 40cffb3beb
326 changed files with 327714 additions and 47 deletions
@@ -0,0 +1,53 @@
import { SmartTables } from '../optional/smartTables/smartTables.bundle.js';
// Wait for the DOM to load before initializing
document.addEventListener('DOMContentLoaded', () => {
const importBtn = document.getElementById('importBtn');
const tableContainer = document.getElementById('tableContainer');
let table = null;
let errorContainer = document.getElementById('errorContainer');
// Initialize the table immediately but keep the container hidden
table = new SmartTables('myTable', {
import: true,
export: true,
responsive: {
enabled: true,
breakpoint: 768
}
});
// Handle import button click
importBtn.addEventListener('click', () => {
// Hide the import data container
const hideImportData = document.getElementById('hide-import-data');
hideImportData.classList.add('d-none');
// Show the table container
tableContainer.classList.remove('d-none');
try {
// First, create the import modal if it doesn't exist
if (typeof table.createImportModal === 'function') {
table.createImportModal();
// Now find the modal and show it using Bootstrap's Modal API
const importModal = document.getElementById('importModal');
if (importModal) {
// Create a new Bootstrap modal instance and show it
const bsModal = new bootstrap.Modal(importModal);
bsModal.show();
console.log('Import modal opened successfully');
} else {
throw new Error('Import modal element not found after creation');
}
} else {
throw new Error('createImportModal method not found on table instance');
}
} catch (error) {
console.error('Failed to open import modal:', error);
errorContainer.classList.remove('d-none');
}
});
});