diff --git a/front/src/modules/ui/breadcrumb/components/Breadcrumb.tsx b/front/src/modules/ui/breadcrumb/components/Breadcrumb.tsx new file mode 100644 index 0000000000000..79b9d5db4dbb5 --- /dev/null +++ b/front/src/modules/ui/breadcrumb/components/Breadcrumb.tsx @@ -0,0 +1,42 @@ +import { Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import styled from '@emotion/styled'; +type BreadcrumbProps = { + className?: string; + links: { children: string; href?: string }[]; +}; + +const StyledWrapper = styled.nav` + align-items: center; + color: ${({ theme }) => theme.font.color.extraLight}; + display: flex; + font-size: ${({ theme }) => theme.font.size.lg}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + gap: ${({ theme }) => theme.spacing(2)}; + height: ${({ theme }) => theme.spacing(6)}; + line-height: ${({ theme }) => theme.text.lineHeight.md}; +`; + +const StyledLink = styled(Link)` + color: inherit; + text-decoration: none; +`; + +const StyledText = styled.span` + color: ${({ theme }) => theme.font.color.tertiary}; +`; + +export const Breadcrumb = ({ className, links }: BreadcrumbProps) => ( + + {links.map((link, index) => ( + + {link.href ? ( + {link.children} + ) : ( + {link.children} + )} + {index < links.length - 1 && '/'} + + ))} + +); diff --git a/front/src/modules/ui/breadcrumb/components/__stories__/Breadcrumb.stories.tsx b/front/src/modules/ui/breadcrumb/components/__stories__/Breadcrumb.stories.tsx new file mode 100644 index 0000000000000..e372290882085 --- /dev/null +++ b/front/src/modules/ui/breadcrumb/components/__stories__/Breadcrumb.stories.tsx @@ -0,0 +1,23 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; + +import { Breadcrumb } from '../Breadcrumb'; + +const meta: Meta = { + title: 'UI/Breadcrumb/Breadcrumb', + component: Breadcrumb, + decorators: [ComponentDecorator], + args: { + links: [ + { children: 'Objects', href: '/link-1' }, + { children: 'Companies', href: '/link-2' }, + { children: 'New' }, + ], + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/front/src/pages/settings/SettingsObjectDetail.tsx b/front/src/pages/settings/SettingsObjectDetail.tsx index de2edd8db633a..49265cd62ddf0 100644 --- a/front/src/pages/settings/SettingsObjectDetail.tsx +++ b/front/src/pages/settings/SettingsObjectDetail.tsx @@ -1,8 +1,14 @@ +import { useEffect } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; import styled from '@emotion/styled'; +import { AppPath } from '@/types/AppPath'; +import { Breadcrumb } from '@/ui/breadcrumb/components/Breadcrumb'; import { IconSettings } from '@/ui/icon'; import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; +import { assertNotNull } from '~/utils/assert'; +import { activeObjectItems } from './constants/mockObjects'; import { objectSettingsWidth } from './constants/objectSettings'; const StyledContainer = styled.div` @@ -10,8 +16,27 @@ const StyledContainer = styled.div` width: ${objectSettingsWidth}; `; -export const SettingsObjectDetail = () => ( - - - -); +export const SettingsObjectDetail = () => { + const navigate = useNavigate(); + const { pluralObjectName = '' } = useParams(); + const activeObject = activeObjectItems.find( + (activeObject) => activeObject.name.toLowerCase() === pluralObjectName, + ); + + useEffect(() => { + if (!activeObject) navigate(AppPath.NotFound); + }, [activeObject, navigate]); + + return ( + + + + + + ); +}; diff --git a/front/src/pages/settings/SettingsObjects.tsx b/front/src/pages/settings/SettingsObjects.tsx index d5d5e965c37e9..d54584646ea4f 100644 --- a/front/src/pages/settings/SettingsObjects.tsx +++ b/front/src/pages/settings/SettingsObjects.tsx @@ -4,14 +4,10 @@ import styled from '@emotion/styled'; import { Button } from '@/ui/button/components/Button'; import { - IconBuildingSkyscraper, IconChevronRight, IconDotsVertical, - IconLuggage, - IconPlane, IconPlus, IconSettings, - IconUser, } from '@/ui/icon'; import { SubMenuTopBarContainer } from '@/ui/layout/components/SubMenuTopBarContainer'; import { Table } from '@/ui/table/components/Table'; @@ -23,6 +19,10 @@ import { Tag } from '@/ui/tag/components/Tag'; import { H1Title } from '@/ui/typography/components/H1Title'; import { H2Title } from '@/ui/typography/components/H2Title'; +import { + activeObjectItems, + disabledObjectItems, +} from './constants/mockObjects'; import { objectSettingsWidth } from './constants/objectSettings'; const StyledContainer = styled.div` @@ -68,40 +68,6 @@ const StyledH1Title = styled(H1Title)` margin-bottom: 0; `; -const activeObjectItems = [ - { - name: 'Companies', - Icon: IconBuildingSkyscraper, - type: 'standard', - fields: 23, - instances: 165, - }, - { - name: 'People', - Icon: IconUser, - type: 'standard', - fields: 16, - instances: 462, - }, -]; - -const disabledObjectItems = [ - { - name: 'Travels', - Icon: IconLuggage, - type: 'custom', - fields: 23, - instances: 165, - }, - { - name: 'Flights', - Icon: IconPlane, - type: 'custom', - fields: 23, - instances: 165, - }, -]; - export const SettingsObjects = () => { const theme = useTheme(); const navigate = useNavigate(); diff --git a/front/src/pages/settings/constants/mockObjects.ts b/front/src/pages/settings/constants/mockObjects.ts new file mode 100644 index 0000000000000..2639cc17f2cb7 --- /dev/null +++ b/front/src/pages/settings/constants/mockObjects.ts @@ -0,0 +1,40 @@ +import { + IconBuildingSkyscraper, + IconLuggage, + IconPlane, + IconUser, +} from '@/ui/icon'; + +export const activeObjectItems = [ + { + name: 'Companies', + Icon: IconBuildingSkyscraper, + type: 'standard', + fields: 23, + instances: 165, + }, + { + name: 'People', + Icon: IconUser, + type: 'standard', + fields: 16, + instances: 462, + }, +]; + +export const disabledObjectItems = [ + { + name: 'Travels', + Icon: IconLuggage, + type: 'custom', + fields: 23, + instances: 165, + }, + { + name: 'Flights', + Icon: IconPlane, + type: 'custom', + fields: 23, + instances: 165, + }, +];