167 lines
6.9 KiB
TypeScript

// components/TopBar.ts
import { createElement, navigateTo, isLoggedInUser } from '../utils/utils';
import { globalAPI, ApiResponse, ProfileResponseData } from '../api/api'; // Import API and types (now exported)
export class TopBar {
private container: HTMLElement;
private menuItems: Array<HTMLElement>;
private profileDropdownVisible: boolean = false;
private profileData: ProfileResponseData | null = null;
constructor() {
this.container = createElement('nav');
this.menuItems = [];
this.container.classList.add('top-bar', 'navbar', 'navbar-expand-lg', 'navbar-light', 'bg-darker', 'mb-3', 'px-4');
this.fetchProfileData();
}
async fetchProfileData() {
if (isLoggedInUser()) {
try {
const response: ApiResponse<ProfileResponseData> = await globalAPI.getProfile('mockUserId');
if (response.success && response.data) {
this.profileData = response.data;
this.render();
} else {
console.error("Failed to fetch profile data");
}
} catch (error) {
console.error("Error fetching profile data:", error);
}
}
}
addMenuItem(text: string, href: string) {
const menuItem = createElement('li');
menuItem.classList.add('nav-item');
const itemLink = createElement('a');
itemLink.classList.add('nav-link');
itemLink.href = href;
itemLink.textContent = text;
menuItem.appendChild(itemLink);
this.menuItems.push(menuItem)
}
render(): HTMLElement {
this.container.innerHTML = '';
const navbarBrand = createElement('a');
navbarBrand.classList.add('navbar-brand');
navbarBrand.href = '#/dashboard';
navbarBrand.textContent = 'LMS';
const navbarToggler = createElement('button');
navbarToggler.classList.add('navbar-toggler');
navbarToggler.type = 'button';
navbarToggler.setAttribute('data-bs-toggle', 'collapse');
navbarToggler.setAttribute('data-bs-target', '#navbarNav');
navbarToggler.setAttribute('aria-controls', 'navbarNav');
navbarToggler.setAttribute('aria-expanded', 'false');
navbarToggler.setAttribute('aria-label', 'Toggle navigation');
navbarToggler.innerHTML = '<span class="navbar-toggler-icon"></span>';
const navbarCollapse = createElement('div');
navbarCollapse.classList.add('collapse', 'navbar-collapse');
navbarCollapse.id = 'navbarNav';
const menuPages = createElement('ul');
menuPages.classList.add('navbar-nav', 'me-auto', 'mb-2', 'mb-lg-0');
for (const item of this.menuItems) {
menuPages.appendChild(item);
}
const profileSection = createElement('div');
profileSection.classList.add('d-flex', 'align-items-center', 'ms-auto');
if (this.profileData) {
const profileButton = createElement('button');
profileButton.classList.add('btn', 'btn-dark', 'dropdown-toggle');
profileButton.type = 'button';
profileButton.id = 'profileDropdownButton';
profileButton.setAttribute('data-bs-toggle', 'dropdown');
profileButton.setAttribute('aria-expanded', String(this.profileDropdownVisible));
const profileImage = createElement('img'); // Placeholder image, replace with actual profile picture logic
profileImage.src = this.profileData.profilePicture || 'src/assets/vite.svg'; // Default placeholder if no picture
profileImage.alt = 'Profile Picture';
profileImage.style.width = '30px';
profileImage.style.height = '30px';
profileImage.style.borderRadius = '50%';
profileImage.style.marginRight = '5px';
const fullNameSpan = createElement('span');
fullNameSpan.textContent = this.profileData.fullName;
profileButton.appendChild(profileImage);
profileButton.appendChild(fullNameSpan);
const dropdownMenu = createElement('ul');
dropdownMenu.classList.add('dropdown-menu', 'dropdown-menu-end');
dropdownMenu.setAttribute('aria-labelledby', 'profileDropdownButton');
const userIdItem = createElement('li');
userIdItem.innerHTML = `<span class="dropdown-item-text">ID: ${this.profileData.schoolId}</span>`;
dropdownMenu.appendChild(userIdItem);
const divider = createElement('li');
divider.innerHTML = '<hr class="dropdown-divider">';
dropdownMenu.appendChild(divider);
const profileMenuItem = createElement('li');
const profileLink = createElement('a');
profileLink.classList.add('dropdown-item');
profileLink.href = '#/profile';
profileLink.textContent = 'Profile';
profileMenuItem.appendChild(profileLink);
dropdownMenu.appendChild(profileMenuItem);
const accountSettingsMenuItem = createElement('li');
const accountSettingsLink = createElement('a');
accountSettingsLink.classList.add('dropdown-item');
accountSettingsLink.href = '#/profile'; // Same profile page, modal will be triggered there
accountSettingsLink.setAttribute('data-action', 'open-account-settings'); // Custom attribute to trigger modal
accountSettingsLink.textContent = 'Account settings';
accountSettingsMenuItem.appendChild(accountSettingsLink);
dropdownMenu.appendChild(accountSettingsMenuItem);
const logoutMenuItem = createElement('li');
const logoutButton = createElement('button');
logoutButton.classList.add('dropdown-item');
logoutButton.textContent = 'Log out';
logoutButton.addEventListener('click', async () => {
await globalAPI.logout();
navigateTo('/login'); // Redirect to login page after logout
});
logoutMenuItem.appendChild(logoutButton);
dropdownMenu.appendChild(logoutMenuItem);
profileSection.appendChild(profileButton);
profileSection.appendChild(dropdownMenu);
} else {
// Fallback if profile data is not loaded (or not logged in, though TopBar is for logged-in users)
const loginLink = createElement('a');
loginLink.classList.add('btn', 'btn-primary');
loginLink.href = '#/login';
loginLink.textContent = 'Login';
profileSection.appendChild(loginLink);
}
navbarCollapse.appendChild(menuPages);
navbarCollapse.appendChild(profileSection);
this.container.appendChild(navbarBrand);
this.container.appendChild(navbarToggler);
this.container.appendChild(navbarCollapse);
return this.container;
}
getContainer(): HTMLElement {
return this.container;
}
}