Skip to content

Commit

Permalink
feat: create individual Photostory page (#331)
Browse files Browse the repository at this point in the history
* feat: create individual photostory page

* feat: create individual photostory page

* feat: add new Carousel and Photostory integration

* chore: remove unused codes

* fix: dynamic tags

* fix: redirect to photostory page

* fix: add exception handling to rendering

* fix: render page 500 on error

* refactor: update props name
  • Loading branch information
Anish-Sarawgi authored Dec 20, 2022
1 parent 8957c9b commit 8cf9578
Show file tree
Hide file tree
Showing 11 changed files with 568 additions and 193 deletions.
35 changes: 5 additions & 30 deletions client/src/components/article/RecommendedArticles.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,27 @@
import React from 'react';

// libraries
import { Container, Typography } from '@mui/material';

import makeStyles from '@mui/styles/makeStyles';

// Components
import ArticleCardStack from '../widgets/article/ArticleCardStack';

const RecommendedArticles = ({ title }) => {
const RecommendedArticles = ({ articles, title }) => {
const classes = useStyles();

return (
<div className={classes.wrapper}>
<Container>
<div className={classes.titleWrapper}>
<Typography variant='h2' className={classes.title}>
{title}
</Typography>
<div className={classes.underline} />
</div>
<ArticleCardStack />
</Container>
<ArticleCardStack articleList={articles.slice(0, 3)} title={title} />
</div>
);
};
export default RecommendedArticles;

const useStyles = makeStyles((theme) => ({
wrapper: {
marginTop: '2rem',
marginTop: '1.5rem',
backgroundColor: theme.palette.primary.blue10,
paddingTop: '2rem',
paddingTop: '0.1rem',
paddingBottom: '2rem',
},
titleWrapper: {
display: 'flex',
marginBottom: '20px',
alignItems: 'center',
justifyContent: 'space-between',
},
title: {
display: 'inline-block',
width: 'auto',
},
underline: {
height: '2px',
backgroundColor: 'black',
marginLeft: '40px',
flex: 1,
},
}));
5 changes: 4 additions & 1 deletion client/src/components/article/comments/Comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function Comment({ comment }) {
<Card className={classes.commentCard}>
<CardContent>
<Grid container>
<Grid item sm={1}>
<Grid item sm={1} className={classes.image}>
<Image src={user} alt='User' />
</Grid>

Expand All @@ -37,4 +37,7 @@ const useStyles = makeStyles((theme) => ({
marginTop: '1rem',
boxShadow: theme.shadows[0],
},
image: {
alignSelf: 'center',
},
}));
10 changes: 7 additions & 3 deletions client/src/components/article/comments/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';

// libraries
import { Typography } from '@mui/material';
import { Container, Typography } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import { Element } from 'react-scroll';

Expand Down Expand Up @@ -32,7 +32,7 @@ const Comments = () => {
};

return (
<div className={classes.container}>
<Container className={classes.container}>
<Element name='commentBox'>
<Typography variant='h2'>Comment</Typography>

Expand Down Expand Up @@ -65,7 +65,7 @@ const Comments = () => {
</Typography>
)}
</Element>
</div>
</Container>
);
};

