.ts
TypeScript
(application/typescript)
// 3rd-party
import React from "react";
import styled, { css } from "styled-components";
// app
import { Const } from "../const";
import { Chip } from "./Chip";
import { NamedColors } from "../utils/style";
import {
  type RepositoryCountersDTO,
  type CommonViewProps,
  type WithThemeSchemeProp,
} from "../types";
import { buildRouteLink } from "../utils/shared";
import { AppRoute } from "../routes.defs";
import { KeyIcon } from "./icons/KeyIcon";
import { SupportIcon } from "./icons/SupportIcon";
import { LogOutIcon } from "./icons/LogOutIcon";
import { UserIcon } from "./icons/UserIcon";
import { CommentIcon } from "./icons/CommentIcon";

export const DrawerSettings = ({
  visible = false,
  commonProps,
  themeScheme,
  username,
  counters = {
    sshKeys: 0,
  },
}: WithThemeSchemeProp & {
  visible: boolean;
  commonProps: CommonViewProps;
  username: string;
  counters?: RepositoryCountersDTO;
}) => {
  const pathMyAccount = buildRouteLink(
    AppRoute.USER_DETAILS,
    {
      username: username,
    },
    { encodeURIComponent: false },
  );

  const pathSSHKeys = buildRouteLink(
    AppRoute.SETTINGS_KEYS,
    {
      username: username,
    },
    { encodeURIComponent: false },
  );

  if (visible === false) {
    return null;
  }

  console.log("counters:", counters);

  return (
    <StyledDrawerSettings themeScheme={themeScheme}>
      <StyledDrawerHeader>
        <StyledLogoArea themeScheme={themeScheme}>
          <a href={"/"}>
            <h1>{Const.APP_NAME}</h1>
          </a>
        </StyledLogoArea>
      </StyledDrawerHeader>
      <StyledDrawerContent>
        <StyledDrawerListHeader>
          <img
            src={commonProps.currentUserAvatarUri || ""}
            style={{
              width: 20,
              height: 20,
              background: "red",
              borderRadius: 16,
              marginRight: 8,
            }}
          />
          <a
            href={buildRouteLink(
              AppRoute.USER_DETAILS,
              { username },
              { encodeURIComponent: false },
            )}
          >
            @{username}
          </a>
        </StyledDrawerListHeader>
        <StyledDrawerList>
          <StyledDrawerListItem
            themeScheme={themeScheme}
            href={pathMyAccount}
            className={
              // commonProps.path!.startsWith(pathMyAccount) ||
              commonProps.path! === pathMyAccount ? "active" : undefined
            }
          >
            <span>My Account</span>
            <UserIcon color={NamedColors.TEXT_DEFAULT[themeScheme]} size={20} />
          </StyledDrawerListItem>
          <StyledDrawerListItem
            themeScheme={themeScheme}
            href={pathSSHKeys}
            className={
              commonProps.path! === pathSSHKeys ||
              commonProps.path!.startsWith(pathSSHKeys)
                ? "active"
                : undefined
            }
          >
            <span>SSH Keys</span>
            <Chip themeScheme={themeScheme} style={{ marginRight: 8 }}>
              {counters.sshKeys || 0}
            </Chip>
            <KeyIcon color={NamedColors.TEXT_DEFAULT[themeScheme]} size={24} />
          </StyledDrawerListItem>
        </StyledDrawerList>
        <StyledDrawerListHeader></StyledDrawerListHeader>
        <StyledDrawerList></StyledDrawerList>
      </StyledDrawerContent>
      <StyledDrawerFooter>
        <StyledDrawerList>
          <StyledDrawerListItem themeScheme={themeScheme} disabled>
            <span>Feedback</span>
            <CommentIcon
              color={NamedColors.TEXT_MUTED[themeScheme]}
              size={20}
            />
          </StyledDrawerListItem>
          <StyledDrawerListItem themeScheme={themeScheme} disabled>
            <span>Help Center</span>
            {counters.helpCenterNotifs! > 0 && (
              <Chip themeScheme={themeScheme}>{counters.helpCenterNotifs}</Chip>
            )}
            <SupportIcon
              color={NamedColors.TEXT_MUTED[themeScheme]}
              size={20}
            />
          </StyledDrawerListItem>
          <StyledDrawerListItem
            themeScheme={themeScheme}
            href={buildRouteLink(AppRoute.AUTH_LOGOUT_ACTION, null)}
          >
            <span>Logout</span>
            <LogOutIcon
              color={NamedColors.TEXT_DEFAULT[themeScheme]}
              size={20}
            />
          </StyledDrawerListItem>
        </StyledDrawerList>
      </StyledDrawerFooter>
    </StyledDrawerSettings>
  );
};

const StyledDrawerSettings = styled.aside<
  WithThemeSchemeProp & { color?: string }
>`
  ${({ themeScheme }) => css`
    min-width: 300px;
    max-width: 320px;
    height: 100vh;

    display: flex;
    flex-flow: column nowrap;
    align-items: center;
    justify-content: center;

    position: sticky;
    top: 0;
    left: 0;
    bottom: 0;

    background: ${NamedColors.HEADER[themeScheme]};
    border-right: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};

    @media only screen and (max-width: 768px) {
      display: none;
    }
  `};
`;

const StyledDrawerHeader = styled.header`
  width: 100%;
  height: 64px;

  display: flex;
  justify-content: center;
  align-items: center;
`;

const StyledLogoArea = styled.div<WithThemeSchemeProp>`
  @media only screen and (max-width: 768px) {
    & > a > h1 {
      font-size: 22px;
    }
  }

  & > a {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;

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

    h1 {
      margin: 0;
    }
  }
`;

const StyledDrawerContent = styled.main`
  width: 100%;
  max-width: 100%;
  min-width: 100%;
  height: 100%;

  flex: 1;

  padding: 12px;
  overflow-y: auto;
`;

const StyledDrawerListHeader = styled.section`
  width: 100%;
  min-height: 40px;

  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;

  font-weight: bold;

  margin-bottom: 12px;

  & > span {
    margin: 0 4px;
  }
`;

const StyledDrawerList = styled.section`
  width: 100%;

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

  gap: 2px;
`;

const StyledDrawerListItem = styled.a<
  WithThemeSchemeProp & { disabled?: boolean }
>`
  ${({ disabled, themeScheme }) => css`
    width: 100%;
    height: 40px;

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

    padding: 0 12px;

    font-weight: normal;
    font-size: 14px;
    color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
    border-radius: 20px;
    text-decoration: none;

    & > span:nth-child(1) {
      flex: 1;
    }

    & > ${Chip} {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
      background-color: ${NamedColors.CARD_OVERLAY[themeScheme]};
    }

    ${(disabled == null || disabled === false) &&
    css`
      &.active,
      &:not(:disabled):hover {
        color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
        background-color: ${NamedColors.CARD[themeScheme]};
        font-weight: bold;
        font-family: monospace;
      }
    `};

    &:hover {
      text-decoration: none;
    }

    &:disabled {
      color: ${NamedColors.TEXT_MUTED[themeScheme]};
    }

    ${disabled &&
    css`
      color: ${NamedColors.TEXT_MUTED[themeScheme]};

      & > ${Chip} {
        color: ${NamedColors.TEXT_MUTED[themeScheme]};
        opacity: 0.3;
      }
    `}
  `}
`;

const StyledDrawerFooter = styled.footer`
  width: 100%;
  height: 128px;

  display: flex;
  justify-content: flex-start;
  align-items: center;

  margin: 16px 0;
  padding: 0 12px;
`;