Skip to content

Commit

Permalink
Portal frontend 5 (#62)
Browse files Browse the repository at this point in the history
* initial

* fixes after testing

* refactor

* use cfl navigate

* initial

* children

* relock

* New version

* fix links

* fix paths

* feedback
  • Loading branch information
SKairinos authored Sep 25, 2024
1 parent baf9ffc commit 6b1e6fc
Show file tree
Hide file tree
Showing 36 changed files with 2,085 additions and 214 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"✅ Do add `devDependencies` below that are `peerDependencies` in the CFL package."
],
"dependencies": {
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.3.4",
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.3.5",
"crypto-js": "^4.2.0"
},
"devDependencies": {
Expand Down
79 changes: 79 additions & 0 deletions src/components/TableOfContents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
Divider,
Unstable_Grid2 as Grid,
Link,
Stack,
Typography,
} from "@mui/material"
import { type FC, type ReactNode, useRef } from "react"

export const ids = {
leftLinkStack: "left-link-stack",
rightLinkStack: "right-link-stack",
}

export interface TableOfContentsProps {
contents: Array<{ header: string; children: ReactNode }>
}

const TableOfContents: FC<TableOfContentsProps> = ({ contents }) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const headerRefs = contents.map(() => useRef<HTMLSpanElement>(null))
const halfLength = Math.ceil(contents.length / 2)

function generateLinkStack(
stackId: string,
sliceStart: number,
sliceEnd: number,
): ReactNode {
return (
<Stack id={stackId}>
{contents.slice(sliceStart, sliceEnd).map((content, index) => {
index += sliceStart
return (
<Typography key={index} mb={index === sliceEnd - 1 ? 0 : undefined}>
{index + 1}.{" "}
<Link
onClick={() => {
const header = headerRefs[index].current
if (header !== null) {
header.scrollIntoView({
behavior: "smooth",
block: "center",
})
}
}}
>
{content.header}
</Link>
</Typography>
)
})}
</Stack>
)
}

return (
<Grid container spacing={0}>
<Grid container xs={12} spacing={2}>
<Grid id={ids.leftLinkStack} xs={12} sm={6}>
{generateLinkStack(ids.leftLinkStack, 0, halfLength)}
</Grid>
<Grid id={ids.rightLinkStack} xs={12} sm={6}>
{generateLinkStack(ids.rightLinkStack, halfLength, contents.length)}
</Grid>
</Grid>
{contents.map((content, index) => (
<Grid key={index} xs={12} mt={index === 0 ? 2 : 0}>
<Divider sx={{ my: 2 }} />
<Typography ref={headerRefs[index]} variant="h5">
{index + 1}. {content.header}
</Typography>
{content.children}
</Grid>
))}
</Grid>
)
}

