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}
+
+ );
+ })}
+
+ );
+};