Skip to content

Commit

Permalink
Merge pull request #6454 from uktrade/feature/project-details-refactor
Browse files Browse the repository at this point in the history
change project details to render the layout before loading the resour…
  • Loading branch information
Richard-Pentecost authored Jan 24, 2024
2 parents a839975 + 7636733 commit 5c8532d
Show file tree
Hide file tree
Showing 7 changed files with 744 additions and 322 deletions.
161 changes: 161 additions & 0 deletions src/client/components/InvestmentLocalHeader/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import React, { Children, Fragment, cloneElement } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { SPACING } from '@govuk-react/constants'
import Main from '@govuk-react/main'
import Breadcrumbs from '@govuk-react/breadcrumbs'
import { Link } from 'react-router-dom'

import { GREY_4 } from '../../../client/utils/colours'
import LocalHeaderHeading from '../LocalHeader/LocalHeaderHeading'
import FlashMessages from '../LocalHeader/FlashMessages'
import { InvestmentResource } from '../Resource'
import urls from '../../../lib/urls'

// Using <div> as there is already a <header> on the page
// role="region" gives the element significance as a landmark
const StyledHeader = styled('div')`
padding-bottom: ${SPACING.SCALE_5};
background-color: ${GREY_4};
padding-top: ${SPACING.SCALE_3};
`

const StyledMain = styled(Main)`
padding-top: 0;
`

const BreadcrumbsWrapper = styled(Breadcrumbs)`
margin-bottom: ${SPACING.SCALE_5};
margin-top: 0;
`

const StyledLink = styled('a')({
fontSize: 20,
display: 'inline-block',
fontFamily: 'Arial, sans-serif',
marginTop: 8,
marginBottom: 8,
})

/**
* The generic local header component.
*/
const InvestmentLocalHeader = ({
breadcrumbs,
flashMessages,
projectId,
children,
useReactRouter = false,
}) => {
const renderChildren = (project) => {
return Children.map(children, (child) => {
return cloneElement(child, {
investment: project,
})
})
}

return (
<StyledHeader
aria-label="local header"
data-auto-id="localHeader"
data-test="localHeader"
role="region"
>
<StyledMain>
<BreadcrumbsWrapper data-test="breadcrumbs">
{breadcrumbs?.map((breadcrumb) =>
breadcrumb.link ? (
useReactRouter && breadcrumb.text !== 'Home' ? (
<Breadcrumbs.Link
as={Link}
key={breadcrumb.link}
to={breadcrumb.link}
>
{breadcrumb.text}
</Breadcrumbs.Link>
) : (
<Breadcrumbs.Link key={breadcrumb.link} href={breadcrumb.link}>
{breadcrumb.text}
</Breadcrumbs.Link>
)
) : (
<Fragment key={breadcrumb.text}>{breadcrumb.text}</Fragment>
)
)}
</BreadcrumbsWrapper>
<FlashMessages flashMessages={flashMessages} />
<InvestmentResource id={projectId}>
{(project) => (
<>
<StyledLink
data-test="heading-link"
href={urls.companies.detail(project.investorCompany.id)}
>
{project.investorCompany.name}
</StyledLink>
<LocalHeaderHeading data-test="heading">
{project.name}
</LocalHeaderHeading>
{renderChildren(project)}
</>
)}
</InvestmentResource>
</StyledMain>
</StyledHeader>
)
}

InvestmentLocalHeader.propTypes = {
/**
* Contains the breadcrumbs
*/
breadcrumbs: PropTypes.arrayOf(
PropTypes.shape({
link: PropTypes.string,
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element])
.isRequired,
})
),
/**
* Contains the flash messages
*/
flashMessages: PropTypes.shape({
type: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.shape({
body: PropTypes.string.isRequired,
heading: PropTypes.string.isRequired,
id: PropTypes.string,
})
),
PropTypes.arrayOf(PropTypes.string).isRequired,
]),
}),
/**
* Contains the heading text to be displayed
*/
heading: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),

/**
* Contains the subheading text to be displayed
*/
subheading: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
/**
* Contains a link that appears above the heading
*/
headingLink: PropTypes.shape({
url: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
}),
/**
* Contains an item that renders above the heading (in the same position as the headingLink)
*/
superheading: PropTypes.node,
/**
* Contains an item that renders below the heading
*/
children: PropTypes.node,
}

export default InvestmentLocalHeader
6 changes: 3 additions & 3 deletions src/client/components/InvestmentProjectLocalHeader/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ const InvestmentProjectLocalHeader = ({ investment }) => (
<MetaListItem text="Created on">
{formatMediumDateTime(investment.createdOn)}
</MetaListItem>
{investment.createdBy?.ditTeam?.name && (
{investment.createdBy?.ditTeam?.name ? (
<MetaListItem text="Created by">
{investment.createdBy.ditTeam.name}
</MetaListItem>
)}
) : null}
</MetaList>
<ThemeProvider theme={timelineTheme}>
<Timeline
Expand All @@ -108,7 +108,7 @@ InvestmentProjectLocalHeader.propTypes = {
/**
* An investment project
*/
investment: PropTypes.object.isRequired,
investment: PropTypes.object,
}

export default InvestmentProjectLocalHeader
70 changes: 70 additions & 0 deletions src/client/components/Layout/InvestmentLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useEffect, useState } from 'react'
import { createGlobalStyle } from 'styled-components'
import PropTypes from 'prop-types'
import GridCol from '@govuk-react/grid-col'
import GridRow from '@govuk-react/grid-row'

import Footer from '../Footer'
import Main from '../Main'
import DataHubHeader from '../DataHubHeader'
import { InvestmentLocalHeader } from '../../components'

const GlobalStyles = createGlobalStyle`
*, *:before, *:after {
box-sizing: initial;
}
`

const InvestmentLayout = ({
projectId,
heading,
pageTitle,
flashMessages,
breadcrumbs,
children,
useReactRouter = false,
localHeaderChildren,
}) => {
const [showVerticalNav, setShowVerticalNav] = useState(false)
useEffect(() => {
document.title = `${pageTitle} - DBT Data Hub`
}, [pageTitle])
return (
<>
<GlobalStyles />
<DataHubHeader
showVerticalNav={showVerticalNav}
onShowVerticalNav={setShowVerticalNav}
/>
<InvestmentLocalHeader
projectId={projectId}
flashMessages={flashMessages}
breadcrumbs={
breadcrumbs || [{ link: '/', text: 'Home' }, { text: heading }]
}
useReactRouter={useReactRouter}
>
{localHeaderChildren}
</InvestmentLocalHeader>
<Main>
<GridRow>
<GridCol>{children}</GridCol>
</GridRow>
</Main>
<Footer />
</>
)
}

InvestmentLayout.propTypes = {
heading: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
headingLink: PropTypes.shape({
url: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
}),
subheading: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
pageTitle: PropTypes.string.isRequired,
children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
}

export default InvestmentLayout
Loading

0 comments on commit 5c8532d

Please sign in to comment.