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,69 @@
// Show comment actions when input is focused
document.addEventListener('DOMContentLoaded', function () {
const commentInput = document.querySelector('.comment-input-wrapper input');
const commentActions = document.querySelector('.comment-actions');
if (commentInput && commentActions) {
commentInput.addEventListener('focus', function () {
commentActions.classList.remove('d-none');
});
document.addEventListener('click', function (e) {
if (!commentInput.contains(e.target) && !commentActions.contains(e.target)) {
if (commentInput.value.length === 0) {
commentActions.classList.add('d-none');
}
}
});
}
});
// Form validation for all modals
document.addEventListener('DOMContentLoaded', function () {
// Get all forms that need validation
const forms = document.querySelectorAll('.needs-validation');
// Function to handle form submission
function handleFormSubmit(event) {
const form = event.target.closest('.modal').querySelector('form');
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
else {
// If form is valid, you can add AJAX submission here
// For demo purposes, we'll just close the modal
const modal = bootstrap.Modal.getInstance(event.target.closest('.modal'));
modal.hide();
// Show success message (optional)
// This would be replaced with actual form submission in a real application
// alert('Form submitted successfully!');
}
form.classList.add('was-validated');
}
// Attach click event handlers to submit buttons
document.getElementById('submitNewsForm').addEventListener('click', handleFormSubmit);
document.getElementById('submitProjectForm').addEventListener('click', handleFormSubmit);
document.getElementById('submitProfileForm').addEventListener('click', handleFormSubmit);
// Optional: Add validation as user types for better UX
Array.from(forms).forEach(form => {
const inputs = form.querySelectorAll('input, textarea, select');
inputs.forEach(input => {
input.addEventListener('input', function () {
if (!this.checkValidity()) {
this.classList.add('is-invalid');
}
else {
this.classList.remove('is-invalid');
this.classList.add('is-valid');
}
});
});
});
});