Expand All @@ -75,4 +75,8 @@ const useStyles = makeStyles(() => ({
container: {
marginTop: '2rem',
},
commentToggle: {
cursor: 'pointer',
marginTop: '1rem',
},
}));
4 changes: 3 additions & 1 deletion client/src/components/expressions/PhotoStory.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ function PhotoStory({ photostory }) {
return (
<div className={classes.wrapper}>
<NewTabLink
to={getArticleLink(photostory[0].id, photostory[0].title)}
to={getArticleLink(photostory[0].id, photostory[0].title, {
isPhotostory: true,
})}
className={classes.link}
>
<Image
Expand Down
65 changes: 11 additions & 54 deletions client/src/components/photostory/Body.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,24 @@
import React from 'react';

import makeStyles from '@mui/styles/makeStyles';
import { Typography } from '@mui/material';
// libraries
import { Container } from '@mui/material';

// Components
import PhotoCarousel from '../widgets/PhotoCarousel';
import Carousel from '../../components/photostory/Carousel';
import Disclaimer from '../article/Disclaimer';
import ArticleTags from '../article/Tags';

// Placeholder
import { PHOTOSTORY } from '../../assets/placeholder/photostory';

const Body = () => {
const classes = useStyles();
const Body = ({ content, tags }) => {
return (
<div>
<div className={classes.carouselWrapper}>
<div>
<PhotoCarousel IMAGE={PHOTOSTORY.image} />
</div>
<div className={classes.textWrapper}>
<Typography variant='body1' className={classes.text}>
{PHOTOSTORY.carousel}
</Typography>
</div>
</div>
<div className={classes.wrapper}>
<>
<Carousel content={content} />
<Container>
<Disclaimer />
<ArticleTags tags={PHOTOSTORY.tags} />
</div>
</div>
<ArticleTags tags={tags} />
<hr />
</Container>
</>
);
};

export default Body;

const useStyles = makeStyles((theme) => ({
carouselWrapper: {
backgroundColor: theme.palette.secondary.main,
padding: '24px 0px 48px 0px',
[theme.breakpoints.down('sm')]: {
padding: '12px 0px',
},
},
textWrapper: {
marginTop: '12px',
display: 'flex',
direction: 'row',
justifyContent: 'center',
[theme.breakpoints.down('sm')]: {
padding: '0px 24px',
justifyContent: 'flex-start',
},
},
text: {
color: theme.palette.common.white,
alignSelf: 'center',
},
wrapper: {
maxWidth: '1280px',
margin: '60px auto 0px auto',
[theme.breakpoints.down('sm')]: {
margin: '40px 16px 0px 24px',
},
},
}));
182 changes: 182 additions & 0 deletions client/src/components/photostory/Carousel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import React, { useState } from 'react';
import Image from 'next/image';
import makeStyles from '@mui/styles/makeStyles';
import { IconButton, Typography, useMediaQuery } from '@mui/material';
import ArrowLeft from '@mui/icons-material/ArrowCircleLeftOutlined';
import ArrowRight from '@mui/icons-material/ArrowCircleRightOutlined';

// Utils
import STORES from '../../utils/getStores';
import theme from '../../config/themes/light';

const Carousel = ({ content }) => {
const classes = useStyles();
const length = content.length;

const [left, setLeft] = useState(length - 1);
const [current, setCurrent] = useState(0);
const [right, setRight] = useState(1);

const nextSlide = () => {
setLeft(left === length - 1 ? 0 : left + 1);
setCurrent(current === length - 1 ? 0 : current + 1);
setRight(right === length - 1 ? 0 : right + 1);
};
const prevSlide = () => {
setLeft(left === 0 ? length - 1 : left - 1);
setCurrent(current === 0 ? length - 1 : current - 1);
setRight(right === 0 ? length - 1 : right - 1);
};

if (!Array.isArray(content) || content.length <= 0) {
return null;
}

const Desktop = useMediaQuery(theme.breakpoints.up('sm'));

return (
<section className={classes.wrapper}>
<div className={classes.imgContainer}>
{Desktop && (
<Image
className={classes.sideImage}
src={
STORES[content[left].media.store] +
encodeURI(content[left].media.storePath)
}
alt='travel image'
width='400px'
height='300px'
objectFit='contain'
/>
)}
<div className={classes.midSlide}>
<Image
className={classes.centreImage}
src={
STORES[content[current].media.store] +
encodeURI(content[current].media.storePath)
}
alt='travel image'
width='600px'
height={Desktop ? '400px' : '700px'}
objectFit='contain'
/>
{content[current].text && (
<div className={classes.textWrapper}>
<Typography
variant='body2'
textAlign='center'
className={classes.text}
>
{content[current].text}
</Typography>
</div>
)}
</div>
{Desktop && (
<Image
className={classes.sideImage}
src={
STORES[content[right].media.store] +
encodeURI(content[right].media.storePath)
}
alt='travel image'
width='400px'
height='300px'
objectFit='contain'
/>
)}
</div>

<span className={classes.navIconWrapper}>
<IconButton
className={classes.navIcon}
onClick={prevSlide}
size='large'
>
<ArrowLeft />
</IconButton>
<IconButton
className={classes.navIcon}
onClick={nextSlide}
size='large'
>
<ArrowRight />
</IconButton>
</span>
</section>
);
};

export default Carousel;

const useStyles = makeStyles((theme) => ({
wrapper: {
maxWidth: '100%',
position: 'relative',
backgroundColor: theme.palette.secondary.main,
paddingTop: '0.5rem',
},

carousel: {
display: 'flex',
overflowX: 'scroll',
overflowY: 'none',
scrollBehavior: 'smooth',
},

imgContainer: {
display: 'flex',
justifyContent: 'center',
marginTop: '1em',
gap: 20,
},

centreImage: {
borderRadius: '16px',
},

sideImage: {
borderRadius: '16px',
opacity: '0.5',
},

midSlide: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
borderRadius: '16px',
},

bottomContainer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
bottom: '3%',
position: 'absolute',
},

textWrapper: {
justifyContent: 'justify',
alignItems: 'justify',
marginTop: '15px',
color: theme.palette.common.white,
[theme.breakpoints.down('sm')]: {
paddingLeft: '15px',
paddingRight: '15px',
},
},

navIconWrapper: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: theme.palette.secondary.neutral70,
},

navIcon: {
color: theme.palette.secondary.neutral70,
},
}));
Loading

0 comments on commit 8cf9578

Please sign in to comment.