Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions components/HomePageSections.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { HomePageQuery } from "graphql/cms/homepage.generated";
import React from "react";
import TwoColumnBlock from "./common/TwoColumnBlock";
import CarouselBlock from "./common/CarouselBlock"
import HeaderBlock from "./common/HeaderBlock";

type Unpacked<T> = T extends (infer U)[]
? U
Expand All @@ -11,20 +13,30 @@ type Unpacked<T> = T extends (infer U)[]
: T;

type Props = {
data: Unpacked<HomePageQuery["homePage"]["data"]["attributes"]["sections"]>;
sections: Unpacked<HomePageQuery["homePage"]["data"]["attributes"]["sections"]>;
};

const HomePageSections = ({ data }: Props) => {
//TODO : Fix this component so that it can render other components
switch (data.__typename) {
case "ComponentCommonCarousel":
return null;
case "ComponentCommonHeader":
return null;
case "ComponentCommonTwoColumnBlock":
//@ts-ignore
return <TwoColumnBlock {...data} />;
}
/*
Holds all the sections of the homepage.
Using Math.random to generate keys for the map() function since the component IDs are not unique.
*/
const HomePageSections: React.FC<Props> = ({ sections }) => {
return(
<>
{/* Similar issue to the Type error in index.tsx. Same outcome */}
{sections.map((section) => {
const mapKey = Math.random() * 1000;
switch(section.__typename) {
case "ComponentCommonCarousel":
return <CarouselBlock data={section} key={mapKey} />;
case "ComponentCommonHeader":
return <HeaderBlock data={section} key={mapKey} />;
case "ComponentCommonTwoColumnBlock":
return <TwoColumnBlock data={section} key={mapKey}/>;
}
})}
</>
)
};

export default HomePageSections;
66 changes: 63 additions & 3 deletions components/common/CarouselBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,70 @@
import { ComponentCommonCarousel } from "graphql/types";
import { Box, ImageList, ImageListItem, Typography, IconButton, Grid } from "@mui/material";
import Image from 'next/image';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import ArrowLeftIcon from '@mui/icons-material/ArrowLeft';

type Props = {
data: ComponentCommonCarousel;
};
const CarouselBlock = ({ data }: Props) => {
//TODO : Complete this component
return null;

//TODO Completed
const CarouselBlock: React.FC<Props> = ({ data }) => {
//myCarouselLength is used to dynamically change the number of items in the Carousel
const myCarouselLength = data.Item.length;

//Return a Carousel view of the data passed down
return(
<Grid container alignItems="center">
{/* Header for this section */}
<Grid item xs={12}>
<Box display="flex" justifyContent="center">
<Typography
variant="h6"
fontWeight="bold"
fontFamily="Roboto"
>
Subscribing Institutions
</Typography>
</Box>
</Grid>
{/* Carousel nav left option. Does not have actual button functionality. */}
<Grid item xs={1}>
<IconButton aria-label="nav left">
<ArrowLeftIcon />
</IconButton>
</Grid>
{/* Carousel Items */}
<Grid item xs={10}>
<ImageList
sx={{ width: 1, height: 120}}
cols={myCarouselLength}
gap={5}
>
{data.Item.map((item) => {
return(
<ImageListItem key={item.Description} >
<Image
alt={item.Image.data.attributes.name}
src={`http://localhost:1337${item.Image.data.attributes.url}`}
layout="fill"
/>
</ImageListItem>
)
})}
</ImageList>
</Grid>
{/* Carousel nav Right button. Does not hae actual button functionality. */}
<Grid item xs={1}>
<Box display="flex" justifyContent="flex-end">
<IconButton aria-label="nav right">
<ArrowRightIcon />
</IconButton>
</Box>
</Grid>

</Grid>
);
};

export default CarouselBlock;
19 changes: 16 additions & 3 deletions components/common/HeaderBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import { Typography, Box, Divider } from "@mui/material";
import { ComponentCommonHeader } from "graphql/types";

type Props = {
data: ComponentCommonHeader;
};
const HeaderBlock = ({ data }: Props) => {
//TODO: Complete this component
return null;

//Return a render of the Header Section pass down from the HomePage query
//TODO Completed
const HeaderBlock: React.FC<Props> = ({ data }) => {
return(
<>
<Box display="flex" justifyContent="center">
<Typography variant="h3" fontFamily="Roboto">
{data.Text}
</Typography>
</Box>
<Divider sx={{mb: 4, mt:2}}/>
</>
);
};

export default HeaderBlock;
72 changes: 69 additions & 3 deletions components/common/TwoColumnBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,77 @@
import { ComponentCommonTwoColumnBlock } from "graphql/types";
import { Typography, Grid, Box, Button, Divider } from "@mui/material";

type Props = {
data: ComponentCommonTwoColumnBlock;
};
const TwoColumnBlock = (props: Props) => {
//TODO: Implement this component
return null;

//TODO Completed
const TwoColumnBlock: React.FC<Props> = ({data}) => {
//myImageUrl used to render the correct image from the API
const myImageUrl: string = `http://localhost:1337${data.Image.data.attributes.url}`;

//Return the components to be rendered
//Use Grid system via MUI to correctly align elements
return(
<>
<Grid
container
spacing={6}
columns={2}
>
{/* Check the value of the Image Position field, render components accordingly */}
{data.ImagePosition === "Left" ?
<Grid item xs={1}>
<Box
component="img"
alt={data.Image.data.attributes.name}
src={myImageUrl}
sx={{
width: 1,
}}
/>
</Grid>
: null
}

{/* Render the details */}
<Grid item xs={1} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item >
<Typography variant="subtitle1" fontWeight="bold">
{data.TitleText}
</Typography>
</Grid>
<Grid item >
<Typography variant="body2">
{data.Description}
</Typography>
</Grid>
<Grid item>
<Button variant="outlined" href={data.ButtonUrl}>
{data.ButtonText}
</Button>
</Grid>
</Grid>
</Grid>

{data.ImagePosition === "Right" ?
<Grid item xs={1}>
<Box
component="img"
alt={data.Image.data.attributes.name}
src={myImageUrl}
sx={{
width: 1,
}}
/>
</Grid>
: null
}
</Grid>
<Divider sx={{mb: 3, mt:3}}/>
</>
);
};

export default TwoColumnBlock;
35 changes: 34 additions & 1 deletion graphql/cms/homepage.generated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const defaultOptions = {} as const;
export type HomePageQueryVariables = Types.Exact<{ [key: string]: never; }>;


export type HomePageQuery = { __typename?: 'Query', homePage?: { __typename?: 'HomePageEntityResponse', data?: { __typename?: 'HomePageEntity', attributes?: { __typename?: 'HomePage', sections?: Array<{ __typename?: 'ComponentCommonCarousel', id: string } | { __typename?: 'ComponentCommonHeader', id: string } | { __typename?: 'ComponentCommonTwoColumnBlock', id: string } | { __typename?: 'Error' } | null> | null } | null } | null } | null };
export type HomePageQuery = { __typename?: 'Query', homePage?: { __typename?: 'HomePageEntityResponse', data?: { __typename?: 'HomePageEntity', attributes?: { __typename?: 'HomePage', sections?: Array<{ __typename?: 'ComponentCommonCarousel', id: string, Item?: Array<{ __typename?: 'ComponentCommonTwoColumnBlock', TitleText?: string | null, Description?: string | null, ButtonText?: string | null, ButtonUrl?: string | null, ImagePosition?: Types.Enum_Componentcommontwocolumnblock_Imageposition | null, Image?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', id?: string | null, attributes?: { __typename?: 'UploadFile', name: string, url: string } | null } | null } | null } | null> | null } | { __typename?: 'ComponentCommonHeader', id: string, Text?: string | null, ButtonText?: string | null, ButtonLink?: string | null } | { __typename?: 'ComponentCommonTwoColumnBlock', id: string, TitleText?: string | null, Description?: string | null, ButtonText?: string | null, ButtonUrl?: string | null, ImagePosition?: Types.Enum_Componentcommontwocolumnblock_Imageposition | null, Image?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', id?: string | null, attributes?: { __typename?: 'UploadFile', name: string, url: string } | null } | null } | null } | { __typename?: 'Error' } | null> | null } | null } | null } | null };


export const HomePageDocument = gql`
Expand All @@ -17,12 +17,45 @@ export const HomePageDocument = gql`
sections {
... on ComponentCommonHeader {
id
Text
ButtonText
ButtonLink
}
... on ComponentCommonCarousel {
id
Item {
TitleText
Description
ButtonText
ButtonUrl
ImagePosition
Image {
data {
id
attributes {
name
url
}
}
}
}
}
... on ComponentCommonTwoColumnBlock {
id
TitleText
Description
ButtonText
ButtonUrl
ImagePosition
Image {
data {
id
attributes {
name
url
}
}
}
}
}
}
Expand Down
44 changes: 41 additions & 3 deletions graphql/cms/homepage.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,53 @@ query HomePage {
sections {
... on ComponentCommonHeader {
id
# TODO: Complete this query
Text
ButtonText
ButtonLink
}
... on ComponentCommonCarousel {
id
# TODO: Complete this query
Item
{
TitleText
Description
ButtonText
ButtonUrl
ImagePosition
Image
{
data
{
id
attributes
{
name
url
}
}
}
}

}
... on ComponentCommonTwoColumnBlock {
id
# TODO: Complete this query
TitleText
Description
ButtonText
ButtonUrl
ImagePosition
Image
{
data
{
id
attributes
{
name
url
}
}
}
}
}
}
Expand Down
25 changes: 12 additions & 13 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// import { NextLink } from "components/common/NextLink";
import { Box, Container, Typography } from "@mui/material";
import { Box, Container } from "@mui/material";
import HomePageSections from "components/HomePageSections";
import {
HomePageDocument,
HomePageQuery,
Expand All @@ -13,9 +14,12 @@ import {
import type { GetStaticProps, NextPage } from "next";
import Head from "next/head";


const Home: NextPage = () => {
//Fetch the data then assign what we need to a variable.
//Pass that data down to the HomePageSections component.
const { data } = useHomePageQuery();

const mySections = data.homePage.data.attributes.sections;
return (
<>
<Head>
Expand All @@ -24,18 +28,13 @@ const Home: NextPage = () => {
<link rel="icon" href="/favicon.ico" />
</Head>
<Container>
<Box my={2}>
<Typography variant="h4">Welcome to JOMI Code Challenge</Typography>
<Typography>
Please follow the instructions on
<a href="https://github.com/jomijournal/jomi-cms-challenge-backend">
https://github.com/jomijournal/jomi-cms-challenge-backend
</a>{" "}
to complete the challenge
</Typography>
{/* TODO Completed */}
<Box>
{/* Seems like an error is being thrown here because eslint doesn't like
the type of the data being passed down. That being said, the webpage works
as expected regardless. */}
<HomePageSections sections={mySections}/>
</Box>

<Box>{/* TODO: Render components from useHomePageQury here */}</Box>
</Container>
</>
);
Expand Down