-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: rewrite header using handlebars
- Loading branch information
1 parent
9454535
commit 9496f66
Showing
4 changed files
with
136 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<header id='header' class='header-wrapper'> | ||
<div class='header' id='header-inner'> | ||
<div class='header__hrefs'> | ||
{{#each menu}} | ||
<a href='{{this.href}}' class='header__href'>{{this.text}}</a> | ||
{{/each}} | ||
</div> | ||
|
||
<a class='header__logo-text-link' href='/'> | ||
<img class='header__img2' src='/name.png' /></a> | ||
|
||
<div class='header__signs'> | ||
{{#each signs}} | ||
<a class='header__sign' href='{{this.href}}'> | ||
<img src='{{this.src}}' width='30' /> | ||
</a> | ||
{{/each}} | ||
</div> | ||
|
||
{{#if isAuthorized}} | ||
<div class='header__avatar-container' id='js-avatar-container'> | ||
<img | ||
src='{{sessionData.avatar}}' | ||
id='js-header-avatar' | ||
class='header__avatar-container__avatar' | ||
width='50' | ||
height='50' | ||
/> | ||
</div> | ||
{{else}} | ||
<button | ||
class='header__button' | ||
id='header-signin-button' | ||
>Войти</button> | ||
{{/if}} | ||
</div> | ||
</header> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,214 +1,126 @@ | ||
'use strict'; | ||
|
||
import ApiClient from '../../modules/ApiClient'; | ||
import globalStore from '../../modules/GlobalStore'; | ||
import AuthPopup from '../AuthPopup/AuthPopup'; | ||
import BaseComponent from '../BaseComponent/BaseComponent'; | ||
import PopupAlert from '../PopupAlert/PopupAlert'; | ||
import ProfilePopup from '../ProfilePopup/ProfilePopup'; | ||
|
||
interface HeaderCallbacks { | ||
messagesPage: () => void; | ||
favoritesPage: () => void; | ||
notificationsPage: () => void; | ||
signInPage: () => void; | ||
interface SessionData { | ||
avatar: string; | ||
id: string; | ||
} | ||
|
||
class Header { | ||
#config; | ||
#isAuthorized; | ||
#headerCallbacks; | ||
#headerState; | ||
#menuContainer; | ||
#menuContainerWrapper; | ||
|
||
constructor(headerCallbacks: HeaderCallbacks, isAuth: boolean) { | ||
this.#headerCallbacks = headerCallbacks; | ||
this.#menuContainerWrapper = document.createElement('header'); | ||
this.#menuContainerWrapper.id = 'header'; | ||
this.#menuContainerWrapper.classList.add('header-wrapper'); | ||
this.#menuContainer = document.createElement('div'); | ||
this.#menuContainer.classList.add('header'); | ||
this.#menuContainer.id = 'header-inner'; | ||
|
||
this.#isAuthorized = isAuth; | ||
|
||
this.#config = { | ||
menu: { | ||
Main: { | ||
href: '/', | ||
text: 'Главная', | ||
export default class Header extends BaseComponent { | ||
constructor(parent: HTMLElement, sessionData?: SessionData) { | ||
super({ | ||
parent: parent, | ||
id: '', | ||
templateName: 'Header', | ||
templateData: { | ||
isAuthorized: globalStore.auth.isAuthorized, | ||
sessionData: sessionData, | ||
menu: { | ||
Main: { | ||
href: '/', | ||
text: 'Главная', | ||
}, | ||
Map: { | ||
href: '/map', | ||
text: 'Карта', | ||
}, | ||
}, | ||
Map: { | ||
href: '/map', | ||
text: 'Карта', | ||
}, | ||
}, | ||
|
||
signs: { | ||
Messages: { | ||
src: '/svg/messages.svg', | ||
href: '/chats', | ||
callback: headerCallbacks.messagesPage, | ||
}, | ||
Favorites: { | ||
src: '/svg/favorites.svg', | ||
href: '/favorites', | ||
callback: headerCallbacks.favoritesPage, | ||
}, | ||
Notifications: { | ||
src: '/svg/notifications.svg', | ||
href: '/notifications', | ||
callback: headerCallbacks.notificationsPage, | ||
signs: { | ||
Messages: { | ||
src: '/svg/messages.svg', | ||
href: '/chats', | ||
}, | ||
Favorites: { | ||
src: '/svg/favorites.svg', | ||
href: '/favorites', | ||
}, | ||
Notifications: { | ||
src: '/svg/notifications.svg', | ||
href: '/notifications', | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
this.#headerState = { | ||
activePageLink: null, | ||
headerElements: {}, | ||
}; | ||
}); | ||
} | ||
|
||
this.#render(); | ||
protected addEventListeners(): void { | ||
this.addLinksEventListeners(); | ||
this.addAvatarEventListeners(); | ||
this.addSignsEventListeners(); | ||
this.addLoginButtonEventListenListener(); | ||
} | ||
|
||
#renderMainText() { | ||
const nameImg = document.createElement('img'); | ||
nameImg.classList.add('header__img2'); | ||
nameImg.src = '/name.png'; | ||
private addLinksEventListeners() { | ||
const links = document.getElementsByClassName( | ||
'header__href' | ||
) as HTMLCollectionOf<HTMLAnchorElement>; | ||
|
||
const link = document.createElement('a'); | ||
link.classList.add('header__logo-text-link'); | ||
link.href = '/'; | ||
[...links].forEach((elem: HTMLAnchorElement) => { | ||
elem.onclick = () => { | ||
document | ||
.querySelector('.header__href--active') | ||
?.classList.remove('header__href--active'); | ||
|
||
link.appendChild(nameImg); | ||
elem.classList.add('header__href--active'); | ||
}; | ||
|
||
this.#menuContainer.appendChild(link); | ||
if (elem.href === location.href) { | ||
elem.classList.add('header__href--active'); | ||
} | ||
}); | ||
} | ||
|
||
#renderHrefs() { | ||
const hrefs = document.createElement('div'); | ||
hrefs.classList.add('header__hrefs'); | ||
Object.entries(this.#config.menu).forEach( | ||
([key, { href, text }], index) => { | ||
const menuElement = document.createElement('a'); | ||
menuElement.href = href; | ||
menuElement.text = text; | ||
menuElement.addEventListener('click', (e) => { | ||
e.preventDefault(); | ||
|
||
const elements = document.getElementsByClassName( | ||
'header__hrefs__href' | ||
); | ||
[...elements].forEach((elem) => | ||
elem.classList.remove('header__hrefs__href-active') | ||
); | ||
|
||
menuElement.classList.add('header__hrefs__href-active'); | ||
}); | ||
menuElement.classList.add('header__hrefs__href'); | ||
private addAvatarEventListeners() { | ||
const avatarContainer = document.getElementById('js-header-avatar'); | ||
if (!avatarContainer) return; | ||
|
||
if (index === 0) { | ||
menuElement.classList.add('header__hrefs__href-active'); | ||
this.#headerState.activePageLink = menuElement; | ||
} | ||
avatarContainer.onclick = function () { | ||
const menu = new ProfilePopup(); | ||
menu.render(avatarContainer.parentElement!); | ||
}; | ||
} | ||
|
||
this.#headerState.headerElements[key] = menuElement; | ||
hrefs.appendChild(menuElement); | ||
} | ||
private addSignsEventListeners() { | ||
const signs = Array.from( | ||
document.getElementsByClassName( | ||
'header__sign' | ||
) as HTMLCollectionOf<HTMLAnchorElement> | ||
); | ||
this.#menuContainer.appendChild(hrefs); | ||
} | ||
|
||
#renderSigns() { | ||
const signsContainer = document.createElement('div'); | ||
signsContainer.classList.add('header__signs'); | ||
Object.entries(this.#config.signs).forEach( | ||
([_, { href, src, callback }]) => { | ||
const signElement = document.createElement('a'); | ||
if (this.#isAuthorized) signElement.href = href; | ||
const img = document.createElement('img'); | ||
img.src = src; | ||
img.width = 30; | ||
signElement.appendChild(img); | ||
signElement.addEventListener('click', (e: Event) => { | ||
if (this.#isAuthorized) { | ||
callback(); | ||
} else { | ||
e.preventDefault(); | ||
this.#headerCallbacks.signInPage(); | ||
const errorMessage = PopupAlert( | ||
'Необходимо зарегистрироваться' | ||
); | ||
document | ||
.querySelector('.overlay') | ||
?.appendChild(errorMessage); | ||
} | ||
}); | ||
|
||
signsContainer.appendChild(signElement); | ||
signs.forEach((elem: HTMLAnchorElement) => { | ||
if (!globalStore.auth.isAuthorized) { | ||
elem.href = ''; | ||
} | ||
); | ||
this.#menuContainer.appendChild(signsContainer); | ||
} | ||
|
||
async #renderButtonOrAvatar() { | ||
if (this.#isAuthorized) { | ||
const avatarContainer = document.createElement('div'); | ||
avatarContainer.classList.add('header__avatar-container'); | ||
const avatar = document.createElement('img'); | ||
|
||
const uuid = await ApiClient.getSessionData(); | ||
const data = await ApiClient.getUser(uuid.id); | ||
avatar.src = data.avatar; | ||
avatar.width = 50; | ||
avatar.height = 50; | ||
avatar.classList.add('header__avatar-container__avatar'); | ||
avatar.classList.add('js-header-avatar'); | ||
|
||
avatar.onclick = () => { | ||
const profileList = new ProfilePopup(); | ||
profileList.render(this.#menuContainer); | ||
}; | ||
elem.onclick = () => { | ||
if (!globalStore.auth.isAuthorized) { | ||
const errorMessage = PopupAlert( | ||
'Необходимо зарегистрироваться' | ||
); | ||
const authPopup = new AuthPopup(); | ||
|
||
avatarContainer.appendChild(avatar); | ||
|
||
this.#menuContainer.appendChild(avatarContainer); | ||
} else { | ||
const entryButton = document.createElement('button'); | ||
entryButton.classList.add('header__button'); | ||
entryButton.textContent = 'Войти'; | ||
entryButton.addEventListener( | ||
'click', | ||
this.#headerCallbacks.signInPage | ||
); | ||
this.#menuContainer.appendChild(entryButton); | ||
} | ||
authPopup.render(document.body); | ||
document | ||
.getElementById('overlay') | ||
?.appendChild(errorMessage); | ||
} | ||
}; | ||
}); | ||
} | ||
|
||
async #render() { | ||
// TODO: REWRITE TO HBS. IT IS TOO HARD TO MAINTAIN JS ONLY COMPONENT LIKE THIS | ||
|
||
const menu = document.createElement('ul'); | ||
menu.classList.add('menu'); | ||
for (const menuSection in this.#config.menu) { | ||
const data = this.#config.menu[menuSection]; | ||
const elem = document.createElement('a'); | ||
elem.classList.add('menu__element'); | ||
elem.textContent = data['text']; | ||
elem.href = data['href']; | ||
menu.appendChild(elem); | ||
} | ||
this.#menuContainer.appendChild(menu); | ||
|
||
this.#menuContainerWrapper.appendChild(this.#menuContainer); | ||
|
||
this.#renderHrefs(); | ||
this.#renderMainText(); | ||
this.#renderSigns(); | ||
await this.#renderButtonOrAvatar(); | ||
} | ||
private addLoginButtonEventListenListener() { | ||
const button = document.getElementById('header-signin-button'); | ||
if (!button) return; | ||
|
||
getElement() { | ||
return this.#menuContainerWrapper; | ||
button.onclick = () => { | ||
const authPopup = new AuthPopup(); | ||
authPopup.render(document.body); | ||
}; | ||
} | ||
} | ||
|
||
export default Header; |