Compare commits

...

27 Commits

Author SHA1 Message Date
llaniau 67b3c97806 no follow 2020-12-13 23:47:51 +01:00
llaniau ee636e27ff US 238 : Mise en place de la version 2020-12-11 16:14:48 +01:00
llaniau ff5055c411 US 435 et 355 sur le module webRTC new look 2020-12-11 15:34:22 +01:00
llaniau d5b1fcd74a Reglage mise en page Offre emploi 2020-12-10 17:31:58 +01:00
llaniau 5ace82986f US 443: Stocker id annonce dans le mail 2020-12-10 16:57:22 +01:00
llaniau c989b6ddfe Point mise en page Corentin 2020-12-10 16:52:29 +01:00
llaniau f3f94e9b51 Navigation intelligente lors du login 2020-12-09 14:08:35 +01:00
llaniau 6c34cad1e7 Social Share 2020-12-03 16:43:29 +01:00
llaniau cb5268bf27 Header maj 2020-12-03 16:20:51 +01:00
llaniau 7b77b2195d US403, US413, US404 2020-12-03 16:17:52 +01:00
llaniau dad7e6b2eb US 420,412,421,414 2020-12-02 16:40:57 +01:00
llaniau 146d1a5061 Mise en place du nouveau parcours talent 2020-12-01 19:21:23 +01:00
llaniau ed626137cf Correction entreprise rattaché à territoir en prod 2020-12-01 11:23:22 +01:00
llaniau 224cedac65 Bug video territoire 2020-11-26 15:03:54 +01:00
llaniau b5b41b4849 next.config.js en mode prod 2020-11-25 09:14:32 +01:00
llaniau d1ee296684 Pour mise en prod, balise nofolow 2020-11-24 13:55:54 +01:00
llaniau 6cf3bcc658 Forcage web app 2020-11-24 11:48:29 +01:00
llaniau b20efef730 Tel + collapse 2020-11-17 17:40:27 +01:00
llaniau 459ff88e9d Correction navigation 2020-10-28 17:06:53 +01:00
llaniau dcdbfed2a3 Garder historique des pages de recherche 2020-10-27 18:23:34 +01:00
llaniau d235b08fe3 Mise en place du lazy 2020-10-22 17:27:28 +02:00
llaniau e5b9f2b75d Nofollow pour pre prod 2020-10-20 09:17:21 +02:00
llaniau 563107e649 Modif mise en page diverses 2020-10-20 09:14:13 +02:00
llaniau 5545dbfad0 Modif next.config.js 2020-10-20 08:50:47 +02:00
llaniau 353128fa8e Suppression balise meta pour mise en prod 2020-10-15 15:12:07 +02:00
llaniau 2e9fa7e9d0 Corrections mineures 2020-10-15 14:45:36 +02:00
llaniau c0e5ec6e90 Test api pole emploi 2020-10-14 17:36:43 +02:00
43 changed files with 2800 additions and 364 deletions
+2
View File
@@ -9,6 +9,7 @@ import BusinessCenterIcon from '@material-ui/icons/BusinessCenter';
import Business from '@material-ui/icons/Business';
import Typography from '@material-ui/core/Typography';
import WatchLater from '@material-ui/icons/WatchLater';
import Home from '@material-ui/icons/Home';
const variantIcon = {
assignment: AssignmentIcon,
@@ -17,6 +18,7 @@ const variantIcon = {
business_center: BusinessCenterIcon,
business: Business,
watch_later: WatchLater,
home: Home,
};
const styles = theme => ({
@@ -4,6 +4,7 @@ import { withStyles } from '@material-ui/core/styles';
import AssignmentIcon from '@material-ui/icons/Assignment';
import RoomIcon from '@material-ui/icons/Room';
import LocationOnIcon from '@material-ui/icons/LocationOn';
import HomeOnIcon from '@material-ui/icons/Home';
import WatchLater from '@material-ui/icons/WatchLater';
import BusinessCenterIcon from '@material-ui/icons/BusinessCenter';
import Typography from '@material-ui/core/Typography';
@@ -13,6 +14,7 @@ const variantIcon = {
assignment: AssignmentIcon,
room: RoomIcon,
location_on: LocationOnIcon,
home: HomeOnIcon,
watch_later: WatchLater,
business_center: BusinessCenterIcon,
business: Business,
+1 -1
View File
@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import Head from 'next/head'
const OgHead = props => {
return (
<Head>
+2 -4
View File
@@ -94,7 +94,7 @@ const useStyles = makeStyles(theme => ({
export default function SimpleCollapse(props) {
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
const [expanded, setExpanded] = React.useState(true);
function handleExpandClick() {
setExpanded(!expanded);
@@ -111,12 +111,10 @@ export default function SimpleCollapse(props) {
</Collapse>
<CardActions disableSpacing classes={{ root: classes.rootCardAction }}>
<IconButton
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="Afficher plus"
aria-label="Afficher plus "
> <Typography className={classes.displayMore}>
{(!expanded) ? 'Afficher plus' : 'Afficher moins'}
</Typography>
+2 -1
View File
@@ -119,7 +119,7 @@ class Etape2 extends React.Component {
componentDidMount() {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
if (!!!localStorage.getItem('ttJWT')) {
Router.push("/Login")
@@ -250,6 +250,7 @@ class Etape2 extends React.Component {
<div className={classes.recorderContainer}>
<Recorder uploader={this.props.uploadMediaPres} titreBouton="Remplacer ma vidéo"/>
</div>
)
}
+1 -1
View File
@@ -69,7 +69,7 @@ class Etape3 extends React.Component {
};
componentDidMount() {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
if(!!!localStorage.getItem('ttJWT'))
{
+204 -6
View File
@@ -1,4 +1,4 @@
import React, { Component, Fragment } from 'react'
import React, { Component, Fragment, useState } from 'react'
import { withStyles } from '@material-ui/core/styles';
import { Button, Typography } from '@material-ui/core';
import TextField from '@material-ui/core/TextField';
@@ -10,6 +10,23 @@ import Avatar from '@material-ui/core/Avatar';
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
import Loader from './../templates/loader'
import getConfig from 'next/config'
import 'video-react/dist/video-react.css';
import { Player } from 'video-react';
import GooglePlaceAutocomplete from 'mui-places-autocomplete'
import { geocodeByAddress } from 'react-places-autocomplete'
import FormControl from '@material-ui/core/FormControl'
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
// import PlacesAutocomplete from 'react-places-autocomplete';
// import {
// geocodeByAddress,
// geocodeByPlaceId,
// getLatLng,
// } from 'react-places-autocomplete';
// import GoogleAutoComplete from 'react-google-autocomplete-address-fields';
const styles = theme => ({
container: {
@@ -89,19 +106,122 @@ const styles = theme => ({
color: theme.palette.secondary.main,
},
},
remplacerButton: {
color: '#1E2327',
borderColor: '#1E2327',
border: '2px solid',
padding: '9.6px 8px',
margin:'15px 0px 25px 0px',
textTransform: 'inherit',
},
player:{
width:"100px"
}
});
export const getCountryFromAddress = (address) => {
if (!address) {
return '';
}
try {
const country = address.address_components.filter(component => component.types.includes('country')).map(c => c.long_name)[0];
console.log('using country for filter ' + country);
return country;
} catch (error) {
console.log(error);
return '';
}
}
const { publicRuntimeConfig } = getConfig()
//https://xd.adobe.com/view/ba98331a-9145-4d67-7e27-25a36e519ef4-cca9/screen/a96779d7-bdb3-410a-8f19-e6987acb98ee/Candidature-Step-3
class Answer extends Component {
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.onSubmit = this.onSubmit.bind(this);
const viewValue = this.props.value;
this.onSuggestionSelected = this.onSuggestionSelected.bind(this);
this.onChange = this.onChange.bind(this);
}
state = {
open: false
};
openDialog() {
this.setState({ open: true });
}
closeDialog() {
this.setState({ open: false });
}
refreshDialog() {
this.setState({ open: false });
window.location.reload();
}
onChange = (e) => {
this.setState({
value: e.target.value
});
if (e.target.value === '') {
console.log('cleared');
this.props.onSelectionChanged('');
}
}
onSuggestionSelected = (suggestion) => {
console.log('Selected suggestion:', suggestion)
const address = suggestion.description;
this.setState({
value: address
});
geocodeByAddress(address)
.then(address => {
console.log('Selected ' + JSON.stringify(address[0]));
this.props.onSelectionChanged(address[0]);
})
.catch(error => console.error('Error', error))
}
onSuggestionSelected(suggestion) {
// Add your business logic here. In this case we just log...
console.log('Selected suggestion:', suggestion)
}
renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions, loading }) => (
<div>
<input className={styles.inputSearchBar} {...getInputProps()} />
<div >
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item';
const style = suggestion.active
? { backgroundColor: 'red', cursor: 'pointer',border: '1px solid' }
: { backgroundColor: '#ffffff', cursor: 'pointer',border: '1px solid' };
return (<div {...getSuggestionItemProps(suggestion,{className,style})}>
<span>{suggestion.description}</span>
</div>
)
})}
</div>
</div>
);
callbackFunc = ( autoCompleteData ) => {
//You can use the address data, passed by autocomplete as you want.
}
state = {
file: null,
firstname: '',
@@ -112,13 +232,19 @@ class Answer extends Component {
twitter: '',
website: '',
mediaId: null,
mediaUrl: null,
thumbnails:null,
heure: null,
companyId: null,
address:'',
errorMessage:''
};
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
firstname: nextProps.user.firstname,
@@ -129,11 +255,16 @@ class Answer extends Component {
twitter: nextProps.user.twitter,
website: nextProps.user.website,
mediaId: nextProps.mediaId,
mediaUrl: nextProps.mediaUrl,
thumbnails: nextProps.thumbnails,
heure: nextProps.heure,
companyId: nextProps.companyId,
})
}
componentDidMount() {
console.log("ANSWER !!!!!!! !!!!!! !!!!!! ");
console.log(this.props);
this.setState({
firstname: this.props.user.firstname,
lastname: this.props.user.lastname,
@@ -142,6 +273,11 @@ class Answer extends Component {
linkedin: this.props.user.linkedin,
twitter: this.props.user.twitter,
website: this.props.user.website,
video: this.props.answer,
mediaUrl : this.props.mediaUrl,
thumbnails : this.props.thumbnails,
heure : this.props.heure
})
}
@@ -170,7 +306,10 @@ class Answer extends Component {
{
adId: this.props.adId,
companyId: this.props.companyId,
mediaId: this.props.mediaId
mediaId: this.props.mediaId,
mediaUrl: this.props.mediaUrl,
thumbnails : this.props.thumbnails,
heure: this.props.heure
})
}
@@ -184,12 +323,30 @@ class Answer extends Component {
data.append('file', file)
this.props.updateUserPictureRequest(data)
}
// recupererAdresse =()=>{
// geocodeByAddress('1 rue de la laine, Questembert')
// .then(results => getLatLng(results[0]))
// .then(({ lat, lng }) =>
// console.log('Successfully got latitude and longitude', { lat, lng })
// )
// geocodeByAddress('1 rue de la laine, Questembert')
// .then(results => console.log(results))
// .catch(error => console.error(error));
// }
render() {
const { classes, user } = this.props
const logoUrl = user.picture;
const inputProps = {
value: this.state.address,
onChange: this.onChange,
}
return (
<section className={classes.container}>
<form className={classes.form}
autoComplete="off">
{!!logoUrl && <Avatar className={classes.logo}
@@ -218,6 +375,39 @@ class Answer extends Component {
</Button>
</label></Fragment>)
}
<Player fluid={false} width={450}
playsInline className={classes.player}
src={publicRuntimeConfig.symphonyUrl + "uploads/videos/"+this.state.mediaUrl}
//src={this.state.mediaUrl}
// src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
/>
{/* <GooglePlaceAutocomplete
name="location"
label="Location"
onSuggestionSelected={this.onSuggestionSelected}
textFieldProps={{ onChange: (e) => this.onChange(e), value: this.state.value, placeholder: 'Search for a place'}}
types={['(regions)']}
renderTarget={() => (<div />)}
/> */}
<Button className={classes.remplacerButton} onClick={this.openDialog.bind(this)}>
Remplacer ma vidéo
</Button>
<Dialog open={this.state.open} onEnter={console.log("Hey.")}>
<DialogTitle> Souhaitez-vous remplacer votre vidéo de réponse ?</DialogTitle>
<DialogContent> Cette vidéo sera définitivement supprimée. Vous pourrez importer ou réaliser une nouvelle video de réponse. </DialogContent>
<DialogActions>
<Button onClick={this.closeDialog.bind(this)} autoFocus>
Annuler
</Button>
<Button onClick={this.refreshDialog.bind(this)} >
Remplacer
</Button>
</DialogActions>
</Dialog>
<TextField
name="lastname"
required
@@ -311,6 +501,7 @@ class Answer extends Component {
value={this.state.website}
onChange={this.handleChange}
/>
</form>
<div id="F" className={classes.foot}>
<Button variant="contained" className={classes.button + ' cypButtonSendApplication'} onClick={this.onSubmit}>Envoyer ma candidature</Button>
@@ -321,13 +512,20 @@ class Answer extends Component {
}
function mapStateToProps(state, ownProps) {
// console.log(state.media.message.heure);
return {
user: state.user,
loading: !!state.user.loading,
pictureLoading: !!state.user.pictureLoading,
errors: state.user.errors || ownProps.errors,
mediaId: state.media.message && state.media.message.mediaId,
mediaUrl: state.media.message && state.media.message.originalUrl,
thumbnails: state.media.message && state.media.message.thumbnails,
mediaUrlVimeo: state.media.message && state.media.message.uriVimeo,
mediaFileName: state.media.message && state.media.message.filename,
heure: state.media.message && state.media.message.heure,
};
}
export default withStyles(styles)(connect(mapStateToProps, { postAdAnswerRequest, updateUserRequest, updateUserPictureRequest })(Answer))
+24 -2
View File
@@ -5,10 +5,11 @@ import { Fragment } from 'react';
import NewsLetterRegistration from './NewsLetterRegistration'
import dynamic from 'next/dynamic'
import Button from '@material-ui/core/Button'
import getConfig from 'next/config'
const PWAInstallSnack = dynamic(() => import('./PWAInstallSnack'), {
ssr: false
});
const { publicRuntimeConfig } = getConfig();
const styles = theme => ({
root: {
@@ -152,6 +153,11 @@ const styles = theme => ({
justifyContent: 'center',
padding: theme.spacing(6, 4),
},
version:{
marginTop: '15px',
fontSize: '0.7em',
fontWeight: '300',
}
});
@@ -215,6 +221,12 @@ function Footer(props) {
</Typography>
</a>
</Link>
<a href="https://blog.talentstube.com" target="_blank">
<Typography gutterBottom color="secondary" component="p" className={classes.textContainer}
>
Blog
</Typography>
</a>
</section>
<section className={classes.container}>
<Typography color="secondary" component="p" className={classes.titleContainer}>
@@ -243,6 +255,13 @@ function Footer(props) {
</Typography>
</a>
</Link>
<Link href="" >
<a href="https://blog.talentstube.com/contact" target="_blank">
<Typography gutterBottom color="secondary" component="p" className={classes.textContainer}>
Contact
</Typography>
</a>
</Link>
</section>
<section className={classes.container}>
<Typography color="secondary" component="p" className={classes.titleContainer}>
@@ -255,7 +274,7 @@ function Footer(props) {
56 000 Vannes
</Typography>
<Typography gutterBottom color="secondary" component="p" className={classes.textContainer}>
02.30.05.06.31
<a href="tel:+33230050631" >02.30.05.06.31 </a>
</Typography>
{/* <Typography gutterBottom color="secondary" component="p" className={classes.textContainer}>
contact@talentstube.com
@@ -270,6 +289,9 @@ function Footer(props) {
<a href="https://www.bretagne.bzh/" target="_blank" className={classes.darkMenuItem} rel="noopener">
<img alt="Région Bretagne" src='/static/images/logos/Logo-region.svg' className={classes.footerLogo} />
</a>
<Typography className={classes.version} align="center" >
{publicRuntimeConfig.version}
</Typography>
</section>
</div>
);
@@ -1,7 +1,8 @@
import React from 'react';
const NextButton = ({ hasNext, onClick, style, className, text }) => hasNext ? (
<button type="button" onClick={onClick} style={style} className={className}>Suivant</button>
// <button type="button" onClick={onClick} style={style} className={className}>Suivant</button>
<div></div>
) :
null;
@@ -0,0 +1,35 @@
// import React, { useState } from 'react';
// import Pagination from '@material-ui/lab/Pagination';
// import PaginationItem from '@material-ui/lab/PaginationItem';
// export default function GriddleCustomPageDropdown(props) {
// let [page] = React.useState(1);
// let PageDropDown = null;
// const setPage = (event, newPage) => {
// console.log('test');
// setPage(newPage);
// };
// return (
// <Pagination count={props.maxPages} defaultPage={props.currentPage} onChange={props.setPage}/>
// );
// }
// const [page, setPage] = useState(1);
// const handleChangePage = (event, newPage) => {
// setPage(newPage);
// };
// const PageDropDown = ({ maxPages, currentPage, setPage }) => <Pagination count={maxPages} defaultPage={currentPage} onChangePage={handleChangePage}/> ;
// export default PageDropDown;
import React from 'react';
import Pagination from '@material-ui/lab/Pagination';
const NextButton = ({ maxPages, currentPage, setPage, className, text }) => maxPages ? (
<Pagination count={maxPages} defaultPage={currentPage} onChange={setPage} shape="rounded"/>
) :
null;
export default NextButton;
@@ -1,8 +1,9 @@
import React from 'react';
const PreviousButton = ({ hasPrevious, onClick, style, className, text }) => hasPrevious ? (
<button type="button" onClick={onClick} style={style} className={className}>Précédent</button>
) :
// <button type="button" onClick={onClick} style={style} className={className}>Précédent</button>
<div></div>
) :
null;
export default PreviousButton;
+28 -8
View File
@@ -40,7 +40,7 @@ import ActiveLink from "./../atoms/Activelink";
import axios from 'axios';
import setAuthorizationHeader from "../../data/setAuthorizationHeader";
import getConfig from 'next/config'
import Router from 'next/router'
const styles = theme => ({
root: {
width: '100%',
@@ -327,7 +327,12 @@ class Header extends React.Component {
}
toggle = () => this.setState(state => ({ toggle: !state.toggle }))
chargerPage =(type)=> {
console.log(type);
//Router.replace(page);
sessionStorage.setItem(type+'_currentPage',1);
}
render() {
const { classes } = this.props;
const { publicRuntimeConfig } = getConfig();
@@ -383,16 +388,25 @@ class Header extends React.Component {
</ListItemText>
</ListItem></a>
</ActiveLink>
<a className={classes.darkMenuItem + ' ' + classes.darkMenuItemSpecific} href="https://blog.talentstube.com/" target="_blank">
<ListItem classes={{ root: classes.rootListItem }}>
<NotesIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Blog'>
</ListItemText>
</ListItem>
</a>
</div>
<div>
<div className={classes.blogLinkGroup}>
{/* <div className={classes.blogLinkGroup}>
<a href={publicRuntimeConfig.blogUrl} className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<NotesIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Blog'>
</ListItemText>
</ListItem>
</a>
</div>
</div> */}
<div className={classes.recruteurLinkGroup}>
<a href={publicRuntimeConfig.symphonyUrl } className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<SupervisorAccountIcon className={classes.icon} />
@@ -440,7 +454,7 @@ class Header extends React.Component {
</ListItem></a>
</Link>
{/* TODO */}
<Link href="/Login?inscription=true" >
<Link href="/Inscription" >
<a className={classes.lightMenuItem + ' cypRegister'}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItem }}>
<PersonAddIcon className={classes.icon} />
<ListItemText primary='Inscription'>
@@ -538,13 +552,13 @@ class Header extends React.Component {
<List className={classes.desktopMenuList}>
<div>
<ActiveLink activeClassName={classes.active} href="/Offres" >
<a className={classes.desktopMenuItem}>
<ActiveLink activeClassName={classes.active} href="/Offres" >
<a className={classes.desktopMenuItem} >
<ListItemText primary="Offres d'emploi">
</ListItemText>
</a>
</ActiveLink>
<ActiveLink activeClassName={classes.active} href="/Entreprises" >
<ActiveLink activeClassName={classes.active} href="/Entreprises" >
<a className={classes.desktopMenuItem}>
<ListItemText primary='Nos entreprises'>
</ListItemText>
@@ -556,12 +570,18 @@ class Header extends React.Component {
</ListItemText>
</a>
</ActiveLink>
<a className={classes.desktopMenuItem} target="_blank" href="https://blog.talentstube.com/">
<ListItemText primary='Blog'>
</ListItemText>
</a>
</div>
<div>
{!!!this.props.loading && !!!this.props.fetched &&
<Fragment>
<Link href="/Login?inscription=true" >
<Link href="Inscription" >
<a className={classes.desktopMenuItem}>
<ListItem classes={{ root: classes.rootListItemDesktop }}>
<Button
+575
View File
@@ -0,0 +1,575 @@
import React, { Fragment, Children } from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import { withStyles, getMuiTheme } from '@material-ui/core/styles';
import MenuIcon from '@material-ui/icons/Menu';
import Link from 'next/link'
import Drawer from '@material-ui/core/Drawer';
import Divider from '@material-ui/core/Divider';
import HomeIcon from '@material-ui/icons/HomeOutlined';
import OfferIcon from '@material-ui/icons/LocalOfferOutlined';
import CompanyIcon from '@material-ui/icons/DomainOutlined';
import HelpIcon from '@material-ui/icons/HelpOutline';
import VideoIcon from '@material-ui/icons/OndemandVideoOutlined';
import NotesIcon from '@material-ui/icons/NotesOutlined';
import SupervisorAccountIcon from '@material-ui/icons/SupervisorAccount';
import PersonIcon from '@material-ui/icons/Person';
import PersonAddIcon from '@material-ui/icons/PersonAdd';
import WorkOutlineIcon from '@material-ui/icons/WorkOutline';
import AccountCircleOutlinedIcon from '@material-ui/icons/AccountCircleOutlined';
import FolderSharedIcon from '@material-ui/icons/FolderShared';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import PermContactCalendar from '@material-ui/icons/PermContactCalendar';
import VideoCam from '@material-ui/icons/Videocam';
import SettingsIcon from '@material-ui/icons/Settings';
import PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew';
import ArrowForward from '@material-ui/icons/ArrowForward';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import { ListItemText } from '@material-ui/core';
import Loader from '../templates/loader'
import { connect } from 'react-redux'
import { fetchCurrentUserRequest } from "../../actions/user";
import { requestLogout } from "../../actions/auth";
import Button from '@material-ui/core/Button';
import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
import Typography from '@material-ui/core/Typography';
import { withRouter } from "next/router";
import ActiveLink from "../atoms/Activelink";
import axios from 'axios';
import setAuthorizationHeader from "../../data/setAuthorizationHeader";
import getConfig from 'next/config'
import Router from 'next/router'
import ButtonBase from "@material-ui/core/ButtonBase";
import ArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import LoadingBar from 'react-redux-loading-bar'
const styles = theme => ({
root: {
width: '100%',
position: 'relative',
zIndex: '999',
'& a': {
textDecoration: 'none'
}
},
toolbar: {
height: '64px',
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
display: 'block'
},
menuLogo: {
cursor: 'pointer',
[theme.breakpoints.down('md')]: {
width: '200px'
},
[theme.breakpoints.down('sm')]: {
width: '130px'
},
},
menuAvatar: {
width: '2.5em',
borderRadius: '50%',
marginTop: theme.spacing(2),
marginLeft: theme.spacing(2),
},
menuUserName: {
color: theme.palette.menu.emailText,
fontSize: '1.3rem',
fontWeight: '500',
},
menuUserEmail: {
color: theme.palette.menu.emailText,
fontSize: '0.9rem',
fontWeight: '200',
},
darkDivider: {
background: 'whitesmoke',
opacity: '0.1',
},
List: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
height: '100%',
paddingTop: 0,
paddingBottom: 0,
'&>a:first-child': {
minHeight: '64px',
height: '64px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
[theme.breakpoints.up('md')]: {
'&>a:first-child': {
height: '64px',
},
'&>a:first-child li': {
height: '64px',
alignItems: 'center',
},
},
},
fullList: {
width: 'auto',
cursor: 'pointer',
paddingBottom: 0
},
lightFullList: {
height: '100vh',
backgroundColor: theme.palette.background.default,
},
darkFullList: {
backgroundColor: theme.palette.background.dark,
},
lightMenuItem: {
color: theme.palette.menu.lightText,
textDecoration: 'none',
},
darkMenuItem: {
color: theme.palette.menu.darkText,
textDecoration: 'none',
},
darkMenuItemSpecific: {
'&:hover,&:active': {
color: theme.palette.primary.main,
}
},
links: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
height: '100%',
},
linkGroup: {
padding: theme.spacing(1.2, 0),
paddingLeft: 0,
},
videothequeLinkGroup: {
backgroundColor: theme.palette.background.videotheque,
},
blogLinkGroup: {
backgroundColor: theme.palette.background.blog,
},
recruteurLinkGroup: {
backgroundColor: theme.palette.background.recruteur,
},
rootListItem: {
padding: theme.spacing(1, 2),
cursor: 'pointer',
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-start',
},
rootListItemIcon: {
padding: theme.spacing(1, 2),
cursor: 'pointer',
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
},
ListItemUserConnected: {
flexDirection: 'column',
},
ListItemText: {
fontSize: '1em',
},
icon: {
paddingRight: theme.spacing(2.5),
},
iconAccount: {
color: theme.palette.primary.dark,
},
title: {
color: theme.palette.secondary.main,
fontSize: '1.5em'
},
email: {
color: theme.palette.menu.emailText,
fontSize: '0.9em'
},
button: {
padding: theme.spacing(0.5, 1),
textTransform: 'inherit',
'& svg': {
width: '0.7em',
height: '0.7em',
},
},
active: {
'& span, & svg': {
color: theme.palette.primary.main + ' !important',
},
},
//DESKTOP PART
desktopMenuItem: {
[theme.breakpoints.down('md')]: {
padding: theme.spacing(0.4),
},
'& span.MuiTypography-root': {
fontSize: '0.8rem',
fontWeight: '500',
},
},
desktopMenuList: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: 0,
},
appBarDesktopSection: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
appBarDesktopSection1: {
padding: theme.spacing(0, 2),
height: '100%',
borderRight: 'solid 1px whitesmoke',
},
appBarDesktopSection2: {
width: '100%',
justifyContent: 'space-between',
padding: theme.spacing(0, 2),
'& ul': {
width: '95%',
},
'& ul>div': {
display: 'flex',
},
'& ul > div:nth-child(1) a span': {
color: theme.palette.primary.dark,
'&:hover, &:active': {
color: theme.palette.primary.main,
}
},
'& .MuiListItemText-root': {
padding: theme.spacing(0, 1),
[theme.breakpoints.down('md')]: {
padding: theme.spacing(0),
},
},
'& a:last-child .MuiButtonBase-root span': {
color: theme.palette.secondary.main,
},
},
appBarDesktopSection3: {
padding: theme.spacing(0, 2),
height: '100%',
backgroundColor: theme.palette.primary.dark,
'& a': {
display: 'flex',
alignItems: 'flex-end',
},
'& span, & svg': {
color: theme.palette.secondary.main,
},
},
toolbarDesktop: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
height: '64px',
},
desktopMenuButtonLogin: {
background: theme.palette.primary.main,
borderColor: theme.palette.primary.main,
},
rootListItemDesktop: {
[theme.breakpoints.up('md')]: {
padding: theme.spacing(1),
},
},
iconDesktop: {
paddingRight: theme.spacing(2.5),
[theme.breakpoints.up('md')]: {
paddingRight: 0,
},
},
loadingBar:{
top:'100px'
}
});
let urlEnv;
class HeaderOffre extends React.Component {
state = {
top: false,
left: false,
bottom: false,
right: false,
toggle: true
};
componentDidMount() {
}
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
onRedirectAccount = e => {
urlEnv = (process.env.NODE_ENV !== 'production') ? '//localhost/app_dev.php' : process.env.SERVER_URL;
e.preventDefault();
var redirectAccountUrl = urlEnv + "/api/talent?bearer=" + localStorage.getItem("ttJWT");
window.open(redirectAccountUrl);
}
toggle = () => this.setState(state => ({ toggle: !state.toggle }))
chargerPage =(type)=> {
console.log(type);
//Router.replace(page);
sessionStorage.setItem(type+'_currentPage',1);
}
render() {
const { classes } = this.props;
const { publicRuntimeConfig } = getConfig();
return (
<div className={classes.root}>
<Drawer anchor="right" open={this.state.right} onClose={this.toggleDrawer('right', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('right', false)}
onKeyDown={this.toggleDrawer('right', false)}
>{!!this.props.loading &&
(<LoadingBar className={classes.loadingBar}/>
)}
{!!!this.props.loading && !!!this.props.fetched
&&
<div className={classes.fullList + ' ' + classes.darkFullList}>
</div>}
{!!!this.props.loading && !!this.props.fetched &&
<Fragment>
{this.props.user.picture ?
<img alt="talents-tube" src={publicRuntimeConfig.symphonyUrl +publicRuntimeConfig.postedContentUrl+ this.props.user.picture} className={classes.menuAvatar} />
:
<img alt="talents-tube" src='/static/images/default/account-avatar-default.svg' className={classes.menuAvatar} />
}
<ListItem classes={{ root: classes.rootListItem }} className={classes.ListItemUserConnected}>
<Typography gutterBottom component="h1" className={classes.menuUserName}>
{this.props.user.firstname + " " + this.props.user.lastname}
</Typography>
<Typography gutterBottom component="h3" className={classes.menuUserEmail} >
{this.props.user.email}
</Typography>
</ListItem>
<Divider className={classes.darkDivider} />
{/* TODO:real links */}
<Link href="/Candidatures" >
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<FolderSharedIcon className={classes.icon} />
<ListItemText primary='Mes candidatures'>
</ListItemText>
</ListItem></a>
</Link>
<Link href="/profileStep" >
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<AccountCircleIcon className={classes.icon} />
<ListItemText primary='Mon compte'>
</ListItemText>
</ListItem></a>
</Link>
<Link href="/Parametres" >
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<SettingsIcon className={classes.icon} />
<ListItemText primary='Paramètres de notification'>
</ListItemText>
</ListItem></a>
</Link>
<Link href="/" >
<a onClick={() => {
localStorage.removeItem("ttJWT");
return this.props.requestLogout();
}} className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<PowerSettingsNewIcon className={classes.icon} />
<ListItemText primary='Déconnexion'>
</ListItemText>
</ListItem></a>
</Link>
</Fragment>
}
</div>
</Drawer>
{isWidthUp('md', this.props.width) ?
(<AppBar position="static" className={classes.appBar}>
<Toolbar disableGutters={true} className={classes.toolbarDesktop}>
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection1}>
<Link href="/" >
<a className={classes.darkMenuItem}>
<ListItem classes={{ root: classes.rootListItemDesktop }}>
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.desktopMenuLogo} />
</ListItem>
</a>
</Link>
</section>
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection2}>
{/* <IconButton className={classes.menuButton} onClick={this.toggleDrawer('left', true)}
color="inherit" aria-label="Open drawer">
<MenuIcon />
</IconButton> */}
{/* <ButtonBase name='back'
focusRipple
className={classes.back}
focusVisibleClassName={classes.focusVisible}
onClick={() => Router.back()}>
<ArrowLeft color="primary" classes={{ root: classes.icon }}></ArrowLeft>
</ButtonBase> */}
<List className={classes.desktopMenuList}>
<div>
<ActiveLink activeClassName={classes.active} href="/Offres" >
<a className={classes.desktopMenuItem} >
<ListItemText primary="Offres d'emploi">
</ListItemText>
</a>
</ActiveLink>
<ActiveLink activeClassName={classes.active} href="/Entreprises" >
<a className={classes.desktopMenuItem}>
<ListItemText primary='Nos entreprises'>
</ListItemText>
</a>
</ActiveLink>
<ActiveLink activeClassName={classes.active} href="/Help" >
<a className={classes.desktopMenuItem}>
<ListItemText primary='Comment ça marche ?'>
</ListItemText>
</a>
</ActiveLink>
<a className={classes.desktopMenuItem} href="https://blog.talentstube.com/" target="_blank">
<ListItemText primary='Blog'>
</ListItemText>
</a>
</div>
<div>
{!!!this.props.loading && !!!this.props.fetched &&
<Fragment>
<Link href="/Inscription" >
<a className={classes.desktopMenuItem}>
<ListItem classes={{ root: classes.rootListItemDesktop }}>
<Button
variant="outlined"
className={classes.button + ' ' + classes.desktopMenuButtonRegister}>
<PersonAddIcon className={classes.iconDesktop} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Inscription'></ListItemText>
</Button >
</ListItem>
</a>
</Link>
<Link href="/Login" >
<a className={classes.desktopMenuItem}>
<ListItem classes={{ root: classes.rootListItemDesktop }}>
<Button
variant="outlined"
className={classes.button + ' ' + classes.desktopMenuButtonLogin}>
<PersonIcon className={classes.iconDesktop} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Connexion'></ListItemText>
</Button >
</ListItem>
</a>
</Link>
</Fragment>
}
{!!!this.props.loading && !!this.props.fetched &&
<IconButton
edge="end"
aria-label="Profile"
aria-controls={'primary-search-account-menu'}
aria-haspopup="true"
onClick={this.toggleDrawer('right', true)}
className={classes.iconAccount + ' cypConnexionMenu'}
>
<AccountCircleOutlinedIcon />
</IconButton>
}
</div>
</List>
</section>
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection3}>
<a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.desktopMenuItem}>
<ListItemText primary='Espace recruteurs'>
</ListItemText>
<ArrowForward className={classes.icon} />
</a>
</section>
</Toolbar>
</AppBar>)
:
(
<AppBar position="static" className={classes.appBar}>
<Toolbar className={classes.toolbar}>
{/* <IconButton className={classes.menuButton} onClick={this.toggleDrawer('left', true)}
color="inherit" role="button">
<MenuIcon />
</IconButton> */}
<ButtonBase name='back'
focusRipple
className={classes.back}
focusVisibleClassName={classes.focusVisible}
onClick={() => Router.back()}>
<ArrowLeft color="primary" classes={{ root: classes.icon }}></ArrowLeft>
</ButtonBase>
<div className={classes.grow} />
<Link href="/" >
<a><img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} /></a>
</Link>
<div className={classes.grow} />
<IconButton
edge="end"
aria-label="Profile"
aria-controls={'primary-search-account-menu'}
aria-haspopup="true"
onClick={this.toggleDrawer('right', true)}
className={classes.iconAccount + ' cypConnexionMenu'}
>
<AccountCircleOutlinedIcon />
</IconButton>
</Toolbar>
</AppBar>
)}
</div >
);
}
}
function mapStateToProps(state) {
return {
user: state.user,
fetched: !!state.user.fetched,
loading: !!state.user.loading
};
}
export default (connect(mapStateToProps, { fetchCurrentUserRequest, requestLogout })(withStyles(styles)(withWidth()(HeaderOffre))));
File diff suppressed because it is too large Load Diff
+193 -25
View File
@@ -7,6 +7,7 @@ import axios from 'axios'
import setAuthorizationHeader from "../../data/setAuthorizationHeader";
import 'videojs/dist/video-js.css';
import 'videojs-record/dist/css/videojs.record.css';
import ArrowRight from '@material-ui/icons/ArrowRight';
dynamic(() => import('webrtc-adapter'), {
ssr: false
@@ -17,8 +18,31 @@ const RTCRecorder = dynamic(() => import('RecordRTC'), {
const videoJsOptions = {
controls: true,
width: '550',
languages: {
fr: {
Replay: 'Jouer'
}
},
autoplay:true,
preload:"auto",
playsinline : false,
//videoEngine: 'webm-wasm',
//liveui : true,
fluid: true,
nativeControlsForTouch:false,
controlBar: {
// hide fullscreen and volume controls
fullscreenToggle: false,
volumePanel: false,
deviceButton: false,
recordIndicator:true,
recordToggle: false,
PictureInPictureToggle:false,
PlayToggle:false
},
poster: '/statique/images/webrtc/module-video-talents-tube.jpg',
plugins: {
/*
// wavesurfer section is only needed when recording audio-only
@@ -40,37 +64,107 @@ const videoJsOptions = {
}
}
};
const styles = theme => ({
root: {
margin: theme.spacing(1),
maxWidth: '400px', [theme.breakpoints.down('md')]: {
maxWidth: `${100 - (theme.spacing(1))}vw`
const styles = theme => ({
primary: {
color: theme.palette.primary.main,
},
sendContainer: {
textAlign: 'center'
root: {
position: 'relative',
textAlign: 'center',
paddingTop: theme.spacing(10),
justifyContent: 'center',
},
button: {
color: '#FFFFFF',
padding: '9.6px 16px',
borderColor: '#25D89A',
border: '2px solid',
margin:'15px 8px 25px 8px',
textTransform: 'inherit',
marginLeft: theme.spacing(8),
marginRight: theme.spacing(8),
marginTop: theme.spacing(4),
marginBottom: theme.spacing(2),
padding: theme.spacing(1.2, 2),
//borderRadius: '3px',
[theme.breakpoints.up('sm')]: {
margin: 'auto',
},
backgroundColor:'#25D89A',
},
buttonRelancer:{
color: '#1E2327',
borderColor: '#1E2327',
border: '2px solid',
margin: '15px 8px 25px 8px',
padding: '9.6px 16px',
textTransform: 'inherit',
color: '#1E2327',
borderColor: '#1E2327',
},
}
})
buttonArret: {
color: '#FFFFFF',
borderColor: '#FF5A5F',
border: '2px solid',
padding: '9.6px 16px',
margin:'15px 8px 25px 8px',
textTransform: 'inherit',
backgroundColor:'#FF5A5F',
},
buttonLire: {
color: '#FFFFFF',
padding: '9.6px 16px',
margin:'15px 8px 25px 8px',
textTransform: 'inherit',
backgroundColor:'#1689FB',
},
conteneurVideo:{
width:'550px!important'
},
sendContainer: {
left: '-40px'
},
})
// const styles = theme => ({
// root: {
// margin: theme.spacing(1),
// maxWidth: '400px', [theme.breakpoints.down('md')]: {
// maxWidth: `${100 - (theme.spacing(1))}vw`
// },
// sendContainer: {
// textAlign: 'center'
// },
// bouton: {
// textTransform: 'inherit',
// marginLeft: theme.spacing(1),
// marginRight: theme.spacing(1),
// padding: theme.spacing(1.2, 2),
// color: theme.palette.secondary.main,
// backgroundColor: theme.palette.primary.important,
// },
// conteneurVideo:{
// width:'550px!important'
// }
// }
// })
class Recorder extends Component {
state={
canSend:false
canSend:false,
isActiveLancer:true,
isActiveArreter:false,
isActiveLancerReplay:false,
lancerText:"Démarrer lenregistrement",
lancerStyleRelance : 0,
}
handleLancer = (replay)=>{
this.setState({
isActiveLancer: !this.state.isActiveLancer,
isActiveArreter: !this.state.isActiveArreter,
lancerText : "Refaire une vidéo",
})
replay==1 ? this.setState({isActiveLancerReplay: 1}) : this.setState({isActiveLancerReplay: 0})
this.setState({lancerStyleRelance: 1})
}
async componentDidMount() {
var record = (await import('videojs-record')).default
// instantiate Video.js
@@ -81,10 +175,42 @@ class Recorder extends Component {
' and recordrtc ' + RTCRecorder.VERSION;
videojs.log(version_info);
});
var vid= this.player;
this.player.bigPlayButton.hide();
// When you pass text in options it just creates a control text,
// which is displayed as tooltip when hovered on
// this button viz the span in you div,
var myButton = this.player.controlBar.addChild("button");
// There are many functions available for button component
// like below mentioned in this docs
// https://docs.videojs.com/button.
// You can set attributes and clasess as well.
// Getting html DOM
var myButtonDom = myButton.el();
//var myButtonDom2 = myButton2.el();
// Since now you have the html dom element
// you can add click events
// Now I am setting the text as you needed.
// myButtonDom.innerHTML = "Youi";
myButtonDom.onclick = function(){
//alert("Redirecting");
vid.pause();
}
// device is ready
this.player.on('deviceReady', () => {
console.info('device is ready!');
this.player.record().start();
this.setState({canSend:false});
});
@@ -129,9 +255,44 @@ class Recorder extends Component {
this.props.uploader(formData);
}
recordPlayer = () => {
// console.log('accessing recording: ', this.player.recordedData)
if (this.player) {
//this.player.recorder.start()
this.player.ready();
this.player.record().getDevice();
this.handleLancer(0);
}
}
playPlayerAuto = () => {
// console.log('accessing recording: ', this.player.recordedData)
if (this.player) {
//this.player.recorder.start()
this.player.autoplay('play');
}
}
pausePlayerAuto = () => {
// console.log('accessing recording: ', this.player.recordedData)
if (this.player) {
//this.player.recorder.start()
this.player.autoplay('pause');
}
}
arretPlayer = () => {
// console.log('accessing recording: ', this.player.recordedData)
if (this.player) {
this.player.record().stop();
this.handleLancer(1);
}
}
render() {
const { classes, titreBouton } = this.props;
let titreButtonLabel= "Envoyer";
let titreButtonLabel= "Choisir cette vidéo";
if (titreBouton) {
@@ -140,17 +301,24 @@ class Recorder extends Component {
console.log(titreButtonLabel);
}
return (
<div>
<div className={classes.conteneurVideo}>
<div data-vjs-player>
<video id="myVideo" ref={node => this.videoNode = node} className="video-js vjs-default-skin" playsInline></video>
<video id="myVideo" width='550' ref={node => this.videoNode = node} className="video-js vjs-default-skin" playsInline></video>
</div>
<div className={classes.sendContainer}>
{ this.state.canSend && <Button type="submit" variant="outlined" color="primary"
{this.state.isActiveLancer ? <Button className={this.state.lancerStyleRelance==1 ? classes.buttonRelancer: classes.button} onClick={this.recordPlayer}>{this.state.lancerText}</Button> : null }
{this.state.isActiveArreter ?<Button className={classes.buttonArret} onClick={this.arretPlayer}>Arrêter l'enregistrement</Button> : null }
{/* {this.state.isActiveLancerReplay ?<Button cyp="ButtonApply" variant="contained" className={classes.buttonLire} onClick={this.playPlayerAuto}><ArrowRight className={ classes.InputKeyboardArrowRightIcon }/>Relire</Button>: null } */}
{ this.state.canSend && <Button type="submit" className={classes.button}
className={classes.button}
onClick={this.sendBlob}>
{titreButtonLabel}
</Button>}
</div>
<div id="controleNav">
</div>
</div>
);
}
+11 -1
View File
@@ -111,6 +111,7 @@ class Register extends React.Component {
password: '',
checkNewsletter: false,
checkCGU: false,
adId : ''
},
errors: {
email:null,
@@ -133,13 +134,22 @@ class Register extends React.Component {
return errors;
};
componentDidMount() {
this.setState({
data: {...this.state.data, adId: localStorage.getItem('adId')},
})
}
onRegister = e => {
e.preventDefault();
const errors = this.validate(this.state.data);
this.setState({ errors: errors });
console.log('adId')
console.log(this.state.data)
if (Object.keys(errors).length === 0) {
this.props.registerUserRequest(this.state.data)
+62 -16
View File
@@ -5,6 +5,7 @@ import { loadCSS } from 'fg-loadcss';
import { makeStyles } from '@material-ui/core/styles';
import { red } from '@material-ui/core/colors';
import Icon from '@material-ui/core/Icon';
import Hidden from '@material-ui/core/Hidden';
const useStyles = makeStyles(theme => ({
root: {
@@ -26,16 +27,44 @@ const useStyles = makeStyles(theme => ({
textAlign: 'center',
},
FacebookIcon: {
backgroundColor: theme.palette.social.facebook,
color: theme.palette.social.facebook,
'&:hover': {
backgroundColor: theme.palette.social.facebook,
color: '#fff',
}
},
TwitterIcon: {
backgroundColor: theme.palette.social.twitter,
color: theme.palette.social.twitter,
'&:hover': {
backgroundColor: theme.palette.social.twitter,
color: '#fff',
}
},
LinkedinIcon: {
backgroundColor: theme.palette.social.linkedin,
color: theme.palette.social.linkedin,
'&:hover': {
backgroundColor: theme.palette.social.linkedin,
color: '#fff',
}
},
MailIcon: {
backgroundColor: theme.palette.social.mail,
color: theme.palette.social.mail,
'&:hover': {
backgroundColor: theme.palette.social.mail,
color: '#fff',
}
},
FacebookIconMobile: {
color: theme.palette.social.facebook,
},
TwitterIconMobile: {
color: theme.palette.social.twitter,
},
LinkedinIconMobile: {
color: theme.palette.social.linkedin,
},
MailIconMobile: {
color: theme.palette.social.mail,
},
}));
@@ -51,19 +80,36 @@ export default function SocialShare(props) {
return (
<div className={classes.root}>
<Hidden smDown>
<a href={"https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(props.url)} target="_blank">
<Icon className={clsx(classes.icon, classes.FacebookIcon, 'fab fa-facebook-f')} />
</a>
<a href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)} target="_blank">
<Icon className={clsx(classes.icon, classes.TwitterIcon, 'fab fa-twitter')} color="secondary" />
</a>
<a href={"https://www.linkedin.com/shareArticle?mini=true&url=" + encodeURIComponent(props.url + "&title=Talent's Tube")} target="_blank">
<Icon className={clsx(classes.icon, classes.LinkedinIcon, 'fab fa-linkedin-in')} color="secondary" />
</a>
{/* change because of https://github.com/zeit/next.js/blob/master/errors/invalid-href-passed.md */}
<a href={"mailto:?subject=Offre d'emploi Talent's Tube&body=Regardez cette offre : " + props.url} target="_blank"s>
<Icon className={clsx(classes.icon, classes.MailIcon, 'fas fa-envelope')} color="secondary" />
</a>
</Hidden>
<Hidden mdUp>
<a href={"https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(props.url)} target="_blank">
<Icon className={clsx(classes.icon, classes.FacebookIcon, 'fab fa-facebook-f')} color="secondary" />
</a>
<a href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)} target="_blank">
<Icon className={clsx(classes.icon, classes.TwitterIcon, 'fab fa-twitter')} color="secondary" />
</a>
<a href={"https://www.linkedin.com/shareArticle?mini=true&url=" + encodeURIComponent(props.url + "&title=Talent's Tube")} target="_blank">
<Icon className={clsx(classes.icon, classes.LinkedinIcon, 'fab fa-linkedin-in')} color="secondary" />
</a>
{/* change because of https://github.com/zeit/next.js/blob/master/errors/invalid-href-passed.md */}
<a href={"mailto:?subject=Offre d'emploi Talent's Tube&body=Regardez cette offre : " + props.url} target="_blank"s>
<Icon className={clsx(classes.icon, classes.MailIcon, 'fas fa-envelope')} color="secondary" />
</a>
<Icon className={clsx(classes.icon, classes.FacebookIconMobile, 'fab fa-facebook-f')} />
</a>
<a href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)} target="_blank">
<Icon className={clsx(classes.icon, classes.TwitterIconMobile, 'fab fa-twitter')} color="secondary" />
</a>
<a href={"https://www.linkedin.com/shareArticle?mini=true&url=" + encodeURIComponent(props.url + "&title=Talent's Tube")} target="_blank">
<Icon className={clsx(classes.icon, classes.LinkedinIconMobile, 'fab fa-linkedin-in')} color="secondary" />
</a>
{/* change because of https://github.com/zeit/next.js/blob/master/errors/invalid-href-passed.md */}
<a href={"mailto:?subject=Offre d'emploi Talent's Tube&body=Regardez cette offre : " + props.url} target="_blank"s>
<Icon className={clsx(classes.icon, classes.MailIconMobile, 'fas fa-envelope')} color="secondary" />
</a>
</Hidden>
</div>
);
}
+3 -2
View File
@@ -1,5 +1,6 @@
import React from 'react';
import videojs from 'video.js'
import React, { lazy } from 'react';
const videojs = lazy(() => import('video.js'));
//import videojs from 'video.js'
export default class VideoPlayer extends React.Component {
componentDidMount() {
+57 -8
View File
@@ -1,4 +1,4 @@
import Griddle, { utils } from "griddle-react";
import Griddle, { utils, plugins } from "griddle-react";
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import { withStyles } from '@material-ui/core/styles';
@@ -7,6 +7,7 @@ import TextField from '@material-ui/core/TextField';
import GriddleCustomTable from "../organisms/GriddleCustomTableComponent";
import GriddleCustomNextButton from "../organisms/GriddleCustomNextButton"
import GriddleCustomPreviousButton from "../organisms/GriddleCustomPreviousButton"
import GriddleCustomPageDropdown from "../organisms/GriddleCustomPageDropdown"
import Loader from './loader'
import IconSearch from '@material-ui/icons/Search';
import NoResult from './../atoms/NoResult';
@@ -80,18 +81,37 @@ class Grid extends Component {
recordCount: 0,
promoted: false,
filterText: "",
// options: [],
};
async componentDidMount() {
this.setState({pageSize:this.props.limit})
let data = sessionStorage.getItem(this.props.type+'_currentPage');
let current;
if(data){
current=data;
}else{
current=this.state.currentPage;
}
this.props.dataFetcher(
{
offset: this.state.currentPage,
offset: ((current-1)*this.props.limit)+1,
limit: this.props.limit
}
);
// let options = [];
// let startIndex = Math.max(this.props.currentPage - 5, 0);
// let endIndex = Math.min(startIndex + 11, this.props.maxPage);
// if (this.props.maxPage >= 11 && (endIndex - startIndex) <= 10) {
// startIndex = endIndex - 11;
// }
// for(let i = startIndex; i < endIndex ; i++){
// let selected = this.props.currentPage == i ? "current-page-selected" : "";
// options.push(<button className={selected} data-value={i} onClick={this.pageChange}>{i + 1}</button>);
// }
}
UNSAFE_componentWillReceiveProps(nextProps) {
@@ -106,10 +126,17 @@ class Grid extends Component {
const { currentPage, pageSize, filterText, promoted } = this.state;
if (nextProps.promoted != this.state.promoted) {
let data = sessionStorage.getItem(this.props.type+'_currentPage');
let current;
if(data){
current=data;
}else{
current=this.state.currentPage;
}
this.setState({ promoted: nextProps.promoted });
this.props.dataFetcher(
{
offset: this.state.currentPage,
offset: ((current-1)*(this.state.pageSize+1))+1,
limit: this.state.pageSize,
keyword: filterText,
isPromoted: nextProps.promoted
@@ -123,19 +150,34 @@ class Grid extends Component {
_onNext = () => {
const { currentPage, pageSize, filterText, promoted } = this.state;
this.props.dataFetcher({ offset: currentPage * pageSize, limit: pageSize, keyword: filterText, isPromoted: promoted })
sessionStorage.setItem(this.props.type+'_currentPage', currentPage+1);
};
_onPrevious = () => {
const { currentPage, pageSize, filterText, promoted } = this.state;
this.props.dataFetcher({ offset: (currentPage - 2) * pageSize + 1, limit: pageSize, keyword: filterText, isPromoted: promoted });
sessionStorage.setItem(this.props.type+'_currentPage', currentPage-1);
};
_onGetPage = pageNumber => {
_onGetPage = (pageNumber, page) => {
const { pageSize, filterText, promoted } = this.state;
this.props.dataFetcher({ offset: (page - 1) * pageSize + 1, limit: pageSize, keyword: filterText, isPromoted: promoted });
console.log(pageNumber);
console.log(page);
sessionStorage.setItem(this.props.type+'_currentPage', page);
console.log("On get Page");
};
_onSetPage = pageNumber => {
const { pageSize, filterText, promoted } = this.state;
this.props.dataFetcher({ offset: (pageNumber - 1) * pageSize + 1, limit: pageSize, keyword: filterText, isPromoted: promoted });
console.log("On set Page");
};
_onFilter = filterText => {
sessionStorage.setItem(this.props.type+'_currentPage', 1);
this.setState({ currentPage: 1 });
const { currentPage, pageSize, promoted } = this.state;
this.setState({ filterText });
@@ -148,11 +190,12 @@ class Grid extends Component {
searchSubmit = () => {
const { currentPage, pageSize, promoted, filterText } = this.state;
sessionStorage.setItem(this.props.type+'_currentPage', 1);
this.props.dataFetcher({ offset: 1, limit: pageSize, keyword: filterText, isPromoted: promoted });
}
render() {
const { classes, placeholder } = this.props
const style = {
styles: {
@@ -203,7 +246,7 @@ class Grid extends Component {
fontSize: '0.9em',
fontWeight: '600',
fontFamily: 'Dosis',
display: 'none',
// display: 'none',
},
}
}
@@ -211,10 +254,12 @@ class Grid extends Component {
const { filterText, data, currentPage, pageSize, recordCount, loading } = this.state;
const NewLayout = ({ Table, Pagination, Filter }) => (
<div>
{/* <Filter /> */}
<Table />
<Pagination />
</div>
);
@@ -278,6 +323,7 @@ class Grid extends Component {
recordCount,
}}
useCustomPagerComponent="true"
plugins={plugins.localPlugin}
components={{
Layout: NewLayout,
Row: this.props.CustomRowComponent,
@@ -285,12 +331,15 @@ class Grid extends Component {
TableBody: CustomTableBody,
PreviousButton: GriddleCustomPreviousButton,
NextButton: GriddleCustomNextButton,
PageDropdown: GriddleCustomPageDropdown,
}}
events={{
onNext: this._onNext,
onPrevious: this._onPrevious,
onGetPage: this._onGetPage,
onFilter: this._onFilter
onFilter: this._onFilter,
onSetPage: this._onSetPage
}}
styleConfig={style}
/>
@@ -0,0 +1,105 @@
import { withStyles } from '@material-ui/core/styles'
import Router from 'next/router';
import RootContainer from '../atoms/RootContainer'
import ButtonBase from "@material-ui/core/ButtonBase";
import Close from '@material-ui/icons/Close';
import Typography from '@material-ui/core/Typography';
const styles = theme => ({
inner: {
height: '100%',
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
// boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.04), 0 1px 10px 0 rgba(0, 0, 0, 0.04), 0 3px 5px -1px rgba(0, 0, 0, 0.04)',
backgroundColor: '#1E2327',
right:'30px'
},
head: {
zIndex: '999',
width: '100%',
height: '100px',
backgroundColor: '#1E2327',
position: 'fixed',
[theme.breakpoints.up('sm')]: {
height: '100px'
}
},
icon: {
fontSize: '3em',
textAlign :'right',
top:'30px',
right:'30px',
color:'#fff',
margin:'20px'
},
title: {
color: theme.palette.primary.dark,
},
content: {
top: '100px',
width: '100%',
minHeight: '1000px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'flex-start',
position: 'relative',
backgroundColor: '#1E2327',
},
contentFixed: {
height: 'calc(100vh - 100px)',
backgroundColor: '#1E2327',
},
back: {
zIndex: 10,
border: 'none',
padding: theme.spacing(0.2),
textAlign: 'center',
textDecoration: 'none',
borderRadius: '50%',
position: 'absolute',
right: theme.spacing(1),
backgroundColor: '#34383C'
},
player: {
background:'#1E2327'
},
});
function LayoutBack(props) {
const { classes, height} = props;
//height fixed = height 100vh
const content = (height == 'fixed') ? classes.content+' '+classes.contentFixed : classes.content
return (
<RootContainer align='center' className={content}>
<div id="H" className={classes.head}>
<div className={classes.inner}>
<ButtonBase name='back'
focusRipple
className={classes.back}
focusVisibleClassName={classes.focusVisible}
onClick={() => Router.push(props.url)}>
<Close color="#fff" classes={{ root: classes.icon }}></Close>
</ButtonBase>
<Typography
component="h1"
align="center"
className={classes.title}
>
{props.text}
</Typography>
</div>
</div>
<div id="C" className={content}>
{props.children}
</div>
</RootContainer>
)
}
export default withStyles(styles)(LayoutBack)
+32 -9
View File
@@ -5,7 +5,8 @@ import Router from 'next/router';
import RootContainer from '../atoms/RootContainer'
import ButtonBase from "@material-ui/core/ButtonBase";
import ArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import Header from '../organisms/Header'
import Header from '../organisms/HeaderOffre'
import SocialShare from '../organisms/SocialShare'
import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
import Hidden from '@material-ui/core/Hidden';
import Link from 'next/link'
@@ -22,6 +23,10 @@ const styles = theme => ({
backgroundColor: theme.palette.secondary.main,
boxShadow: '0px 0px 10px rgba(30, 35, 39, 0.10)',
},
lien:{
textDecoration:'none',
color:'#fff'
},
contentDefault: {
height: 'auto',
position: 'relative',
@@ -72,16 +77,19 @@ const styles = theme => ({
backgroundColor: '#F3F3F4',
},
pourvuButton:{
padding :'10px'
},
})
function LayoutOffre(props) {
const { classes, offreId, offre, isProvided } = props;
const { classes, offreId, offre, isProvided, socialShareUrl } = props;
const contentClass = (!isProvided) ? classes.contentDefault : classes.contentProvided
return (
<RootContainer>
{isWidthUp('sm', props.width) ?
{isWidthUp('xs', props.width) ?
(<Header />)
:
(<ButtonBase name='back'
@@ -101,21 +109,36 @@ function LayoutOffre(props) {
<div id="F" className={classes.foot}>
{/* <div className={classes.inner}>
<div className={classes.grow} /> */}
<Link href={`/Entreprise/${offre.company.id}-${_.kebabCase(offre.company.brand_name)}`} >
{/* <Link href={`/Entreprise/${offre.company.id}-${_.kebabCase(offre.company.brand_name)}`} >
<Button
variant="contained"
className={classes.voirEntreprise + ' cypButtonApply'}
>Voir l'entreprise</Button>
</Link>
>Voir l'entreprise</Button>
</Link> */}
<Button
variant="contained"
className={classes.button + ' cypButtonApply'}
classes={{ root: classes.rootButton}}
onClick={() => Router.push(`/Reponse?adId=${offreId}`)}
>
Postuler</Button>
<a href={`/Reponse?adId=${offreId}`} className={classes.lien }>Postuler</a>
</Button>
<SocialShare url={socialShareUrl} />
{/* <div className={classes.grow} />
</div> */}
</div>
)}
{isProvided && (
<div id="F" className={classes.foot}>
{/* <div className={classes.inner}>
<div className={classes.grow} /> */}
<Button variant="contained" disabled className={classes.pourvuButton}>
Pourvue
</Button>
{/* <div className={classes.grow} />
</div> */}
</div>
+16 -2
View File
@@ -1,6 +1,7 @@
import React, { Fragment } from 'react'
import CircularProgress from '@material-ui/core/CircularProgress'
import { withStyles } from '@material-ui/core/styles'
import LinearProgress from '@material-ui/core/LinearProgress';
const styles = theme => ({
loader: {
display: 'flex',
@@ -14,14 +15,27 @@ const styles = theme => ({
padding: theme.spacing(6,0),
color: theme.palette.primary.main,
},
root: {
top:"200px",
width: '100%',
'& > * + *': {
marginTop: theme.spacing(2),
},
},
})
class LoaderVideo extends React.Component {
render() {
const { classes } = this.props;
return (
<div className={classes.loader + ' ' + 'alert alert-info'}><CircularProgress color="primary" />Chargement... <br/>Le temps de chargement peut varier de quelques secondes à <b>plusieurs minutes</b> en fonction de la qualité de votre connexion internet.<br/></div>
)
<div className={classes.root}>
<div className={classes.loader + ' ' + 'alert alert-info'}><CircularProgress color="primary" />Veuillez ne pas quitter la page.<br/> Le temps de chargement peut varier de quelques secondes à plusieurs minutes en fonction de la qualité de votre connexion internet.<br/></div>
<div >
<LinearProgress />
<LinearProgress color="secondary" />
</div>
</div>
)
}
}
+1
View File
@@ -12,6 +12,7 @@ axios.interceptors.response.use(response => {
}, error => {
if (error.response.status === 401) {
localStorage.setItem('ttJWT', '');
console.log("REPONSE REDIRECT LOGIN")
Router.push("/Login");
}
return error;
+12 -8
View File
@@ -40,18 +40,22 @@ module.exports = withPlugins(
}],
[{
publicRuntimeConfig: {
//symphonyUrl: 'http://localhost/app_dev.php',
//blogUrl: 'https://blog.talentstube.com',
//frontServerUrl: 'http://localhost:3000',
//cvThequeUrl: 'https://recruteur.talentstube.com',
//symphonyUrl: 'https://recruteur.talentstube.com',
//blogUrl: 'https://blog.talentstube.com',
//frontServerUrl: 'https://www.talentstube.com',
//cvThequeUrl: 'https://recruteur.talentstube.com',
// DEV
// symphonyUrl: 'http://localhost/',
// blogUrl: 'https://blog.talentstube.com',
// frontServerUrl: 'http://localhost:3000',
// cvThequeUrl: 'https://recruteur.talentstube.com',
// PROD
// symphonyUrl: 'https://recruteur.talentstube.com/',
// blogUrl: 'https://blog.talentstube.com',
// frontServerUrl: 'https://www.talentstube.com/',
// cvThequeUrl: 'https://recruteur.talentstube.com',
// PRE PROD
symphonyUrl: 'https://pp.talentstube.com/',
blogUrl: 'https://blog.talentstube.com',
frontServerUrl: 'https://pp.app.talentstube.com/',
cvThequeUrl: 'https://recruteur.talentstube.com',
version : 'V2.3.4',
adListDefaultUrl: '/statique/images/default/default_picture_company.svg',
cachedMediaUrl: '/media/cache/profile_thumb/uploads/img/',
postedContentUrl: '/uploads/img/',
+6
View File
@@ -27,6 +27,7 @@
"jss": "latest",
"lodash": "^4.17.11",
"mongodb": "^3.1.6",
"mui-places-autocomplete": "^2.0.0",
"nedb": "^1.8.0",
"next": "^9.1.1",
"next-auth": "^1.11.0",
@@ -55,7 +56,11 @@
"react-html-parser": "^2.0.2",
"react-jss": "latest",
"react-moment": "^0.9.7",
"react-places-autocomplete": "^7.3.0",
"react-redux": "^7.0.3",
"react-redux-loading-bar": "^5.0.0",
"react-router-dom": "^5.2.0",
"react-sticky-box": "^0.9.3",
"react-swipeable-views": "^0.13.3",
"reactstrap": "^6.4.0",
"recordrtc": "^5.5.4",
@@ -69,6 +74,7 @@
"terser": "3.14",
"universal-cookie": "^3.0.4",
"validator": "^11.0.0",
"video-react": "^0.14.1",
"videojs-record": "^3.8.0",
"webrtc-adapter": "^7.2.3"
},
+13 -2
View File
@@ -84,10 +84,20 @@ class ConfirmAccount extends Component {
e-mail validé
</Typography>
<Typography gutterBottom align="left" className={classes.text}>
Votre email a bien été validé.
Votre email a bien été validé.
</Typography>
<Typography gutterBottom align="left" className={classes.text}>
Vous pouvez maintenant vous connecter.
<Button
variant="contained"
className={classes.button}
classes={{ root: classes.rootButton }}
onClick={() => Router.push('/Login')}
>
Connexion
</Button>
</Typography>
<section className={classes.bottomContainer}>
<Button
@@ -117,7 +127,8 @@ function mapStateToProps(state, ownProps) {
}
ConfirmAccount.getInitialProps = function (context) {
const { token, email } = context.query
const { token, email, url } = context.query
localStorage.setItem('loginRedirect', url)
context.store.dispatch(requestConfirmationAccountRequest({ 'confirmationToken': token, 'email': email }))
return email;
}
+12 -10
View File
@@ -1,5 +1,5 @@
import React, { Fragment } from 'react'
import React, { Fragment,lazy, Suspense } from 'react'
import Router from 'next/router'
import { connect } from "react-redux"
import PropTypes from 'prop-types'
@@ -16,7 +16,8 @@ import { fetchCompanyRequest, clearCompany, countCompanyViewRequest } from '../a
import IconText from '../components/atoms/IconText'
import IconTextInline from '../components/atoms/IconTextInline'
import SimpleCollapse from '../components/atoms/SimpleCollapse'
import VideoVimeo from '../components/atoms/VideoVimeo'
const VideoVimeo = lazy(() => import('../components/atoms/VideoVimeo'));
//import VideoVimeo from '../components/atoms/VideoVimeo'
import SocialShare from '../components/organisms/SocialShare'
import Loader from '../components/templates/loader'
import _ from "lodash"
@@ -25,7 +26,7 @@ import withWidth from '@material-ui/core/withWidth'
import Hidden from '@material-ui/core/Hidden';
import NoResult from '../components/atoms/NoResult';
import OgHead from '../components/atoms/OgHead';
const renderLoader = () => <p>Chargement</p>;
const styles = theme => ({
companyContainer: {
[theme.breakpoints.up('md')]: {
@@ -432,11 +433,7 @@ class Entreprise extends React.Component {
</div>
</div>
<div className={classes.buttonContainer}>
<Button
variant="contained"
className={classes.button}
onClick={() => Router.push(`/Reponse?companyId=${company.id}`)}
>Candidature spontanée</Button>
<Link href="#discover" >
<Button
variant="contained"
@@ -444,10 +441,15 @@ class Entreprise extends React.Component {
>Voir les offres</Button>
</Link>
<Button
variant="contained"
className={classes.button}
onClick={() => Router.push(`/Reponse?companyId=${company.id}`)}
>Candidature spontanée</Button>
</div>
</section>
</Hidden>
{company.presentation_video && <VideoVimeo videoId={Ar.last(_.split(company.presentation_video.cdn_url, '/'))} autoplay='1' />}
{company.presentation_video && <Suspense fallback={renderLoader()}><VideoVimeo videoId={Ar.last(_.split(company.presentation_video.cdn_url, '/'))} autoplay='1' /></Suspense>}
<div className={classes.container}>
<Hidden mdUp>
<section className={classes.headerContainer}>
@@ -567,7 +569,7 @@ class Entreprise extends React.Component {
Découvrir le <span className={classes.primary}>territoire</span>
</Typography>
<section className={classes.discoverTerritoryContentContainer}>
<VideoVimeo classesOverride={classes.videoVimeo} videoId={territoryVideoId} autoplay='0' />
<Suspense fallback={renderLoader()}><VideoVimeo classesOverride={classes.videoVimeo} videoId={territoryVideoId} autoplay='0' /></Suspense>
<Typography className={classes.territoryTitle}>
{(company.territories) ? company.territories[0].territory.brand_name : ''}
</Typography>
+5 -1
View File
@@ -63,7 +63,10 @@ const styles = theme => ({
});
class Entreprises extends React.Component {
componentDidMount() {
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("Redirect"+window.location.pathname)
}
render() {
const { classes } = this.props;
const { publicRuntimeConfig } = getConfig();
@@ -112,6 +115,7 @@ class Entreprises extends React.Component {
currentPage={this.props.currentPage}
recordCount={this.props.recordCount}
loading={this.props.loading}
type="entreprises"
limit={12}
placeholder={"Rechercher une entreprise"}
/>
+252
View File
@@ -0,0 +1,252 @@
import React, { Fragment } from 'react';
import PropTypes from "prop-types";
import Layout from '../components/templates/Layout';
import { TextField, Button, Typography } from '@material-ui/core';
import SwipeableViews from 'react-swipeable-views';
import AppBar from '@material-ui/core/AppBar';
import Link from '@material-ui/core/Link';
import { withStyles } from '@material-ui/core/styles';
import Loader from '../components/templates/loader'
import { connect } from "react-redux";
import Validator from "validator";
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Router from 'next/router'
import Register from '../components/organisms/Register';
// import { requestLogin, requestOauthLogin, requestLoginFailure } from "../actions/auth";
import { makeStyles } from '@material-ui/core/styles';
import { amber, green } from '@material-ui/core/colors';
import _ from "lodash"
import Snack from '../components/atoms/snack'
import SocialButtonsAuth from '../components/atoms/SocialButtonsAuth';
import jssPluginPropsSort from 'jss-plugin-props-sort';
import Head from 'next/head'
import ReCAPTCHA from "react-google-recaptcha";
import getConfig from 'next/config'
const {publicRuntimeConfig} = getConfig()
function TabContainer({ children, dir }) {
return (
<Typography component="div" dir={dir} style={{ padding: 8 * 3 }}>
{children}
</Typography>
);
}
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
dir: PropTypes.string.isRequired,
};
const styles = theme => ({
container: {
display: 'flex',
flexDirection: 'column',
},
AppBar: {
position: 'fixed',
top: theme.spacing(8),
},
tab: {
'& span.MuiTab-wrapper': {
fontSize: '1.1em',
fontWeight: '600',
textTransform: 'none',
}
},
tabContainer: {
display: 'flex',
flexDirection: 'column',
height: '100%',
paddingTop: theme.spacing(4),
[theme.breakpoints.up('sm')]: {
padding: '5vw 10vw',
},
[theme.breakpoints.up('md')]: {
padding: '5vw 25vw',
},
},
textField: {
width: '100%'
},
form: {
display: 'flex',
flexDirection: 'column',
},
formText: {
padding: theme.spacing(0, 2),
paddingTop: theme.spacing(3),
fontSize: '0.9em',
fontWeight: '300',
},
formLink: {
paddingLeft: theme.spacing(1),
fontWeight: '500',
cursor: 'pointer',
},
forgetPasswordText: {
marginTop: theme.spacing(2),
},
conditionalText: {
display: 'flex',
flexDirection: 'row',
color: theme.palette.primary.conditional,
textTransform: 'uppercase',
'&:before': {
content: '""',
flex: '1 1',
borderBottom: '1px solid',
borderColor: theme.palette.primary.conditional,
marginRight: '10px',
marginTop: 'auto',
marginBottom: 'auto',
},
'&:after': {
content: '""',
flex: '1 1',
borderBottom: '1px solid',
borderColor: theme.palette.primary.conditional,
marginLeft: '10px',
marginTop: 'auto',
marginBottom: 'auto',
},
},
link: {
color: theme.palette.primary.dark,
fontWeight: 400,
fontSize: '0.9em',
},
input50: {
width: '50%',
},
button: {
textTransform: 'inherit',
marginLeft: theme.spacing(8),
marginRight: theme.spacing(8),
marginTop: theme.spacing(4),
marginBottom: theme.spacing(2),
padding: theme.spacing(1.2, 2),
borderRadius: '3px',
color: theme.palette.secondary.main,
backgroundColor: theme.palette.primary.important,
[theme.breakpoints.up('sm')]: {
margin: 'auto',
},
},
buttonImportant: {
marginTop: theme.spacing(6),
},
});
const recaptchaRef = React.createRef();
class LoginPage extends React.Component {
state = {
data: {
email: "",
password: ""
},
errors: {},
loading: false,
tabIndex: 0,
openSnack: false
};
static getInitialProps({ query }) {
const { error, inscription } = query
let err = null;
if (!!error)
err = { message: error };
return { errors: err, openSnack: !!error, inscription };
}
UNSAFE_componentWillReceiveProps(nextProps) {
}
componentDidMount() {
}
onChange = e =>
this.setState({
data: { ...this.state.data, [e.target.name]: e.target.value }
});
// onSubmit = e => {
// e.preventDefault();
// const errors = this.validate(this.state.data);
// recaptchaRef.current.execute();
// this.setState({ errors });
// if (Object.keys(errors).length === 0) {
// this.setState({ loading: true });
// this.props.requestLogin(this.state.data)
// }
// };
submit = data => { this.props.login(data) }
validate = data => {
const errors = {};
if (!Validator.isEmail(data.email)) errors.email = "Invalid email";
if (!data.password) errors.password = "Can't be blank";
return errors;
};
// linkedInAuth = () => {
// this.props.requestOauthLogin();
// Router.push('/auth/linkedin')
// }
// facebookAuth = () => {
// this.props.requestOauthLogin();
// Router.push('/auth/facebook')
// }
render() {
const { classes } = this.props;
const { data, errors, loading, openSnack } = this.state;
return (
<Layout>
<Head>
<title key="title">Login</title>
<meta key="robots" name="robots" content="noindex, follow"></meta>
</Head>
<div className={classes.container}>
{/* {!!errors && (
<div className="alert alert-danger">{errors && errors.message}</div>
)} */}
{loading && (
<Loader />
)}
{!loading && (
<Fragment>
<Register linkedInAuth={this.linkedInAuth} facebookAuth={this.facebookAuth} />
</Fragment>
)}
</div>
<Snack variant="error" message={!!!_.isEmpty(this.state.errors) && this.state.errors.message}
openSnack={this.state.openSnack} onClose={this.handleClose} />
</Layout>
);
}
}
function mapStateToProps(state, ownProps) {
return {
loading: !!state.user.loading,
errors: state.user.errors || ownProps.errors
};
}
export default withStyles(styles)(connect(mapStateToProps, { })(LoginPage));
+17 -10
View File
@@ -12,7 +12,7 @@ import Validator from "validator";
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Router from 'next/router'
import Register from '../components/organisms/Register';
// import Register from '../components/organisms/Register';
import { requestLogin, requestOauthLogin, requestLoginFailure } from "../actions/auth";
import { makeStyles } from '@material-ui/core/styles';
import { amber, green } from '@material-ui/core/colors';
@@ -149,7 +149,8 @@ class LoginPage extends React.Component {
errors: {},
loading: false,
tabIndex: 0,
openSnack: false
openSnack: false,
redirection:""
};
static getInitialProps({ query }) {
@@ -175,8 +176,11 @@ class LoginPage extends React.Component {
}
componentDidMount() {
console.log("redirect login");
console.log(localStorage.getItem('loginRedirect'));
this.setState({
tabIndex: (this.props.inscription) ? 1 : 0,
redirection : localStorage.getItem('loginRedirect')
})
}
@@ -246,7 +250,7 @@ class LoginPage extends React.Component {
)}
{!loading && (
<Fragment>
<AppBar className={classes.AppBar} color="default">
{/* <AppBar className={classes.AppBar} color="default">
<Tabs
value={this.state.tabIndex}
onChange={this.handleChange}
@@ -256,7 +260,7 @@ class LoginPage extends React.Component {
<Tab label="Connexion" className={classes.tab} />
<Tab label="Inscription" className={classes.tab} />
</Tabs>
</AppBar>
</AppBar> */}
<SwipeableViews
axis={'x'}
index={this.state.tabIndex}
@@ -312,7 +316,9 @@ class LoginPage extends React.Component {
>
<Link href={"/ResetPassword"} className={classes.link}>
Mot de passe oublié ?
</Link>
</Link>
</Typography>
@@ -332,9 +338,9 @@ class LoginPage extends React.Component {
align="center"
className={classes.formText}
>Je ne possède pas de compte Talents Tube ?
<span onClick={() => this.handleChangeIndex(1)} className={classes.formLink}>
S'inscrire
</span>
<Link href="/Inscription">S'inscrire</Link>
</Typography>
</div>
@@ -348,9 +354,9 @@ class LoginPage extends React.Component {
</div>
</TabContainer>
<TabContainer dir={'x'}>
{/* <TabContainer dir={'x'}>
<Register linkedInAuth={this.linkedInAuth} facebookAuth={this.facebookAuth} />
</TabContainer>
</TabContainer> */}
</SwipeableViews>
</Fragment>
)}
@@ -363,6 +369,7 @@ class LoginPage extends React.Component {
}
function mapStateToProps(state, ownProps) {
return {
loading: !!state.user.loading,
errors: state.user.errors || ownProps.errors
+10 -5
View File
@@ -1,22 +1,26 @@
import React from 'react';
import React, { Fragment,lazy, Suspense } from 'react'
import { connect } from "react-redux";
import PropTypes from 'prop-types';
import getConfig from 'next/config'
import { withStyles } from '@material-ui/core/styles';
import LayoutOffre from "../components/templates/LayoutOffre";
import OffreDetail from "../components/organisms/OffreDetail";
const OffreDetail = lazy(() => import('../components/organisms/OffreDetail'));
//import OffreDetail from "../components/organisms/OffreDetail";
import { fetchJobRequest, clearAd, countAdViewRequest } from '../actions/ads'
import _ from "lodash/string";
const renderLoader = () => <p>Chargement</p>;
const styles = theme => ({
});
const { publicRuntimeConfig } = getConfig()
class Offre extends React.Component {
componentDidMount() {
localStorage.setItem('loginRedirect', window.location.pathname)
localStorage.setItem('adId', this.props.offre.id)
this.props.countAdViewRequest(this.props.offre.id);
}
@@ -29,10 +33,11 @@ class Offre extends React.Component {
}
render() {
const { classes, offre } = this.props;
const socialShareUrl = typeof window !== 'undefined' ? window.location : publicRuntimeConfig.frontServerUrl + `/Offre/${offre.id}-${_.kebabCase(offre.title)}`;
return (
<LayoutOffre backLink="/Offres" offreId={offre.id} offre={offre} isProvided={offre.is_promoted}>
<OffreDetail offre={offre}/>
{/* <Suspense fallback={renderLoader()}><OffreDetail offre={offre}/></Suspense> */}
<Suspense fallback={renderLoader()}><OffreDetail offre={offre}/></Suspense>
</LayoutOffre>
);
}
+18 -1
View File
@@ -80,9 +80,24 @@ class Offres extends React.Component {
constructor(props) {
super(props);
}
voirOffre(){
this.props.togglePromotedFilterRequest()
sessionStorage.setItem('offres_currentPage',1);
}
static getInitialProps({ query }) {
const { init } = query
//this.props.promotedFilter =init
return { init };
}
componentDidMount() {
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("Redirect"+window.location.pathname)
}
render() {
const { classes } = this.props;
const countColor = this.props.promotedFilter ? classes.provided : classes.primary;
const btnClass = this.props.promotedFilter ? classes.buttonDefault : classes.buttonProvided;
@@ -113,12 +128,14 @@ class Offres extends React.Component {
recordCount={this.props.recordCount}
promoted={this.props.promotedFilter}
loading={this.props.loading}
type="offres"
placeholder={"Rechercher un job"}
/>
<Button
name="Rechercher un job"
variant="outlined"
onClick={() => this.props.togglePromotedFilterRequest()}
onClick={() => this.voirOffre()
}
className={classes.button + ' ' + btnClass}>
{this.props.promotedFilter? 'Voir les offres en cours' : 'Voir les offres pourvues'}
</Button>
+82
View File
@@ -0,0 +1,82 @@
import React, { Component, Fragment,lazy, Suspense } from 'react';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography'
import LayoutBackUrl from '../components/templates/LayoutBackUrl';
import Router from 'next/router';
import Head from 'next/head'
// const VideoVimeo = lazy(() => import('../components/atoms/VideoVimeo'));
import VideoVimeo from '../components/atoms/VideoVimeo';
import queryString from 'query-string';
const renderLoader = () => <p>Chargement</p>;
const styles = theme => ({
player: {
background:'#1E2327',
height: '100%'
},
container: {
display: 'flex',
flexDirection: 'column',
position: 'relative',
height: '100%',
padding: '0 10px',
},
bottomContainer: {
display: 'flex',
flexDirection: 'column',
alignSelf: 'center',
justifyContent: 'center',
position: 'absolute',
bottom: 0,
},
title: {
fontFamily: 'Dosis',
fontSize: '1.5em',
fontWeight: '600',
padding: theme.spacing(3, 0),
},
text: {
fontSize: '1em',
fontWeight: '300',
padding: theme.spacing(1, 0),
whiteSpace: 'pre-line',
},
video: {
width:"100%",
height:"100%",
[theme.breakpoints.up('md')]: {
paddingBottom: '35%', /* 16:9 */
},
}
})
class Player extends Component {
render() {
const { classes } = this.props
const params = queryString.parse(location.search);
console.log(params.id);
console.log(params.type);
console.log(params.videoId);
let url = params.id;
return (
<LayoutBackUrl text="Player" url={url} >
<VideoVimeo classes={{ video: classes.video }} videoId={params.videoId} options="" autoplay='1' />
</LayoutBackUrl>
)
}
}
Player.getInitialProps = function (context) {
let { id, videoId,type } = context.query;
let {res} = context;
return {};
}
export default withStyles(styles)(Player);
+9 -3
View File
@@ -217,11 +217,15 @@ class Reponse extends React.Component {
};
componentDidMount() {
localStorage.setItem('loginRedirect', window.location)
console.log('loginRedirect reponse');
console.log(window.location.pathname+ window.location.search);
//localStorage.setItem('loginRedirect', window.location.pathname+ window.location.search)
if(!!!localStorage.getItem('ttJWT'))
{
Router.push("/Login")
console.log("REPONSE REDIRECT LOGIN")
Router.push("/Inscription")
}
else
this.setState({loading: false})
@@ -427,7 +431,7 @@ Reponse.getInitialProps = function (context) {
const { adId, companyId } = context.query
const {res} = context
//TODO :really needed ?
context.store.dispatch(fetchCurrentUserRequest())
context.store.dispatch(fetchCurrentUserRequest())
if(!!adId)
context.store.dispatch(fetchJobRequest(adId))
@@ -438,7 +442,9 @@ Reponse.getInitialProps = function (context) {
}
function mapStateToProps(state) {
console.log("attente")
console.log(state.media)
return {
loading: !!state.answer.loading || !!state.media.loading,
media: state.media,
+2 -2
View File
@@ -76,7 +76,7 @@ class VerifyEmail extends Component {
N'oubliez pas de consulter vos spams, si vous ne trouvez pas le lien d'activation dans votre boite de réception.
</Typography>
<section className={classes.bottomContainer}>
<Typography gutterBottom align="center" className={classes.bottomText}>
{/* <Typography gutterBottom align="center" className={classes.bottomText}>
Cliquez sur suivant pour continuer votre candidature
</Typography>
<Button
@@ -86,7 +86,7 @@ class VerifyEmail extends Component {
onClick={() => Router.push('/Login')}
>
Suivant
</Button>
</Button> */}
</section>
</div>
</Layout>
+2 -2
View File
@@ -18,7 +18,7 @@ class MyDocument extends Document {
const { pageContext } = this.props;
return (
<html lang="en" dir="ltr">
<html lang="fr" dir="ltr">
<Head>
<meta name="google-site-verification" content="CQsVLRoDEzxN5TT4zoTIPy_v4JWGPQgg29OLNx8EkXw" />
<meta charSet="utf-8" />
@@ -34,7 +34,7 @@ class MyDocument extends Document {
<link href="https://fonts.googleapis.com/css?family=Dosis:600|Roboto:100,300,400,500,700,900&display=swap" rel="stylesheet">
</link>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript" src="/static/js/pwaInstaller.js" ></script>
{/* Global Site Tag (gtag.js) - Google Analytics */}
{/* <script
+4 -2
View File
@@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, {Fragment} from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Layout from "../components/templates/Layout"
@@ -8,7 +8,9 @@ import { Typography } from '@material-ui/core';
import Button from '@material-ui/core/Button';
import Router from 'next/router'
import { connect } from 'react-redux'
//const fetchEmphasisJobsRequest = lazy(() => import('../actions/ads'));
import { fetchEmphasisJobsRequest } from "../actions/ads";
//const fetchEmphasisCompaniesRequest = lazy(() => import('../actions/companies'));
import { fetchEmphasisCompaniesRequest } from "../actions/companies";
import Loader from './../components/templates/loader'
import { isEmpty } from "lodash"
@@ -163,7 +165,7 @@ class Index extends React.Component {
const imgUrl = DefaultUrl
return (
<Layout>
<OgHead seo_title="Talents Tube - Plateforme de recrutement en vidéo"
<OgHead seo_title="Espace candidat - Plateforme de recrutement en vidéo | Talents Tube"
seo_description="Talents Tube est la première plateforme réservée aux offres d'emploi vidéo, vidéo marque employeur et aux CV vidéos. Découvrez une nouvelle méthode de recrutement."
seo_url={socialShareUrl}
image={imgUrl}
+1 -1
View File
@@ -217,7 +217,7 @@ class Index extends React.Component {
// Filter logic
getSuggestionsMetier = async (valueMetier) => {
const inputValue = valueMetier.trim().toLowerCase();
let response = await fetch(publicRuntimeConfig.symphonyUrl+"/api/getAppelationsLibelle?q=" + inputValue );
let response = await fetch(publicRuntimeConfig.symphonyUrl+"api/getAppelationsLibelle?q=" + inputValue );
// let response = await fetch("http://www.omdbapi.com/?s=" + inputValue + "&apikey=a591bb53");
let data = await response.json()
return data;
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

+15 -6
View File
@@ -46,8 +46,10 @@ export function* postAdAnswerRequestSaga(action) {
} catch (err) {
if (_.includes(err, "401")) {
console.error("401")
console.error(window.location)
localStorage.setItem('loginRedirect', window.location)
console.error(window.location.pathname)
console.log("ERREUR 401")
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(postAdAnswerRequestFailure(err.response));
@@ -67,7 +69,8 @@ export function* uploadMediaSaga(action) {
} catch (err) {
if (_.includes(err, "401") || err.response.status === 401) {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(uploadMediaFailure(err.response));
@@ -87,7 +90,8 @@ export function* uploadMediaPresSaga(action) {
} catch (err) {
if (_.includes(err, "401") || err.response.status === 401) {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(uploadMediaPresFailure(err.response));
@@ -107,7 +111,8 @@ export function* uploadMediaCvSaga(action) {
} catch (err) {
if (_.includes(err, "401") || err.response.status === 401) {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(uploadMediaCvFailure(err.response));
@@ -126,6 +131,7 @@ export function* fetchJobsAnsweredRequestSaga(action) {
} catch (err) {
if (_.includes(err, "401") || err.response.status === 401) {
localStorage.setItem('loginRedirect', "/Candidatures")
console.log("ERREUR 401")
Router.push("/Login");
}
@@ -149,6 +155,7 @@ export function* fetchAnswerRequestSaga(action) {
if (_.includes(err, "401") || err.response.status === 401) {
localStorage.setItem('loginRedirect', "/Candidatures")
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(fetchAnswerFailure(err.response));
@@ -171,7 +178,8 @@ export function* postAnswerMessageSaga(action) {
} catch (err) {
if (_.includes(err, "401")) {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(postMessageAnswerFailure(err.response));
@@ -191,6 +199,7 @@ export function* fetchAnswerMessagesRequestSaga(action) {
} catch (err) {
if (_.includes(err, "401")) {
localStorage.setItem('loginRedirect', "/Candidatures")
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(fetchAnswerMessagesFailure(err.response));
+20 -7
View File
@@ -33,16 +33,25 @@ export function* requestLoginSaga(action) {
yield put(userLoggedIn());
yield put(fetchCurrentUserRequest());
let url = localStorage.getItem('loginRedirect');
console.log("requestLoginSaga1!!!!!!!!!!!!!! "+url)
console.log(url)
if (!!!url)
url = "/"
console.log(url)
Router.push(url);
localStorage.setItem('loginRedirect', '/');
} else
throw new Error("Mauvais identifiants.")
// <Redirect to={url}/>
console.log("requestLoginSaga2!!!!!!!!!!!!!! "+url)
//localStorage.setItem('loginRedirect', '/');
} else{
throw new Error("Mauvais identifiants.")
console.log("requestLoginSaga!!!!!!!!!!!!!! Mauvais identifiants.")
}
} catch (error) {
setAuthorizationHeader();
yield put(requestLoginFailure({ message: "Mauvais identifiants." }));
console.log("requestLoginSaga!!!!!!!!!!!!!! Mauvais identifiants.")
yield put(requestLoginFailure({ message: "Mauvais identifiants" }));
}
}
@@ -124,15 +133,18 @@ export function* requestRegisterSaga(action) {
try {
//console.log('function* requestRegisterSaga')
const res = yield call(api.user.register, action.payload);
console.log("requestRegisterSaga");
console.log(res);
console.log(action);
if (res.data.status === 'success') {
yield put(registerUserSuccess(res));
yield put(sendConfirmationEmailRequest(res));
Router.push(`/VerifyEmail/${action.payload.email}`);
} else
throw new Error("L'inscription à échouée. Merci de contacter contact@talentstube.com")
throw new Error("L'inscription a échouée. Merci de contacter contact@talentstube.com")
} catch (err) {
console.error(err)
@@ -260,7 +272,8 @@ export function* requestUpdateUserRequestSaga(action) {
} catch (err) {
if (_.includes(err, "401") || (!!err.response && err.response.status === 401)) {
localStorage.setItem('loginRedirect', window.location)
localStorage.setItem('loginRedirect', window.location.pathname)
console.log("ERREUR 401")
Router.push("/Login");
}
yield put(updateUserPictureFailure(err.response));
+15 -5
View File
@@ -163,15 +163,21 @@ app.prepare()
app.render(req, res, actualPage, queryParams)
})
server.get('/Player', (req, res) => {
const actualPage = '/Player'
const queryParams = { id: req.query.id, videoId:req.query.videoId, type:req.query.type }
app.render(req, res, actualPage, queryParams)
})
server.get('/VerifyEmail/:email', (req, res) => {
const actualPage = '/VerifyEmail'
const queryParams = { email: req.params.email }
app.render(req, res, actualPage, queryParams)
})
server.get('/ConfirmAccount/:token/:email', (req, res) => {
server.get('/ConfirmAccount/:token/:email/:url', (req, res) => {
const actualPage = '/ConfirmAccount'
const queryParams = { token: req.params.token, email: req.params.email }
const queryParams = { token: req.params.token, email: req.params.email, url: req.params.url }
app.render(req, res, actualPage, queryParams)
})
@@ -200,9 +206,13 @@ app.prepare()
const email = req.body.email
const nom = req.body.lastname
const prenom = req.body.firstname
const tokenUrl = `${process.env.FRONT_SERVER}/ConfirmAccount/${token}/${email}`
console.log("prenom "+prenom)
const url = req.body.adId
console.log("Envoi d'email "+url)
//TODO Ajouter le contexte de l'annonce
//Envoyer URL
const tokenUrl = `${process.env.FRONT_SERVER}/ConfirmAccount/${token}/${email}/${url}`
console.log("tokenUrl "+tokenUrl)
mailer.sendConfirmationEmail(nom, prenom, tokenUrl, email);
res.json({ status: 'success' });
+180
View File
@@ -0,0 +1,180 @@
import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import { withStyles, getMuiTheme } from '@material-ui/core/styles';
import MenuIcon from '@material-ui/icons/Menu';
import Link from 'next/link'
import Drawer from '@material-ui/core/Drawer';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import Divider from '@material-ui/core/Divider';
import SendIcon from '@material-ui/icons/Send';
import CodeIcon from '@material-ui/icons/Code';
import HomeIcon from '@material-ui/icons/Home';
import FingerprintIcon from '@material-ui/icons/Fingerprint';
import LocalBarIcon from '@material-ui/icons/LocalBar';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import { ListItemText } from '@material-ui/core';
import { Spring, animated } from 'react-spring'
const styles = theme => ({
root: {
width: '100%',
'& a':{
textDecoration:'none'
}
},
grow: {
flexGrow: 1,
},
bar: {
},
menuButton: {
marginLeft: -12,
marginRight: 20,
[theme.breakpoints.up('sm')]: {
display: 'none',
},
[theme.breakpoints.down('md')]: {
display: 'block',
},
},
menuLogo: {
marginLeft: 20,
marginRight: 40,
cursor: 'pointer'
},
title: {
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
[theme.breakpoints.down('md')]: {
display: 'none',
},
marginRight: 15,
cursor: 'pointer'
},
sectionDesktop: {
display: 'none',
[theme.breakpoints.up('md')]: {
display: 'flex',
},
},
sectionMobile: {
display: 'flex',
[theme.breakpoints.up('md')]: {
display: 'none',
},
},
fullList: {
width: 'auto',
cursor: 'pointer'
},
});
class HeaderOffre extends React.Component {
state = {
top: false,
left: false,
bottom: false,
right: false,
toggle: true
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
toggle = () => this.setState(state => ({ toggle: !state.toggle }))
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<Drawer anchor="top" open={this.state.top} onClose={this.toggleDrawer('top', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('top', false)}
onKeyDown={this.toggleDrawer('top', false)}
>
<div className={classes.fullList}>
<List>
<Link href="/" prefetch >
<a><ListItem>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
<ListItemText primary='Accueil'>
</ListItemText>
</ListItem></a>
</Link>
<Divider />
<Link href="/contact" prefetch >
<a><ListItem>
<ListItemIcon>
<SendIcon />
</ListItemIcon>
<ListItemText primary='contact'>
</ListItemText>
</ListItem></a>
</Link>
</List>
</div>
</div>
</Drawer>
<AppBar position="static" className={classes.appBar}>
<Toolbar>
<IconButton className={classes.menuButton} onClick={this.toggleDrawer('top', true)}
color="inherit" aria-label="Open drawer">
<MenuIcon />
</IconButton>
<Link href="/" prefetch>
<a><div onClick={this.toggle}>
<Spring native from={{ x: 0 }} to={{ x: this.state.toggle ? 1 : 0 }} config={{ duration: 1000 }}>
{({ x }) => (
<animated.div
style={{
opacity: x.interpolate({ output: [1, 1] }),
transform: x
.interpolate({
range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1]
})
.interpolate(x => `scale(${x})`)
}}>
<img alt="e-declic" src='https://www.e-declic.com/files/e-declic/img/logo.png' className={classes.menuLogo} />
</animated.div>
)}
</Spring>
</div></a>
</Link>
<Link href="/contact" prefetch >
<a><Typography className={classes.title} variant="h5" color="inherit" noWrap>
Contact
</Typography></a>
</Link>
</Toolbar>
</AppBar>
</div >
);
}
}
HeaderOffre.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(HeaderOffre)