diff --git a/packages/tupaia-web/src/api/queries/index.ts b/packages/tupaia-web/src/api/queries/index.ts index 10817d64db..bd83e52712 100644 --- a/packages/tupaia-web/src/api/queries/index.ts +++ b/packages/tupaia-web/src/api/queries/index.ts @@ -9,6 +9,7 @@ export { useProject } from './useProject'; export { useProjects } from './useProjects'; export { useUser } from './useUser'; export { useEntity } from './useEntity'; +export { useEntityAncestors } from './useEntityAncestors'; export { useEntities, useEntitiesWithLocation } from './useEntities'; export { useEmailVerification } from './useEmailVerification'; export { useDashboards } from './useDashboards'; diff --git a/packages/tupaia-web/src/api/queries/useEntityAncestors.ts b/packages/tupaia-web/src/api/queries/useEntityAncestors.ts new file mode 100644 index 0000000000..3b5c79bbac --- /dev/null +++ b/packages/tupaia-web/src/api/queries/useEntityAncestors.ts @@ -0,0 +1,19 @@ +/* + * Tupaia + * Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd + */ + +import { useQuery } from 'react-query'; +import { EntityCode, ProjectCode } from '../../types'; +import { get } from '../api'; + +export const useEntityAncestors = (projectCode?: ProjectCode, entityCode?: EntityCode) => { + return useQuery( + ['entityAncestors', projectCode, entityCode], + () => + get(`entityAncestors/${projectCode}/${entityCode}`, { params: { includeRootEntity: true } }), + { + enabled: !!projectCode && !!entityCode, + }, + ); +}; diff --git a/packages/tupaia-web/src/features/Dashboard/Breadcrumbs.tsx b/packages/tupaia-web/src/features/Dashboard/Breadcrumbs.tsx index c97bfb1508..3d3c2aaa7d 100644 --- a/packages/tupaia-web/src/features/Dashboard/Breadcrumbs.tsx +++ b/packages/tupaia-web/src/features/Dashboard/Breadcrumbs.tsx @@ -2,20 +2,68 @@ * Tupaia * Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd */ - +import React from 'react'; +import { Link, useLocation, useParams } from 'react-router-dom'; import styled from 'styled-components'; +import { Breadcrumbs as MuiBreadcrumbs } from '@material-ui/core'; +import NavigateNextIcon from '@material-ui/icons/NavigateNext'; import { MOBILE_BREAKPOINT } from '../../constants'; +import { useEntityAncestors } from '../../api/queries'; -export const Breadcrumbs = styled.div` +const StyledBreadcrumbs = styled(MuiBreadcrumbs)` position: absolute; - top: 10px; - left: 10px; - width: 100%; - max-width: 220px; - background: #efefefaa; - height: 15px; + top: 0.3125rem; + left: 0.625rem; z-index: 1; + font-size: 0.8rem; + line-height: 1.2rem; + @media screen and (max-width: ${MOBILE_BREAKPOINT}) { display: none; } + + .MuiBreadcrumbs-separator { + margin-left: 0.2rem; + margin-right: 0.3rem; + + svg { + font-size: 0.8rem; + } + } +`; + +const ActiveCrumb = styled.span` + color: ${({ theme }) => theme.palette.text.primary}; `; + +const Crumb = styled(Link)` + cursor: pointer; + color: ${({ theme }) => theme.palette.text.primary}; + text-decoration: none; + + &:hover { + text-decoration: underline; + } +`; + +export const Breadcrumbs = () => { + const location = useLocation(); + const { projectCode, entityCode } = useParams(); + const { data = [] } = useEntityAncestors(projectCode, entityCode); + const breadcrumbs = data.map(({ code, name }) => ({ code, name })).reverse(); + + return ( + }> + {breadcrumbs.map(({ code: entityCode, name: entityName }, index) => { + const last = index === breadcrumbs.length - 1; + return last ? ( + {entityName} + ) : ( + + {entityName} + + ); + })} + + ); +};