William Nemenchaimprove app
5c6496d (parent 48b426e)4/10/2024, 1:10:30 AM
.ts
TypeScript
(application/typescript)
// 3rd-party
import React, { useMemo, VFC } from "react";
import styled, { css } from "styled-components";
// app
import type { CommonProps, WithThemeSchemeProp } from "../types";
import { AppRoute } from "../routes.defs";
import { Const } from "../const";
import { NamedColors } from "../utils/style";
import { buildRouteLink } from "../utils/shared";
import { PageWrapper } from "./PageWrapper";

interface PageHeaderProps extends CommonProps {}

export const PageHeader: VFC<PageHeaderProps & WithThemeSchemeProp> = ({
  commonProps,
  themeScheme,
}) => {
  const invertThemeScheme = themeScheme === "light" ? "dark" : "light";

  const pageHeaderActions = useMemo(() => {
    if (commonProps.authenticated) {
      return (
        <>
          <a
            aria-label={"View your profile and repositories"}
            href={buildRouteLink(
              AppRoute.USER_DETAILS,
              {
                username: commonProps.currentUserUsername || "ghost",
              },
              { encodeURIComponent: false }
            )}
          >
            {commonProps.currentUserUsername || "ghost"}
          </a>
        </>
      );
    }

    return (
      <>
        <a
          aria-label={"Register a new account"}
          href={buildRouteLink(AppRoute.AUTH_REGISTER, null)}
        >
          Register
        </a>
        <a
          aria-label={"Login to your account"}
          href={buildRouteLink(AppRoute.AUTH_LOGIN, null)}
        >
          Login
        </a>
      </>
    );
  }, [commonProps.authenticated]);

  return (
    <StyledPageHeader themeScheme={themeScheme}>
      <PageWrapper>
        <StyledLogoArea themeScheme={themeScheme}>
          <a href={"/"}>
            <h1 style={{ margin: 0 }}>{Const.APP_NAME}</h1>
          </a>
        </StyledLogoArea>
        <StyledPageHeaderNav>
          <a
            aria-label={"Explore Repositories"}
            href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, null)}
          >
            Explore
          </a>
        </StyledPageHeaderNav>
        <StyledActionsArea>
          {commonProps.authenticated && (
            <a
              aria-label={"Create a new Repository"}
              href={buildRouteLink(AppRoute.REPOSITORY_CREATE, null)}
            >
              New Repository
            </a>
          )}
          <a
            aria-label={`Switch to ${invertThemeScheme} theme`}
            data-smooth-scroll={"disabled"}
            href={buildRouteLink(AppRoute.THEME_SET_SCHEME_ACTION, {
              themeScheme: invertThemeScheme,
            })}
            title={`Click to enable ${invertThemeScheme} mode`}
          >
            {`${themeScheme === "light" ? "Dark" : "Light"} mode`}
          </a>
          {pageHeaderActions}
        </StyledActionsArea>
      </PageWrapper>
    </StyledPageHeader>
  );
};

const StyledPageHeader = styled.header<WithThemeSchemeProp>`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: center;

  height: 100%;
  width: 100%;

  & > ${PageWrapper} {
    height: 100%;

    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;

    padding: 0 16px;
    gap: 16px;
  }

  & a {
    transition: color 140ms ease-in-out 0s;
    text-decoration: none;

    ${({ themeScheme }) => css`
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
    `};

    &:hover {
      ${({ themeScheme }) => css`
        color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
      `};
      text-decoration: underline;
    }
  }
`;

const StyledLogoArea = styled.div<WithThemeSchemeProp>`
  & > a {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;

    ${({ themeScheme }) => css`
      color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
    `};
  }
`;

const StyledPageHeaderNav = styled.nav`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: center;

  flex: 1;
  height: 100%;
  width: 100%;

  gap: 24px;
  margin-left: 4px;

  & > a {
    white-space: nowrap;
  }
`;

const StyledActionsArea = styled.div`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-end;
  align-items: center;

  & > a {
    margin-left: 12px;
    white-space: nowrap;
  }
`;