Verified Commit 93b4ae78 authored by Sandro Lutz's avatar Sandro Lutz
Browse files

Add joboffers to home page

parent c71b673a
import React from 'react'
import PropTypes from 'prop-types'
import { makeStyles, useTheme } from '@material-ui/core/styles'
import Skeleton from '@material-ui/lab/Skeleton'
import { Paper, Box } from '@material-ui/core'
import { apiUrl } from 'config'
import Image from '../general/image'
import Link from '../general/link'
import Spinner from '../general/spinner'
import TranslatedContent from '../general/translatedContent'
const useStyles = makeStyles(
theme => ({
root: {
borderRadius: '4px',
overflow: 'hidden',
},
container: {
display: 'flex',
flexWrap: 'wrap',
alignContent: 'space-between',
height: '100%',
padding: '1em',
},
title: {
color: theme.palette.text.primary,
},
titleSkeleton: {
margin: '0 auto',
},
logo: {
marginTop: '1em',
background: 'transparent',
},
logoSkeleton: {
marginTop: '1em',
},
placeholderText: {
textAlign: 'center',
width: '65%',
'& > div': {
display: 'inline-block',
height: '2.5em',
},
},
}),
{ name: 'jobsCard' }
)
const JobsCard = ({ joboffer, elevation, className, ...props }) => {
const classes = useStyles()
const theme = useTheme()
const logoLoadingPlaceholder = (
<React.Fragment>
<Skeleton width="100%" height="100%" variant="rect" animation="pulse" />
<Spinner centered background={theme.palette.common.white} elevation={2} />
</React.Fragment>
)
return (
<Paper boxShadow={2} className={[classes.root].join(' ')} {...props}>
{joboffer ? (
<Link to={`/jobs/${joboffer._id}`} className={classes.container}>
<TranslatedContent
className={classes.title}
content={{ en: joboffer.title_en, de: joboffer.title_de }}
typographyProps={{ variant: 'h6' }}
noHint
/>
<Image
className={classes.logo}
type="dynamic"
src={`${apiUrl}${joboffer.logo.file}`}
ratioX={4}
ratioY={1}
alt={joboffer.company}
loadingPlaceholder={logoLoadingPlaceholder}
/>
</Link>
) : (
<div className={classes.container}>
<Skeleton
className={classes.titleSkeleton}
width="80%"
height="2em"
variant="text"
animation="pulse"
/>
<Skeleton
className={classes.logoSkeleton}
width="100%"
height="6em"
variant="rect"
animation="pulse"
/>
</div>
)}
</Paper>
)
}
JobsCard.propTypes = {
/** Joboffer object */
joboffer: PropTypes.object,
/** Specifies the size of the shadow around the card */
elevation: PropTypes.number,
/** Additional class for the outermost box */
className: PropTypes.string,
}
JobsCard.defaultProps = {
elevation: 0,
}
export default JobsCard
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { FormattedMessage } from 'gatsby-plugin-intl'
import { makeStyles } from '@material-ui/core/styles'
import { Typography } from '@material-ui/core'
import { listLoadNextPage } from '~store/common/actions'
import { EVENTS } from '~store/events/constants'
import Layout from '../components/layout'
import Link from '../components/general/link'
import EventPoster from '../components/events/eventPoster'
import { JOBOFFERS } from '../store/joboffers/constants'
import JobsCard from '../components/jobs/card'
const useStyles = makeStyles(
theme => ({
......@@ -14,6 +18,9 @@ const useStyles = makeStyles(
textAlign: 'center',
paddingTop: '5em',
},
title: {
color: theme.palette.text.primary,
},
cardRow: {
marginBottom: '30px',
......@@ -31,29 +38,58 @@ const useStyles = makeStyles(
)
const IndexPage = () => {
const classes = useStyles()
const events = useSelector(state => state.events.items)
const frontpage = useSelector(state => state.events.frontpage)
const joboffers = useSelector(state => state.joboffers.items)
const eventsFrontpage = useSelector(state => state.events.frontpage)
const joboffersFrontpage = useSelector(state => state.joboffers.frontpage)
const dispatch = useDispatch()
const classes = useStyles()
// Note: the second empty array ensures that the effect is called only once after mount.
useEffect(() => {
if (frontpage.totalPages === 0 && !frontpage.isPending) {
if (eventsFrontpage.totalPages === 0 && !eventsFrontpage.isPending) {
dispatch(listLoadNextPage(EVENTS, { listName: 'frontpage' }))
}
}, [])
useEffect(() => {
if (joboffersFrontpage.totalPages === 0 && !joboffersFrontpage.isPending) {
dispatch(listLoadNextPage(JOBOFFERS, { listName: 'frontpage' }))
}
}, [])
return (
<Layout className={classes.root} seoProps={{ title: 'home.title' }}>
<Link to="/events">
<h1>Events</h1>
<Typography variant="h3" className={classes.title}>
<FormattedMessage id="events.title" />
</Typography>
</Link>
<div className={classes.cardRow}>
{frontpage.lastPageLoaded > 0
? frontpage.items.map(eventId => (
{eventsFrontpage.lastPageLoaded > 0
? eventsFrontpage.items.map(eventId => (
<EventPoster key={eventId} event={events[eventId].data} />
))
: Array.from(Array(3)).map(i => <EventPoster key={i} event={null} />)}
: Array.from(Array(3)).map((_, i) => (
<EventPoster key={i} event={null} />
))}
</div>
<Link to="/jobs">
<Typography variant="h3" className={classes.title}>
<FormattedMessage id="jobs.title" />
</Typography>
</Link>
<div className={classes.cardRow}>
{joboffersFrontpage.lastPageLoaded > 0
? joboffersFrontpage.items.map(jobofferId => (
<JobsCard
key={jobofferId}
joboffer={joboffers[jobofferId].data}
/>
))
: Array.from(Array(3)).map((_, i) => (
<JobsCard key={i} joboffer={null} />
))}
</div>
</Layout>
)
......
......@@ -2,6 +2,17 @@ import { JOBOFFERS } from './constants'
import generateReducer from '../common/reducer'
const lists = {
frontpage: {
useQuery: false,
createBaseQuery: now => ({
max_results: 6,
where: {
time_end: { $gte: now },
show_website: true,
},
sort: ['time_end'],
}),
},
default: {
useQuery: true,
createBaseQuery: now => ({
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment