Mise en forme détail de candiature

This commit is contained in:
2021-05-25 17:41:54 +02:00
parent d8ded1e8d7
commit 3c39e8da12
3 changed files with 477 additions and 0 deletions
@@ -0,0 +1,39 @@
import React, { Fragment } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import _ from "lodash"
import Ar from "lodash/array"
import VideoVimeo from '../atoms/VideoVimeo'
const useStyles = makeStyles(theme => ({
card: {
width: '100%',
},
title: {
fontSize: '1em',
fontWeight: '500',
},
titleBorder: {
'&:after': {
content: '""',
width: '15px',
borderBottom: 'solid 2px',
borderColor: theme.palette.primary.main + '!important',
display: 'flex',
},
},
video: {
[theme.breakpoints.up('md')]: {
paddingBottom: '35%', /* 16:9 */
},
}
}));
export default function CandidatureDetail(props) {
const classes = useStyles();
return (
<Fragment>
<VideoVimeo classes={{ video: classes.video }} videoId={Ar.last(_.split(props.video.cdn_url, '/'))} />
</Fragment>
);
}
+432
View File
@@ -0,0 +1,432 @@
import React, {Fragment} from 'react';
import {connect} from "react-redux";
import PropTypes from 'prop-types';
import _ from "lodash"
import {withStyles} from '@material-ui/core/styles';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import {TextField, Button, Typography, Grid, Hidden} from '@material-ui/core';
import SwipeableViews from 'react-swipeable-views';
import Snack from '../components/atoms/snack'
import Loader from '../components/templates/loader'
import LayoutCandidature from '../components/templates/LayoutCandidature';
import CandidatureDetail from '../components/organisms/AnswerDetail'
import OffreDetail from '../components/organisms/OffreDetail'
import Chat from '../components/organisms/Chat'
import AppBar from '@material-ui/core/AppBar';
import {AnswersSelector} from '../reducers/answers'
import {fetchAnswerRequest} from '../actions/answer'
import Head from 'next/head'
import Chip from '@material-ui/core/Chip';
import getConfig from 'next/config'
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
import ButtonBase from '@material-ui/core/ButtonBase';
const {publicRuntimeConfig} = getConfig()
const styles = theme => ({
root: {
position: 'relative',
textAlign: 'center',
paddingTop: theme.spacing(20),
justifyContent: 'center'
},
container: {
// display: 'flex',
// flexDirection: 'column',
height: '100%'
},
userDataContainer: {
// display: 'flex',
padding: theme.spacing(2) + 'px 18vw'
},
userTextContainer: {
// display: 'flex',
// flexDirection: 'column',
paddingLeft: theme.spacing(2)
},
AppBar: {
top: '64px',
position: 'fixed'
},
SwipeableViews: {
paddingTop: '64px'
},
tab: {
'& span.MuiTab-wrapper': {
fontSize: '1.1em',
fontWeight: '300',
textTransform: 'none'
}
},
title: {
fontSize: '1em',
fontWeight: '500'
},
titleBorder: {
'&:after': {
content: '""',
width: '15px',
borderBottom: 'solid 2px',
borderColor: theme.palette.primary.main + '!important',
// display: 'flex'
}
},
userTextName: {
fontWeight: '500',
fontSize: '1em'
},
userTextDate: {
fontWeight: '500',
fontSize: '0.9em'
},
texteInfo:{
fontWeight: '300',
fontSize: '0.9em'
},
userAvatar: {
maxWidth: '104px',
},
menuLogo: {
cursor: 'pointer',
[
theme
.breakpoints
.down('md')
]: {
width: '200px'
},
[
theme
.breakpoints
.down('sm')
]: {
width: '130px'
}
},
information: {
padding: "1em",
width: "100%",
backgroundColor: theme.palette.secondary.main,
borderRadius: "5px",
marginBottom: "30px",
borderColor: "1px solid #E5E5E6"
},
grille: {
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
paddingLeft : theme.spacing(4),
marginBottom: "30px",
borderRadius: "5px",
border: "1px solid #1E2327",
color: theme.palette.primary.dark
},
menuLien: {
fontSize: "1em",
textTransform: "uppercase",
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
color: theme.palette.primary.dark,
textDecoration: "none",
'&:hover': {
color: theme.palette.primary.dark
},
'&:active': {
color: theme.palette.primary.dark
},
'&:visited': {
color: theme.palette.primary.dark
}
},
grilleGauche: {
textAlign: "center"
},
grilleDroite: {
textAlign: "center"
},
grilleBas: {
backgroundColor: theme.palette.secondary.dark
},
chip: {
marginTop: "10px",
backgroundColor: "#E7F3FF",
color: theme.palette.primary.dark
},
icon: {
color: theme.palette.secondary.dark
}
});
function TabContainer({children, dir}) {
return (
<Typography
component="div"
dir={dir}
style={{
padding: 8 * 3
}}>
{children}
</Typography>
);
}
const status = new Map([
["A_TRAITER"
, "Envoyée"]
,
["CONTACTE"
, "En cours de traitement"]
,
["ENTRETIEN"
, "En cours de traitement"]
,
["REFUSE"
, "Refusée"]
,
["EMBAUCHE"
, "Embauchée"]
,
["EXPIRED"
, "Expirée"]
,
[""
, "Envoyée"]
,
["Null"
, "Envoyée"]
,
])
class Candidature extends React.Component {
state = {
data: {},
errors: {},
loading: true,
tabIndex: 0,
openSnack: false
}
static getInitialProps(context) {
const {id} = context.query
return {
id: id * 1
}
}
componentDidMount() {
this
.props
.fetchAnswerRequest(this.props.id)
}
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({loading: nextProps.answer.loading})
}
componentWillUnmount() {}
handleChange = (event, newValue) => {
this.setState({tabIndex: newValue});
}
handleChangeIndex = (index) => {
this.setState({tabIndex: index});
}
render() {
const {classes} = this.props;
const {data, errors, loading, openSnack} = this.state;
console.log("test");
const logoUrl = (this.props.answer.ad
? (this.props.answer.ad.company.logo
? publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + this.props.answer.ad.company.logo
: publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg")
: "")
const nomCompany = (this.props.answer.ad
? (this.props.answer.ad.company.brand_name
? this.props.answer.ad.company.brand_name
: "")
: this.props.answer.company
? this.props.answer.company.brand_name
: "")
//L'entreprise {nomCompany} étudie actuellement votre candidature
const infos = new Map([
[
"A_TRAITER", "Votre candidature a bien été envoyée à lentreprise "+nomCompany
],
[
"CONTACTE", "L'entreprise "+nomCompany+" étudie actuellement votre candidature"
],
[
"ENTRETIEN", "L'entreprise "+nomCompany+" étudie actuellement votre candidature"
],
[
"REFUSE", "Votre candidature a été refusée par lentreprise "+nomCompany+"."
],
[
"EMBAUCHE", "Votre candidature a été acceptée par lentreprise "+nomCompany+"."
],
[
"EXPIRED", "Expirée"
],
[
"", "Envoyée"
],
["Null", "Envoyée"]
])
//brand_name
return (
<LayoutCandidature>
<Head>
<title key="title">Candidature</title>
<meta name="robots" content="noindex, nofollow"></meta>
</Head>
<Fragment>
<div className={classes.container}>
{/* {!!errors && (<div className="alert alert-danger">{errors && errors.message}</div> )} */}
{loading && (<Loader/>)}
{!loading && (
<Fragment>
<AppBar color="default" className={classes.AppBar}>
<Tabs
value={this.state.tabIndex}
onChange={this.handleChange}
indicatorColor="primary"
variant="fullWidth">
<Tab label="Candidature" className={classes.tab}/>
<Tab label="Messagerie" className={classes.tab}/>
<Tab label="Offre d'emploi" className={classes.tab}/>
</Tabs>
</AppBar>
<SwipeableViews
axis={'x'}
index={this.state.tabIndex}
onChangeIndex={() => this.handleChangeIndex()}
className={classes.SwipeableViews}>
<TabContainer dir={'x'}>
<Fragment>
<section className={classes.userDataContainer}>
<Grid container spacing={2} className={classes.grille}>
<Grid item>
<ButtonBase className={classes.image}>
<img alt="talents-tube" src={logoUrl} className={classes.userAvatar}/>
</ButtonBase>
</Grid>
<Grid item lg={12} xl container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xl>
<Typography gutterBottom variant="subtitle1">
{(this.props.answer.ad
? (this.props.answer.ad.company.brand_name
? this.props.answer.ad.company.brand_name
: "")
: this.props.answer.company.brand_name)}
</Typography>
<Typography variant="body2" gutterBottom>
{this.props.answer.ad
? (this.props.answer.ad.title
? this.props.answer.ad.title
: "Candidature spontanée")
: "Candidature spontanée"}
</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container spacing={2} className={classes.grille}>
<Grid container >
<Grid item>
<Typography gutterBottom className={classes.userTextDate}>
Envoyé le :
</Typography>
</Grid>
<Grid item xs={12} sm container>
<Typography gutterBottom className={classes.texteInfo}>
{(new Date(this.props.answer.c_time)).toLocaleDateString("fr-FR")}
</Typography>
</Grid>
</Grid>
<Grid container spacing={2} >
<Grid item>
<Typography gutterBottom variant="subtitle1" className={classes.userTextDate}>
Statut :
</Typography>
</Grid>
<Grid item xl={12} xl >
<Grid xl={12} xl container>
<Typography gutterBottom className={classes.texteInfo}>
<Chip size="small" label={status.get(this.props.answer.status_reponse)? status.get(this.props.answer.status_reponse) : "Envoyée" } className={classes.chip} />
</Typography>
</Grid>
<Grid xl={12} xl container>
<Typography gutterBottom className={classes.texteInfo}>
{infos.get(this.props.answer.status_reponse)
? infos.get(this.props.answer.status_reponse)
: "L'entreprise "+nomCompany+" étudie actuellement votre candidature"}
</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.grille} spacing={2}>
{this.props.answer.video && <CandidatureDetail {...this.props.answer}/>}
</Grid>
</section>
</Fragment>
</TabContainer>
<TabContainer dir={'x'}>
{this.props.answer.messages && <Chat answerId={this.props.answer.id}></Chat>}
</TabContainer>
<TabContainer dir={'x'}>
{this.props.answer.ad && <OffreDetail isCandidature='true' offre={this.props.answer.ad}/>}
</TabContainer>
</SwipeableViews>
</Fragment>
)}
</div>
<Snack
variant="error"
message={this.state.errors.message}
openSnack={this.state.openSnack}
onClose={this.handleClose}/>
</Fragment>
</LayoutCandidature>
);
}
}
function mapStateToProps(state) {
return {answer: state.answer, user: state.user}
}
Candidature.propTypes = {
classes: PropTypes.object.isRequired,
id: PropTypes.number
};
export default withStyles(styles)(connect(mapStateToProps, {fetchAnswerRequest})(Candidature))
+6
View File
@@ -147,6 +147,12 @@ app.prepare()
app.render(req, res, actualPage, queryParams)
})
server.get('/Answer/:id', (req, res) => {
const actualPage = '/Answer'
const queryParams = { id: req.params.id }
app.render(req, res, actualPage, queryParams)
})
server.get('/Offre/:id-:rest', (req, res) => {
const actualPage = '/Offre'
const queryParams = { id: req.params.id }