196 lines
No EOL
7.3 KiB
TypeScript
196 lines
No EOL
7.3 KiB
TypeScript
import React, { useState, useEffect, useRef } from 'react'
|
|
import { useMsal } from '@azure/msal-react'
|
|
import { FaSignOutAlt } from 'react-icons/fa'
|
|
import styles from './SidebarStyles/SidebarUser.module.css'
|
|
import { User } from '../../hooks/useUsers'
|
|
import { SidebarUserProps } from './sidebarTypes';
|
|
import { getUserDataCache, CachedUserData } from '../../utils/userCache';
|
|
import { useCurrentUser } from '../../hooks/useUsers';
|
|
|
|
const SidebarUser: React.FC<SidebarUserProps> = ({ isMinimized = false }) => {
|
|
const { instance } = useMsal();
|
|
const { logout } = useCurrentUser(); // Only use logout function from hook
|
|
|
|
// Local state for user data created from cached data
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [userError, setUserError] = useState<string | null>(null);
|
|
const [cachedUserData, setCachedUserData] = useState<CachedUserData | null>(null);
|
|
|
|
const [showLogoutMenu, setShowLogoutMenu] = useState(false);
|
|
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
const userSectionRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
// Function to get initials from full name
|
|
const getInitials = (fullName: string): string => {
|
|
return fullName
|
|
.split(' ')
|
|
.map(name => name.charAt(0).toUpperCase())
|
|
.join('')
|
|
.substring(0, 2); // Limit to 2 characters
|
|
};
|
|
|
|
const handleUserClick = () => {
|
|
setShowLogoutMenu(!showLogoutMenu);
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
if (!user || isLoggingOut) return;
|
|
|
|
setIsLoggingOut(true);
|
|
try {
|
|
// Pass MSAL instance for Microsoft authentication
|
|
if (user.authenticationAuthority === 'msft') {
|
|
await logout(instance);
|
|
} else {
|
|
await logout();
|
|
}
|
|
setShowLogoutMenu(false);
|
|
} catch (error) {
|
|
console.error('Logout failed:', error);
|
|
// Keep the menu open if logout fails so user can try again
|
|
setIsLoggingOut(false);
|
|
}
|
|
};
|
|
|
|
// Load cached user data on mount and when user updates
|
|
useEffect(() => {
|
|
const loadCachedUserData = () => {
|
|
const cached = getUserDataCache();
|
|
setCachedUserData(cached);
|
|
|
|
if (cached?.id) {
|
|
// Create a User object from cached data with fallback values
|
|
const userData: User = {
|
|
id: cached.id,
|
|
username: cached.username,
|
|
email: cached.email || cached.username, // Use email or username as fallback
|
|
fullName: cached.fullName || cached.username.split('@')[0] || cached.username,
|
|
language: cached.language || 'de', // Default language
|
|
enabled: cached.enabled ?? true, // Assume enabled if logged in
|
|
roleLabels: cached.roleLabels || [],
|
|
authenticationAuthority: cached.authenticationAuthority || 'local',
|
|
mandateId: cached.mandateId || ''
|
|
};
|
|
setUser(userData);
|
|
setUserError(null);
|
|
} else {
|
|
setUser(null);
|
|
}
|
|
};
|
|
|
|
loadCachedUserData();
|
|
}, []); // Empty dependency array - only run on mount
|
|
|
|
// Listen for user updates from settings page
|
|
useEffect(() => {
|
|
const handleUserUpdate = () => {
|
|
// Refresh cached user data when user info is updated
|
|
const cached = getUserDataCache();
|
|
setCachedUserData(cached);
|
|
|
|
if (cached?.id) {
|
|
const userData: User = {
|
|
id: cached.id,
|
|
username: cached.username,
|
|
email: cached.email || cached.username,
|
|
fullName: cached.fullName || cached.username.split('@')[0] || cached.username,
|
|
language: cached.language || 'de',
|
|
enabled: cached.enabled ?? true,
|
|
roleLabels: cached.roleLabels || [],
|
|
authenticationAuthority: cached.authenticationAuthority || 'local',
|
|
mandateId: cached.mandateId || ''
|
|
};
|
|
setUser(userData);
|
|
setUserError(null);
|
|
} else {
|
|
setUser(null);
|
|
}
|
|
};
|
|
|
|
window.addEventListener('userInfoUpdated', handleUserUpdate);
|
|
return () => {
|
|
window.removeEventListener('userInfoUpdated', handleUserUpdate);
|
|
};
|
|
}, []); // Empty dependency array - only set up listener once
|
|
|
|
// Close popup when clicking outside
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (userSectionRef.current && !userSectionRef.current.contains(event.target as Node)) {
|
|
setShowLogoutMenu(false);
|
|
}
|
|
};
|
|
|
|
if (showLogoutMenu) {
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
}
|
|
|
|
return () => {
|
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
};
|
|
}, [showLogoutMenu]);
|
|
|
|
if (!cachedUserData) {
|
|
return (
|
|
<div className={`${styles.user_section} ${isMinimized ? styles.minimized : ''}`}>
|
|
<div className={styles.userContainer}>Lädt...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (userError) {
|
|
return (
|
|
<div className={`${styles.user_section} ${isMinimized ? styles.minimized : ''}`}>
|
|
<div className={styles.userContainer}>Fehler beim Laden des Benutzerprofils</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!user) {
|
|
return (
|
|
<div className={`${styles.user_section} ${isMinimized ? styles.minimized : ''}`}>
|
|
<div className={styles.userContainer}>Kein Benutzer gefunden</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
ref={userSectionRef}
|
|
className={`${styles.user_section} ${isMinimized ? styles.minimized : ''}`}
|
|
>
|
|
{showLogoutMenu && (
|
|
<div className={`${styles.logout_popup} ${isMinimized ? styles.logout_popup_minimized : ''}`}>
|
|
<button
|
|
className={styles.logout_menu_button}
|
|
onClick={handleLogout}
|
|
disabled={isLoggingOut}
|
|
>
|
|
<FaSignOutAlt className={styles.logout_icon} />
|
|
{!isMinimized && (isLoggingOut ? 'Abmelden...' : 'Abmelden')}
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
<div
|
|
className={`${styles.user_info} ${showLogoutMenu ? styles.notClickable : styles.clickable}`}
|
|
onClick={handleUserClick}
|
|
>
|
|
<div className={styles.user_header}>
|
|
<div className={styles.user_avatar}>
|
|
{getInitials(user.fullName)}
|
|
</div>
|
|
{!isMinimized && (
|
|
<div className={styles.text_content}>
|
|
<h1>{user.fullName}</h1>
|
|
<p className={styles.username}>{user.username}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default SidebarUser; |