|
1 | | -import { FC } from 'react' |
2 | | - |
3 | | -import { Logo } from './logo' |
4 | | -import { ToolSelectors } from './tool-selectors' |
5 | | -import { UtilitySelectors } from './utility-selectors' |
6 | | -import styles from './Header.module.scss' |
7 | | - |
8 | | -const Header: FC<{}> = () => ( |
9 | | - <div className={styles['header-wrap']}> |
10 | | - <header className={styles.header}> |
11 | | - <ToolSelectors isWide={false} /> |
12 | | - <Logo /> |
13 | | - <ToolSelectors isWide /> |
14 | | - <UtilitySelectors /> |
15 | | - </header> |
16 | | - <div id='page-subheader-portal-el' className={styles.subheader} /> |
17 | | - </div> |
18 | | -) |
| 1 | +import { |
| 2 | + Dispatch, |
| 3 | + FC, |
| 4 | + MutableRefObject, |
| 5 | + SetStateAction, |
| 6 | + useCallback, |
| 7 | + useContext, |
| 8 | + useEffect, |
| 9 | + useMemo, |
| 10 | + useRef, |
| 11 | + useState, |
| 12 | +} from 'react' |
| 13 | +import { NavigateFunction, useNavigate } from 'react-router-dom' |
| 14 | +import type { AuthUser as NavAuthUser, TcUniNavFn } from 'universal-navigation' |
| 15 | +import classNames from 'classnames' |
| 16 | + |
| 17 | +import { EnvironmentConfig, PageSubheaderPortalId } from '../config' |
| 18 | +import { |
| 19 | + authUrlLogin, |
| 20 | + authUrlLogout, |
| 21 | + authUrlSignup, |
| 22 | + profileContext, |
| 23 | + ProfileContextData, |
| 24 | + routeContext, |
| 25 | + RouteContextData, |
| 26 | +} from '../lib' |
| 27 | + |
| 28 | +import UniNavSnippet from './universal-nav-snippet' |
| 29 | + |
| 30 | +declare let tcUniNav: TcUniNavFn |
| 31 | +UniNavSnippet(EnvironmentConfig.UNIVERSAL_NAV.URL) |
| 32 | + |
| 33 | +interface NavigationRequest { |
| 34 | + label: string |
| 35 | + path: string |
| 36 | +} |
| 37 | + |
| 38 | +const Header: FC = () => { |
| 39 | + |
| 40 | + const { activeToolName, activeToolRoute }: RouteContextData = useContext(routeContext) |
| 41 | + const { profile, initialized: profileReady }: ProfileContextData = useContext(profileContext) |
| 42 | + const [ready, setReady]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false) |
| 43 | + const headerInit: MutableRefObject<boolean> = useRef(false) |
| 44 | + const navElementId: string = 'main-nav-el' |
| 45 | + const navigate: NavigateFunction = useNavigate() |
| 46 | + |
| 47 | + // userinfo will be an empty object until profileReady=true |
| 48 | + // userinfo will be {user: undefined} if user is logged out |
| 49 | + // userinfo will have all user's details when user is logged in |
| 50 | + const userInfo: {} | undefined | NavAuthUser = useMemo(() => ( |
| 51 | + !profileReady ? {} : ({ |
| 52 | + user: profile ? { |
| 53 | + email: profile.email, |
| 54 | + firstName: profile.firstName, |
| 55 | + handle: profile.handle, |
| 56 | + lastName: profile.lastName, |
| 57 | + photoUrl: profile.photoURL, |
| 58 | + userId: profile.userId, |
| 59 | + } : undefined, |
| 60 | + }) |
| 61 | + ), [profile, profileReady]) |
| 62 | + |
| 63 | + const navigationHandler: (request: NavigationRequest) => void |
| 64 | + = useCallback((request: NavigationRequest) => { |
| 65 | + |
| 66 | + try { |
| 67 | + // strip the domain and navigate to the path |
| 68 | + navigate(new URL(request.path).pathname) |
| 69 | + } catch (error) { |
| 70 | + // if we couldn't navigate to the path, just go to the route of the currently active tool |
| 71 | + navigate(new URL(activeToolRoute || '/').pathname) |
| 72 | + } |
| 73 | + |
| 74 | + }, [ |
| 75 | + activeToolRoute, |
| 76 | + navigate, |
| 77 | + ]) |
| 78 | + |
| 79 | + // initialize uni-nav elements |
| 80 | + useEffect(() => { |
| 81 | + |
| 82 | + if (headerInit.current) { |
| 83 | + return |
| 84 | + } |
| 85 | + |
| 86 | + headerInit.current = true |
| 87 | + |
| 88 | + tcUniNav( |
| 89 | + 'init', |
| 90 | + navElementId, |
| 91 | + { |
| 92 | + handleNavigation: navigationHandler, |
| 93 | + onReady() { setReady(true) }, |
| 94 | + signIn() { window.location.href = authUrlLogin() }, |
| 95 | + signOut() { window.location.href = authUrlLogout }, |
| 96 | + signUp() { window.location.href = authUrlSignup() }, |
| 97 | + toolName: activeToolName, |
| 98 | + toolRoot: activeToolRoute, |
| 99 | + type: 'tool', |
| 100 | + ...userInfo, |
| 101 | + }, |
| 102 | + ) |
| 103 | + }, [ |
| 104 | + activeToolName, |
| 105 | + activeToolRoute, |
| 106 | + navigationHandler, |
| 107 | + userInfo, |
| 108 | + profileReady, |
| 109 | + ]) |
| 110 | + |
| 111 | + // update uni-nav's tool details |
| 112 | + useEffect(() => { |
| 113 | + |
| 114 | + tcUniNav( |
| 115 | + 'update', |
| 116 | + navElementId, |
| 117 | + { |
| 118 | + toolName: activeToolName, |
| 119 | + toolRoot: activeToolRoute, |
| 120 | + }, |
| 121 | + ) |
| 122 | + }, [ |
| 123 | + activeToolName, |
| 124 | + activeToolRoute, |
| 125 | + ]) |
| 126 | + |
| 127 | + // update uni-nav's user/auth details |
| 128 | + useEffect(() => { |
| 129 | + |
| 130 | + if (!profileReady) { |
| 131 | + return |
| 132 | + } |
| 133 | + |
| 134 | + tcUniNav( |
| 135 | + 'update', |
| 136 | + navElementId, |
| 137 | + { |
| 138 | + ...userInfo, |
| 139 | + }, |
| 140 | + ) |
| 141 | + }, [ |
| 142 | + profileReady, |
| 143 | + userInfo, |
| 144 | + ]) |
| 145 | + |
| 146 | + return ( |
| 147 | + <> |
| 148 | + <div id={navElementId} /> |
| 149 | + <div |
| 150 | + id={PageSubheaderPortalId} |
| 151 | + className={classNames('full-width-relative', !ready && 'hidden')} |
| 152 | + /> |
| 153 | + </> |
| 154 | + ) |
| 155 | +} |
19 | 156 |
|
20 | 157 | export default Header |
0 commit comments