Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: team subnav #25

Merged
merged 1 commit into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
import { Badge, Divider, Stack, Title, NavLink } from "@mantine/core";
import { Badge, Divider, Title, NavLink } from "@mantine/core";
import {
IconApps,
IconAspectRatio,
IconBuildingCommunity,
IconCash,
IconServerBolt,
IconUser,
IconUsers,
} from "@tabler/icons-react";
import { Link, useLocation } from "react-router-dom";
import { useSubnav } from "../../providers/nav.provider";
import { useWorkspace } from "../../providers/workspace.provider";
import { useWorkspace } from "../../../../providers/workspace.provider";
import { Subnav } from "../../../../components/subnav";

export const SubnavSettings = () => {
const { pathname } = useLocation();
const { workspace } = useWorkspace();
useSubnav();

// TO-DO: Create subnav-item component, abstract styles and add menus to spotlight.
// TO-DO: Add menus to spotlight.
return (
<Stack
h="100%"
pt={10}
style={{ flexGrow: 1, flexWrap: "nowrap" }}
gap={4}
p="md"
>
<Subnav>
<Title order={3} mt={34}>
Settings
</Title>
Expand All @@ -37,7 +31,6 @@ export const SubnavSettings = () => {
to="/settings/workspace"
active={pathname === "/settings/workspace"}
component={Link}
style={{ borderRadius: 4 }}
label="Workspace"
leftSection={<IconBuildingCommunity stroke={1.5} size={18} />}
/>
Expand All @@ -55,14 +48,12 @@ export const SubnavSettings = () => {
to="/settings/integrations"
active={pathname.includes("/settings/integrations")}
component={Link}
style={{ borderRadius: 4 }}
label="Integrations"
leftSection={<IconApps stroke={1.5} size={18} />}
/>
<NavLink
to="#"
component={Link}
style={{ borderRadius: 4 }}
label="Members"
disabled
rightSection={
Expand All @@ -76,7 +67,18 @@ export const SubnavSettings = () => {
<NavLink
to="#"
component={Link}
style={{ borderRadius: 4 }}
label="Deployments"
leftSection={<IconServerBolt stroke={1.5} size={18} />}
disabled
rightSection={
<Badge size="xs" variant="default">
Soon
</Badge>
}
/>
<NavLink
to="#"
component={Link}
label="Pull Request Size"
leftSection={<IconAspectRatio stroke={1.5} size={18} />}
disabled
Expand All @@ -91,10 +93,9 @@ export const SubnavSettings = () => {
to="/settings/my-account"
active={pathname === "/settings/my-account"}
component={Link}
style={{ borderRadius: 4 }}
label="My account"
leftSection={<IconUser stroke={1.5} size={18} />}
/>
</Stack>
</Subnav>
);
};
2 changes: 1 addition & 1 deletion apps/web/src/app/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Portal } from "@mantine/core";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { SubnavSettings } from "../../components/subnav-settings";
import { SubnavSettings } from "./components/subnav-settings";

export const SettingsPage = () => {
const { pathname } = useLocation();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { SubnavTeam } from "./subnav-team";
97 changes: 97 additions & 0 deletions apps/web/src/app/teams/[id]/components/subnav-team/subnav-team.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Divider, Title, NavLink, Badge } from "@mantine/core";
import {
IconChartArcs,
IconForms,
IconGitPullRequest,
IconMessage,
IconTarget,
IconUsers,
} from "@tabler/icons-react";
import { Link, useLocation } from "react-router-dom";
import { Team } from "@sweetr/graphql-types/frontend/graphql";
import { Subnav } from "../../../../../components/subnav";

interface SubnavTeamProps {
team: Omit<Team, "members">;
}

export const SubnavTeam = ({ team }: SubnavTeamProps) => {
const { pathname } = useLocation();

const getLink = (path: string) =>
`/teams/${team.id}${path ? `/${path}` : ""}`;

return (
<Subnav>
<Title order={3} mt={34} lineClamp={1} title={team.name}>
{team.name} {team.icon}
</Title>

<Divider label="Team" labelPosition="left" mt="sm" />
<NavLink
to={getLink("")}
active={pathname === getLink("")}
component={Link}
label="Members"
leftSection={<IconUsers stroke={1.5} size={18} />}
/>

<Divider label="Insights" labelPosition="left" mt="sm" />
<NavLink
to={getLink("pull-requests")}
active={pathname.startsWith(getLink("pull-requests"))}
component={Link}
label="Pull Requests"
leftSection={<IconGitPullRequest stroke={1.5} size={18} />}
/>
<NavLink
to={getLink("health-and-performance")}
active={pathname.startsWith(getLink("health-and-performance"))}
component={Link}
label="Health & Performance"
leftSection={<IconChartArcs stroke={1.5} size={18} />}
/>
<NavLink
to={getLink("dx-surveys")}
active={pathname.startsWith(getLink("dx-surveys"))}
component={Link}
label="DX Surveys"
leftSection={<IconForms stroke={1.5} size={18} />}
disabled
rightSection={
<Badge size="xs" variant="default">
Soon
</Badge>
}
/>

<Divider label="Improve" labelPosition="left" mt="sm" />
<NavLink
to={getLink("digests")}
active={pathname.startsWith(getLink("digests"))}
component={Link}
label="Digests"
disabled
rightSection={
<Badge size="xs" variant="default">
Soon
</Badge>
}
leftSection={<IconMessage stroke={1.5} size={18} />}
/>
<NavLink
to={getLink("targets")}
active={pathname.startsWith(getLink("targets"))}
component={Link}
label="Goals"
disabled
rightSection={
<Badge size="xs" variant="default">
Soon
</Badge>
}
leftSection={<IconTarget stroke={1.5} size={18} />}
/>
</Subnav>
);
};
73 changes: 9 additions & 64 deletions apps/web/src/app/teams/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
import {
Grid,
Group,
Paper,
Stack,
Title,
Text,
Skeleton,
Badge,
Tabs,
Box,
Portal,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { DrawerUpsertTeam } from "../components/drawer-upsert-team";
import { PageTitle } from "../../../components/page-title";
import { Outlet, useLocation, useNavigate, useParams } from "react-router-dom";
import { Outlet, useParams } from "react-router-dom";
import { useTeamQuery } from "../../../api/teams.api";
import { Breadcrumbs } from "../../../components/breadcrumbs";
import { HeaderActions } from "../../../components/header-actions";
import { MenuTeam } from "./components/menu-team";
import classes from "./page.module.css";
import { Team } from "@sweetr/graphql-types/frontend/graphql";
import { useWorkspace } from "../../../providers/workspace.provider";
import {
IconChartArcs,
IconGitPullRequest,
IconPencil,
IconUsers,
} from "@tabler/icons-react";
import { IconPencil } from "@tabler/icons-react";
import { PageContainer } from "../../../components/page-container";
import { ResourceNotFound } from "../../../exceptions/resource-not-found.exception";
import { useContextualActions } from "../../../providers/contextual-actions.provider";
import { SubnavTeam } from "./components/subnav-team";

export const TeamPage = () => {
const [isDrawerOpen, drawerControl] = useDisclosure(false);
const { teamId } = useParams();
const { workspace } = useWorkspace();
const navigate = useNavigate();
const { pathname } = useLocation();

if (!teamId) throw new ResourceNotFound();

Expand Down Expand Up @@ -67,24 +60,6 @@ export const TeamPage = () => {

const isArchived = !!team.archivedAt;

const getActiveTab = () => {
const basePath = `/teams/${teamId}/`;

if (pathname === basePath) return "members";

return [`pull-requests`, `code-reviews`, `health-and-performance`].find(
(path) => pathname.includes(basePath + path),
);
};

const navigateTo = (path: string) => navigate(`/teams/${team.id}/${path}`);

const handleChangeTab = (tab: string | null) => {
if (!tab || tab === "members") return navigateTo("");

return navigateTo(tab);
};

return (
<PageContainer>
<Breadcrumbs
Expand All @@ -99,6 +74,10 @@ export const TeamPage = () => {
/>
</HeaderActions>

<Portal target="#subnav">
<SubnavTeam team={team} />
</Portal>

<PageTitle
title={
<Stack
Expand Down Expand Up @@ -134,41 +113,7 @@ export const TeamPage = () => {
}
/>

<Paper radius="sm">
<Tabs
value={getActiveTab()}
defaultValue="members"
radius="none"
variant="default"
onChange={handleChangeTab}
>
<Tabs.List>
<Tabs.Tab
value="members"
onClick={() => navigateTo("")}
leftSection={<IconUsers size={24} stroke={1.5} />}
>
Members
</Tabs.Tab>
<Tabs.Tab
value="pull-requests"
onClick={() => navigateTo("pull-requests")}
leftSection={<IconGitPullRequest size={24} stroke={1.5} />}
>
Pull Requests
</Tabs.Tab>
<Tabs.Tab
value="health-and-performance"
onClick={() => navigateTo("health-and-performance")}
leftSection={<IconChartArcs size={24} stroke={1.5} />}
>
Health & Performance
</Tabs.Tab>
</Tabs.List>
</Tabs>
</Paper>

<Box mt="xl">
<Box mt="md">
<Outlet context={{ drawerControl }} />
</Box>

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/navbar/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const Navbar = ({ closeMobileNav }: NavbarProps) => {
return (
<AppShell.Navbar bg="dark.8">
<AppShellSection grow>
<Group h={"100%"} gap={0}>
<Group h={"100%"} gap={0} wrap="nowrap">
<Stack
h={"100%"}
style={{
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/subnav/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Subnav } from "./subnav";
5 changes: 5 additions & 0 deletions apps/web/src/components/subnav/subnav.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.subnav {
a {
border-radius: 4px;
}
}
20 changes: 20 additions & 0 deletions apps/web/src/components/subnav/subnav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Stack, StackProps } from "@mantine/core";
import { useSubnav } from "../../providers/nav.provider";
import classes from "./subnav.module.css";
export const Subnav = ({ children, ...props }: StackProps) => {
useSubnav();

return (
<Stack
h="100%"
pt={10}
style={{ flexGrow: 1, flexWrap: "nowrap" }}
gap={4}
p="md"
{...props}
className={classes.subnav}
>
{children}
</Stack>
);
};