US-029: Add post-login loading state and update TopBar session name

This commit is contained in:
2026-02-14 03:04:16 +00:00
parent a8c7d5b41d
commit dbdd51243d
3 changed files with 255 additions and 199 deletions
+43 -2
View File
@@ -14,6 +14,7 @@ export function LoginScreen({ onComplete }: LoginScreenProps) {
const [activeField, setActiveField] = useState<'username' | 'password' | 'done' | null>('username')
const [buttonPressed, setButtonPressed] = useState(false)
const [isExiting, setIsExiting] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const [typingComplete, setTypingComplete] = useState(false)
const [buttonHovered, setButtonHovered] = useState(false)
const [connectionState, setConnectionState] = useState<'connecting' | 'connected'>('connecting')
@@ -42,16 +43,19 @@ export function LoginScreen({ onComplete }: LoginScreenProps) {
const canLogin = typingComplete && connectionState === 'connected'
const handleLogin = useCallback(() => {
if (!canLogin || isExiting) return
if (!canLogin || isExiting || isLoading) return
setButtonPressed(true)
addTimeout(() => {
setIsLoading(true)
addTimeout(() => {
setIsExiting(true)
addTimeout(() => {
requestFocusAfterLogin()
onComplete()
}, prefersReducedMotion ? 0 : 200)
}, prefersReducedMotion ? 0 : 600)
}, 100)
}, [canLogin, isExiting, onComplete, requestFocusAfterLogin, prefersReducedMotion, addTimeout])
}, [canLogin, isExiting, isLoading, onComplete, requestFocusAfterLogin, prefersReducedMotion, addTimeout])
const startLoginSequence = useCallback(() => {
if (prefersReducedMotion) {
@@ -159,6 +163,41 @@ export function LoginScreen({ onComplete }: LoginScreenProps) {
animate={isExiting ? { scale: 1.03, opacity: 0 } : { scale: 1, opacity: 1 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
>
{isLoading ? (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
padding: '48px 0',
gap: '16px',
}}
>
<div
className="login-spinner"
style={{
width: '32px',
height: '32px',
border: '3px solid #E5E7EB',
borderTopColor: '#0D6E6E',
borderRadius: '50%',
}}
role="status"
aria-label="Loading clinical records"
/>
<span
style={{
fontFamily: "var(--font-ui)",
fontSize: '12px',
color: 'var(--text-secondary, #5B7A78)',
}}
>
Loading clinical records...
</span>
</div>
) : (
<>
{/* Branding Header */}
<div
className="flex flex-col items-center"
@@ -369,6 +408,8 @@ export function LoginScreen({ onComplete }: LoginScreenProps) {
Secure clinical system login
</p>
</div>
</>
)}
</motion.div>
</div>
)
+1 -1
View File
@@ -169,7 +169,7 @@ export function TopBar({ onSearchClick }: TopBarProps) {
fontFamily: 'var(--font-ui)',
}}
>
Dr. A.CHARLWOOD
A.RECRUITER
</span>
<span
className="font-geist hidden xs:inline"
+15
View File
@@ -250,6 +250,15 @@ html {
}
}
/* Login spinner */
@keyframes login-spin {
to { transform: rotate(360deg); }
}
.login-spinner {
animation: login-spin 0.8s linear infinite;
}
/* Custom scrollbar for sidebar */
.pmr-scrollbar {
scrollbar-width: thin;
@@ -415,4 +424,10 @@ textarea:focus-visible {
from { opacity: 1; }
to { opacity: 1; }
}
/* Static login spinner indicator */
.login-spinner {
animation: none;
border-top-color: #0D6E6E;
}
}