export default TableOfContents
2 changes: 2 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export { default as OpenInEmailButtons } from "./OpenInEmailButtons"
export * from "./OpenInEmailButtons"
export { default as StudentCredentialsTable } from "./StudentCredentialsTable"
export * from "./StudentCredentialsTable"
export { default as TableOfContents } from "./TableOfContents"
export * from "./TableOfContents"
8 changes: 6 additions & 2 deletions src/features/footer/Links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ const Links: FC<LinksProps> = () => {
</Grid>
<Grid xs={12} sm={4}>
<Stack spacing={1}>
<FooterLink to={paths.privacyNotice._}>Privacy notice</FooterLink>
<FooterLink to={paths.termsOfUse._}>Terms of use</FooterLink>
<FooterLink to={paths.privacyNotice.tab.privacyNotice._}>
Privacy notice
</FooterLink>
<FooterLink to={paths.termsOfUse.tab.termsOfUse._}>
Terms of use
</FooterLink>
{/*TODO: Use OneTrust banner hook*/}
<MuiLink sx={LINK_STYLE}>Cookie settings</MuiLink>
</Stack>
Expand Down
32 changes: 32 additions & 0 deletions src/pages/privacyNotice/PrivacyNotice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as pages from "codeforlife/components/page"
import { type FC } from "react"
import { getParam } from "codeforlife/utils/router"

import Adults from "./adults/Adults"
import Children from "./children/Children"
import { paths } from "../../routes"

export interface PrivacyNoticeProps {}

const PrivacyNotice: FC<PrivacyNoticeProps> = () => (
<pages.Page>
<pages.TabBar
header="Privacy notice"
originalPath={paths.privacyNotice.tab._}
tabs={[
{
label: "Privacy notice",
children: <Adults />,
path: getParam(paths.privacyNotice.tab.privacyNotice, "tab"),
},
{
label: "Child-friendly",
children: <Children />,
path: getParam(paths.privacyNotice.tab.childFriendly, "tab"),
},
]}
/>
</pages.Page>
)

export default PrivacyNotice
104 changes: 104 additions & 0 deletions src/pages/privacyNotice/adults/Adults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import * as pages from "codeforlife/components/page"
import { type FC } from "react"
import { Typography } from "@mui/material"

import ChangeOfPurpose from "./ChangeOfPurpose"
import Changes from "./Changes"
import ContactUs from "./ContactUs"
import Cookies from "./Cookies"
import ExtraHelp from "./ExtraHelp"
import HowToComplain from "./HowToComplain"
import HowWeUseInfo from "./HowWeUseInfo"
import InfoSecurity from "./InfoSecurity"
import KeepInfo from "./KeepInfo"
import OurCommitment from "./OurCommitment"
import SharingInfo from "./SharingInfo"
import { TableOfContents } from "../../../components"
import TypesOfInfo from "./TypesOfInfo"
import WhoWeAre from "./WhoWeAre"
import YourRights from "./YourRights"

export interface AdultsProps {}

const Adults: FC<AdultsProps> = () => {
const lastUpdated = "11th April 2024"

return (
<pages.Section>
<Typography fontWeight="bold">Last Updated: {lastUpdated}</Typography>
<Typography>
Please read this notice carefully. This notice contains important
information on who manages the Code for Life portal, how and why we
collect information about you (for example, your name and email
address), how we use your information, and with which persons we share
your information. We also explain what rights you have in relation to
your personal information, for example, the right to say no to the use
of your information in certain cases, and how to contact us if you want
to find out more about your rights or if you have other questions about
this notice.
</Typography>
<TableOfContents
contents={[
{
header: "Our commitment",
children: <OurCommitment />,
},
{
header: "Who we are",
children: <WhoWeAre />,
},
{
header: "Types of information we hold about you",
children: <TypesOfInfo />,
},
{
header: "How we will use information about you",
children: <HowWeUseInfo />,
},
{
header: "Change of purpose",
children: <ChangeOfPurpose />,
},
{
header: "Cookies",
children: <Cookies />,
},
{
header: "Sharing your personal information with other persons",
children: <SharingInfo />,
},
{
header: "How long will we keep your personal information?",
children: <KeepInfo />,
},
{
header: "Your rights",
children: <YourRights />,
},
{
header: "Keeping your personal information secure",
children: <InfoSecurity />,
},
{
header: "How to complain",
children: <HowToComplain />,
},
{
header: "Changes to this Privacy Notice",
children: <Changes lastUpdated={lastUpdated} />,
},
{
header: "How to contact us",
children: <ContactUs />,
},
{
header: "Do you need extra help?",
children: <ExtraHelp />,
},
]}
/>
</pages.Section>
)
}

export default Adults
20 changes: 20 additions & 0 deletions src/pages/privacyNotice/adults/ChangeOfPurpose.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { type FC } from "react"
import { Typography } from "@mui/material"

export interface ChangeOfPurposeProps {}

const ChangeOfPurpose: FC<ChangeOfPurposeProps> = () => (
<>
<Typography mb={0}>
We will only use your personal information for the purposes for which we
collected it or for other compatible purposes. If we need to use your
personal information for an unrelated purpose, we will notify you and we
will explain the basis on which we do so. Please note that we do not
always need to rely on your consent to collect and process your personal
information, and we will not seek your consent unless this is required by
law.
</Typography>
</>
)

export default ChangeOfPurpose
21 changes: 21 additions & 0 deletions src/pages/privacyNotice/adults/Changes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type FC } from "react"
import { Typography } from "@mui/material"

export interface ChangesProps {
lastUpdated: string
}

const Changes: FC<ChangesProps> = ({ lastUpdated }) => (
<>
<Typography>
This Privacy Notice was last updated on {lastUpdated}.
</Typography>
<Typography mb={0}>
We may change this Privacy Notice from time to time and you should check
it regularly. If we make any material changes to this notice we will
inform via appropriate means (e.g. email).
</Typography>
</>
)

export default Changes
20 changes: 20 additions & 0 deletions src/pages/privacyNotice/adults/ContactUs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { type FC } from "react"
import { Link } from "codeforlife/components/router"
import { Typography } from "@mui/material"

export interface ContactUsProps {}

const ContactUs: FC<ContactUsProps> = () => (
<>
<Typography mb={0}>
Please contact our Data Protection Officer or us at&nbsp;
<Link to="mailto:[email protected]" target="_blank">
[email protected]
</Link>
&nbsp;if you have any questions about this Privacy Notice or the
information we hold about you.
</Typography>
</>
)

export default ContactUs
Loading

0 comments on commit 6b1e6fc

Please sign in to comment.