From 17710dc74281f63fc56731de68d7d7ed95da4bc6 Mon Sep 17 00:00:00 2001 From: cade Date: Fri, 29 Nov 2024 12:56:38 -0800 Subject: [PATCH] add page breadcrumb --- app/(pages)/(with-nav)/inbox/layout.tsx | 14 -- app/(pages)/(with-nav)/inbox/loading.tsx | 8 +- app/(pages)/(with-nav)/inbox/page.tsx | 17 +- app/(pages)/(with-nav)/inputs/layout.tsx | 14 -- app/(pages)/(with-nav)/inputs/loading.tsx | 8 +- app/(pages)/(with-nav)/inputs/page.tsx | 25 +-- app/(pages)/(with-nav)/layout.tsx | 72 +++---- app/(pages)/(with-nav)/subjects/loading.tsx | 3 +- app/(pages)/(with-nav)/subjects/page.tsx | 3 +- app/(pages)/(with-nav)/templates/layout.tsx | 14 -- app/(pages)/(with-nav)/templates/loading.tsx | 8 +- app/(pages)/(with-nav)/templates/page.tsx | 29 ++- app/_components/account-menu.tsx | 1 + app/_components/breadcrumb.tsx | 105 +++++++++ app/_components/filterable-inputs.tsx | 13 ++ app/_components/filterable-templates.tsx | 13 ++ app/_components/page-breadcrumb.tsx | 66 ++++++ app/_components/subject-loading.tsx | 4 +- app/_components/subject-page.tsx | 212 ++++++++++--------- 19 files changed, 411 insertions(+), 218 deletions(-) delete mode 100644 app/(pages)/(with-nav)/inbox/layout.tsx delete mode 100644 app/(pages)/(with-nav)/inputs/layout.tsx delete mode 100644 app/(pages)/(with-nav)/templates/layout.tsx create mode 100644 app/_components/breadcrumb.tsx create mode 100644 app/_components/page-breadcrumb.tsx diff --git a/app/(pages)/(with-nav)/inbox/layout.tsx b/app/(pages)/(with-nav)/inbox/layout.tsx deleted file mode 100644 index d808b1b8..00000000 --- a/app/(pages)/(with-nav)/inbox/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ReactNode } from 'react'; - -interface PageProps { - children: ReactNode; -} - -const Layout = ({ children }: PageProps) => ( - <> -

Inbox

- {children} - -); - -export default Layout; diff --git a/app/(pages)/(with-nav)/inbox/loading.tsx b/app/(pages)/(with-nav)/inbox/loading.tsx index 8437b84e..e609f86c 100644 --- a/app/(pages)/(with-nav)/inbox/loading.tsx +++ b/app/(pages)/(with-nav)/inbox/loading.tsx @@ -1,5 +1,11 @@ +import PageBreadcrumb from '@/_components/page-breadcrumb'; import Spinner from '@/_components/spinner'; -const Loading = () => ; +const Loading = () => ( + <> + + + +); export default Loading; diff --git a/app/(pages)/(with-nav)/inbox/page.tsx b/app/(pages)/(with-nav)/inbox/page.tsx index 6bacdddb..8cbf29ea 100644 --- a/app/(pages)/(with-nav)/inbox/page.tsx +++ b/app/(pages)/(with-nav)/inbox/page.tsx @@ -1,9 +1,22 @@ import Notifications from '@/_components/notifications'; +import PageBreadcrumb from '@/_components/page-breadcrumb'; +import getCurrentUser from '@/_queries/get-current-user'; import listNotifications from '@/_queries/list-notifications'; const Page = async () => { - const { data: notifications } = await listNotifications(); - return ; + const [{ data: notifications }, user] = await Promise.all([ + listNotifications(), + getCurrentUser(), + ]); + + if (!notifications || !user) return null; + + return ( + <> + + + + ); }; export default Page; diff --git a/app/(pages)/(with-nav)/inputs/layout.tsx b/app/(pages)/(with-nav)/inputs/layout.tsx deleted file mode 100644 index 9d56435e..00000000 --- a/app/(pages)/(with-nav)/inputs/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ReactNode } from 'react'; - -interface LayoutProps { - children: ReactNode; -} - -const Layout = ({ children }: LayoutProps) => ( - <> -

Inputs

- {children} - -); - -export default Layout; diff --git a/app/(pages)/(with-nav)/inputs/loading.tsx b/app/(pages)/(with-nav)/inputs/loading.tsx index 8437b84e..e609f86c 100644 --- a/app/(pages)/(with-nav)/inputs/loading.tsx +++ b/app/(pages)/(with-nav)/inputs/loading.tsx @@ -1,5 +1,11 @@ +import PageBreadcrumb from '@/_components/page-breadcrumb'; import Spinner from '@/_components/spinner'; -const Loading = () => ; +const Loading = () => ( + <> + + + +); export default Loading; diff --git a/app/(pages)/(with-nav)/inputs/page.tsx b/app/(pages)/(with-nav)/inputs/page.tsx index 183a07c0..b67094f1 100644 --- a/app/(pages)/(with-nav)/inputs/page.tsx +++ b/app/(pages)/(with-nav)/inputs/page.tsx @@ -1,25 +1,22 @@ -import Empty from '@/_components/empty'; import FilterableInputs from '@/_components/filterable-inputs'; +import PageBreadcrumb from '@/_components/page-breadcrumb'; +import getCurrentUser from '@/_queries/get-current-user'; import listInputsWithUses from '@/_queries/list-inputs-with-uses'; -import InformationCircleIcon from '@heroicons/react/24/outline/InformationCircleIcon'; import { sortBy } from 'lodash'; const Page = async () => { - const { data: inputs } = await listInputsWithUses(); + const [{ data: inputs }, user] = await Promise.all([ + listInputsWithUses(), + getCurrentUser(), + ]); - if (!inputs?.length) { - return ( - - - Inputs define the specific data points -
- you are interested in tracking. -
- ); - } + if (!inputs || !user) return null; return ( - + <> + + + ); }; diff --git a/app/(pages)/(with-nav)/layout.tsx b/app/(pages)/(with-nav)/layout.tsx index d2221e62..5188d59f 100644 --- a/app/(pages)/(with-nav)/layout.tsx +++ b/app/(pages)/(with-nav)/layout.tsx @@ -53,44 +53,8 @@ const Layout = async ({ children }: LayoutProps) => { Subjects - {!user.app_metadata.is_client && ( <> - - - } - label="Add new…" - variant="primary" - /> - - - - - Add new menu - - - - - diff --git a/app/(pages)/(with-nav)/subjects/loading.tsx b/app/(pages)/(with-nav)/subjects/loading.tsx index e05fcd54..e609f86c 100644 --- a/app/(pages)/(with-nav)/subjects/loading.tsx +++ b/app/(pages)/(with-nav)/subjects/loading.tsx @@ -1,8 +1,9 @@ +import PageBreadcrumb from '@/_components/page-breadcrumb'; import Spinner from '@/_components/spinner'; const Loading = () => ( <> -

Subjects

+ ); diff --git a/app/(pages)/(with-nav)/subjects/page.tsx b/app/(pages)/(with-nav)/subjects/page.tsx index bf1046f5..6d57b7d5 100644 --- a/app/(pages)/(with-nav)/subjects/page.tsx +++ b/app/(pages)/(with-nav)/subjects/page.tsx @@ -1,5 +1,6 @@ import CollapsibleArchive from '@/_components/collapsible-archive'; import Empty from '@/_components/empty'; +import PageBreadcrumb from '@/_components/page-breadcrumb'; import SubjectList from '@/_components/subject-list'; import canInsertSubjectOnCurrentPlan from '@/_queries/can-insert-subject-on-current-plan'; import getCurrentUser from '@/_queries/get-current-user'; @@ -43,7 +44,7 @@ const Page = async () => { return ( <> -

Subjects

+
{!clientSubjects.length && !teamSubjects.length && ( diff --git a/app/(pages)/(with-nav)/templates/layout.tsx b/app/(pages)/(with-nav)/templates/layout.tsx deleted file mode 100644 index c7b313d5..00000000 --- a/app/(pages)/(with-nav)/templates/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ReactNode } from 'react'; - -interface LayoutProps { - children: ReactNode; -} - -const Layout = ({ children }: LayoutProps) => ( - <> -

Templates

- {children} - -); - -export default Layout; diff --git a/app/(pages)/(with-nav)/templates/loading.tsx b/app/(pages)/(with-nav)/templates/loading.tsx index 8437b84e..e609f86c 100644 --- a/app/(pages)/(with-nav)/templates/loading.tsx +++ b/app/(pages)/(with-nav)/templates/loading.tsx @@ -1,5 +1,11 @@ +import PageBreadcrumb from '@/_components/page-breadcrumb'; import Spinner from '@/_components/spinner'; -const Loading = () => ; +const Loading = () => ( + <> + + + +); export default Loading; diff --git a/app/(pages)/(with-nav)/templates/page.tsx b/app/(pages)/(with-nav)/templates/page.tsx index 1890d95b..a4ef4afd 100644 --- a/app/(pages)/(with-nav)/templates/page.tsx +++ b/app/(pages)/(with-nav)/templates/page.tsx @@ -1,27 +1,24 @@ -import Empty from '@/_components/empty'; import FilterableTemplates from '@/_components/filterable-templates'; +import PageBreadcrumb from '@/_components/page-breadcrumb'; +import getCurrentUser from '@/_queries/get-current-user'; import listTemplates from '@/_queries/list-templates'; -import InformationCircleIcon from '@heroicons/react/24/outline/InformationCircleIcon'; import { sortBy } from 'lodash'; const Page = async () => { - const { data: templates } = await listTemplates(); + const [{ data: templates }, user] = await Promise.all([ + listTemplates(), + getCurrentUser(), + ]); - if (!templates?.length) { - return ( - - - Templates define reusable content -
- for event types and protocols. -
- ); - } + if (!templates || !user) return null; return ( - + <> + + + ); }; diff --git a/app/_components/account-menu.tsx b/app/_components/account-menu.tsx index c27f6781..7c70e335 100644 --- a/app/_components/account-menu.tsx +++ b/app/_components/account-menu.tsx @@ -84,6 +84,7 @@ const AccountMenu = ({ user, teams }: AccountMenuProps) => { onClick={(e) => { e.preventDefault(); setChangeTeamsId(team.id); + startChangeTeamsTransition(() => setActiveTeam(team.id), ); diff --git a/app/_components/breadcrumb.tsx b/app/_components/breadcrumb.tsx new file mode 100644 index 00000000..027f0285 --- /dev/null +++ b/app/_components/breadcrumb.tsx @@ -0,0 +1,105 @@ +import ChevronRightIcon from '@heroicons/react/24/outline/ChevronRightIcon'; +import EllipsisHorizontalIcon from '@heroicons/react/24/outline/EllipsisHorizontalIcon'; +import { Slot } from '@radix-ui/react-slot'; +import NextLink from 'next/link'; +import * as React from 'react'; +import { twMerge } from 'tailwind-merge'; + +const Ellipsis = ({ className, ...props }: React.ComponentProps<'span'>) => ( + +); + +Ellipsis.displayName = 'Ellipsis'; + +const Item = React.forwardRef< + HTMLLIElement, + React.ComponentPropsWithoutRef<'li'> +>(({ className, ...props }, ref) => ( +
  • +)); + +Item.displayName = 'Item'; + +const Link = React.forwardRef< + HTMLAnchorElement, + React.ComponentPropsWithoutRef & { + asChild?: boolean; + } +>(({ asChild, className, ...props }, ref) => { + const Comp = asChild ? Slot : NextLink; + return ; +}); + +Link.displayName = 'Link'; + +const List = React.forwardRef< + HTMLOListElement, + React.ComponentPropsWithoutRef<'ol'> +>(({ className, ...props }, ref) => ( +
      +)); + +List.displayName = 'List'; + +const Page = React.forwardRef< + HTMLSpanElement, + React.ComponentPropsWithoutRef<'span'> +>(({ className, ...props }, ref) => ( + +)); + +Page.displayName = 'Page'; + +const Root = React.forwardRef< + HTMLElement, + React.ComponentPropsWithoutRef<'nav'> & { + separator?: React.ReactNode; + } +>(({ ...props }, ref) =>