Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e06cb60bfb | |||
| 11eedf3a8b | |||
| f9a8b598da | |||
| b488e3399c | |||
| c82cd3be1e | |||
| fed0d99e64 | |||
| 24e05ff7fc | |||
| 9af90d3fd0 | |||
| 0b3d5c9ebb | |||
| c3f4832b30 | |||
| 4bd6e8c580 | |||
| 8e896114bf | |||
| f757997392 | |||
| 67b3c97806 | |||
| ee636e27ff | |||
| ff5055c411 | |||
| d5b1fcd74a | |||
| 5ace82986f | |||
| c989b6ddfe | |||
| f3f94e9b51 | |||
| 6c34cad1e7 | |||
| cb5268bf27 | |||
| 7b77b2195d | |||
| dad7e6b2eb | |||
| 146d1a5061 | |||
| ed626137cf | |||
| 224cedac65 | |||
| b5b41b4849 | |||
| d1ee296684 | |||
| 6cf3bcc658 | |||
| b20efef730 | |||
| 459ff88e9d | |||
| dcdbfed2a3 | |||
| d235b08fe3 | |||
| e5b9f2b75d | |||
| 563107e649 | |||
| 5545dbfad0 | |||
| 353128fa8e | |||
| 2e9fa7e9d0 | |||
| c0e5ec6e90 | |||
| 33adc4c819 | |||
| ebe81cd588 | |||
| c3ced21cce | |||
| a156050184 | |||
| 535069bb64 | |||
| e4603f4ca8 | |||
| cab481cd2f | |||
| 34d1384fb7 | |||
| 4b2fabd4b4 | |||
| 130fb89c5f | |||
| eeee4d3f45 | |||
| 7f2c8374a4 | |||
| e380dec152 | |||
| 58bf654651 | |||
| ead5370495 | |||
| ce8f8660f3 | |||
| 28fbf3a013 | |||
| 726cd78bd3 | |||
| 70a0e47d28 | |||
| d338cfaad4 | |||
| 1815b2834e | |||
| 27ac00bafb | |||
| 6a7024d5ac | |||
| 485ccece1e | |||
| 1fd45a00a3 | |||
| 36571b5cca | |||
| 7ad96db928 | |||
| 5ce9f108cd | |||
| 99bb737647 | |||
| e2ef540aac | |||
| 6e6119ffaf | |||
| 473edf7472 | |||
| 96b08352a0 | |||
| 7a45d19d2b | |||
| c73b08c1aa | |||
| b6e4347abb | |||
| adb9d2ccde | |||
| edd7f705ab | |||
| ea372ba0f2 | |||
| 779b722662 | |||
| 6bb8baf636 | |||
| 083f7b9c16 | |||
| 0eed896aec | |||
| e8ae224414 | |||
| fa3dcd8fd2 | |||
| 2c0c0a2632 | |||
| 501ee57430 | |||
| 0f6ec17fef | |||
| 112541275b | |||
| e08b879691 | |||
| 527351c232 | |||
| 0ed8da11e1 | |||
| f522e4389e | |||
| efb6527b9b | |||
| ba43bcddc7 | |||
| 3523cc95ee | |||
| c0d32cee12 | |||
| 3b6aa331db | |||
| fe7932e5ae | |||
| 05b64ac44c | |||
| 446e13ceba | |||
| 6570e28bbd | |||
| d146da7ab3 | |||
| ae06e730ad | |||
| f386b93dd2 | |||
| cebdf4d1d2 | |||
| e6738a1565 | |||
| ce9b8b6031 | |||
| 00eac45913 | |||
| 89719a8bbc |
@@ -5,7 +5,7 @@
|
||||
Download the example [or clone the repo](https://git.e-declic.net/talents-tube/app.git):
|
||||
|
||||
```bash
|
||||
git clone
|
||||
git clone
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
@@ -27,10 +27,11 @@ https://redux-saga.js.org/docs/basics/ErrorHandling.html
|
||||
is a library that aims to make application side effect asynchronous things like data fetching and impure things like accessing the browser cache
|
||||
|
||||
## Integration
|
||||
### Naming conventions
|
||||
style classes name syntax : Camel case
|
||||
Try to name without too much precision
|
||||
|
||||
### Naming conventions
|
||||
|
||||
style classes name syntax : Camel case
|
||||
Try to name without too much precision
|
||||
|
||||
### Material UI
|
||||
|
||||
@@ -52,16 +53,16 @@ sudo docker exec -it frontnginx.nginx bash
|
||||
nginx -t && nginx -s reload
|
||||
|
||||
## Test
|
||||
|
||||
### Cypress
|
||||
|
||||
[Gmail-tester]
|
||||
https://github.com/levz0r/gmail-tester
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
### Jenkins
|
||||
|
||||
>in case of emergency
|
||||
make docker-restart ENV=dev
|
||||
|
||||
adduser jenkins root
|
||||
|
||||
> in case of emergency
|
||||
> make docker-restart ENV=dev
|
||||
> adduser jenkins root
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
FETCH_ADS_REQUEST,
|
||||
FETCH_ADS_SUCCESS,
|
||||
FETCH_ADS_FAILURE,
|
||||
FETCH_AD_REQUEST,
|
||||
FETCH_AD_SUCCESS,
|
||||
FETCH_AD_FAILURE,
|
||||
FETCH_EMPHASIS_ADS_REQUEST,
|
||||
FETCH_EMPHASIS_ADS_SUCCESS,
|
||||
FETCH_EMPHASIS_ADS_FAILURE,
|
||||
FETCH_JOBS_REQUEST,
|
||||
FETCH_JOBS_SUCCESS,
|
||||
FETCH_JOBS_FAILURE,
|
||||
FETCH_JOB_REQUEST,
|
||||
FETCH_JOB_SUCCESS,
|
||||
FETCH_JOB_FAILURE,
|
||||
FETCH_EMPHASIS_JOBS_REQUEST,
|
||||
FETCH_EMPHASIS_JOBS_SUCCESS,
|
||||
FETCH_EMPHASIS_JOBS_FAILURE,
|
||||
CLEAR_AD,
|
||||
COUNT_AD_VIEW,
|
||||
TOGGLE_PROMOTED_FILTER_ADS
|
||||
@@ -28,52 +28,52 @@ export const togglePromotedFilterRequest = () => ({
|
||||
|
||||
//Ads list
|
||||
|
||||
export const fetchAdsRequest = (payload) => ({
|
||||
type: FETCH_ADS_REQUEST,
|
||||
export const fetchJobsRequest = (payload) => ({
|
||||
type: FETCH_JOBS_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const fetchAdsSuccess = res => ({
|
||||
type: FETCH_ADS_SUCCESS,
|
||||
export const fetchJobsSuccess = res => ({
|
||||
type: FETCH_JOBS_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const fetchAdsFailure = res => ({
|
||||
type: FETCH_ADS_FAILURE,
|
||||
export const fetchJobsFailure = res => ({
|
||||
type: FETCH_JOBS_FAILURE,
|
||||
res
|
||||
});
|
||||
|
||||
//Ads list
|
||||
|
||||
export const fetchEmphasisAdsRequest = (payload) => ({
|
||||
type: FETCH_EMPHASIS_ADS_REQUEST,
|
||||
export const fetchEmphasisJobsRequest = (payload) => ({
|
||||
type: FETCH_EMPHASIS_JOBS_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const fetchEmphasisAdsSuccess = res => ({
|
||||
type: FETCH_EMPHASIS_ADS_SUCCESS,
|
||||
export const fetchEmphasisJobsSuccess = res => ({
|
||||
type: FETCH_EMPHASIS_JOBS_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const fetchEmphasisAdsFailure = res => ({
|
||||
type: FETCH_EMPHASIS_ADS_FAILURE,
|
||||
export const fetchEmphasisJobsFailure = res => ({
|
||||
type: FETCH_EMPHASIS_JOBS_FAILURE,
|
||||
res
|
||||
});
|
||||
|
||||
//Single ad
|
||||
|
||||
export const fetchAdRequest = payload => ({
|
||||
type: FETCH_AD_REQUEST,
|
||||
export const fetchJobRequest = payload => ({
|
||||
type: FETCH_JOB_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const fetchAdSuccess = res => ({
|
||||
type: FETCH_AD_SUCCESS,
|
||||
export const fetchJobSuccess = res => ({
|
||||
type: FETCH_JOB_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const fetchAdFailure = res => ({
|
||||
type: FETCH_AD_FAILURE,
|
||||
export const fetchJobFailure = res => ({
|
||||
type: FETCH_JOB_FAILURE,
|
||||
res
|
||||
});
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import {
|
||||
POST_AD_ANSWER_REQUEST,
|
||||
POST_AD_ANSWER_FAILURE,
|
||||
POST_AD_ANSWER_SUCCESS,
|
||||
FETCH_ADS_ANSWER_REQUEST,
|
||||
FETCH_ADS_ANSWER_SUCCESS,
|
||||
FETCH_ADS_ANSWER_FAILURE,
|
||||
FETCH_JOBS_ANSWER_REQUEST,
|
||||
FETCH_JOBS_ANSWER_SUCCESS,
|
||||
FETCH_JOBS_ANSWER_FAILURE,
|
||||
FETCH_ANSWER_REQUEST,
|
||||
FETCH_ANSWER_SUCCESS,
|
||||
FETCH_ANSWER_FAILURE,
|
||||
@@ -47,19 +47,19 @@ export const postMessageAnswerSuccess = res => ({
|
||||
});
|
||||
|
||||
|
||||
export const fetchAdsAnsweredRequest = payload => ({
|
||||
type: FETCH_ADS_ANSWER_REQUEST,
|
||||
export const fetchJobsAnsweredRequest = payload => ({
|
||||
type: FETCH_JOBS_ANSWER_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const fetchAdsAnsweredSuccess = res => ({
|
||||
type: FETCH_ADS_ANSWER_SUCCESS,
|
||||
export const fetchJobsAnsweredSuccess = res => ({
|
||||
type: FETCH_JOBS_ANSWER_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
|
||||
export const fetchAdsAnsweredFailure = errors => ({
|
||||
type: FETCH_ADS_ANSWER_FAILURE,
|
||||
export const fetchJobsAnsweredFailure = errors => ({
|
||||
type: FETCH_JOBS_ANSWER_FAILURE,
|
||||
errors
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import {
|
||||
UPLOAD_MEDIA_REQUEST,
|
||||
UPLOAD_MEDIA_FAILURE,
|
||||
UPLOAD_MEDIA_SUCCESS
|
||||
UPLOAD_MEDIA_SUCCESS,
|
||||
UPLOAD_MEDIA_PRES_REQUEST,
|
||||
UPLOAD_MEDIA_PRES_FAILURE,
|
||||
UPLOAD_MEDIA_PRES_SUCCESS,
|
||||
UPLOAD_MEDIA_CV_REQUEST,
|
||||
UPLOAD_MEDIA_CV_FAILURE,
|
||||
UPLOAD_MEDIA_CV_SUCCESS,
|
||||
|
||||
} from "../types";
|
||||
|
||||
export const uploadMedia = payload => ({
|
||||
@@ -18,6 +25,35 @@ import {
|
||||
type: UPLOAD_MEDIA_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const uploadMediaPres = payload => ({
|
||||
type: UPLOAD_MEDIA_PRES_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const uploadMediaPresFailure = errors => ({
|
||||
type: UPLOAD_MEDIA_PRES_FAILURE,
|
||||
errors
|
||||
});
|
||||
|
||||
|
||||
export const uploadMediaPresSuccess = res => ({
|
||||
type: UPLOAD_MEDIA_PRES_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const uploadMediaCv = payload => ({
|
||||
type: UPLOAD_MEDIA_CV_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const uploadMediaCvFailure = errors => ({
|
||||
type: UPLOAD_MEDIA_CV_FAILURE,
|
||||
errors
|
||||
});
|
||||
|
||||
export const uploadMediaCvSuccess = res => ({
|
||||
type: UPLOAD_MEDIA_CV_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function ChatCard(props) {
|
||||
className={classes.messageDate}
|
||||
align="center"
|
||||
>
|
||||
Envoyée le {(new Date(props.message.c_time)).toLocaleDateString("fr-FR")} à {(new Date(props.message.c_time)).toLocaleTimeString("fr-FR")}
|
||||
Envoyé le {(new Date(props.message.c_time)).toLocaleDateString("fr-FR")} à {(new Date(props.message.c_time)).toLocaleTimeString("fr-FR")}
|
||||
</Typography>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
@@ -6,13 +6,19 @@ import AssignmentIcon from '@material-ui/icons/Assignment';
|
||||
import RoomIcon from '@material-ui/icons/Room';
|
||||
import LocationOnIcon from '@material-ui/icons/LocationOn';
|
||||
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,
|
||||
room: RoomIcon,
|
||||
location_on: LocationOnIcon,
|
||||
business_center: BusinessCenterIcon,
|
||||
business: Business,
|
||||
watch_later: WatchLater,
|
||||
home: Home,
|
||||
};
|
||||
|
||||
const styles = theme => ({
|
||||
|
||||
@@ -4,14 +4,20 @@ 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';
|
||||
import Business from '@material-ui/icons/Business';
|
||||
|
||||
const variantIcon = {
|
||||
assignment: AssignmentIcon,
|
||||
room: RoomIcon,
|
||||
location_on: LocationOnIcon,
|
||||
home: HomeOnIcon,
|
||||
watch_later: WatchLater,
|
||||
business_center: BusinessCenterIcon,
|
||||
business: Business,
|
||||
};
|
||||
|
||||
const styles = theme => ({
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import React from 'react'
|
||||
import { JobPostingJsonLd } from 'next-seo';
|
||||
|
||||
const JobPosting = props => {
|
||||
return (
|
||||
|
||||
<JobPostingJsonLd
|
||||
datePosted={props.job_date}
|
||||
description={props.job_description}
|
||||
hiringOrganization={{
|
||||
name: props.job_brand,
|
||||
sameAs: props.job_brand_link,
|
||||
}}
|
||||
jobLocation={{
|
||||
addressLocality: props.job_ville,
|
||||
addressRegion: props.job_dept,
|
||||
// postalCode: props.job_location,
|
||||
streetAddress: props.job_location,
|
||||
addressCountry: props.job_pays,
|
||||
|
||||
}}
|
||||
title={props.job_title}
|
||||
validThrough={props.job_date_fin}
|
||||
applicantLocationRequirements="FR"
|
||||
employmentType = {props.job_contract_type + ","+props.job_temps_type }
|
||||
/>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
JobPosting.propTypes = {
|
||||
// seo_title: PropTypes.string.isRequired,
|
||||
// seo_description: PropTypes.string.isRequired,
|
||||
// seo_url: PropTypes.string.isRequired,
|
||||
// image: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default JobPosting
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Head from 'next/head'
|
||||
|
||||
|
||||
const OgHead = props => {
|
||||
return (
|
||||
<Head>
|
||||
<title key="title">{props.seo_title}</title>
|
||||
<meta name="description" key="description" content={props.seo_description} />
|
||||
|
||||
<meta name="robots" content="noindex, nofollow"></meta>
|
||||
<meta name="description" kenoindexy="description" content={props.seo_description} />
|
||||
<meta name="keywords" content={props.seo_key}/>
|
||||
<meta key="og:url" property="og:url" content={props.seo_url} />
|
||||
<meta key="og:type" property="og:type" content="article" />
|
||||
<meta key="og:title" property="og:title" content={props.seo_title} />
|
||||
@@ -16,10 +17,20 @@ const OgHead = props => {
|
||||
property="og:description"
|
||||
content={props.seo_description}
|
||||
/>
|
||||
<meta name="keywords" content={props.seo_key}/>
|
||||
<meta key="og:image" property="og:image" content={props.image} />
|
||||
|
||||
<link rel="canonical" href={"https://www.application.bzh/" + props.seo_url} />
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="@TalentsTube"/>
|
||||
<meta name="twitter:title" content={props.seo_title}/>
|
||||
<meta name="twitter:description" content={props.seo_description}/>
|
||||
<meta name="twitter:image" content={props.image}/>
|
||||
{/* <meta httpEquiv='cache-control' content='no-store,no-cache'></meta>
|
||||
<meta httpEquiv='expires' content='0'></meta>
|
||||
<meta httpEquiv='pragma' content='no-cache'></meta> */}
|
||||
{/* <link rel="canonical" href={ props.seo_url} /> */}
|
||||
|
||||
</Head>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -30,6 +30,32 @@ const useStyles = makeStyles(theme => ({
|
||||
height: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
videoPresentation: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
paddingBottom: '56%', /* 16:9 58%*/
|
||||
'& iframe': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 'calc(50% - 50vw)',
|
||||
width: '100vw',
|
||||
height: '100%',
|
||||
},
|
||||
[theme.breakpoints.up('md')]: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
paddingBottom: '56.5%', /* 16:9 */
|
||||
'& iframe': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 'calc(50% - 32vw)',
|
||||
width: '64vw',
|
||||
height: '100%',
|
||||
},
|
||||
},
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -37,14 +63,20 @@ export default function VideoVimeo(props) {
|
||||
|
||||
const {videoId, title, options, classesOverride, autoplay} = props;
|
||||
const classes = useStyles();
|
||||
|
||||
let className = classes.video;
|
||||
if (classesOverride) {
|
||||
className = classes.videoPresentation;
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={classes.video +' '+classesOverride}>
|
||||
|
||||
<section className={className +' '+classesOverride}>
|
||||
<iframe className='player'
|
||||
src={"https://player.vimeo.com/video/"+ videoId + options+"?autoplay="+autoplay}
|
||||
frameBorder="0"
|
||||
title={title}
|
||||
webkitallowfullscreen="true" mozallowfullscreen="true" allowFullScreen></iframe>
|
||||
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@ import React, { Component, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from "react-redux";
|
||||
import { subscribeUserToPushRequest } from '../../actions/user'
|
||||
import getConfig from 'next/config'
|
||||
|
||||
|
||||
import { urlB64ToUint8Array, payloadFromSubscription } from './Utility'
|
||||
|
||||
var swRegistration = null
|
||||
|
||||
//TODO: put in config
|
||||
const applicationServerPublicKey = 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU=';
|
||||
|
||||
const WebPushContext = React.createContext()
|
||||
|
||||
function WebPushConsumer(props) {
|
||||
@@ -26,6 +25,8 @@ function WebPushConsumer(props) {
|
||||
</WebPushContext.Consumer>
|
||||
)
|
||||
}
|
||||
|
||||
const { publicRuntimeConfig } = getConfig()
|
||||
class WebPush extends Component {
|
||||
static Consumer = WebPushConsumer;
|
||||
|
||||
@@ -91,7 +92,7 @@ class WebPush extends Component {
|
||||
if (isSubscribed) {
|
||||
this.onUpdateSubscriptionOnServer(subscription)
|
||||
} else {
|
||||
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey)
|
||||
const applicationServerKey = urlB64ToUint8Array(publicRuntimeConfig.applicationServerPublicKey)
|
||||
swRegistration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: applicationServerKey
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
import React, { useState, Component, Fragment } from 'react'
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { connect } from 'react-redux'
|
||||
import { updateUserRequest } from '../../actions/user'
|
||||
import getConfig from 'next/config'
|
||||
import Validator from "validator";
|
||||
import AccountProfile from '../organisms/AccountProfile';
|
||||
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
|
||||
import {
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '85%',
|
||||
},
|
||||
form: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: '24px',
|
||||
paddingBottom: theme.spacing(8),
|
||||
marginBottom: theme.spacing(8),
|
||||
'&>div': {
|
||||
marginTop: theme.spacing(1.5),
|
||||
marginBottom: theme.spacing(1.5),
|
||||
}
|
||||
|
||||
},
|
||||
textField: {
|
||||
width: '85%',
|
||||
'&:disabled': {
|
||||
color: theme.palette.secondary.dark,
|
||||
},
|
||||
'& label': {
|
||||
color: theme.palette.primary.dark,
|
||||
},
|
||||
'& fieldset:hover': {
|
||||
borderColor: theme.palette.primary.main + ' !important',
|
||||
},
|
||||
},
|
||||
textFieldSmall: {
|
||||
width: '48%',
|
||||
'&:disabled': {
|
||||
color: theme.palette.secondary.dark,
|
||||
},
|
||||
'& label': {
|
||||
color: theme.palette.primary.dark,
|
||||
},
|
||||
'& fieldset:hover': {
|
||||
borderColor: theme.palette.primary.main + ' !important',
|
||||
},
|
||||
padding: '5px',
|
||||
},
|
||||
});
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
|
||||
//https://xd.adobe.com/view/ba98331a-9145-4d67-7e27-25a36e519ef4-cca9/screen/a96779d7-bdb3-410a-8f19-e6987acb98ee/Candidature-Step-3
|
||||
class AccountEtape1 extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// This binding is necessary to make `this` work in the callback
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleClose = this.handleClose.bind(this);
|
||||
this.onBlur = this.onBlur.bind(this)
|
||||
this.onSubmit = this.onSubmit.bind(this);
|
||||
}
|
||||
|
||||
state = {
|
||||
file: null,
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
email:'',
|
||||
phone: '',
|
||||
currentJob: '',
|
||||
address1:'',
|
||||
address2 : '',
|
||||
zipCode : '',
|
||||
city : '',
|
||||
country : '',
|
||||
linkedin: '',
|
||||
twitter: '',
|
||||
website: '',
|
||||
mediaId: null,
|
||||
companyId: null,
|
||||
|
||||
};
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
|
||||
//console.log(this.refs.myTextField.input.value);
|
||||
//this.soumettre(e);
|
||||
|
||||
}
|
||||
|
||||
handleClose = (e, reason) => {
|
||||
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
|
||||
//setOpen(false);
|
||||
};
|
||||
|
||||
onBlur(e) {
|
||||
console.log("blur")
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
|
||||
this.soumettre(e.target.name, "unitaire");
|
||||
}
|
||||
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
firstname: nextProps.user.firstname,
|
||||
lastname: nextProps.user.lastname,
|
||||
phone: nextProps.user.phone,
|
||||
email: nextProps.user.email,
|
||||
currentJob: nextProps.user.currentJob,
|
||||
address1 : nextProps.user.address1,
|
||||
address2 : nextProps.user.address2,
|
||||
zipCode : nextProps.user.zipCode,
|
||||
city : nextProps.user.city,
|
||||
country : nextProps.user.country,
|
||||
linkedin: nextProps.user.linkedin,
|
||||
twitter: nextProps.user.twitter,
|
||||
website: nextProps.user.website,
|
||||
companyId: nextProps.companyId,
|
||||
errors: !!!nextProps.errors ? { errors: { message: "" } } : nextProps.errors,
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
firstname: this.props.user.firstname,
|
||||
lastname: this.props.user.lastname,
|
||||
phone: this.props.user.phone,
|
||||
email: this.props.user.email,
|
||||
address1: this.props.user.address1,
|
||||
address2 : this.props.user.address2,
|
||||
zipCode : this.props.user.zipCode,
|
||||
city : this.props.user.city,
|
||||
country : this.props.user.country,
|
||||
currentJob: this.props.user.currentJob,
|
||||
linkedin: this.props.user.linkedin,
|
||||
twitter: this.props.user.twitter,
|
||||
website: this.props.user.website,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
onSubmit = (e) => {
|
||||
|
||||
e.preventDefault();
|
||||
console.log("submit")
|
||||
console.log(e.keyCode)
|
||||
|
||||
this.soumettre(e.target.name, "global")
|
||||
|
||||
}
|
||||
soumettre(champ, type){
|
||||
console.log("soumettre");
|
||||
console.log(champ);
|
||||
const errors = this.validate(this.state, champ, type);
|
||||
const success = {};
|
||||
this.setState({ errors });
|
||||
if (!this.state.errors || !this.state.errors.message){
|
||||
|
||||
success.message ="Profil mis à jour";
|
||||
this.setState({ success });
|
||||
const data = new FormData()
|
||||
data.append('firstname', this.state.firstname)
|
||||
data.append('lastname', this.state.lastname)
|
||||
data.append('phone', this.state.phone)
|
||||
//data.append('email', this.state.email)
|
||||
data.append('currentJob', this.state.currentJob)
|
||||
data.append('address1', this.state.address1)
|
||||
data.append('address2', this.state.address2)
|
||||
data.append('zipCode', this.state.zipCode)
|
||||
data.append('city', this.state.city)
|
||||
data.append('country', this.state.country)
|
||||
data.append('linkedin', this.state.linkedin)
|
||||
data.append('twitter', this.state.twitter)
|
||||
data.append('website', this.state.website)
|
||||
|
||||
//TODO:maybe add this two in a single transactionnal saga
|
||||
this.props.updateUserRequest(data)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
validate(data,champ, type){
|
||||
console.log("valdiate")
|
||||
console.log(champ);
|
||||
const errors = {};
|
||||
errors.message ="";
|
||||
//if (!Validator.isEmail(data.currentJob)) errors.message += "Le poste actuel doit etre un email\n";
|
||||
if (type=="global" || (champ=="firstname" && data.firstname=="")) errors.message += "Veuillez saisir votre prénom<br />";
|
||||
if (type=="global" || (champ=="lastname" && data.lastname=="")) errors.message += " Veuillez saisir votre nom<br />";
|
||||
if (type=="global" || (champ=="phone" && data.phone=="")) errors.message += "Veuillez saisir un numéro de téléphone<br />";
|
||||
if (type=="global" || (champ=="currentJob" && data.currentJob=="")) errors.message += "Veuillez saisir votre intitulé de poste actuel ou poste recherché<br />";
|
||||
if (type=="global" || (champ=="zipCode" && (data.zipCode && data.zipCode!="") && !Validator.isPostalCode(data.zipCode, "FR"))) errors.message += "Le code postal n'est pas correct<br />";
|
||||
// if ((data.website && data.website!="") && !Validator.isURL(data.website)) errors.message += " Veuillez ajouter un site internet avec une url valide<br />";
|
||||
if (!Validator.isMobilePhone(data.phone, "fr-FR") && !Validator.isNumeric(data.phone, "fr-FR")) errors.message += "Le téléphone n'est pas correct<br />";
|
||||
//console.log(errors.email);
|
||||
|
||||
return errors;
|
||||
};
|
||||
AfficherErreurs() {
|
||||
if (!this.state.errors || !this.state.errors.message){
|
||||
return "";
|
||||
}else if (this.state.errors.length != 0 && this.state.errors.message!="") {
|
||||
return (
|
||||
<Alert severity="error">
|
||||
{ ReactHtmlParser(this.state.errors.message)}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
AfficherSuccess() {
|
||||
// if (this.state.success && this.state.success.length != 0 && this.state.success.message != "") {
|
||||
// return (
|
||||
// <Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
// <Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
// {ReactHtmlParser(this.state.success.message)}
|
||||
// </Alert>
|
||||
// </Snackbar>
|
||||
|
||||
|
||||
// );
|
||||
|
||||
// }
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
|
||||
console.log("inputFilesystemChange");
|
||||
var file = e.target.files[0]
|
||||
this.setState({ picture: file })
|
||||
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
this.props.updateUserPictureRequest(data)
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { classes, user } = this.props
|
||||
const logoUrl = user.picture;
|
||||
function refresh() {
|
||||
document
|
||||
.location
|
||||
.reload(true);
|
||||
|
||||
}
|
||||
return (
|
||||
<section className={classes.container}>
|
||||
<form className={classes.form}
|
||||
autoComplete="off" focused="true" name="monForm" ref="formToSubmit">
|
||||
{/* {!!logoUrl && <Avatar className={classes.logo}
|
||||
classes={{ img: classes.MuiAvatarImg }}
|
||||
src={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentUrl + logoUrl} alt="candidatLogo" />} */}
|
||||
|
||||
{/* {!!user.pictureLoading && <Loader />}
|
||||
{!!!user.pictureLoading && !!!logoUrl &&
|
||||
(<Fragment><input
|
||||
type="file" accept="image/*" capture="filesystem"
|
||||
className={classes.input}
|
||||
style={{ display: 'none' }}
|
||||
id="raised-button-file"
|
||||
multiple
|
||||
type="file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="raised-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/static/images/default/account-avatar-default.svg'
|
||||
className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma photo de profil
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={classes.InputKeyboardArrowRightIcon} />
|
||||
</Button>
|
||||
</label></Fragment>)
|
||||
} */}
|
||||
{this.AfficherErreurs()}
|
||||
{this.AfficherSuccess()}
|
||||
|
||||
|
||||
<TextField
|
||||
name="firstname"
|
||||
required
|
||||
id="outlined-required"
|
||||
label="Prénom"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.firstname}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="lastname"
|
||||
required
|
||||
id="outlined-required"
|
||||
label="Nom"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.lastname}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
name="email"
|
||||
id="outlined"
|
||||
label="E-mail"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.email}
|
||||
onChange={this.handleChange}
|
||||
type="mail"
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="phone"
|
||||
id="outlined"
|
||||
label="Téléphone"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.phone ? this.state.phone: ''}
|
||||
onChange={this.handleChange}
|
||||
type="tel"
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<TextField
|
||||
name="currentJob"
|
||||
id="outlined"
|
||||
label="Poste actuel"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.currentJob ? this.state.currentJob : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="address1"
|
||||
id="outlined"
|
||||
label="Adresse"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.address1 ? this.state.address1 : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="address2"
|
||||
id="outlined"
|
||||
label="Adresse complémentaire"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.address2 ? this.state.address2 : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
<div className={classes.container}>
|
||||
<TextField
|
||||
name="zipCode"
|
||||
id="outlined"
|
||||
label="Code postal"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.zipCode ? this.state.zipCode : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="city"
|
||||
id="outlined"
|
||||
label="Ville"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.city ? this.state.city : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="country"
|
||||
id="outlined"
|
||||
label="Pays"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.country ? this.state.country : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TextField
|
||||
name="linkedin"
|
||||
id="outlined"
|
||||
label="Linkedin"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://www.linkedin.com/in/"
|
||||
value={this.state.linkedin ? this.state.linkedin : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="twitter"
|
||||
id="outlined"
|
||||
label="Twitter"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://twitter.com/.."
|
||||
value={this.state.twitter ? this.state.twitter : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="website"
|
||||
id="outlined"
|
||||
label="Site internet"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://monsite.fr"
|
||||
value={this.state.website ? this.state.website : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
|
||||
className={classes.button}>
|
||||
Enregistrer
|
||||
</Button>
|
||||
</form>
|
||||
{/* <div id="F" className={classes.foot}>
|
||||
<Button variant="contained" className={classes.button + ' cypButtonSendApplication'} onClick={this.onSubmit}>Mettre à jour!</Button>
|
||||
</div> */}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, { updateUserRequest })(AccountEtape1));
|
||||
@@ -0,0 +1,362 @@
|
||||
import React, {Fragment} from 'react'
|
||||
import {connect} from "react-redux";
|
||||
import {makeStyles} from '@material-ui/styles';
|
||||
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import {Button, Typography} from '@material-ui/core';
|
||||
import dynamic from 'next/dynamic'
|
||||
import {withStyles} from '@material-ui/core/styles'
|
||||
import {uploadMediaPres} from '../../actions/media'
|
||||
import {errorMessageSelector} from '../../reducers/media'
|
||||
import {fetchCompanyRequest} from '../../actions/companies'
|
||||
import {fetchCurrentUserRequest} from '../../actions/user'
|
||||
import VideoVimeo from '../atoms/VideoVimeo'
|
||||
import Router from 'next/router'
|
||||
import LoaderVideo from '../templates/loaderVideo'
|
||||
import Ar from "lodash/array"
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Container from '@material-ui/core/Container';
|
||||
import Hidden from '@material-ui/core/Hidden';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '100%',
|
||||
},
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
margin: theme.spacing(1),
|
||||
flexWrap: 'wrap',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
|
||||
recorderContainer: {
|
||||
//display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: '100%'
|
||||
},
|
||||
rootButton: {
|
||||
textTransform: 'inherit'
|
||||
},
|
||||
underlined: {
|
||||
textDecoration: 'underline'
|
||||
},
|
||||
textButton: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2)
|
||||
},
|
||||
videoPresentation: {
|
||||
width: "100%",
|
||||
height: "100%"
|
||||
},
|
||||
conseilButton: {
|
||||
color: "#ffffff",
|
||||
backgroundColor: "#25D89A",
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "100%",
|
||||
textAlign: "right",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: "#ffffff",
|
||||
backgroundColor: "#25D89A",
|
||||
}
|
||||
},
|
||||
captureButton: {
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: theme.spacing(5, 2),
|
||||
margin: theme.spacing(1),
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 4px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
importButton: {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "100%",
|
||||
textAlign: "right",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
}
|
||||
},
|
||||
InputKeyboardArrowDownIconBlank: {
|
||||
fontSize: '2.5em',
|
||||
color: "#ffffff",
|
||||
textAlign: "right"
|
||||
},
|
||||
InputKeyboardArrowDownIcon: {
|
||||
fontSize: '2.5em',
|
||||
color: "#1689FB",
|
||||
textAlign: "right"
|
||||
},
|
||||
buttons :{
|
||||
display: "inline-table",
|
||||
}
|
||||
});
|
||||
const Recorder = dynamic(() => import ('../organisms/Recorder'), {ssr: false})
|
||||
class Etape2 extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
activeStep: 0,
|
||||
data: {},
|
||||
openSnack: false,
|
||||
errors: {},
|
||||
success : {}
|
||||
};
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem('loginRedirect', window.location.pathname)
|
||||
|
||||
if (!!!localStorage.getItem('ttJWT')) {
|
||||
Router.push("/Login")
|
||||
} else
|
||||
this.setState({loading: false, firstname: this.props.user.firstname, videoPres: this.props.user.videoPres, video: this.props.user.presentation_video_id})
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
loading: nextProps.loading,
|
||||
openSnack: !!!_.isEmpty(nextProps.errors),
|
||||
errors: !!!nextProps.errors
|
||||
? {
|
||||
errors: {
|
||||
message: ""
|
||||
}
|
||||
}
|
||||
: nextProps.errors,
|
||||
videoPres: nextProps.videoPres,
|
||||
video: nextProps.video
|
||||
})
|
||||
//window.location.reload(false);
|
||||
if (nextProps.media.status === 'success') {
|
||||
const success = {};
|
||||
success.message ="Vidéo mise à jour";
|
||||
this.setState({ success });
|
||||
this.setActiveStep(1);
|
||||
}
|
||||
}
|
||||
|
||||
setActiveStep = (step) => {
|
||||
this.setState({activeStep: step})
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
this.uploadMediaPres(e)
|
||||
}
|
||||
|
||||
inputCamRecorderChange = (e) => {
|
||||
this.uploadMediaPres(e)
|
||||
}
|
||||
|
||||
uploadMediaPres = (e) => {
|
||||
var file = e.target.files[0]
|
||||
|
||||
const data = new FormData()
|
||||
data.append('upload', file)
|
||||
//this.setState({ videoPres: videoPres })
|
||||
|
||||
this
|
||||
.props
|
||||
.uploadMediaPres(data)
|
||||
}
|
||||
|
||||
AfficherSuccess() {
|
||||
if (!this.state.success || !this.state.success.message) {
|
||||
|
||||
} else if (this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
handleClose = (event, reason) => {
|
||||
this.setState({openSnack: false});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classes, company} = this.props;
|
||||
const {loading, activeStep} = this.state;
|
||||
let video;
|
||||
if (this.state.videoPres) {
|
||||
video = <VideoVimeo videoId={Ar.last(_.split(this.state.videoPres, '/'))} autoplay='1' classesOverride="videoPresentation"/>;
|
||||
} else {
|
||||
video = "";
|
||||
}
|
||||
return (
|
||||
<section className={classes.container}>
|
||||
<Fragment>
|
||||
{this.AfficherSuccess()}
|
||||
{ loading ? <LoaderVideo/> : <div></div> }
|
||||
|
||||
<div className={classes.root}>
|
||||
<Hidden xsUp>
|
||||
|
||||
</Hidden>
|
||||
<Container maxWidth="md">
|
||||
|
||||
<Grid container
|
||||
justify="center"
|
||||
alignItems="center"
|
||||
spacing={2}
|
||||
className={classes.buttons}>
|
||||
<Grid item xs={12} sm={12} md={12} lg={6} lg={6}>
|
||||
|
||||
|
||||
|
||||
{ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ?
|
||||
(
|
||||
<Fragment >
|
||||
<input
|
||||
type="file" accept="video/*" capture="camcorder"
|
||||
className={classes.input}
|
||||
style={{ display: 'none' }}
|
||||
id="record-button-file"
|
||||
multiple
|
||||
onChange={this.inputCamRecorderChange}
|
||||
/>
|
||||
<label htmlFor="record-button-file">
|
||||
<Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/static/images/capture.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
Je <span className={classes.underlined}>réalise</span> ma vidéo de présentation
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
</Fragment>
|
||||
):
|
||||
(
|
||||
|
||||
|
||||
<div className={classes.recorderContainer}>
|
||||
<Recorder uploader={this.props.uploadMediaPres} titreBouton="Remplacer ma vidéo"/>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={12} lg={6} xl={6}>
|
||||
<div>
|
||||
<label htmlFor="import-conseil">
|
||||
<Button
|
||||
component="span"
|
||||
className={classes.conseilButton}
|
||||
classes={{
|
||||
root: classes.rootButton}}
|
||||
onClick={() => Router.push(`/Conseils`)}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/conseils-talentstube.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
<span className={classes.underlined}>Comment</span> créer ma vidéo
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={classes.InputKeyboardArrowDownIconBlank}/>
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="file"
|
||||
accept="video/*"
|
||||
className={classes.input + ' cypButtonImportVid'}
|
||||
style={{display: 'none'}}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button
|
||||
component="span"
|
||||
className={classes.importButton}
|
||||
classes={{
|
||||
root: classes.rootButton}}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/Import.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma vidéo de présentation
|
||||
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={classes.InputKeyboardArrowDownIcon}/>
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</Grid>
|
||||
<Hidden xsUp>
|
||||
|
||||
</Hidden>
|
||||
|
||||
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
|
||||
<div className={classes.videoPresentation}>
|
||||
{video}
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Container>
|
||||
</div>
|
||||
{/* <div className={classes.textContainer}>
|
||||
|
||||
</div> */}
|
||||
|
||||
</Fragment>
|
||||
</section>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Etape2.getInitialProps = function (context) {
|
||||
|
||||
const {companyId} = context.query
|
||||
const {res} = context
|
||||
//TODO :really needed ?
|
||||
context
|
||||
.store
|
||||
.dispatch(fetchCurrentUserRequest())
|
||||
|
||||
if (!!companyId)
|
||||
context.store.dispatch(fetchCompanyRequest(companyId))
|
||||
|
||||
return {}; //leave this please
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
||||
return {
|
||||
loading: !!state.media.loading,
|
||||
media: state.media,
|
||||
offre: state.ad,
|
||||
//errors: errorMessageSelector(state),
|
||||
user: state.user,
|
||||
company: state.company
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {fetchCurrentUserRequest, fetchCompanyRequest, uploadMediaPres})(Etape2));
|
||||
@@ -0,0 +1,257 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from "react-redux";
|
||||
import { fetchCurrentUserRequest } from '../../actions/user'
|
||||
import { fetchCompanyRequest } from '../../actions/companies'
|
||||
import { uploadMediaCv } from '../../actions/media'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import { Button, Typography, Divider, Hidden } from '@material-ui/core';
|
||||
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import LoaderVideo from '../../components/templates/loaderVideo'
|
||||
import Snack from '../../components/atoms/snack';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import ReactHtmlParser from 'react-html-parser';
|
||||
import getConfig from 'next/config'
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
margin: theme.spacing(1),
|
||||
},
|
||||
rootButton: {
|
||||
textTransform: 'inherit',
|
||||
},
|
||||
underlined: {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
textButton: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
InputKeyboardArrowDownIcon: {
|
||||
fontSize: '2.5em',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
importButton: {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "370px",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
class Etape3 extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
openSnack: false,
|
||||
cv:false,
|
||||
errors: {},
|
||||
success : {}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem('loginRedirect', window.location.pathname)
|
||||
|
||||
if(!!!localStorage.getItem('ttJWT'))
|
||||
{
|
||||
Router.push("/Login")
|
||||
}
|
||||
else
|
||||
this.setState({
|
||||
loading: false,
|
||||
cvLink: this.props.user.cv
|
||||
})
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
cvLink: nextProps.cvLink,
|
||||
loading: nextProps.loading,
|
||||
openSnack: !!!_.isEmpty(nextProps.errors),
|
||||
errors: !!!nextProps.errors ? { errors: { message: "" } } : nextProps.errors,
|
||||
})
|
||||
this.state.cvLink = nextProps.cvLink;
|
||||
if (nextProps.loading) {
|
||||
const success = {};
|
||||
success.message ="CV mis à jour";
|
||||
console.log("CV mis à jour!!!")
|
||||
if(this.state.cvLink) console.log(this.state.cvLink)
|
||||
this.setState({ success });
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
this.uploadMediaCv(e)
|
||||
}
|
||||
|
||||
uploadMediaCv = (e) => {
|
||||
var file = e.target.files[0]
|
||||
|
||||
const data = new FormData()
|
||||
data.append('upload', file)
|
||||
|
||||
this.props.uploadMediaCv(data)
|
||||
}
|
||||
|
||||
AfficherSuccess() {
|
||||
if (!this.state.success || !this.state.success.message) {
|
||||
console.log("Erreur Upload CV");
|
||||
return "";
|
||||
} else if (this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
AfficherLienCv() {
|
||||
console.log("afficher lien");
|
||||
if (this.state.cvLink !="") {
|
||||
|
||||
return (
|
||||
|
||||
<Fragment>
|
||||
<Hidden> </Hidden>
|
||||
<Hidden> </Hidden>
|
||||
|
||||
<Hidden> </Hidden>
|
||||
<Hidden> </Hidden>
|
||||
<Card variant="" style={{
|
||||
width:370+"px",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
marginLeft : '10px',
|
||||
marginTop:'10px'
|
||||
|
||||
}}>
|
||||
<Hidden> </Hidden>
|
||||
<CardActions>
|
||||
<Button size="small">MON CV</Button>
|
||||
</CardActions>
|
||||
<CardContent>
|
||||
<Typography >
|
||||
<a href={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentCv + this.state.cvLink}
|
||||
target="_blank"
|
||||
style={{
|
||||
color:'#1689FB',
|
||||
'&:hover': {
|
||||
color: '#1689FB',
|
||||
},
|
||||
fontWeight: '700',
|
||||
fontSize: '1em',
|
||||
}}
|
||||
>
|
||||
Visualiser mon CV
|
||||
</a>
|
||||
<br />
|
||||
{/* <a href="https://www.permatheque.fr/PDF/mansobufukuoka-larevolutiondunseulbrindepaille.pdf" target="_blank">lien</a> */}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
</Card>
|
||||
</Fragment>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, company } = this.props;
|
||||
const { loading } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
{ loading ?
|
||||
<LoaderVideo /> :
|
||||
<Fragment>
|
||||
{this.AfficherSuccess()}
|
||||
|
||||
<input
|
||||
type="file"
|
||||
accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document, .pdf, .odt"
|
||||
className={classes.input+' cypButtonImportVid'}
|
||||
style={{ display: 'none' }}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/statique/images/Import-cv-candidat.svg' className={classes.iconButton} />
|
||||
<Typography className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> mon CV
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/>
|
||||
</Button>
|
||||
|
||||
</label>
|
||||
<Hidden> </Hidden>
|
||||
{this.AfficherLienCv()}
|
||||
|
||||
</Fragment>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Etape3.getInitialProps = function (context) {
|
||||
|
||||
const { adId, companyId } = context.query
|
||||
const {res} = context
|
||||
//TODO :really needed ?
|
||||
context.store.dispatch(fetchCurrentUserRequest())
|
||||
|
||||
if(!!adId)
|
||||
context.store.dispatch(fetchJobRequest(adId))
|
||||
else if(!!companyId)
|
||||
context.store.dispatch(fetchCompanyRequest(companyId))
|
||||
|
||||
return {};//leave this please
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
// console.log("mapStateToProps")
|
||||
// console.log(state.loading)
|
||||
// console.log(state.user)
|
||||
// console.log(state.media.message)
|
||||
return {
|
||||
user: state.user ,
|
||||
cvLink : state.media.message,
|
||||
loading: !!state.media.loading,
|
||||
cv : true,
|
||||
//errors: errorMessageSelector(state),
|
||||
user: state.user,
|
||||
company: state.company
|
||||
};
|
||||
}
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchCurrentUserRequest, fetchCompanyRequest, uploadMediaCv })(Etape3));
|
||||
@@ -0,0 +1,485 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import clsx from 'clsx';
|
||||
// import AccountStep from "../../components/organisms/AccountStep";
|
||||
import AccountEtape1 from '../organisms/AccountEtape1';
|
||||
import AccountEtape2 from '../organisms/AccountEtape2';
|
||||
import AccountEtape3 from '../organisms/AccountEtape3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
// import Switch from '@material-ui/core/Switch';
|
||||
import PhoneIcon from '@material-ui/icons/Phone';
|
||||
import MailIcon from '@material-ui/icons/Mail';
|
||||
import PublicIcon from '@material-ui/icons/Public';
|
||||
import DuoIcon from '@material-ui/icons/Duo';
|
||||
import LinkedInIcon from '@material-ui/icons/LinkedIn';
|
||||
import Facebook from '@material-ui/icons/Facebook';
|
||||
// import FormGroup from '@material-ui/core/FormGroup'; import FormControlLabel
|
||||
// from '@material-ui/core/FormControlLabel'; import FormControl from
|
||||
// '@material-ui/core/FormControl';
|
||||
import {updateUserRequest, updateUserPictureRequest} from '../../actions/user'
|
||||
import {makeStyles} from '@material-ui/styles';
|
||||
import {connect} from 'react-redux'
|
||||
import getConfig from 'next/config'
|
||||
import BottomNavigation from '@material-ui/core/BottomNavigation';
|
||||
// import BottomNavigationAction from
|
||||
// '@material-ui/core/BottomNavigationAction';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
// import FavoriteIcon from '@material-ui/icons/Favorite'; import LocationOnIcon
|
||||
// from '@material-ui/icons/LocationOn';
|
||||
|
||||
import Box from '@material-ui/core/Box';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
Avatar,
|
||||
Typography,
|
||||
Divider,
|
||||
Button,
|
||||
LinearProgress,
|
||||
Stepper,
|
||||
Step,
|
||||
StepLabel,
|
||||
StepContent,
|
||||
StepButton,
|
||||
Paper,
|
||||
Grid
|
||||
} from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '100%'
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important
|
||||
},
|
||||
stickToBottom: {
|
||||
width: '100%',
|
||||
position: 'fixed',
|
||||
bottom: 0
|
||||
}
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {},
|
||||
details: {
|
||||
display: 'flex'
|
||||
},
|
||||
avatar: {
|
||||
marginLeft: 'auto',
|
||||
height: 110,
|
||||
width: 100,
|
||||
flexShrink: 0,
|
||||
flexGrow: 0
|
||||
},
|
||||
progress: {
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
information: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
[
|
||||
theme
|
||||
.breakpoints
|
||||
.up('md')
|
||||
]: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: theme.spacing(7, 7)
|
||||
},
|
||||
'& a': {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
},
|
||||
texteBlanc: {
|
||||
color: "#fff"
|
||||
},
|
||||
uploadButton: {
|
||||
marginRight: theme.spacing(2)
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
actionsContainer: {
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
resetContainer: {
|
||||
padding: theme.spacing(3)
|
||||
}
|
||||
}));
|
||||
|
||||
function getSteps() {
|
||||
return ['Informations personnelles', 'Vidéo de présentation', 'Expériences professionnelles'];
|
||||
}
|
||||
|
||||
function getStepContent(step) {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <AccountEtape1 ></AccountEtape1>;
|
||||
case 1:
|
||||
return <AccountEtape2></AccountEtape2>;
|
||||
case 2:
|
||||
return <AccountEtape3></AccountEtape3>;
|
||||
default:
|
||||
return 'Unknown step';
|
||||
}
|
||||
}
|
||||
|
||||
const AccountProfile = props => {
|
||||
const {
|
||||
className,
|
||||
user,
|
||||
...rest
|
||||
} = props;
|
||||
const logoUrl = user.picture;
|
||||
const classes = useStyles();
|
||||
|
||||
// const user = { name: 'Laurent Laniau', city: 'Questembert', country:
|
||||
// 'France', timezone: '', avatar: '/images/avatars/avatar_11.png' };
|
||||
const {publicRuntimeConfig} = getConfig()
|
||||
const [activeStep,
|
||||
setActiveStep] = React.useState(0);
|
||||
const [completed,
|
||||
setCompleted] = React.useState(new Set());
|
||||
const [skipped,
|
||||
setSkipped] = React.useState(new Set());
|
||||
const [state,
|
||||
setState] = React.useState({checkedA: true, checkedB: true});
|
||||
const steps = getSteps();
|
||||
|
||||
const totalSteps = () => {
|
||||
return getSteps().length;
|
||||
};
|
||||
|
||||
const isStepOptional = (step) => {
|
||||
return step === 4;
|
||||
};
|
||||
|
||||
const handleSkip = () => {
|
||||
if (!isStepOptional(activeStep)) {
|
||||
// You probably want to guard against something like this it should never occur
|
||||
// unless someone's actively trying to break something.
|
||||
throw new Error("You can't skip a step that isn't optional.");
|
||||
}
|
||||
|
||||
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
||||
setSkipped((prevSkipped) => {
|
||||
const newSkipped = new Set(prevSkipped.values());
|
||||
newSkipped.add(activeStep);
|
||||
return newSkipped;
|
||||
});
|
||||
};
|
||||
|
||||
const skippedSteps = () => {
|
||||
return skipped.size;
|
||||
};
|
||||
|
||||
const completedSteps = () => {
|
||||
return completed.size;
|
||||
};
|
||||
|
||||
const allStepsCompleted = () => {
|
||||
return completedSteps() === totalSteps() - skippedSteps();
|
||||
};
|
||||
|
||||
const isLastStep = () => {
|
||||
return activeStep === totalSteps() - 1;
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const newActiveStep = isLastStep() && !allStepsCompleted()
|
||||
? // It's the last step, but not all steps have been completed
|
||||
// find the first step that has been completed
|
||||
steps.findIndex((step, i) => !completed.has(i))
|
||||
: activeStep + 1;
|
||||
|
||||
setActiveStep(newActiveStep);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
||||
};
|
||||
|
||||
const handleStep = (step) => () => {
|
||||
console.log("step");
|
||||
console.log(step);
|
||||
setActiveStep(step);
|
||||
};
|
||||
|
||||
const handleComplete = () => {
|
||||
const newCompleted = new Set(completed);
|
||||
newCompleted.add(activeStep);
|
||||
setCompleted(newCompleted);
|
||||
|
||||
/**
|
||||
* Sigh... it would be much nicer to replace the following if conditional with
|
||||
* `if (!this.allStepsComplete())` however state is not set when we do this,
|
||||
* thus we have to resort to not being very DRY.
|
||||
*/
|
||||
if (completed.size !== totalSteps() - skippedSteps()) {
|
||||
handleNext();
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setActiveStep(0);
|
||||
setCompleted(new Set());
|
||||
setSkipped(new Set());
|
||||
};
|
||||
|
||||
const isStepSkipped = (step) => {
|
||||
return skipped.has(step);
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
setState({
|
||||
...state,
|
||||
[event.target.name]: event.target.checked
|
||||
});
|
||||
};
|
||||
|
||||
function isStepComplete(step) {
|
||||
return completed.has(step);
|
||||
}
|
||||
function refresh() {
|
||||
document
|
||||
.location
|
||||
.reload(true);
|
||||
console.log("refresh")
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
direction="row"
|
||||
justify="space-between"
|
||||
alignItems="flex-start">
|
||||
<Grid item lg={3} md={6} xl={4} xs={12}>
|
||||
<Card {...rest} className={clsx(classes.root, className)}>
|
||||
<CardContent>
|
||||
<div id="fb-root"></div>
|
||||
<script
|
||||
async
|
||||
defer
|
||||
crossorigin="anonymous"
|
||||
src="https://connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v8.0&appId=2332071840142634&autoLogAppEvents=1"
|
||||
nonce="O28M4TTm"></script>
|
||||
<div className={classes.details}>
|
||||
<div>
|
||||
<Typography gutterBottom variant="h5">
|
||||
{user.lastname}
|
||||
{user.firstname}
|
||||
<a href="#" onClick={refresh}><RefreshIcon className={classes.menuButton}/></a>
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.locationText}
|
||||
color="textSecondary"
|
||||
variant="body1">
|
||||
<MailIcon className={classes.menuButton}/>
|
||||
: {user.email}<br/>
|
||||
<PhoneIcon className={classes.menuButton}/>
|
||||
: {user.phone}<br/>
|
||||
<LinkedInIcon className={classes.menuButton}/>
|
||||
: {(user.linkedin && user.linkedin != '' && user.linkedin != 'null')
|
||||
? <a href={user.linkedin} target="_blank">Lien sur mon linkedIn</a>
|
||||
: 'Non renseigné'}<br/>
|
||||
<PublicIcon className={classes.menuButton}/>
|
||||
: {(user.website && user.website != '' && user.website != 'null')
|
||||
? <a href={user.website} target="_blank">Lien sur mon site</a>
|
||||
: 'Non renseigné'}<br/>
|
||||
|
||||
|
||||
|
||||
</Typography>
|
||||
|
||||
</div>
|
||||
{/* <Avatar
|
||||
className={classes.avatar}
|
||||
src={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentUrl + logoUrl}/> */}
|
||||
</div>
|
||||
<div>
|
||||
<Box m={3}/>
|
||||
<Divider/>
|
||||
<Box m={3}/>
|
||||
<Typography
|
||||
className={classes.locationText}
|
||||
color="textSecondary"
|
||||
variant="body1">
|
||||
|
||||
<DuoIcon className={classes.menuButton}/>
|
||||
: {(user.alias && user.alias != '' && user.alias != 'null')
|
||||
? <a
|
||||
href={publicRuntimeConfig.cvThequeUrl + "/talent/" + user.alias}
|
||||
target="_blank">Voir mon profil TalentsTube
|
||||
</a>
|
||||
: 'Non renseigné'}<br/>
|
||||
<div
|
||||
class="fb-share-button"
|
||||
data-href={publicRuntimeConfig.cvThequeUrl + "/talent/" + user.alias}
|
||||
data-layout="button_count"
|
||||
data-size="small">
|
||||
|
||||
<Facebook className={classes.menuButton}/>
|
||||
:
|
||||
<a
|
||||
target="_blank"
|
||||
href={"https://www.facebook.com/sharer/sharer.php?u=" + publicRuntimeConfig.cvThequeUrl + "/talent/" + user.alias + "%2F&src=sdkpreparse"}
|
||||
class="fb-xfbml-parse-ignore"> Partager mon profil
|
||||
</a>
|
||||
</div>
|
||||
</Typography>
|
||||
</div>
|
||||
{/* <div className={classes.progress}>
|
||||
<Typography variant="body1">Etat du Profil: 70%</Typography>
|
||||
<LinearProgress value={70} variant="determinate"/>
|
||||
</div> */}
|
||||
|
||||
</CardContent>
|
||||
<Box m={2}/>
|
||||
<Divider/>
|
||||
<Box m={2}/>
|
||||
<div className={classes.information}>
|
||||
<Typography className={classes.texteBlanc} align="left"></Typography>
|
||||
</div>
|
||||
{/* <CardActions>
|
||||
<Button className={classes.uploadButton} color="primary" variant="text">
|
||||
Remplacer une photo de profil
|
||||
</Button>
|
||||
<Button variant="text">Supprimer photo de profil</Button>
|
||||
</CardActions> */}
|
||||
<Box m={1}/>
|
||||
<Divider/>
|
||||
{/* <CardContent>
|
||||
<Typography variant="body1"></Typography>
|
||||
<FormControlLabel
|
||||
value="end"
|
||||
control={< Switch checked = {
|
||||
state.checkedA
|
||||
}
|
||||
onChange = {
|
||||
handleChange
|
||||
}
|
||||
name = "checkedA" color = "primary" />}
|
||||
label="Je souhaite afficher mon profil sur la CV Vidéothèque Talents Tube"
|
||||
labelPlacement="start"/>
|
||||
|
||||
</CardContent> */}
|
||||
|
||||
|
||||
|
||||
<CardActions>
|
||||
|
||||
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
|
||||
{steps.map((label, index) => {
|
||||
const stepProps = {};
|
||||
const buttonProps = {};
|
||||
if (isStepOptional(index)) {
|
||||
buttonProps.optional = <Typography variant="caption">Optional</Typography>;
|
||||
}
|
||||
if (isStepSkipped(index)) {
|
||||
stepProps.completed = false;
|
||||
}
|
||||
return (
|
||||
<Step key={label} className={classes.actionsContainer} {...stepProps}>
|
||||
<StepButton
|
||||
onClick={handleStep(index)}
|
||||
completed={isStepComplete(index)}
|
||||
{...buttonProps}>
|
||||
{label}
|
||||
</StepButton>
|
||||
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
</Stepper>
|
||||
</CardActions>
|
||||
<Divider/>
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
|
||||
{/* {isStepOptional(activeStep) && !completed.has(activeStep) && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSkip}
|
||||
className={classes.button}
|
||||
>
|
||||
Skip
|
||||
</Button>
|
||||
)} */}
|
||||
|
||||
{/* {activeStep !== steps.length &&
|
||||
(completed.has(activeStep) ? (
|
||||
<Typography variant="caption" className={classes.completed}>
|
||||
Step {activeStep + 1} already completed
|
||||
</Typography>
|
||||
) : (
|
||||
<Button variant="contained" color="primary" onClick={handleComplete}>
|
||||
{completedSteps() === totalSteps() - 1 ? 'Finish' : 'Complete Step'}
|
||||
</Button>
|
||||
))} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<Box m={2}/>
|
||||
<CardContent>
|
||||
<BottomNavigation className={classes.stickToBottom}>
|
||||
<Button
|
||||
disabled={activeStep === 0}
|
||||
onClick={handleBack}
|
||||
className={classes.button}>
|
||||
Etape précédente
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleNext}
|
||||
className={classes.button}>
|
||||
Etape suivante
|
||||
</Button>
|
||||
{/* <BottomNavigationAction label="Recents" icon={< RestoreIcon />}/>
|
||||
<BottomNavigationAction label="Favorites" icon={< FavoriteIcon />}/>
|
||||
<BottomNavigationAction label="Nearby" icon={< LocationOnIcon />}/> */}
|
||||
</BottomNavigation>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
</Grid>
|
||||
<Grid item lg={9} md={6} xl={8} xs={12}>
|
||||
{getStepContent(activeStep)}
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
AccountProfile.propTypes = {
|
||||
className: PropTypes.string
|
||||
};
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
user: state.user,
|
||||
loading: !!state.user.loading,
|
||||
errors: state.user.errors || ownProps.errors
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {updateUserRequest})(AccountProfile))
|
||||
@@ -0,0 +1,306 @@
|
||||
import React, {Fragment} from 'react';
|
||||
import {Hidden} from '@material-ui/core';
|
||||
import PropTypes from 'prop-types';
|
||||
import clsx from 'clsx';
|
||||
// import AccountStep from "../../components/organisms/AccountStep";
|
||||
import AccountEtape1 from './AccountEtape1';
|
||||
import AccountEtape2 from './AccountEtape2';
|
||||
import AccountEtape3 from './AccountEtape3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
// import Switch from '@material-ui/core/Switch';
|
||||
import PhoneIcon from '@material-ui/icons/Phone';
|
||||
import MailIcon from '@material-ui/icons/Mail';
|
||||
import PublicIcon from '@material-ui/icons/Public';
|
||||
import DuoIcon from '@material-ui/icons/Duo';
|
||||
import LinkedInIcon from '@material-ui/icons/LinkedIn';
|
||||
import Facebook from '@material-ui/icons/Facebook';
|
||||
// import FormGroup from '@material-ui/core/FormGroup'; import FormControlLabel
|
||||
// from '@material-ui/core/FormControlLabel'; import FormControl from
|
||||
// '@material-ui/core/FormControl';
|
||||
import {updateUserRequest, updateUserPictureRequest} from '../../actions/user'
|
||||
import {makeStyles} from '@material-ui/styles';
|
||||
import {connect} from 'react-redux'
|
||||
import getConfig from 'next/config'
|
||||
import Router from 'next/router'
|
||||
|
||||
import BottomNavigation from '@material-ui/core/BottomNavigation';
|
||||
// import BottomNavigationAction from
|
||||
// '@material-ui/core/BottomNavigationAction';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
// import FavoriteIcon from '@material-ui/icons/Favorite'; import LocationOnIcon
|
||||
// from '@material-ui/icons/LocationOn';
|
||||
|
||||
import Box from '@material-ui/core/Box';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
Avatar,
|
||||
Typography,
|
||||
Divider,
|
||||
Button,
|
||||
LinearProgress,
|
||||
Stepper,
|
||||
Step,
|
||||
StepLabel,
|
||||
StepContent,
|
||||
StepButton,
|
||||
Paper,
|
||||
Grid
|
||||
} from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '100%'
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important
|
||||
},
|
||||
stickToBottom: {
|
||||
width: '100%',
|
||||
position: 'fixed',
|
||||
bottom: 0
|
||||
}
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {},
|
||||
details: {
|
||||
display: 'flex'
|
||||
},
|
||||
avatar: {
|
||||
marginLeft: 'auto',
|
||||
height: 110,
|
||||
width: 100,
|
||||
flexShrink: 0,
|
||||
flexGrow: 0
|
||||
},
|
||||
progress: {
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
information: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
[
|
||||
theme
|
||||
.breakpoints
|
||||
.up('md')
|
||||
]: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: theme.spacing(7, 7)
|
||||
},
|
||||
'& a': {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
},
|
||||
texteBlanc: {
|
||||
color: "#fff"
|
||||
},
|
||||
uploadButton: {
|
||||
marginRight: theme.spacing(2)
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
actionsContainer: {
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
resetContainer: {
|
||||
padding: theme.spacing(3)
|
||||
},
|
||||
iconButton:{
|
||||
marginTop: "50px",
|
||||
|
||||
[theme.breakpoints.down('md')]: {
|
||||
marginTop: "50px",
|
||||
|
||||
},
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginTop: theme.spacing(4),
|
||||
marginBottom: theme.spacing(2),
|
||||
padding: theme.spacing(1.2, 1),
|
||||
borderRadius: '3px',
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important,
|
||||
},
|
||||
title:{
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '1.625em',
|
||||
fontWeight: '600',
|
||||
padding: theme.spacing(3, 0),
|
||||
},
|
||||
texteEtape:{
|
||||
fontSize: '1em',
|
||||
fontWeight: '300',
|
||||
|
||||
},
|
||||
conteneur:{
|
||||
width:'400px',
|
||||
},
|
||||
tabContainer:{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems:'center',
|
||||
textAlign:'center',
|
||||
align:'center',
|
||||
alignSelf:'center',
|
||||
},
|
||||
|
||||
}));
|
||||
|
||||
const AccountProfile = props => {
|
||||
const {
|
||||
className,
|
||||
user,
|
||||
...rest
|
||||
} = props;
|
||||
const logoUrl = user.picture;
|
||||
const classes = useStyles();
|
||||
|
||||
// const user = { name: 'Laurent Laniau', city: 'Questembert', country:
|
||||
// 'France', timezone: '', avatar: '/images/avatars/avatar_11.png' };
|
||||
const {publicRuntimeConfig} = getConfig()
|
||||
|
||||
return (
|
||||
<Fragment >
|
||||
<div className={classes.tabContainer}>
|
||||
<div className={classes.conteneur}>
|
||||
<Typography gutterBottom align="center" >
|
||||
<span className={classes.title}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/inscription/candidature-video-envoyee.svg'
|
||||
className={classes.iconButton}/>
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center" >
|
||||
<span className={classes.title}>Bravo !<br></br>
|
||||
Votre candidature a été envoyée
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center" className={classes.conteneur}>
|
||||
<div className={classes.texteEtape}>
|
||||
Pour suivre l’état d’avancement de vos candidatures, rendez-vous sur votre espace <b>Mon compte</b>.
|
||||
</div>
|
||||
</Typography>
|
||||
|
||||
|
||||
<Typography gutterBottom align="center" className={classes.text}>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
classes={{ root: classes.rootButton }}
|
||||
onClick={() => Router.push('/Candidatures')}
|
||||
>
|
||||
Accéder à Mon compte
|
||||
</Button>
|
||||
|
||||
</Typography>
|
||||
{/* <section className={classes.bottomContainer}>
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
classes={{ root: classes.rootButton }}
|
||||
onClick={() => Router.push('/Login')}
|
||||
>
|
||||
Connexion
|
||||
</Button>
|
||||
</section> */}
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
// <Grid
|
||||
// container
|
||||
// spacing={4}
|
||||
// direction="row"
|
||||
// justify="space-between"
|
||||
// alignItems="flex-start">
|
||||
|
||||
// <Grid item lg={9} md={6} xl={8} xs={12}>
|
||||
// <Fragment>
|
||||
// <Hidden> </Hidden>
|
||||
// <Hidden> </Hidden>
|
||||
|
||||
// <Card
|
||||
// variant="outlined"
|
||||
// style={{
|
||||
// width: 420 + "px",
|
||||
// textAlign:"center"
|
||||
// }}>
|
||||
// <CardActions></CardActions>
|
||||
// <CardContent>
|
||||
// <Typography>
|
||||
// Tu n'as pas tout dit dans ta vidéo?<br/>
|
||||
// Pour mettre toutes les chances de ton côté,
|
||||
// <b> dépose ton CV old school (format pdf, word)!</b>
|
||||
// </Typography>
|
||||
// </CardContent>
|
||||
|
||||
// </Card>
|
||||
// <Hidden> </Hidden>
|
||||
// <Card
|
||||
// variant="outlined"
|
||||
// style={{
|
||||
// width: 420 + "px",
|
||||
// textAlign:"center"
|
||||
// }}>
|
||||
// <CardContent>
|
||||
// <AccountEtape3></AccountEtape3>
|
||||
// </CardContent>
|
||||
// </Card>
|
||||
// <Hidden> </Hidden>
|
||||
// <Hidden> </Hidden>
|
||||
// <Card
|
||||
// variant="outlined"
|
||||
// style={{
|
||||
// width: 420 + "px",
|
||||
// textAlign:"center"
|
||||
// }}>
|
||||
// <CardContent>
|
||||
|
||||
// <Button
|
||||
// variant="contained"
|
||||
// color="primary"
|
||||
// onClick={() => Router.push(`/Candidatures`)}
|
||||
// className={classes.button}>
|
||||
// Voir mes candidatures
|
||||
// </Button>
|
||||
// </CardContent>
|
||||
// </Card>
|
||||
// </Fragment>
|
||||
|
||||
// </Grid>
|
||||
// <Grid item lg={3} md={6} xl={4} xs={12}></Grid>
|
||||
|
||||
// </Grid>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
AccountProfile.propTypes = {
|
||||
className: PropTypes.string
|
||||
};
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
user: state.user,
|
||||
loading: !!state.user.loading,
|
||||
errors: state.user.errors || ownProps.errors
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {updateUserRequest})(AccountProfile))
|
||||
@@ -0,0 +1,147 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Stepper from '@material-ui/core/Stepper';
|
||||
import Step from '@material-ui/core/Step';
|
||||
import StepButton from '@material-ui/core/StepButton';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import AccountEtape1 from '../organisms/AccountEtape1';
|
||||
import AccountEtape2 from '../organisms/AccountEtape2';
|
||||
import AccountEtape3 from '../organisms/AccountEtape3';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
button: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
completed: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
instructions: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
function getSteps() {
|
||||
return ['Informations personnelles', 'Vidéo de présentation', 'Expériences professionnelles'];
|
||||
}
|
||||
|
||||
function getStepContent(step) {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <AccountEtape1 ></AccountEtape1>;
|
||||
case 1:
|
||||
return <AccountEtape2></AccountEtape2>;
|
||||
case 2:
|
||||
return <AccountEtape3></AccountEtape3>;
|
||||
default:
|
||||
return 'Unknown step';
|
||||
}
|
||||
}
|
||||
|
||||
export default function HorizontalNonLinearStepper() {
|
||||
const classes = useStyles();
|
||||
const [activeStep, setActiveStep] = React.useState(0);
|
||||
const [completed, setCompleted] = React.useState({});
|
||||
const steps = getSteps();
|
||||
|
||||
const totalSteps = () => {
|
||||
return steps.length;
|
||||
};
|
||||
|
||||
const completedSteps = () => {
|
||||
return Object.keys(completed).length;
|
||||
};
|
||||
|
||||
const isLastStep = () => {
|
||||
return activeStep === totalSteps() - 1;
|
||||
};
|
||||
|
||||
const allStepsCompleted = () => {
|
||||
return completedSteps() === totalSteps();
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const newActiveStep =
|
||||
isLastStep() && !allStepsCompleted()
|
||||
? // It's the last step, but not all steps have been completed,
|
||||
// find the first step that has been completed
|
||||
steps.findIndex((step, i) => !(i in completed))
|
||||
: activeStep + 1;
|
||||
setActiveStep(newActiveStep);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
||||
};
|
||||
|
||||
const handleStep = (step) => () => {
|
||||
setActiveStep(step);
|
||||
};
|
||||
|
||||
const handleComplete = () => {
|
||||
const newCompleted = completed;
|
||||
newCompleted[activeStep] = true;
|
||||
setCompleted(newCompleted);
|
||||
handleNext();
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setActiveStep(0);
|
||||
setCompleted({});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Stepper alternativeLabel nonLinear activeStep={activeStep}>
|
||||
{steps.map((label, index) => (
|
||||
<Step key={label}>
|
||||
<StepButton onClick={handleStep(index)} completed={completed[index]}>
|
||||
{label}
|
||||
</StepButton>
|
||||
</Step>
|
||||
))}
|
||||
</Stepper>
|
||||
<div>
|
||||
{allStepsCompleted() ? (
|
||||
<div>
|
||||
{/* <Typography className={classes.instructions}>
|
||||
Toutes les étapes sont terminées -
|
||||
</Typography>
|
||||
<Button onClick={handleReset}>Annuler</Button> */}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Typography className={classes.instructions}>{getStepContent(activeStep)}</Typography>
|
||||
<div>
|
||||
{/* <Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
|
||||
Précédent
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleNext}
|
||||
className={classes.button}
|
||||
>
|
||||
Suivant
|
||||
</Button> */}
|
||||
{/* {activeStep !== steps.length &&
|
||||
(completed[activeStep] ? (
|
||||
<Typography variant="caption" className={classes.completed}>
|
||||
Step {activeStep + 1} already completed
|
||||
</Typography>
|
||||
) : (
|
||||
<Button variant="contained" color="primary" onClick={handleComplete}>
|
||||
{completedSteps() === totalSteps() - 1 ? 'Etape valide' : 'Processus terminé'}
|
||||
</Button>
|
||||
))} */}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import React, { useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import PropTypes from 'prop-types';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import Link from 'next/link';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
CardActions,
|
||||
Divider,
|
||||
Grid,
|
||||
Button,
|
||||
TextField
|
||||
} from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
root: {}
|
||||
}));
|
||||
|
||||
const AccountVideoPres = props => {
|
||||
const { className, ...rest } = props;
|
||||
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Card
|
||||
{...rest}
|
||||
className={clsx(classes.root, className)}
|
||||
>
|
||||
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
AccountVideoPres.propTypes = {
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
||||
export default AccountVideoPres;
|
||||
@@ -1,6 +1,6 @@
|
||||
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 { Button, Typography, Divider, Hidden } from '@material-ui/core';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import { connect } from 'react-redux'
|
||||
@@ -10,6 +10,26 @@ 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 KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
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 { uploadMediaCv } from '../../actions/media'
|
||||
import GetApp from '@material-ui/icons/GetApp';
|
||||
// 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: {
|
||||
@@ -61,10 +81,7 @@ const styles = theme => ({
|
||||
},
|
||||
rootButton: {
|
||||
textTransform: 'inherit',
|
||||
border: '1px solid',
|
||||
'&:hover': {
|
||||
border: '1px solid',
|
||||
},
|
||||
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
@@ -76,32 +93,58 @@ const styles = theme => ({
|
||||
},
|
||||
|
||||
importButton: {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
InputKeyboardArrowRightIcon: {
|
||||
fontSize: '2.5em',
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
},
|
||||
});
|
||||
padding: '4px 8px',
|
||||
textTransform: 'inherit',
|
||||
border: '2px solid #1E2327',
|
||||
color: '#1E2327',
|
||||
|
||||
},
|
||||
remplacerButton: {
|
||||
color: '#1E2327',
|
||||
borderColor: '#1E2327',
|
||||
border: '2px solid',
|
||||
padding: '9.6px 8px',
|
||||
margin:'15px 0px 25px 0px',
|
||||
textTransform: 'inherit',
|
||||
},
|
||||
popup: {
|
||||
fontFamily: '"Roboto", "Helvetica", "Arial", "sans-serif"',
|
||||
fontWeight: '400',
|
||||
color: '#8E9092'
|
||||
},
|
||||
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 = {
|
||||
file: null,
|
||||
firstname: '',
|
||||
@@ -112,13 +155,18 @@ class Answer extends Component {
|
||||
twitter: '',
|
||||
website: '',
|
||||
mediaId: null,
|
||||
mediaUrl: null,
|
||||
thumbnails:null,
|
||||
heure: null,
|
||||
companyId: null,
|
||||
address:'',
|
||||
errorMessage:'',
|
||||
open: false,
|
||||
loading: true,
|
||||
openSnack: false,
|
||||
cv:false,
|
||||
};
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value })
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
firstname: nextProps.user.firstname,
|
||||
@@ -129,11 +177,26 @@ 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,
|
||||
cvLink: nextProps.cvLink,
|
||||
loading: nextProps.loading,
|
||||
openSnack: !!!_.isEmpty(nextProps.errors),
|
||||
})
|
||||
if (nextProps.loading) {
|
||||
const success = {};
|
||||
success.message ="CV mis à jour";
|
||||
console.log("CV mis à jour!!!")
|
||||
this.setState({ success });
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log("ANSWER !!!!!!! !!!!!! !!!!!! ");
|
||||
console.log(this.props);
|
||||
this.setState({
|
||||
firstname: this.props.user.firstname,
|
||||
lastname: this.props.user.lastname,
|
||||
@@ -142,8 +205,170 @@ 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,
|
||||
loading: false,
|
||||
cvLink: this.props.cvLink instanceof Object ? this.props.user.cv : this.props.cvLink
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
this.uploadMediaCv(e)
|
||||
}
|
||||
|
||||
uploadMediaCv = (e) => {
|
||||
var file = e.target.files[0]
|
||||
|
||||
const data = new FormData()
|
||||
data.append('upload', file)
|
||||
|
||||
this.props.uploadMediaCv(data)
|
||||
}
|
||||
|
||||
AfficherSuccess() {
|
||||
if (!this.state.success || !this.state.success.message) {
|
||||
console.log("Erreur Upload CV");
|
||||
return "";
|
||||
} else if (this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
AfficherLienCv() {
|
||||
console.log("afficher lien");
|
||||
if (this.state.cvLink !="") {
|
||||
|
||||
return (
|
||||
|
||||
<Fragment>
|
||||
<Hidden> </Hidden>
|
||||
<Hidden> </Hidden>
|
||||
|
||||
<Hidden> </Hidden>
|
||||
<Hidden> </Hidden>
|
||||
|
||||
<Hidden> </Hidden>
|
||||
|
||||
<Button size="small">MON CV</Button>
|
||||
|
||||
|
||||
<Typography >
|
||||
<a href={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentCv + this.state.cvLink}
|
||||
target="_blank"
|
||||
style={{
|
||||
color:'#1689FB',
|
||||
'&:hover': {
|
||||
color: '#1689FB',
|
||||
},
|
||||
fontWeight: '700',
|
||||
fontSize: '1em',
|
||||
}}
|
||||
>
|
||||
Visualiser mon CV
|
||||
</a>
|
||||
<br />
|
||||
{/* <a href="https://www.permatheque.fr/PDF/mansobufukuoka-larevolutiondunseulbrindepaille.pdf" target="_blank">lien</a> */}
|
||||
</Typography>
|
||||
|
||||
</Fragment>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value })
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
@@ -160,39 +385,66 @@ class Answer extends Component {
|
||||
|
||||
//TODO:maybe add this two in a single transactionnal saga
|
||||
this.props.updateUserRequest(data)
|
||||
|
||||
//TODO: faire appel à une méthode qui va encoyer le mail a l'entreprise
|
||||
|
||||
// this.props.companyMails.map((user) =>
|
||||
// //TODO Envoyer un mail a chaque user
|
||||
// console.log(user.email)
|
||||
// )
|
||||
this.props.postAdAnswerRequest(
|
||||
{
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
// inputFilesystemChange = (e) => {
|
||||
|
||||
console.log("inputFilesystemChange");
|
||||
var file = e.target.files[0]
|
||||
this.setState({ picture: file })
|
||||
// console.log("inputFilesystemChange");
|
||||
// var file = e.target.files[0]
|
||||
// this.setState({ picture: file })
|
||||
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
this.props.updateUserPictureRequest(data)
|
||||
// const data = new FormData()
|
||||
// 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 { loading } = this.state;
|
||||
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}
|
||||
classes={{ img: classes.MuiAvatarImg }}
|
||||
src={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentUrl + logoUrl} alt="candidatLogo" />}
|
||||
|
||||
{!!user.pictureLoading && <Loader />}
|
||||
{!!!user.pictureLoading && !!!logoUrl &&
|
||||
{/* {!!user.pictureLoading && <Loader />} */}
|
||||
{/* {!!!user.pictureLoading && !!!logoUrl &&
|
||||
(<Fragment><input
|
||||
type="file" accept="image/*" capture="filesystem"
|
||||
className={classes.input}
|
||||
@@ -212,7 +464,40 @@ class Answer extends Component {
|
||||
<KeyboardArrowRightIcon className={classes.InputKeyboardArrowRightIcon} />
|
||||
</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 className={classes.popup}> 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
|
||||
@@ -270,6 +555,29 @@ class Answer extends Component {
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
|
||||
{this.AfficherSuccess()}
|
||||
|
||||
<input
|
||||
type="file"
|
||||
accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document, .pdf, .odt"
|
||||
className={classes.input+' cypButtonImportVid'}
|
||||
style={{ display: 'none' }}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
|
||||
|
||||
<GetApp className={classes.icon} /> Importer mon CV
|
||||
|
||||
|
||||
</Button>
|
||||
|
||||
</label>
|
||||
<Hidden> </Hidden>
|
||||
{this.AfficherLienCv()}
|
||||
|
||||
<TextField
|
||||
name="linkedin"
|
||||
id="outlined"
|
||||
@@ -306,9 +614,10 @@ 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}>Postuler</Button>
|
||||
<Button variant="contained" className={classes.button + ' cypButtonSendApplication'} onClick={this.onSubmit}>Envoyer ma candidature</Button>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
@@ -316,13 +625,24 @@ class Answer extends Component {
|
||||
}
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
// console.log(state.media.message.heure);
|
||||
return {
|
||||
user: state.user ,
|
||||
cvLink : state.media.message,
|
||||
loading: !!state.media.loading,
|
||||
cv : true,
|
||||
user: state.user,
|
||||
loading: !!state.user.loading,
|
||||
// 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))
|
||||
export default withStyles(styles)(connect(mapStateToProps, { postAdAnswerRequest, updateUserRequest, updateUserPictureRequest, uploadMediaCv })(Answer))
|
||||
@@ -151,7 +151,7 @@ class CompanyRowComponent extends React.Component {
|
||||
const nbOffre = (rowData.count_ads > 0) ? offre : 'Candidature spontanée';
|
||||
|
||||
return (
|
||||
<Link href={`/Entreprise/${rowData.id}-${_.kebabCase(rowData.brand_name)}-${_.kebabCase(rowData.addresses.billing.city)}`} >
|
||||
<Link href={`/Entreprise/${rowData.id}-${_.kebabCase(rowData.brand_name)}`} >
|
||||
<Card className={classes.card + ' cypCardCompany'}>
|
||||
<CardContent className={classes.content}>
|
||||
<CardMedia
|
||||
|
||||
@@ -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,11 +274,11 @@ 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}>
|
||||
{/* <Typography gutterBottom color="secondary" component="p" className={classes.textContainer}>
|
||||
contact@talentstube.com
|
||||
</Typography>
|
||||
</Typography> */}
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@@ -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;
|
||||
@@ -20,6 +20,8 @@ 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';
|
||||
@@ -37,6 +39,8 @@ 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'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -299,11 +303,11 @@ class Header extends React.Component {
|
||||
left: false,
|
||||
bottom: false,
|
||||
right: false,
|
||||
toggle: true
|
||||
toggle: true,
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
@@ -324,12 +328,26 @@ 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);
|
||||
|
||||
}
|
||||
|
||||
redirectionrecruteur=(props) => {
|
||||
console.log("redirection recruteur")
|
||||
localStorage.removeItem("ttJWT");
|
||||
//this.openDialog()
|
||||
props.requestLogout();
|
||||
window.location.href = "https://recruteur.talentstube.com/";
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
console.log("user",this.props.user)
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Drawer anchor="left" open={this.state.left} onClose={this.toggleDrawer('left', false)}>
|
||||
@@ -344,13 +362,14 @@ class Header extends React.Component {
|
||||
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem}><ListItem classes={{ root: classes.rootListItem }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} />
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
|
||||
<Divider />
|
||||
<div className={classes.links}>
|
||||
{/* Menu Accueil /Offres Entreprises */}
|
||||
<div className={classes.linkGroup}>
|
||||
<ActiveLink activeClassName={classes.active} href="/" >
|
||||
<a className={classes.darkMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
@@ -380,33 +399,36 @@ class Header extends React.Component {
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</ActiveLink>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={classes.videothequeLinkGroup}>
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<VideoIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='CV vidéothèque'>
|
||||
|
||||
<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 className={classes.blogLinkGroup}>
|
||||
<a href="https://blog.talentstube.com" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
{/* FIN Menu Accueil /Offres Entreprises */}
|
||||
{/* Menu recruteur */}
|
||||
<div>
|
||||
{/* <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="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<a href={publicRuntimeConfig.symphonyUrl } className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<SupervisorAccountIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='Recruteurs'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</div>
|
||||
</div>
|
||||
{/* FIN Menu recruteur*/}
|
||||
|
||||
</div>
|
||||
</List>
|
||||
@@ -421,16 +443,18 @@ class Header extends React.Component {
|
||||
role="button"
|
||||
onClick={this.toggleDrawer('right', false)}
|
||||
onKeyDown={this.toggleDrawer('right', false)}
|
||||
>{!!this.props.loading &&
|
||||
>
|
||||
{!!this.props.loading &&
|
||||
(<Loader />
|
||||
)}
|
||||
)
|
||||
}
|
||||
{!!!this.props.loading && !!!this.props.fetched
|
||||
&&
|
||||
<div className={classes.fullList + ' ' + classes.darkFullList}>
|
||||
<List>
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem + ' cypFrontPage'}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-blanc.svg' className={classes.menuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-blanc.svg' className={classes.menuLogo} />
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
@@ -446,7 +470,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'>
|
||||
@@ -458,7 +482,7 @@ class Header extends React.Component {
|
||||
<Divider light={true} />
|
||||
|
||||
<div className={classes.linkGroup}>
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
|
||||
<a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
|
||||
<WorkOutlineIcon className={classes.icon} />
|
||||
<ListItemText primary='Connexion recruteurs'>
|
||||
</ListItemText>
|
||||
@@ -466,14 +490,16 @@ class Header extends React.Component {
|
||||
</a>
|
||||
</div>
|
||||
</List>
|
||||
</div>}
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
</div>
|
||||
}
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
<Fragment>
|
||||
{this.props.user.picture ?
|
||||
<img alt="talents-tube" src={`http://localhost/uploads/img/${this.props.user.picture}`} className={classes.menuAvatar} />
|
||||
<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}
|
||||
@@ -486,28 +512,51 @@ class Header extends React.Component {
|
||||
|
||||
<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="" >
|
||||
<a onClick={this.onRedirectAccount} 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'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
{this.props.user.type=="TALENT"
|
||||
?
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
:
|
||||
this.redirectionrecruteur(this.props)
|
||||
|
||||
// <div>
|
||||
|
||||
// <a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.lightMenuItem}>
|
||||
// <ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
// <SettingsIcon className={classes.icon} />
|
||||
// <ListItemText primary='Espace recruteur'>
|
||||
// </ListItemText>
|
||||
// </ListItem></a>
|
||||
|
||||
// </div>
|
||||
|
||||
}
|
||||
|
||||
|
||||
<Link href="/" >
|
||||
<a onClick={() => {
|
||||
localStorage.removeItem("ttJWT");
|
||||
@@ -530,7 +579,7 @@ class Header extends React.Component {
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem}>
|
||||
<ListItem classes={{ root: classes.rootListItemDesktop }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.desktopMenuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.desktopMenuLogo} />
|
||||
</ListItem>
|
||||
</a>
|
||||
</Link>
|
||||
@@ -543,13 +592,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>
|
||||
@@ -561,12 +610,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
|
||||
@@ -593,7 +648,7 @@ class Header extends React.Component {
|
||||
</Link>
|
||||
</Fragment>
|
||||
}
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="Profile"
|
||||
@@ -610,7 +665,7 @@ class Header extends React.Component {
|
||||
</section>
|
||||
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection3}>
|
||||
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.desktopMenuItem}>
|
||||
<a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.desktopMenuItem}>
|
||||
<ListItemText primary='Espace recruteurs'>
|
||||
</ListItemText>
|
||||
<ArrowForward className={classes.icon} />
|
||||
@@ -628,7 +683,7 @@ class Header extends React.Component {
|
||||
</IconButton>
|
||||
<div className={classes.grow} />
|
||||
<Link href="/" >
|
||||
<a><img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} /></a>
|
||||
<a><img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} /></a>
|
||||
</Link>
|
||||
<div className={classes.grow} />
|
||||
<IconButton
|
||||
|
||||
@@ -0,0 +1,634 @@
|
||||
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,
|
||||
},
|
||||
appBar:{
|
||||
position:'fixed'
|
||||
},
|
||||
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,
|
||||
},
|
||||
},
|
||||
});
|
||||
let urlEnv;
|
||||
|
||||
class Header extends React.Component {
|
||||
state = {
|
||||
top: false,
|
||||
left: false,
|
||||
bottom: false,
|
||||
right: false,
|
||||
toggle: true
|
||||
};
|
||||
|
||||
redirectionrecruteur=(props) => {
|
||||
console.log("redirection recruteur")
|
||||
localStorage.removeItem("ttJWT");
|
||||
//this.openDialog()
|
||||
props.requestLogout();
|
||||
window.location.href = "https://recruteur.talentstube.com/";
|
||||
}
|
||||
|
||||
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 &&
|
||||
(<Loader />
|
||||
)}
|
||||
{!!!this.props.loading && !!!this.props.fetched
|
||||
&&
|
||||
<div className={classes.fullList + ' ' + classes.darkFullList}>
|
||||
<List>
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem + ' cypFrontPage'}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-blanc.svg' className={classes.menuLogo} />
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
|
||||
<Divider light={true} />
|
||||
|
||||
<div className={classes.linkGroup}>
|
||||
<Link href="/Login" >
|
||||
<a className={classes.lightMenuItem + ' cypConnexion'}><ListItem classes={{ root: classes.rootListItemIcon }} >
|
||||
<PersonIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='Connexion'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
{/* TODO */}
|
||||
<Link href="/Inscription" >
|
||||
<a className={classes.lightMenuItem + ' cypRegister'}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItem }}>
|
||||
<PersonAddIcon className={classes.icon} />
|
||||
<ListItemText primary='Inscription'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<Divider light={true} />
|
||||
|
||||
<div className={classes.linkGroup}>
|
||||
<a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
|
||||
<WorkOutlineIcon className={classes.icon} />
|
||||
<ListItemText primary='Connexion recruteurs'>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
</a>
|
||||
</div>
|
||||
</List>
|
||||
</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} />
|
||||
{this.props.user.type=="TALENT"
|
||||
?
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
:
|
||||
this.redirectionrecruteur(this.props)
|
||||
|
||||
// <div>
|
||||
|
||||
// <a href={publicRuntimeConfig.symphonyUrl + "/"} className={classes.lightMenuItem}>
|
||||
// <ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
// <SettingsIcon className={classes.icon} />
|
||||
// <ListItemText primary='Espace recruteur'>
|
||||
// </ListItemText>
|
||||
// </ListItem></a>
|
||||
|
||||
// </div>
|
||||
|
||||
}
|
||||
|
||||
|
||||
<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> */}
|
||||
|
||||
<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} target="_blank" href="https://blog.talentstube.com/">
|
||||
<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.push("/Offres")}>
|
||||
<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()(Header))));
|
||||
@@ -17,7 +17,7 @@ const styles = theme => ({
|
||||
card: {
|
||||
display: 'flex',
|
||||
minHeight: '21vh',
|
||||
maxHeight: '32vh',
|
||||
// maxHeight: '32vh',
|
||||
borderRadius: '5px',
|
||||
width: '100%',
|
||||
cursor: 'pointer',
|
||||
@@ -38,7 +38,7 @@ const styles = theme => ({
|
||||
},
|
||||
[theme.breakpoints.up('md')]: {
|
||||
minHeight: '15vh',
|
||||
maxHeight: '20vh',
|
||||
// maxHeight: '20vh',
|
||||
},
|
||||
margin: '1vh 2vh 1vh 2vh',
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
@@ -51,14 +51,15 @@ const styles = theme => ({
|
||||
alignItems: 'flex-start',
|
||||
padding: theme.spacing(2),
|
||||
width: '75%',
|
||||
// minHeight: '200px',
|
||||
},
|
||||
jobTitle: {
|
||||
fontSize: '1em',
|
||||
fontSize: '1.2em',
|
||||
fontWeight: 'bold',
|
||||
color: theme.palette.offerlistitem.title,
|
||||
},
|
||||
companyTitle: {
|
||||
fontSize: '0.8em',
|
||||
fontSize: '1.2em',
|
||||
fontWeight: '300',
|
||||
color: theme.palette.offerlistitem.title,
|
||||
},
|
||||
@@ -96,11 +97,11 @@ const styles = theme => ({
|
||||
},
|
||||
iconTextIcon: {
|
||||
color: theme.palette.offerlistitem.icon,
|
||||
fontSize: '0.8em',
|
||||
fontSize: '1.2em',
|
||||
},
|
||||
iconTextText: {
|
||||
color: theme.palette.offerlistitem.text,
|
||||
fontSize: '0.6em',
|
||||
fontSize: '1em',
|
||||
paddingLeft: theme.spacing(1),
|
||||
},
|
||||
chip: {
|
||||
@@ -126,7 +127,7 @@ class OffreRowComponent extends React.Component {
|
||||
const imgUrl = (rowData.video && rowData.video.thumbnails && rowData.video.thumbnails[0] && rowData.video.thumbnails[0].sizes[4]) ? rowData.video.thumbnails[0].sizes[4].link : publicRuntimeConfig.adListDefaultUrl
|
||||
|
||||
return (
|
||||
<Link href={`/Offre/${rowData.id}-${_.kebabCase(rowData.title)}-${_.kebabCase(rowData.location.gmap_address.name)}`} >
|
||||
<Link href={`/Offre/${rowData.id}-${_.kebabCase(rowData.title)}`} >
|
||||
<Card className={classes.card + ' cypCardOffre'} >
|
||||
<CardContent className={classes.content}>
|
||||
<CardMedia
|
||||
@@ -144,24 +145,26 @@ class OffreRowComponent extends React.Component {
|
||||
variant="h6"
|
||||
component="h3"
|
||||
className={classes.jobTitle}>
|
||||
{rowData.title}
|
||||
{rowData.title}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="headline"
|
||||
variant="h6"
|
||||
component="h4"
|
||||
component="h3"
|
||||
className={classes.companyTitle}>
|
||||
{!!companyR.brand_name?companyR.brand_name:"-"}
|
||||
{companyR.brand_name ? companyR.brand_name : "Non renseigné"}
|
||||
</Typography>
|
||||
<div>
|
||||
{rowData.is_promoted && (
|
||||
<Chip label="Pourvue" className={classes.chip} />
|
||||
<Chip label="Offre pourvue" className={classes.chip} />
|
||||
)}
|
||||
|
||||
{!rowData.is_promoted && (
|
||||
<Fragment>
|
||||
<IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="location_on" text={rowData.extra.contract_type} />
|
||||
<IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={rowData.location.gmap_address.formatted_address} />
|
||||
<IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={rowData.extra.contract_type} />
|
||||
<IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="location_on" text={rowData.location.gmap_address.formatted_address} />
|
||||
{rowData.beneficiaire ? <IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business" text={rowData.beneficiaire} /> : ""}
|
||||
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
|
||||
@@ -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.svg',
|
||||
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 l’enregistrement",
|
||||
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,20 +255,70 @@ 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 } = this.props;
|
||||
const { classes, titreBouton } = this.props;
|
||||
let titreButtonLabel= "Choisir cette vidéo";
|
||||
|
||||
|
||||
if (titreBouton) {
|
||||
titreButtonLabel = titreBouton;
|
||||
console.log("titre");
|
||||
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}>
|
||||
Envoyer
|
||||
{titreButtonLabel}
|
||||
</Button>}
|
||||
</div>
|
||||
<div id="controleNav">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import { registerUserRequest, subscribeToNewsletterRequest } from "../../actions/user"
|
||||
import SocialButtonsAuth from '../atoms/SocialButtonsAuth';
|
||||
import Snack from '../atoms/snack'
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
@@ -111,6 +112,7 @@ class Register extends React.Component {
|
||||
password: '',
|
||||
checkNewsletter: false,
|
||||
checkCGU: false,
|
||||
adId : ''
|
||||
},
|
||||
errors: {
|
||||
email:null,
|
||||
@@ -120,7 +122,8 @@ class Register extends React.Component {
|
||||
checkCGU:null
|
||||
},
|
||||
loading: false,
|
||||
showPassword: false
|
||||
showPassword: false,
|
||||
passwordValid : false
|
||||
}
|
||||
|
||||
validate = data => {
|
||||
@@ -131,18 +134,28 @@ class Register extends React.Component {
|
||||
if (!!!data.lastname) errors.lastname = "Requis";
|
||||
if (!data.checkCGU) errors.checkCGU = "Requis";
|
||||
|
||||
if(data.password.length <8){
|
||||
errors.password = "Too short";
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
data: {...this.state.data, adId: localStorage.getItem('adId')},
|
||||
})
|
||||
}
|
||||
|
||||
onRegister = e => {
|
||||
e.preventDefault();
|
||||
const errors = this.validate(this.state.data);
|
||||
|
||||
let 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)
|
||||
console.log(this.props.registerUserRequest(this.state.data))
|
||||
|
||||
if (this.state.data.checkNewsletter)
|
||||
this.props.subscribeToNewsletterRequest({ email: this.state.data.email })
|
||||
@@ -156,10 +169,12 @@ class Register extends React.Component {
|
||||
loading: nextProps.loading
|
||||
})
|
||||
}
|
||||
onChange = e =>
|
||||
onChange = e => {
|
||||
|
||||
this.setState({
|
||||
data: { ...this.state.data, [e.target.name]: e.target.value }
|
||||
});
|
||||
}
|
||||
handleCheckBoxChange = name => event => {
|
||||
this.setState({ data: { ...this.state.data, [name]: event.target.checked } });
|
||||
};
|
||||
@@ -173,7 +188,7 @@ class Register extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { classes, erreurs } = this.props;
|
||||
const { data, errors } = this.state;
|
||||
|
||||
return (
|
||||
@@ -182,6 +197,7 @@ class Register extends React.Component {
|
||||
<form className={classes.form}>
|
||||
|
||||
<TextField
|
||||
className={classes.champ}
|
||||
value={data.lastname}
|
||||
onChange={this.onChange}
|
||||
id="nom"
|
||||
@@ -191,6 +207,7 @@ class Register extends React.Component {
|
||||
variant="outlined"
|
||||
required
|
||||
error={!!errors.lastname}
|
||||
helperText={!!errors.lastname && "Veuillez saisir votre nom."}
|
||||
/>
|
||||
<TextField
|
||||
value={data.firstname}
|
||||
@@ -202,6 +219,7 @@ class Register extends React.Component {
|
||||
variant="outlined"
|
||||
required
|
||||
error={!!errors.firstname}
|
||||
helperText={!!errors.firstname && "Veuillez saisir votre prénom."}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
@@ -214,8 +232,9 @@ class Register extends React.Component {
|
||||
type="email"
|
||||
variant="outlined"
|
||||
required
|
||||
error={!!errors.email}
|
||||
error={!!errors.email || !!erreurs}
|
||||
autoComplete="username email"
|
||||
helperText={!!errors.email ? "Saisissez une adresse e-mail valide." : !!erreurs && erreurs}
|
||||
/>
|
||||
|
||||
|
||||
@@ -230,6 +249,7 @@ class Register extends React.Component {
|
||||
value={this.state.password}
|
||||
onChange={this.onChange}
|
||||
error={!!errors.password}
|
||||
helperText={!!errors.password && "Votre mot de passe doit contenir au minimum 8 caractères."}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
@@ -273,19 +293,20 @@ class Register extends React.Component {
|
||||
label="Je déclare avoir pris connaissance et accepte les termes et les CGU *"
|
||||
required
|
||||
/>
|
||||
<Link href={`/Cgu`} >Lien vers les CGU</Link>
|
||||
<Button type="submit" variant="contained" className={classes.button + ' ' + classes.buttonImportant + ' cypButtonRegister'} onClick={this.onRegister}>
|
||||
S'inscrire
|
||||
</Button>
|
||||
|
||||
<Typography
|
||||
{/* <Typography
|
||||
paragraph={true}
|
||||
align="center"
|
||||
className={classes.conditionalText}
|
||||
>Ou</Typography>
|
||||
>Ou</Typography> */}
|
||||
|
||||
</form>
|
||||
|
||||
<SocialButtonsAuth linkedInAuth={this.props.linkedInAuth} facebookAuth={this.props.facebookAuth} />
|
||||
{/* <SocialButtonsAuth linkedInAuth={this.props.linkedInAuth} facebookAuth={this.props.facebookAuth} /> */}
|
||||
|
||||
<div classes={classes.form}>
|
||||
<Typography
|
||||
@@ -300,7 +321,12 @@ class Register extends React.Component {
|
||||
</Link>
|
||||
</Typography>
|
||||
</div>
|
||||
<Snack name= 'snackWarning'
|
||||
variant= 'warning'
|
||||
message={errors.message}
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
|
||||
|
||||
import VideoVimeo from '../atoms/VideoVimeo'
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
@@ -169,7 +170,7 @@ class ShortVideoHooker extends Component {
|
||||
|
||||
return (
|
||||
<div className={classes.video}>
|
||||
<VideoVimeo classesOverride={ classes.videoVimeo } videoId={videoList[this.state.i].vimeoId} title={videoList[this.state.i].title}
|
||||
{/* <VideoVimeo classesOverride={ classes.videoVimeo } videoId={videoId}
|
||||
options={`?byline=0&title=0&background=1&autoplay=1&mute=1`} />
|
||||
<section className={classes.text}>
|
||||
<Typography gutterBottom
|
||||
@@ -199,7 +200,7 @@ class ShortVideoHooker extends Component {
|
||||
>
|
||||
Voir l'offre
|
||||
</Button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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,52 @@ 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,
|
||||
paddingRight:'0px',
|
||||
paddingLeft:'3px'
|
||||
},
|
||||
TwitterIconMobile: {
|
||||
color: theme.palette.social.twitter,
|
||||
paddingRight:'3px' ,
|
||||
paddingLeft:'3px'
|
||||
},
|
||||
LinkedinIconMobile: {
|
||||
color: theme.palette.social.linkedin,
|
||||
paddingRight:'3px',
|
||||
paddingLeft:'3px'
|
||||
},
|
||||
MailIconMobile: {
|
||||
color: theme.palette.social.mail,
|
||||
paddingRight:'3px' ,
|
||||
paddingLeft:'3px'
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -51,19 +88,36 @@ export default function SocialShare(props) {
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<a href={"https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(props.url)}>
|
||||
<Icon className={clsx(classes.icon, classes.FacebookIcon, 'fab fa-facebook-f')} color="secondary" />
|
||||
</a>
|
||||
<a href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)}>
|
||||
<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")}>
|
||||
<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} >
|
||||
<Icon className={clsx(classes.icon, classes.MailIcon, 'fas fa-envelope')} color="secondary" />
|
||||
</a>
|
||||
<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.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>
|
||||
);
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class Tile extends React.Component {
|
||||
const logoName = (rowData.company) ? rowData.company.logo : rowData.logo
|
||||
const logoUrl = publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + logoName
|
||||
|
||||
const router = (rowData.company) ? `/Offre/${rowData.id}-${_.kebabCase(rowData.title)}-${_.kebabCase(rowData.location.gmap_address.name)}` : `/Entreprise/${rowData.id}-${_.kebabCase(rowData.brand_name)}-${_.kebabCase(rowData.addresses.billing.city)}`
|
||||
const router = (rowData.company) ? `/Offre/${rowData.id}-${_.kebabCase(rowData.title)}` : `/Entreprise/${rowData.id}-${_.kebabCase(rowData.brand_name)}}`
|
||||
|
||||
//rowData._embedded.company.brand_name
|
||||
return (
|
||||
@@ -113,7 +113,7 @@ class Tile extends React.Component {
|
||||
/>
|
||||
<KeyboardArrowleftIcon className={classes.iconPlay} />
|
||||
<div className={classes.logoContainer}>
|
||||
<Avatar className={classes.logo} src={logoUrl} alt="company"/>
|
||||
<Avatar className={classes.logo} src={logoUrl} alt={rowData.title}/>
|
||||
</div>
|
||||
{ children }
|
||||
</CardContent>
|
||||
|
||||
@@ -10,11 +10,11 @@ const styles = theme => ({
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
position: 'absolute',
|
||||
top: '51%',
|
||||
top: '44%',
|
||||
width: '100%',
|
||||
},
|
||||
companyTitle: {
|
||||
fontSize: '0.8em',
|
||||
fontSize: '1em',
|
||||
fontWeight: '100',
|
||||
padding: theme.spacing(0, 2),
|
||||
marginTop: '4vh',
|
||||
@@ -24,7 +24,7 @@ const styles = theme => ({
|
||||
},
|
||||
},
|
||||
jobTitle: {
|
||||
fontSize: '1em',
|
||||
fontSize: '1.2em',
|
||||
padding: theme.spacing(0, 2),
|
||||
minHeight: '8vh',
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
@@ -59,7 +59,7 @@ class TileOffre extends React.Component {
|
||||
component="h4"
|
||||
align="center"
|
||||
className={classes.companyTitle}>
|
||||
{tile.company.brand_name && tile.company.brand_name}
|
||||
{tile.company.brand_name && tile.company.brand_name}
|
||||
</Typography>
|
||||
<Typography
|
||||
gutterBottom
|
||||
@@ -82,6 +82,10 @@ class TileOffre extends React.Component {
|
||||
{tile.extra && tile.extra.contract_type &&
|
||||
<IconText classes={{ root: classes.rootIconText }} variant="assignment" text={tile.extra.contract_type} />
|
||||
}
|
||||
|
||||
{tile.beneficiaire &&
|
||||
<IconText classes={{ root: classes.rootIconText }} variant="business" text={tile.beneficiaire} />
|
||||
}
|
||||
</section>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@ import RootContainer from '../atoms/RootContainer'
|
||||
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||
import ArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { Hidden } from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
inner: {
|
||||
@@ -54,6 +55,13 @@ const styles = theme => ({
|
||||
position: 'absolute',
|
||||
left: theme.spacing(1),
|
||||
},
|
||||
retour:{
|
||||
fontFamily: 'Roboto',
|
||||
color: '#1E2327',
|
||||
fontSize: '0.8rem',
|
||||
fontWeight: '500',
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
function LayoutBack(props) {
|
||||
@@ -72,6 +80,8 @@ function LayoutBack(props) {
|
||||
focusVisibleClassName={classes.focusVisible}
|
||||
onClick={() => Router.back()}>
|
||||
<ArrowLeft color="primary" classes={{ root: classes.icon }}></ArrowLeft>
|
||||
{/* <Hidden mdUp className={classes.retour}></Hidden> */}
|
||||
<Hidden smDown className={classes.retour}>Retour</Hidden>
|
||||
</ButtonBase>
|
||||
<Typography
|
||||
component="h1"
|
||||
|
||||
@@ -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)
|
||||
@@ -10,6 +10,7 @@ import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
|
||||
import Header from '../organisms/Header'
|
||||
import {AppBar,CssBaseline,Container,Toolbar,IconButton,Typography} from "@material-ui/core";
|
||||
import Hidden from '@material-ui/core/Hidden';
|
||||
import Link from 'next/link'
|
||||
|
||||
const styles = theme => ({
|
||||
RootContainer: {
|
||||
@@ -65,11 +66,21 @@ const styles = theme => ({
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
marginLeft: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important,
|
||||
textDecoration:'none',
|
||||
},
|
||||
voirOffre: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: '#BBBCBD',
|
||||
backgroundColor: '#F3F3F4',
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
@@ -105,13 +116,21 @@ function LayoutCompany(props) {
|
||||
|
||||
<Hidden mdUp>
|
||||
<div id="F" className={classes.foot}>
|
||||
<Link href="#discover" >
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.voirOffre + ' cypButtonApply'}
|
||||
>Voir les offres</Button>
|
||||
|
||||
</Link>
|
||||
<a
|
||||
href={`/Reponse?companyId=${companyId}`}
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
classes={{ root: classes.rootButton }}
|
||||
onClick={() => Router.push(`/Reponse?companyId=${companyId}`)}
|
||||
// onClick={() => Router.push(`/Reponse?companyId=${companyId}`)}
|
||||
>
|
||||
Candidature spontanée</Button>
|
||||
Candidature spontanée</a>
|
||||
</div>
|
||||
</Hidden>
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@ 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'
|
||||
|
||||
const styles = theme => ({
|
||||
foot: {
|
||||
@@ -21,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',
|
||||
@@ -56,22 +62,35 @@ const styles = theme => ({
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
marginLeft: theme.spacing(4.5),
|
||||
marginRight: theme.spacing(4.5),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important,
|
||||
},
|
||||
voirEntreprise: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: '#BBBCBD',
|
||||
backgroundColor: '#F3F3F4',
|
||||
|
||||
},
|
||||
pourvuButton:{
|
||||
padding :'10px',
|
||||
textTransform: 'inherit',
|
||||
},
|
||||
})
|
||||
|
||||
function LayoutOffre(props) {
|
||||
|
||||
const { classes, offreId, isProvided } = props;
|
||||
const { classes, offreId, offre, isProvided } = props;
|
||||
const contentClass = (!isProvided) ? classes.contentDefault : classes.contentProvided
|
||||
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location : publicRuntimeConfig.frontServerUrl + `/Offre/${offreId}-${_.kebabCase(offre.title)}`;
|
||||
return (
|
||||
<RootContainer>
|
||||
{isWidthUp('sm', props.width) ?
|
||||
{isWidthUp('xs', props.width) ?
|
||||
(<Header />)
|
||||
:
|
||||
(<ButtonBase name='back'
|
||||
@@ -91,13 +110,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)}`} >
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.voirEntreprise + ' cypButtonApply'}
|
||||
>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}>
|
||||
Offre pourvue
|
||||
</Button>
|
||||
{/* <div className={classes.grow} />
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ const styles = theme => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
justifyContent: 'center',
|
||||
fontFamily: 'Dosis',
|
||||
fontWeight: '500',
|
||||
@@ -19,7 +20,7 @@ class Loader extends React.Component {
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div className={classes.loader + ' ' + 'alert alert-info'}><CircularProgress color="primary" />Chargement...</div>
|
||||
<div className={classes.loader + ' ' + 'alert alert-info'}><CircularProgress color="primary" />Chargement... </div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
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',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
justifyContent: 'center',
|
||||
fontFamily: 'Dosis',
|
||||
fontWeight: '500',
|
||||
fontSize: '1em',
|
||||
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.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>
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(LoaderVideo)
|
||||
@@ -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;
|
||||
@@ -67,17 +68,17 @@ export default {
|
||||
},
|
||||
},
|
||||
ads: {
|
||||
fetchAd: (id) => {
|
||||
return axios.get(`api/ads/${id}`).then(res => res.data)
|
||||
fetchJob: (id) => {
|
||||
return axios.get(`api/jobs/${id}`).then(res => res.data)
|
||||
},
|
||||
|
||||
//offset is the index position of the first element to start requesting at
|
||||
// use 0|1 for isPromoted
|
||||
fetchAds: ({ limit = null, order = "", keyword = "", offset = 1, status = 'PUBLISHED', isPromoted = null, isEmphasis = null }) => {
|
||||
fetchJobs: ({ limit = null, order = "", keyword = "", offset = 1, status = 'PUBLISHED', isPromoted = false, isEmphasis = false }) => {
|
||||
isPromoted = isPromoted !== null ? isPromoted * 1 : isPromoted;
|
||||
isEmphasis = isEmphasis !== null ? isEmphasis * 1 : isEmphasis;
|
||||
|
||||
return axios.get('api/ads', { params: { offset, limit, order, keyword, status, isPromoted, isEmphasis } })
|
||||
return axios.get('api/jobs', { params: { offset, limit, order, keyword, status, isPromoted, isEmphasis } })
|
||||
.then(res => res.data)
|
||||
}
|
||||
|
||||
@@ -96,7 +97,7 @@ export default {
|
||||
postAnswer: (payload) => {
|
||||
return axios.post("/api/answers", { adId: payload.adId, mediaId: payload.mediaId, companyId: payload.companyId }).then(res => res)
|
||||
},
|
||||
fetchAdsAnswered: ({ limit = null, order = "", keyword = "", offset = 1 }) => {
|
||||
fetchJobsAnswered: ({ limit = null, order = "", keyword = "", offset = 1 }) => {
|
||||
return axios.get(`api/answers`, { params: { offset, limit, order, keyword } }).then(res => res.data)
|
||||
},
|
||||
fetchAnswer: (payload) => {
|
||||
@@ -120,6 +121,22 @@ export default {
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
},
|
||||
uploadMediaPres: (payload) => {
|
||||
return axios.post("/api/mediaPres", payload, {
|
||||
headers: {
|
||||
'Content-Type': `multipart/form-data;`
|
||||
},
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
},
|
||||
uploadMediaCv: (payload) => {
|
||||
return axios.post("/api/mediaCv", payload, {
|
||||
headers: {
|
||||
'Content-Type': `multipart/form-data;`
|
||||
},
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
}
|
||||
},
|
||||
stats: {
|
||||
countAdView: id => {
|
||||
@@ -135,4 +152,4 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
@@ -33,21 +33,38 @@ module.exports = withPlugins(
|
||||
}
|
||||
],
|
||||
importScripts:
|
||||
['/static/js/Edeclic-service-worker.js',
|
||||
'/static/js/backgroundSync-sw.js'
|
||||
['/statique/js/Edeclic-service-worker.js',
|
||||
'/statique/js/backgroundSync-sw.js'
|
||||
]
|
||||
},
|
||||
}],
|
||||
[{
|
||||
publicRuntimeConfig: {
|
||||
symphonyUrl: 'https://www.talentstube.com',
|
||||
frontServerUrl: 'https://pp.app.talentstube.com',
|
||||
adListDefaultUrl: '/static/images/default/default_picture_company.svg',
|
||||
// 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.4.2',
|
||||
adListDefaultUrl: '/statique/images/default/default_picture_company.svg',
|
||||
cachedMediaUrl: '/media/cache/profile_thumb/uploads/img/',
|
||||
postedContentUrl: '/uploads/img/',
|
||||
postedContentCv: '/uploads/cv/',
|
||||
ReCAPTCHA: {
|
||||
"siteKey": "6LdyqLwUAAAAADKI5uC7d5W9VqVgzd8VEmMU2Yi-"
|
||||
},
|
||||
applicationServerPublicKey: 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='
|
||||
//applicationServerPublicKey: 'BG2lV673DvB67dzEwX9GKfds3sXaEdtZo2oWO1cO2xUdTJAFZ_rV_UrP1nHQz-F8LJNO9HxG0kmQRIb54JL1ZCA'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@blunck/next-alias": "^1.0.0",
|
||||
"@material-ui/core": "^4.2.0",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"@material-ui/core": "^4.9.10",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||
"@ostai/next-css": "^1.0.2",
|
||||
"autosuggest-highlight": "^3.1.1",
|
||||
"axios": "^0.18.0",
|
||||
"connect-mongo": "^2.0.1",
|
||||
"cross-env": "^5.2.0",
|
||||
@@ -25,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",
|
||||
@@ -33,6 +36,7 @@
|
||||
"next-optimized-images": "^1.4.1",
|
||||
"next-redux-saga": "^4.0.2",
|
||||
"next-redux-wrapper": "^3.0.0-alpha.2",
|
||||
"next-seo": "^4.7.3",
|
||||
"next-transpile-modules": "^2.3.1",
|
||||
"node-mailjet": "^3.3.1",
|
||||
"nodemailer": "^4.6.8",
|
||||
@@ -44,11 +48,20 @@
|
||||
"passport-oauth2": "https://github.com/Huaoe/passport-oauth2.git",
|
||||
"prop-types": "latest",
|
||||
"react": "^16.9.0",
|
||||
"react-ad-block-detect": "^1.0.1",
|
||||
"react-autosuggest": "^10.0.2",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-facebook-login": "^4.1.1",
|
||||
"react-ga": "^2.5.7",
|
||||
"react-google-recaptcha": "^2.0.1",
|
||||
"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",
|
||||
@@ -62,6 +75,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"
|
||||
},
|
||||
|
||||
@@ -147,6 +147,7 @@ class Candidature extends React.Component {
|
||||
<LayoutCandidature>
|
||||
<Head>
|
||||
<title key="title">Candidature</title>
|
||||
<meta name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<Fragment>
|
||||
<div className={classes.container}>
|
||||
@@ -187,7 +188,7 @@ class Candidature extends React.Component {
|
||||
{this.props.user.firstname + " " + this.props.user.lastname}
|
||||
</Typography>
|
||||
<Typography gutterBottom className={classes.userTextDate}>
|
||||
Envoyée le {(new Date(this.props.answer.c_time)).toLocaleDateString("fr-FR")}
|
||||
Envoyé le {(new Date(this.props.answer.c_time)).toLocaleDateString("fr-FR")}
|
||||
</Typography>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Layout from "../components/templates/Layout";
|
||||
import AccountProfileCandidature from "../components/organisms/AccountProfileCandidature";
|
||||
import Head from 'next/head'
|
||||
// import AdBlockDetect from 'react-ad-block-detect';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
button: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
completed: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
instructions: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
|
||||
export default function HorizontalNonLinearStepper() {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Profil – Talents Tube</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<div >
|
||||
<AccountProfileCandidature />
|
||||
</div>
|
||||
|
||||
{/* <AdBlockDetect>
|
||||
<p>AdBlocks a été détecté. Pour que Talents Tube puisse fonctionner correctement, veuillez désactiver Ad Blocks</p>
|
||||
</AdBlockDetect> */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -8,9 +8,10 @@ import { Typography } from '@material-ui/core';
|
||||
import LayoutGrid from "../components/templates/LayoutGrid";
|
||||
import Grid from "../components/templates/Grid"
|
||||
import AnswerRow from "../components/organisms/AnswerRow"
|
||||
import { fetchAdsAnsweredRequest } from '../actions/answer'
|
||||
import { fetchJobsAnsweredRequest } from '../actions/answer'
|
||||
import { AnswersSelector } from '../reducers/answers'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -24,6 +25,13 @@ const styles = theme => ({
|
||||
flexDirection: 'column',
|
||||
padding: theme.spacing(0,3),
|
||||
},
|
||||
profil: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: theme.spacing(3,3),
|
||||
textAlign: 'center',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Dosis',
|
||||
fontSize: '1.5em',
|
||||
@@ -45,16 +53,18 @@ class Candidatures extends React.Component {
|
||||
<LayoutGrid backLink="/">
|
||||
<Head>
|
||||
<title key="title">Candidatures</title>
|
||||
<meta name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
|
||||
{/* TODO */}
|
||||
<Typography component="h1" align="center" className={classes.title} gutterBottom>
|
||||
Mes candidatures
|
||||
</Typography>
|
||||
|
||||
<div className={classes.container}>
|
||||
|
||||
<Grid CustomRowComponent={AnswerRow}
|
||||
dataFetcher={this.props.fetchAdsAnsweredRequest}
|
||||
dataFetcher={this.props.fetchJobsAnsweredRequest}
|
||||
data={this.props.answers}
|
||||
currentPage={this.props.currentPage}
|
||||
recordCount={this.props.recordCount}
|
||||
@@ -63,6 +73,16 @@ class Candidatures extends React.Component {
|
||||
searchable={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</LayoutGrid>
|
||||
);
|
||||
}
|
||||
@@ -83,4 +103,4 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {fetchAdsAnsweredRequest })(Candidatures))
|
||||
export default withStyles(styles)(connect(mapStateToProps, {fetchJobsAnsweredRequest })(Candidatures))
|
||||
|
||||
@@ -57,7 +57,7 @@ class Confidentialite extends Component {
|
||||
</Head>
|
||||
<div className={classes.container}>
|
||||
<Typography className={classes.text} gutterBottom align="left">
|
||||
Nous vous invitons à lire avec attention le présent document. Pour toute question concernant ce document et, d’une manière générale, sur la collecte et le traitement de vos informations personnelles par la société talentstube.com, n’hésitez pas à nous contacter via le formulaire présent sur la page contact : <a href="https://blog.talentstube.com/contact.html" className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a>
|
||||
Nous vous invitons à lire avec attention le présent document. Pour toute question concernant ce document et, d’une manière générale, sur la collecte et le traitement de vos informations personnelles par la société talentstube.com, n’hésitez pas à nous contacter via le formulaire présent sur la page contact : <a href="https://blog.talentstube.com/contact" className={classes.link} target="_blank">https://blog.talentstube.com/contact</a>
|
||||
</Typography>
|
||||
|
||||
<Typography className={classes.title} component="h2" gutterBottom align="left">
|
||||
@@ -155,7 +155,7 @@ class Confidentialite extends Component {
|
||||
`
|
||||
Vous disposez d'un droit d'accès, de rectification, de suppression, d’opposition et de portabilité des données. Nous disposons d’un délai de 30 jours à compter de votre demande pour apporter une réponse.
|
||||
Vous pouvez demander une limitation du traitement des données collectées. L’exercice de ces droits peut exercer ce droit auprès de TALENTS TUBE en adressant une requête soit par voie postale à l'adresse suivante : 3 Rue Louis de Broglie, Village By CA 56000 Vannes, soit par courrier électronique via le formulaire présent sur la page Contact `
|
||||
}<a href="https://blog.talentstube.com/contact.html" className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a>{`. Cette requête devra être accompagnée d'une pièce d'identité revêtant la signature de l'Utilisateur et devra préciser l'adresse et le moyen par lesquelles une réponse pourra être envoyée..
|
||||
}<a href="https://blog.talentstube.com/contact" className={classes.link} target="_blank">https://blog.talentstube.com/contact</a>{`. Cette requête devra être accompagnée d'une pièce d'identité revêtant la signature de l'Utilisateur et devra préciser l'adresse et le moyen par lesquelles une réponse pourra être envoyée..
|
||||
`
|
||||
}
|
||||
</Typography>
|
||||
@@ -178,7 +178,7 @@ class Confidentialite extends Component {
|
||||
<a href="http://windows.microsoft.com/fr-fr/internet-explorer/delete-manage-cookies#ie=ie-11" className={classes.link} target="_blank">Internet Explorer</a><br />
|
||||
|
||||
`
|
||||
Pour plus d’informations sur les cookies et la façon de les gérer, nous vous recommandons de consulter le site `} <a href="http://www.youronlinechoices.com/fr/" className={classes.link} target="_blank">www.youronlinechoices.com</a>{`, développé par l’organisme EDAA (European Interactive Digital Advertising Alliance).
|
||||
Pour plus d’informations sur les cookies et la façon de les gérer, nous vous recommandons de consulter le site ` <a href="http://www.youronlinechoices.com/fr/" className={classes.link} target="_blank">www.youronlinechoices.com</a>{`, développé par l’organisme EDAA (European Interactive Digital Advertising Alliance).
|
||||
`
|
||||
}
|
||||
</Typography>
|
||||
|
||||
@@ -25,8 +25,8 @@ const styles = theme => ({
|
||||
bottom: 0,
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Dosis',
|
||||
fontSize: '1.5em',
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '1.625em',
|
||||
fontWeight: '600',
|
||||
padding: theme.spacing(3, 0),
|
||||
},
|
||||
@@ -47,6 +47,24 @@ const styles = theme => ({
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important,
|
||||
},
|
||||
iconButton:{
|
||||
marginTop: "50px",
|
||||
|
||||
[theme.breakpoints.down('md')]: {
|
||||
marginTop: "50px",
|
||||
|
||||
},
|
||||
},
|
||||
texteEtape:{
|
||||
fontSize: '1em',
|
||||
fontWeight: '300',
|
||||
},
|
||||
etape:{
|
||||
fontSize: '1em',
|
||||
fontWeight: '500',
|
||||
color:'#1689FB',
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -69,7 +87,7 @@ class ConfirmAccount extends Component {
|
||||
const { classes } = this.props
|
||||
const { loading } = this.state
|
||||
return (
|
||||
<LayoutBack text="Validation" height="fixed">
|
||||
<LayoutBack text="Inscription" height="fixed">
|
||||
<Head>
|
||||
<title key="title">Confirmation de compte</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
@@ -80,16 +98,45 @@ class ConfirmAccount extends Component {
|
||||
)}
|
||||
{!loading && (
|
||||
<Fragment>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/inscription/validation-plateforme-recrutement-video.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography gutterBottom align="center" className={classes.title}>
|
||||
e-mail validé
|
||||
Bienvenue sur Talents Tube
|
||||
</Typography>
|
||||
<Typography gutterBottom align="left" className={classes.text}>
|
||||
Votre email a bien été validé.
|
||||
<Typography gutterBottom align="center" className={classes.etape}>
|
||||
Étape 1.
|
||||
</Typography>
|
||||
<Typography gutterBottom align="left" className={classes.text}>
|
||||
Vous pouvez maintenant vous connecter.
|
||||
<Typography gutterBottom align="center" className={classes.texteEtape}>
|
||||
Découvrez les entreprises et les offres d’emploi en vidéo.
|
||||
</Typography>
|
||||
<section className={classes.bottomContainer}>
|
||||
<Typography gutterBottom align="center" className={classes.etape}>
|
||||
Étape 2.
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center" className={classes.texteEtape}>
|
||||
Postulez en vidéo.
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center" className={classes.etape}>
|
||||
Étape 3.
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center" className={classes.texteEtape}>
|
||||
Gérez vos candidatures depuis votre compte Talent.
|
||||
</Typography>
|
||||
|
||||
<Typography gutterBottom align="center" className={classes.text}>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
classes={{ root: classes.rootButton }}
|
||||
onClick={() => Router.push('/Login')}
|
||||
>
|
||||
Se connecter
|
||||
</Button>
|
||||
|
||||
</Typography>
|
||||
{/* <section className={classes.bottomContainer}>
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
@@ -98,7 +145,7 @@ class ConfirmAccount extends Component {
|
||||
>
|
||||
Connexion
|
||||
</Button>
|
||||
</section>
|
||||
</section> */}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
@@ -118,6 +165,7 @@ function mapStateToProps(state, ownProps) {
|
||||
|
||||
ConfirmAccount.getInitialProps = function (context) {
|
||||
const { token, email } = context.query
|
||||
//localStorage.setItem('loginRedirect', url)
|
||||
context.store.dispatch(requestConfirmationAccountRequest({ 'confirmationToken': token, 'email': email }))
|
||||
return email;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const styles = theme => ({
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: theme.spacing(3,2),
|
||||
padding: theme.spacing(3, 2),
|
||||
width: '100%',
|
||||
},
|
||||
vimeoVideo: {
|
||||
@@ -26,17 +26,17 @@ class Conseils extends React.Component {
|
||||
const { classes } = this.props
|
||||
|
||||
return (
|
||||
<LayoutBack text="Quelques conseils !">
|
||||
<LayoutBack text="Quelques conseils !">
|
||||
<Head>
|
||||
<title>Quelques conseils !</title>
|
||||
<meta name="description" content="Quelques conseils !" />
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
<link rel="canonical" href="https://app.talentstube.com" />
|
||||
|
||||
</Head>
|
||||
<section className={ classes.container }>
|
||||
<VideoVimeo videoId='356411947' autoplay='1'/>
|
||||
<section className={classes.container}>
|
||||
<VideoVimeo videoId='356411947' autoplay='1' />
|
||||
</section>
|
||||
</LayoutBack>
|
||||
</LayoutBack>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -26,6 +27,7 @@ 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')]: {
|
||||
@@ -278,12 +280,26 @@ const styles = theme => ({
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(4),
|
||||
marginRight: theme.spacing(4),
|
||||
marginLeft: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important,
|
||||
alignSelf: 'center',
|
||||
textDecoration:'none',
|
||||
fontFamily: '"Roboto", "Helvetica", "Arial", "sans-serif"',
|
||||
},
|
||||
voirOffre: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: '#BBBCBD',
|
||||
backgroundColor: '#F3F3F4',
|
||||
|
||||
},
|
||||
buttonContainer: {
|
||||
alignItems: 'right',
|
||||
},
|
||||
chip: {
|
||||
color: theme.palette.secondary.main,
|
||||
@@ -328,6 +344,9 @@ const styles = theme => ({
|
||||
borderBottomLeftRadius: '5px',
|
||||
borderBottomRightRadius: '5px',
|
||||
},
|
||||
lien:{
|
||||
textDecoration:'none'
|
||||
},
|
||||
});
|
||||
|
||||
const CustomTableBody = ({ rowIds, Row, style, className }) => (
|
||||
@@ -337,13 +356,13 @@ const CustomTableBody = ({ rowIds, Row, style, className }) => (
|
||||
);
|
||||
|
||||
const { publicRuntimeConfig } = getConfig()
|
||||
|
||||
class Entreprise extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem('loginRedirect', window.location.pathname)
|
||||
this.props.countCompanyViewRequest(this.props.company.id);
|
||||
}
|
||||
|
||||
@@ -357,9 +376,9 @@ class Entreprise extends React.Component {
|
||||
|
||||
render() {
|
||||
const { classes, company } = this.props;
|
||||
const logoUrl = (company.logo ? publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + company.logo : "https://www.talentstube.com/img/default_picture_svg")
|
||||
const logoUrl = (company.logo ? publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + company.logo : publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg")
|
||||
|
||||
const DefaultUrl = "https://www.talentstube.com/img/default_picture_svg"
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = (company.presentation_video && company.presentation_video.thumbnails[0] && company.presentation_video.thumbnails[0].sizes[2]) ? company.presentation_video.thumbnails[0].sizes[2].link : DefaultUrl
|
||||
|
||||
const offre = (company.count_ads == 1) ? company.count_ads + ' offre' : company.count_ads + ' offres'
|
||||
@@ -384,11 +403,12 @@ class Entreprise extends React.Component {
|
||||
const { loading } = this.state;
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl + `/Entreprise/${company.id}`;
|
||||
|
||||
const descriptionVille = company.addresses.billing.city ? company.addresses.billing.city : "";
|
||||
const descriptionCompany = company.brand_name ? company.brand_name : "";
|
||||
return (
|
||||
<LayoutCompany backLink="/Entreprises" companyId={company.id}>
|
||||
<OgHead seo_title={company.brand_name && company.brand_name}
|
||||
seo_description={company.description}
|
||||
<OgHead seo_title={company.brand_name && company.brand_name+" recrute des candidats en vidéo | Talents Tube"}
|
||||
seo_description={"Découvrez l'entreprise "+descriptionCompany +" et ses offres en vidéo - "+descriptionVille+ ". Envoyez votre candidature spontanée en vidéo."}
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrl}
|
||||
></OgHead>
|
||||
@@ -414,17 +434,30 @@ class Entreprise extends React.Component {
|
||||
:
|
||||
(<Chip label={nbOffre} className={classes.chip + ' ' + classes.chipHeader} />)
|
||||
}
|
||||
|
||||
{/* ville */}
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.buttonContainer}>
|
||||
|
||||
<Link href="#discover" >
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.voirOffre + ' cypButtonApply'}
|
||||
>Voir les offres</Button>
|
||||
|
||||
</Link>
|
||||
<a href={`/Reponse?companyId=${company.id}`} className={classes.lien}>
|
||||
<Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
onClick={() => Router.push(`/Reponse?companyId=${company.id}`)}
|
||||
>Candidature spontanée</Button>
|
||||
</a>
|
||||
</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}>
|
||||
@@ -498,11 +531,19 @@ class Entreprise extends React.Component {
|
||||
</SimpleCollapse>
|
||||
|
||||
<div className={classes.shareContainer}>
|
||||
<Button
|
||||
{/* <Button
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
onClick={() => Router.push(`/Reponse?companyId=${company.id}`)}
|
||||
>Candidature spontanée</Button>
|
||||
>Candidature spontanée</Button> */}
|
||||
<a
|
||||
href={`/Reponse?companyId=${company.id}`}
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
classes={{ root: classes.rootButton }}
|
||||
// onClick={() => Router.push(`/Reponse?companyId=${companyId}`)}
|
||||
>Candidature spontanée</a>
|
||||
|
||||
<Typography className={classes.contentCondition}>
|
||||
ou
|
||||
</Typography>
|
||||
@@ -543,7 +584,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>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import getConfig from 'next/config'
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import _ from "lodash"
|
||||
import Grid from "../components/templates/Grid"
|
||||
@@ -11,6 +12,7 @@ import { fetchCompaniesRequest } from '../actions/companies'
|
||||
import { CompaniesSelector } from '../reducers/companies'
|
||||
import { connect } from "react-redux";
|
||||
import Head from 'next/head'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -61,16 +63,47 @@ 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();
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl + `/Entreprises`;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl ;
|
||||
return (
|
||||
<LayoutGrid backLink="/">
|
||||
<Head>
|
||||
{/* <Head>
|
||||
<title key="title">Entreprises qui recrutent – Talents Tube</title>
|
||||
<meta name="description" content="Les entreprises en vidéo." />
|
||||
</Head>
|
||||
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="@TalentsTube"/>
|
||||
<meta name="twitter:title" content="Les entreprises qui recrutent en vidéo | TalentsTube"/>
|
||||
<meta name="twitter:description" content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient."/>
|
||||
<meta name="twitter:image" content=""/>
|
||||
|
||||
|
||||
<meta property="og:title" content="Les entreprises qui recrutent en vidéo | TalentsTube"/>
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta property="og:image" content=""/>
|
||||
<meta property="og:description"
|
||||
content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient."/>
|
||||
<meta property="og:site_name" content="Talents Tube"/>
|
||||
<meta property="og:url"
|
||||
content=""/>
|
||||
|
||||
</Head> */}
|
||||
<OgHead seo_title="Vidéos marque employeur d'entreprises qui recrutent | Talents Tube"
|
||||
seo_description="Vidéos marque employeur d'entreprises qui recrutent, découvrez leurs offres d'emploi en vidéo. Postulez simplement en vidéo à l'offre de votre choix."
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrl}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
<Typography gutterBottom component="h1"
|
||||
className={classes.title}>
|
||||
Les entreprises en <span className={classes.primary}>vidéo</span>
|
||||
@@ -82,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"}
|
||||
/>
|
||||
|
||||
@@ -8,8 +8,8 @@ import { withStyles } from '@material-ui/core/styles';
|
||||
import Layout from "../components/templates/Layout"
|
||||
import Footer from '../components/organisms/Footer';
|
||||
import Link from 'next/link';
|
||||
import Head from 'next/head'
|
||||
import VideoVimeo from './../components/atoms/VideoVimeo'
|
||||
import Head from 'next/head';
|
||||
import VideoVimeo from './../components/atoms/VideoVimeo';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -102,6 +102,7 @@ function Help(props) {
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Recrutement vidéo : fonctionnement – Talents Tube</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<section className={classes.root}>
|
||||
<Typography gutterBottom component="h1"
|
||||
@@ -120,7 +121,7 @@ function Help(props) {
|
||||
<img alt="talents-tube" src='/static/images/help/image-aide-web-app.svg' className={classes.teamworkingImg} />
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Découvrez les offres d'emploi en vidéo
|
||||
Comment postuler à une offre d’emploi en vidéo
|
||||
</Typography>
|
||||
<VideoVimeo videoId='356411947' classesOverride={classes.video} autoplay='0'/>
|
||||
<Typography
|
||||
@@ -130,13 +131,34 @@ function Help(props) {
|
||||
</Typography>
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Vous possédez déjà un CV vidéo ?
|
||||
Comment réussir votre CV vidéo
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.text}
|
||||
gutterBottom>
|
||||
Vous n'avez pas trouvé votre bonheur dans nos offres d'emploi, mais vous souhaitez diffuser votre <span className={classes.bold}>CV vidéo à l'ensemble de notre communauté de talents.</span> <br></br> Découvrez les vidéos de nos talents sur notre CV vidéothèque.
|
||||
Suivez ce <a href="https://blog.talentstube.com/faire-cv-video" target="_blank" >lien</a>
|
||||
</Typography>
|
||||
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Accompagnement à la création d'un CV vidéo professionnel
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.text}
|
||||
gutterBottom>
|
||||
Suivez ce <a href="https://blog.talentstube.com/accompagnement-cv-video" target="_blank" >lien</a>
|
||||
</Typography>
|
||||
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Pourquoi faire un CV vidéo ?
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.text}
|
||||
gutterBottom>
|
||||
Suivez ce <a href="https://blog.talentstube.com/cv-video" target="_blank" >lien</a>
|
||||
</Typography>
|
||||
|
||||
|
||||
</section>
|
||||
<Footer />
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
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: { message: "" },
|
||||
loading: false,
|
||||
tabIndex: 0,
|
||||
openSnack: false,
|
||||
success: false,
|
||||
};
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
errors: !!!nextProps.errors ? { errors: { message: "" } } : nextProps.errors,
|
||||
loading: nextProps.loading,
|
||||
success: nextProps.success,
|
||||
openSnack: !_.isEmpty(nextProps.errors) || nextProps.success
|
||||
})
|
||||
}
|
||||
static getInitialProps({ query }) {
|
||||
const { error, inscription } = query
|
||||
let err = null;
|
||||
if (!!error)
|
||||
err = { message: error };
|
||||
return { errors: err, openSnack: !!error, inscription };
|
||||
}
|
||||
|
||||
handleClose = e =>
|
||||
this.setState({
|
||||
openSnack: false
|
||||
});
|
||||
|
||||
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,success, errors, loading, openSnack } = this.state;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Inscription</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} erreurs={errors.message} />
|
||||
|
||||
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
{/* <Snack name={success ? 'snackSuccess' : 'snackWarning'}
|
||||
variant={success ? 'success' : 'warning'}
|
||||
message={success ? 'Inscription validée.' : errors.message}
|
||||
openSnack={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));
|
||||
@@ -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';
|
||||
@@ -23,6 +23,7 @@ import jssPluginPropsSort from 'jss-plugin-props-sort';
|
||||
import Head from 'next/head'
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import getConfig from 'next/config'
|
||||
import FacebookLogin from 'react-facebook-login';
|
||||
const {publicRuntimeConfig} = getConfig()
|
||||
|
||||
function TabContainer({ children, dir }) {
|
||||
@@ -149,7 +150,8 @@ class LoginPage extends React.Component {
|
||||
errors: {},
|
||||
loading: false,
|
||||
tabIndex: 0,
|
||||
openSnack: false
|
||||
openSnack: false,
|
||||
redirection:""
|
||||
};
|
||||
|
||||
static getInitialProps({ query }) {
|
||||
@@ -175,8 +177,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')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -226,11 +231,14 @@ class LoginPage extends React.Component {
|
||||
handleClose = (event, reason) => {
|
||||
this.setState({ openSnack: false });
|
||||
}
|
||||
responseFacebook = (response) => {
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { data, errors, loading, openSnack } = this.state;
|
||||
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
@@ -246,7 +254,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 +264,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}
|
||||
@@ -276,7 +284,7 @@ class LoginPage extends React.Component {
|
||||
onChange={this.onChange}
|
||||
autoComplete="username"
|
||||
variant="outlined"
|
||||
error={this.state.errors && !!this.state.errors.email}
|
||||
error={!!!_.isEmpty(this.state.errors) || (this.state.errors && !!this.state.errors.email)}
|
||||
className={'cypInputEmail'}
|
||||
required
|
||||
|
||||
@@ -294,11 +302,19 @@ class LoginPage extends React.Component {
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
className={'cypInputPassword'}
|
||||
error={!!!_.isEmpty(this.state.errors)}
|
||||
helperText={!!!_.isEmpty(this.state.errors) && this.state.errors.message}
|
||||
required
|
||||
/>
|
||||
<Button type="submit" variant="contained" className={classes.button + ' ' + classes.buttonImportant + ' cypButtonConnexion'}>
|
||||
Se connecter
|
||||
</Button>
|
||||
</Button>
|
||||
{/* <FacebookLogin
|
||||
appId="1800752833559014"
|
||||
autoLoad={true}
|
||||
fields="name,email,picture"
|
||||
textButton ="Connexion Facebook"
|
||||
callback={this.responseFacebook} /> */}
|
||||
<ReCAPTCHA
|
||||
id="component-outlined"
|
||||
ref={recaptchaRef}
|
||||
@@ -312,19 +328,21 @@ class LoginPage extends React.Component {
|
||||
>
|
||||
<Link href={"/ResetPassword"} className={classes.link}>
|
||||
Mot de passe oublié ?
|
||||
</Link>
|
||||
|
||||
</Link>
|
||||
|
||||
</Typography>
|
||||
|
||||
|
||||
<Typography
|
||||
{/* <Typography
|
||||
paragraph={true}
|
||||
align="center"
|
||||
className={classes.conditionalText}
|
||||
>Ou</Typography>
|
||||
>Ou</Typography> */}
|
||||
|
||||
|
||||
</form>
|
||||
<SocialButtonsAuth linkedInAuth={this.linkedInAuth} facebookAuth={this.facebookAuth} />
|
||||
{/* <SocialButtonsAuth linkedInAuth={this.linkedInAuth} facebookAuth={this.facebookAuth} /> */}
|
||||
|
||||
<div className={classes.form}>
|
||||
<Typography
|
||||
@@ -332,9 +350,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,21 +366,22 @@ class LoginPage extends React.Component {
|
||||
</div>
|
||||
|
||||
</TabContainer>
|
||||
<TabContainer dir={'x'}>
|
||||
{/* <TabContainer dir={'x'}>
|
||||
<Register linkedInAuth={this.linkedInAuth} facebookAuth={this.facebookAuth} />
|
||||
</TabContainer>
|
||||
</TabContainer> */}
|
||||
</SwipeableViews>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
<Snack variant="error" message={!!!_.isEmpty(this.state.errors) && this.state.errors.message}
|
||||
openSnack={this.state.openSnack} onClose={this.handleClose} />
|
||||
{/* <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
|
||||
|
||||
@@ -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";
|
||||
import { fetchAdRequest, clearAd, countAdViewRequest } from '../actions/ads'
|
||||
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} isProvided={offre.is_promoted}>
|
||||
<OffreDetail offre={offre}/>
|
||||
<LayoutOffre backLink="/Offres" offreId={offre.id} offre={offre} isProvided={offre.is_promoted}>
|
||||
{/* <Suspense fallback={renderLoader()}><OffreDetail offre={offre}/></Suspense> */}
|
||||
<Suspense fallback={renderLoader()}><OffreDetail offre={offre}/></Suspense>
|
||||
</LayoutOffre>
|
||||
);
|
||||
}
|
||||
@@ -42,7 +47,7 @@ class Offre extends React.Component {
|
||||
Offre.getInitialProps = function (context) {
|
||||
const { id } = context.query
|
||||
|
||||
context.store.dispatch(fetchAdRequest(id))
|
||||
context.store.dispatch(fetchJobRequest(id))
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -57,4 +62,4 @@ Offre.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchAdRequest, clearAd, countAdViewRequest})(Offre));
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchJobRequest, clearAd, countAdViewRequest})(Offre));
|
||||
|
||||
@@ -9,10 +9,12 @@ import LayoutGrid from "../components/templates/LayoutGrid";
|
||||
import Grid from "../components/templates/Grid"
|
||||
import OffreRow from "../components/organisms/OffreRow"
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { fetchAdsRequest, togglePromotedFilterRequest} from '../actions/ads'
|
||||
import { fetchJobsRequest, togglePromotedFilterRequest} from '../actions/ads'
|
||||
import { AdsSelector } from '../reducers/ads'
|
||||
import { TextField } from '@material-ui/core';
|
||||
import Head from 'next/head'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
import getConfig from 'next/config'
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
@@ -78,20 +80,41 @@ 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;
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl + `/Offres`;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl ;
|
||||
return (
|
||||
<LayoutGrid backLink="/">
|
||||
<Head>
|
||||
<title key="title">Offres d’emploi en vidéo – Talents Tube</title>
|
||||
<meta name="description" content="Les offres d'emploi en vidéo." />
|
||||
|
||||
</Head>
|
||||
<OgHead seo_title="Vidéos d'offres d'emploi, CDI, CDD, alternance et Stage | Talents Tube"
|
||||
seo_description="Vidéos d'offres d'emploi, CDI, CDD, alternance, stage et apprentissage d'entreprises qui recrutent sur Talents Tube."
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrl}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
|
||||
<Typography gutterBottom component="h1"
|
||||
className={classes.title}>
|
||||
@@ -99,18 +122,20 @@ class Offres extends React.Component {
|
||||
</Typography>
|
||||
<div className={classes.container}>
|
||||
<Grid CustomRowComponent={OffreRow}
|
||||
dataFetcher={this.props.fetchAdsRequest}
|
||||
dataFetcher={this.props.fetchJobsRequest}
|
||||
data={this.props.ads}
|
||||
currentPage={this.props.currentPage}
|
||||
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>
|
||||
@@ -140,4 +165,4 @@ function mapStateToProps(state) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchAdsRequest, togglePromotedFilterRequest })(Offres))
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchJobsRequest, togglePromotedFilterRequest })(Offres))
|
||||
|
||||
@@ -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);
|
||||
@@ -5,11 +5,11 @@ import PropTypes from 'prop-types';
|
||||
import Stepper from '@material-ui/core/Stepper';
|
||||
import Step from '@material-ui/core/Step';
|
||||
import StepLabel from '@material-ui/core/StepLabel';
|
||||
import { fetchAdRequest } from '../actions/ads'
|
||||
import { fetchJobRequest } from '../actions/ads'
|
||||
import { fetchCompanyRequest } from '../actions/companies'
|
||||
import { fetchCurrentUserRequest } from '../actions/user'
|
||||
import { uploadMedia } from '../actions/media'
|
||||
import Loader from './../components/templates/loader'
|
||||
import LoaderVideo from './../components/templates/loaderVideo'
|
||||
import Answer from '../components/organisms/Answer'
|
||||
import LayoutBack from '../components/templates/LayoutBack'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
@@ -36,9 +36,9 @@ const styles = theme => ({
|
||||
},
|
||||
rootStepperContainer: {
|
||||
padding: theme.spacing(2, 12),
|
||||
width: '25vw',
|
||||
width: '50vw',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
width: '7vw',
|
||||
width: '25vw',
|
||||
alignItems: 'center',
|
||||
},
|
||||
'& .MuiStep-horizontal, & .MuiStepLabel-iconContainer': {
|
||||
@@ -48,11 +48,30 @@ const styles = theme => ({
|
||||
},
|
||||
},
|
||||
'& .Mui-disabled .MuiStepConnector-line': {
|
||||
borderColor: theme.palette.answer.main + '!important',
|
||||
borderColor: 'd2d3d3 !important',
|
||||
},
|
||||
'& .Mui-disabled .MuiStepIcon-root': {
|
||||
color: theme.palette.answer.main + '!important',
|
||||
},
|
||||
'& .MuiStepIcon-root': {
|
||||
color: '#1689FB !important',
|
||||
},
|
||||
'& .MuiTypography-root ': {
|
||||
color: '#1e2327 !important',
|
||||
},
|
||||
|
||||
},
|
||||
stepContainer:{
|
||||
width:'600px',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
align: 'center',
|
||||
},
|
||||
stepLabel:{
|
||||
// width:'150px',
|
||||
// display:'inline',
|
||||
// alignItems: 'center',
|
||||
// align: 'center',
|
||||
},
|
||||
rootStepperDefault: {
|
||||
'& .MuiStepConnector-line': {
|
||||
@@ -75,15 +94,29 @@ const styles = theme => ({
|
||||
flexDirection: 'column',
|
||||
padding: theme.spacing(0, 1.5),
|
||||
},
|
||||
titreContainer: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '5px',
|
||||
maxWidth:'600px',
|
||||
boxShadow: '0px 6px 16px rgba(30, 35, 39, 0.15)',
|
||||
display: 'flex',
|
||||
padding: '25px',
|
||||
margin: '40px 0 20px 0',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
|
||||
},
|
||||
logoContainer: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: 60,
|
||||
height: 60,
|
||||
width: 75,
|
||||
height: 75,
|
||||
backgroundColor: 'white',
|
||||
boxShadow: '0px 6px 15px rgba(30, 35, 39, 0.10)',
|
||||
border: 'solid 5px white',
|
||||
borderRadius: '6px',
|
||||
marginLeft:'30px',
|
||||
|
||||
},
|
||||
recorderContainer: {
|
||||
//display: 'flex',
|
||||
@@ -107,11 +140,11 @@ const styles = theme => ({
|
||||
objectFit: 'contain',
|
||||
},
|
||||
title: {
|
||||
fontSize: '1em',
|
||||
fontSize: '1.25em',
|
||||
fontWeight: '500',
|
||||
},
|
||||
companyName: {
|
||||
fontSize: '0.9em',
|
||||
fontSize: '1em',
|
||||
fontWeight: '300',
|
||||
},
|
||||
textContainer: {
|
||||
@@ -147,6 +180,12 @@ const styles = theme => ({
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
textButtonReponse: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2),
|
||||
color:'#1e2327',
|
||||
},
|
||||
iconHelpButton: {
|
||||
fontSize: '1.5em',
|
||||
fontWeight: '500',
|
||||
@@ -167,6 +206,7 @@ const styles = theme => ({
|
||||
},
|
||||
|
||||
captureButton: {
|
||||
width:400,
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: theme.spacing(5, 2),
|
||||
@@ -177,6 +217,7 @@ const styles = theme => ({
|
||||
},
|
||||
},
|
||||
importButton: {
|
||||
width:400,
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
@@ -198,9 +239,13 @@ const styles = theme => ({
|
||||
fontSize: '2.5em',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
InputKeyboardArrowDownIconNoir: {
|
||||
fontSize: '2.5em',
|
||||
color: '#1e2327',
|
||||
},
|
||||
});
|
||||
|
||||
const steps = ["", ""]
|
||||
const steps = ["Réaliser une vidéo de réponse", "Renseigner mes informations"]
|
||||
|
||||
const Recorder = dynamic(() => import('../components/organisms/Recorder'), {
|
||||
ssr: false
|
||||
@@ -214,14 +259,19 @@ class Reponse extends React.Component {
|
||||
data:{},
|
||||
openSnack: false,
|
||||
errors: {},
|
||||
openStudio : false
|
||||
};
|
||||
|
||||
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})
|
||||
@@ -265,6 +315,16 @@ class Reponse extends React.Component {
|
||||
this.setState({ openSnack: false });
|
||||
}
|
||||
|
||||
realise =() =>{
|
||||
console.log("realise");
|
||||
this.setState({ openStudio: true});
|
||||
}
|
||||
|
||||
retour =() =>{
|
||||
console.log("retour");
|
||||
this.setState({ openStudio: false});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loading, activeStep } = this.state;
|
||||
const { classes, menu, offre, company } = this.props;
|
||||
@@ -282,33 +342,35 @@ class Reponse extends React.Component {
|
||||
<title>Candidature vidéo</title>
|
||||
<meta name="description" content="Talent's tube, postulez en video." />
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
<link rel="canonical" href="https://app.talentstube.com" />
|
||||
|
||||
</Head>
|
||||
{/* https://codesandbox.io/s/ii0us */}
|
||||
{ loading ?
|
||||
<Loader /> :
|
||||
<LoaderVideo /> :
|
||||
<Fragment>
|
||||
|
||||
<section className={classes.headerContainer}>
|
||||
{ !!offre.company && (
|
||||
|
||||
<Fragment>
|
||||
<div className={classes.logoContainer}>
|
||||
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoUrl} alt="companylogo"/>
|
||||
</div>
|
||||
<div className={classes.infoContainer}>
|
||||
<Typography gutterBottom variant="h5" component="h1" className={classes.title}>
|
||||
{!!offre.title? offre.title: ''}
|
||||
</Typography>
|
||||
<Typography gutterBottom variant="subtitle1" className={classes.companyName}>
|
||||
{!!offre.company.brand_name? offre.company.brand_name: ''}
|
||||
</Typography>
|
||||
{/* ville */}
|
||||
</div>
|
||||
</Fragment>)
|
||||
|
||||
<div className={classes.titreContainer}>
|
||||
<div className={classes.logoContainer}>
|
||||
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoUrl} alt="companylogo"/>
|
||||
</div>
|
||||
<div className={classes.infoContainer}>
|
||||
<Typography gutterBottom variant="h5" component="h1" className={classes.title}>
|
||||
{!!offre.title? offre.title: ''}
|
||||
</Typography>
|
||||
<Typography gutterBottom variant="subtitle1" className={classes.companyName}>
|
||||
{!!offre.company.brand_name? offre.company.brand_name: ''}
|
||||
</Typography>
|
||||
{/* ville */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{ !!company.brand_name && (<Fragment><div className={classes.logoContainer}>
|
||||
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoCompanyUrl} alt="companylogo"/>
|
||||
{/* <Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoCompanyUrl} alt="companylogo"/> */}
|
||||
</div>
|
||||
<div className={classes.infoContainer}>
|
||||
<Typography gutterBottom variant="h5" component="h1" className={classes.title}>
|
||||
@@ -322,92 +384,132 @@ class Reponse extends React.Component {
|
||||
}
|
||||
|
||||
</section>
|
||||
|
||||
<Stepper activeStep={activeStep} classes={{ root: rootStepper }} className={classes.rootStepperContainer}>
|
||||
<section className={classes.headerContainer}>
|
||||
<Stepper activeStep={activeStep} classes={{ root: rootStepper }} className={classes.rootStepperContainer} alternativeLabel>
|
||||
{steps.map((label, index) => {
|
||||
return (
|
||||
<Step key={label} >
|
||||
<StepLabel>{label}</StepLabel>
|
||||
<Step className={classes.stepContainer} key={index} >
|
||||
<StepLabel className={classes.stepLabel}>{label}</StepLabel>
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
</Stepper>
|
||||
</section>
|
||||
{loading ? ( <Loader />)
|
||||
: activeStep === 0 ?
|
||||
(
|
||||
<div className={classes.root}>
|
||||
|
||||
<div className={classes.textContainer}>
|
||||
<Typography gutterBottom align="center">
|
||||
Vous allez postuler en <span>vidéo</span> !
|
||||
</Typography>
|
||||
<Typography gutterBottom align="center">
|
||||
C'est <span>simple</span>,<span> rapide</span> et <span>plus humain</span>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div className={ classes.helpContainer}>
|
||||
<Button component="span" className={classes.helpButton} classes={{ root: classes.rootButton }} onClick={() => Router.push(`/Conseils`)}>
|
||||
<Typography align="center" className={classes.textButton}>
|
||||
Par <span className={classes.underlined}>ici</span> pour quelques conseils !
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.HelpKeyboardArrowRightIcon }/>
|
||||
</Button>
|
||||
</div>
|
||||
{ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ?
|
||||
(
|
||||
<Fragment>
|
||||
<input
|
||||
type="file" accept="video/*" capture="camcorder"
|
||||
className={classes.input}
|
||||
style={{ display: 'none' }}
|
||||
id="record-button-file"
|
||||
multiple
|
||||
onChange={this.inputCamRecorderChange}
|
||||
/>
|
||||
<label htmlFor="record-button-file">
|
||||
<Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/static/images/capture.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
Je <span className={classes.underlined}>réalise</span> ma vidéo de réponse
|
||||
{this.state.openStudio == false &&
|
||||
<div>
|
||||
{/* <div className={classes.textContainer}>
|
||||
<Typography gutterBottom align="center">
|
||||
Vous allez postuler en <span>vidéo</span> !
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/>
|
||||
<Typography gutterBottom align="center">
|
||||
C'est <span>simple</span>,<span> rapide</span> et <span>plus humain</span>
|
||||
</Typography>
|
||||
</div> */}
|
||||
|
||||
{/* <div className={ classes.helpContainer}>
|
||||
<Button component="span" className={classes.helpButton} classes={{ root: classes.rootButton }} onClick={() => Router.push(`/Conseils`)}>
|
||||
<Typography align="center" className={classes.textButton}>
|
||||
Par <span className={classes.underlined}>ici</span> pour quelques conseils !
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.HelpKeyboardArrowRightIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
</Fragment>
|
||||
</div> */}
|
||||
</div>
|
||||
}
|
||||
{/* Soit on affiche le module Web RTC soit on affiche un module de camrecorder */}
|
||||
{ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ?
|
||||
(
|
||||
<Fragment>
|
||||
<input
|
||||
type="file" accept="video/*" capture="camcorder"
|
||||
className={classes.input}
|
||||
style={{ display: 'none' }}
|
||||
id="record-button-file"
|
||||
multiple
|
||||
onChange={this.inputCamRecorderChange}
|
||||
/>
|
||||
<label htmlFor="record-button-file">
|
||||
<Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/statique/images/capture.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
Je <span className={classes.underlined}>réalise</span> ma vidéo de réponse
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
</Fragment>
|
||||
):
|
||||
(
|
||||
<div className={classes.recorderContainer}>
|
||||
<Recorder uploader={this.props.uploadMedia} />
|
||||
</div>
|
||||
<Fragment>
|
||||
|
||||
{this.state.openStudio == false ?
|
||||
<Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }} onClick={this.realise}>
|
||||
<img alt="talents-tube" src='/statique/images/capture.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
Je <span className={classes.underlined}>réalise</span> ma vidéo de réponse
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/>
|
||||
</Button>
|
||||
:
|
||||
<div className={classes.recorderContainer}>
|
||||
<Recorder uploader={this.props.uploadMedia} />
|
||||
<Button onClick={this.retour}>Revenir au menu</Button>
|
||||
</div>
|
||||
|
||||
}
|
||||
</Fragment>
|
||||
// <div className={classes.recorderContainer}>
|
||||
// <Recorder uploader={this.props.uploadMedia} />
|
||||
// </div>
|
||||
)
|
||||
}
|
||||
|
||||
<input
|
||||
type="file"
|
||||
accept="video/*"
|
||||
className={classes.input+' cypButtonImportVid'}
|
||||
style={{ display: 'none' }}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/static/images/import.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma vidéo de réponse
|
||||
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
|
||||
{this.state.openStudio == false ?
|
||||
<div>
|
||||
<div>
|
||||
<input
|
||||
type="file"
|
||||
accept="video/*"
|
||||
className={classes.input+' cypButtonImportVid'}
|
||||
style={{ display: 'none' }}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/statique/images/Import.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma vidéo de réponse
|
||||
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }} onClick={() => Router.push(`/Conseils`)}>
|
||||
<img alt="talents-tube" src='/statique/images/comment-faire-une-video-reponse.svg' className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButtonReponse}>
|
||||
Comment faire ma vidéo de réponse
|
||||
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={ classes. InputKeyboardArrowDownIconNoir }/>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div></div>
|
||||
}
|
||||
</div>
|
||||
) :
|
||||
(
|
||||
<Answer mediaId={!!this.props.media && this.props.media.id}
|
||||
companyId={!!offre.company ? offre.company.id : !!company.brand_name ? company.id : null}
|
||||
adId={offre.id}>
|
||||
adId={offre.id}
|
||||
>
|
||||
</Answer>
|
||||
)}
|
||||
<Snack variant="error" message={!!!_.isEmpty(this.state.errors) && this.state.errors.message }
|
||||
@@ -426,10 +528,10 @@ 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(fetchAdRequest(adId))
|
||||
context.store.dispatch(fetchJobRequest(adId))
|
||||
else if(!!companyId)
|
||||
context.store.dispatch(fetchCompanyRequest(companyId))
|
||||
|
||||
@@ -437,7 +539,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,
|
||||
@@ -452,4 +556,4 @@ Reponse.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchCurrentUserRequest, fetchAdRequest, fetchCompanyRequest, uploadMedia })(Reponse));
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchCurrentUserRequest, fetchJobRequest, fetchCompanyRequest, uploadMedia })(Reponse));
|
||||
@@ -107,6 +107,7 @@ class ResetPassword extends Component {
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Reset password</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<div className={classes.container}>
|
||||
<Typography
|
||||
|
||||
@@ -5,8 +5,15 @@ import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Router from 'next/router';
|
||||
import Head from 'next/head'
|
||||
|
||||
import { TextField } from '@material-ui/core';
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
margin: theme.spacing(1),
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
@@ -24,33 +31,74 @@ const styles = theme => ({
|
||||
width: '100%',
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Dosis',
|
||||
fontSize: '1.5em',
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '1.625em',
|
||||
fontWeight: '600',
|
||||
padding: theme.spacing(3, 0),
|
||||
},
|
||||
text: {
|
||||
fontFamily: 'Roboto',
|
||||
width:"400px",
|
||||
fontSize: '1em',
|
||||
fontWeight: '300',
|
||||
padding: theme.spacing(1, 0),
|
||||
},
|
||||
textSpam:{
|
||||
fontFamily: 'Roboto',
|
||||
width:"400px",
|
||||
fontSize: "1em",
|
||||
fontWeight: "500",
|
||||
padding: theme.spacing(1, 0),
|
||||
},
|
||||
email: {
|
||||
fontWeight: '500',
|
||||
},
|
||||
bottomText: {
|
||||
fontWeight: '500',
|
||||
},
|
||||
|
||||
iconButton:{
|
||||
marginTop: "50px",
|
||||
|
||||
[theme.breakpoints.down('md')]: {
|
||||
marginTop: "50px",
|
||||
|
||||
},
|
||||
},
|
||||
textContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
|
||||
},
|
||||
notUnderline:{
|
||||
textDecoration :'none'
|
||||
},
|
||||
rootButton: {
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.primary.important + '!important',
|
||||
},
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
marginTop: theme.spacing(4),
|
||||
marginBottom: theme.spacing(2),
|
||||
marginRight: 'auto',
|
||||
marginLeft: 'auto',
|
||||
padding: theme.spacing(1.2, 1),
|
||||
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),
|
||||
},
|
||||
champEmail:{
|
||||
width:'400px'
|
||||
}
|
||||
|
||||
});
|
||||
class VerifyEmail extends Component {
|
||||
@@ -62,18 +110,49 @@ class VerifyEmail extends Component {
|
||||
<title key="title">Vérification d'email</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<div className={classes.container}>
|
||||
<Typography gutterBottom align="center" className={classes.title}>
|
||||
Consultez vos e-mails
|
||||
</Typography>
|
||||
<Typography gutterBottom align="left" className={classes.text}>
|
||||
Un e-mail a été envoyé à l'adresse <span className={classes.email}>{email}</span>
|
||||
</Typography>
|
||||
<Typography gutterBottom align="left" className={classes.text}>
|
||||
Cliquez sur le lien dans l'e-mail que nous vous avons envoyé pour activer votre compte.
|
||||
</Typography>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.textContainer}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/inscription/inscription-plateforme-recrutement-video.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography gutterBottom align="center" className={classes.title}>
|
||||
Consultez vos e-mails
|
||||
</Typography>
|
||||
<Typography gutterBottom align="left" className={classes.text}>
|
||||
Cliquez sur le lien dans l’email que nous vous avons envoyé pour activer votre compte Talent. Vous pourrez ensuite vous connecter.
|
||||
|
||||
</Typography>
|
||||
<TextField
|
||||
value={email}
|
||||
className={classes.champEmail}
|
||||
id="emailVerif"
|
||||
name="emailVerif"
|
||||
label="Email"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
}}
|
||||
|
||||
/>
|
||||
<Typography align="center" className={classes.textSpam}>
|
||||
Vous n'avez pas reçu l'email ? Pensez à consulter vos spams
|
||||
</Typography>
|
||||
<a
|
||||
href={`/Login`}
|
||||
variant="contained"
|
||||
className={classes.notUnderline}
|
||||
|
||||
>
|
||||
<Button variant="contained" className={classes.button + ' ' + classes.buttonImportant + ' cypButtonConnexion'}>
|
||||
Se connecter
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
<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
|
||||
@@ -83,7 +162,7 @@ class VerifyEmail extends Component {
|
||||
onClick={() => Router.push('/Login')}
|
||||
>
|
||||
Suivant
|
||||
</Button>
|
||||
</Button> */}
|
||||
</section>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -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" />
|
||||
@@ -32,9 +32,9 @@ class MyDocument extends Document {
|
||||
{/* PWA primary color */}
|
||||
<meta name="theme-color" content={theme.palette.primary.main} />
|
||||
|
||||
<link href="https://fonts.googleapis.com/css?family=Dosis:200,300,400,500,600,700,800|Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Dosis:600|Roboto:200,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
|
||||
|
||||
@@ -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,17 +8,21 @@ import { Typography } from '@material-ui/core';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Router from 'next/router'
|
||||
import { connect } from 'react-redux'
|
||||
import { fetchEmphasisAdsRequest } from "../actions/ads";
|
||||
//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"
|
||||
import NoResult from './../components/atoms/NoResult';
|
||||
import Head from 'next/head'
|
||||
// import Head from 'next/head'
|
||||
import dynamic from 'next/dynamic'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
import getConfig from 'next/config'
|
||||
|
||||
const VideoSlider = dynamic(() => import('../components/organisms/ShortVideoHooker'), {
|
||||
ssr: false
|
||||
});
|
||||
// const VideoSlider = dynamic(() => import('../components/organisms/ShortVideoHooker'), {
|
||||
// ssr: false
|
||||
// });
|
||||
const HorizontalScroller = dynamic(() => import('../components/organisms/HorizontalScroller'), {
|
||||
ssr: false
|
||||
});
|
||||
@@ -34,7 +38,7 @@ const TileOffre = dynamic(() => import('../components/organisms/TileOffre'), {
|
||||
const Footer = dynamic(() => import('../components/organisms/Footer'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
@@ -138,31 +142,39 @@ const styles = theme => ({
|
||||
|
||||
class Index extends React.Component {
|
||||
state = {
|
||||
emphasisAds: [],
|
||||
emphasisJobs: [],
|
||||
emphasisCompanies: []
|
||||
}
|
||||
componentDidMount() {
|
||||
localStorage.setItem("loginRedirect", "/")
|
||||
this.props.fetchEmphasisAdsRequest({ isEmphasis: 1 })
|
||||
this.props.fetchEmphasisJobsRequest({ isEmphasis: 1 })
|
||||
this.props.fetchEmphasisCompaniesRequest({ isEmphasis: 1 })
|
||||
}
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
emphasisAds: nextProps.emphasisAds,
|
||||
emphasisJobs: nextProps.emphasisJobs,
|
||||
emphasisCompanies: nextProps.emphasisCompanies
|
||||
})
|
||||
}
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl ;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title"> Talents tube - La recherche d'emploi en vidéo</title>
|
||||
<meta name="description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement ! Installez notre application." />
|
||||
</Head>
|
||||
<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}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
<div className={classes.container}>
|
||||
|
||||
<VideoSlider />
|
||||
{/* <VideoSlider /> */}
|
||||
|
||||
<section className={classes.scrollerSection + ' ' + classes.scrollerSectionOffer}>
|
||||
<div
|
||||
@@ -179,11 +191,11 @@ class Index extends React.Component {
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
{this.state.emphasisAds.loading ?
|
||||
{this.state.emphasisJobs.loading ?
|
||||
(<Loader />)
|
||||
: !isEmpty(this.state.emphasisAds.data) ? (
|
||||
: !isEmpty(this.state.emphasisJobs.data) ? (
|
||||
<HorizontalScroller
|
||||
data={this.state.emphasisAds.data}
|
||||
data={this.state.emphasisJobs.data}
|
||||
className={classes.HorizontalScroller}
|
||||
type="offre"
|
||||
>
|
||||
@@ -253,7 +265,7 @@ class Index extends React.Component {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
emphasisAds: state.emphasisAds,
|
||||
emphasisJobs: state.emphasisJobs,
|
||||
emphasisCompanies: state.emphasisCompanies
|
||||
};
|
||||
}
|
||||
@@ -262,4 +274,4 @@ Index.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default (connect(mapStateToProps, { fetchEmphasisAdsRequest, fetchEmphasisCompaniesRequest })(withStyles(styles)(Index)));
|
||||
export default (connect(mapStateToProps, { fetchEmphasisJobsRequest, fetchEmphasisCompaniesRequest })(withStyles(styles)(Index)));
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import Layout from "../components/templates/Layout";
|
||||
import AccountProfile from "../components/organisms/AccountProfile";
|
||||
import AccountVideoPres from "../components/organisms/AccountVideoPres";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {
|
||||
padding: theme.spacing(4)
|
||||
}
|
||||
}));
|
||||
|
||||
const Account = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className={classes.root}>
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
direction="row"
|
||||
justify="space-between"
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
lg={4}
|
||||
md={6}
|
||||
xl={4}
|
||||
xs={12}
|
||||
>
|
||||
<AccountProfile />
|
||||
<div><br/></div>
|
||||
<AccountVideoPres />
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
lg={8}
|
||||
md={6}
|
||||
xl={8}
|
||||
xs={12}
|
||||
>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Account;
|
||||
@@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import {makeStyles} from '@material-ui/core/styles';
|
||||
import Layout from "../components/templates/Layout";
|
||||
import AccountProfile from "../components/organisms/AccountProfile";
|
||||
import { Typography } from '@material-ui/core';
|
||||
import Head from 'next/head'
|
||||
import AdBlockDetect from 'react-ad-block-detect';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '100%'
|
||||
},
|
||||
button: {
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
completed: {
|
||||
display: 'inline-block'
|
||||
},
|
||||
instructions: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1)
|
||||
},
|
||||
information: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: "#fff",
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
fontFamily: 'Roboto',
|
||||
[
|
||||
theme
|
||||
.breakpoints
|
||||
.up('md')
|
||||
]: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: theme.spacing(2, 2)
|
||||
},
|
||||
'& a': {
|
||||
textDecoration: 'none'
|
||||
},
|
||||
texteBlanc: {
|
||||
color: "#fff",
|
||||
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default function HorizontalNonLinearStepper() {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Profil – Talents Tube</title>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<div >
|
||||
|
||||
<AdBlockDetect >
|
||||
<div className={classes.information}>
|
||||
|
||||
<p>AdBlocks a été détecté. Pour que Talents Tube puisse fonctionner
|
||||
correctement, veuillez désactiver Ad Blocks</p>
|
||||
|
||||
</div>
|
||||
</AdBlockDetect>
|
||||
</div>
|
||||
<div >
|
||||
<AccountProfile/>
|
||||
</div>
|
||||
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import React from 'react';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Autocomplete from '@material-ui/lab/Autocomplete';
|
||||
import LocationOnIcon from '@material-ui/icons/LocationOn';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import parse from 'autosuggest-highlight/parse';
|
||||
import throttle from 'lodash/throttle';
|
||||
|
||||
function loadScript(src, position, id) {
|
||||
if (!position) {
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('async', '');
|
||||
script.setAttribute('id', id);
|
||||
script.src = src;
|
||||
position.appendChild(script);
|
||||
}
|
||||
|
||||
const autocompleteService = { current: null };
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
icon: {
|
||||
color: theme.palette.text.secondary,
|
||||
marginRight: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
export default function GoogleMaps() {
|
||||
const classes = useStyles();
|
||||
const [value, setValue] = React.useState(null);
|
||||
const [inputValue, setInputValue] = React.useState('');
|
||||
const [options, setOptions] = React.useState([]);
|
||||
const loaded = React.useRef(false);
|
||||
|
||||
if (typeof window !== 'undefined' && !loaded.current) {
|
||||
if (!document.querySelector('#google-maps')) {
|
||||
loadScript(
|
||||
'https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places',
|
||||
document.querySelector('head'),
|
||||
'google-maps',
|
||||
);
|
||||
}
|
||||
|
||||
loaded.current = true;
|
||||
}
|
||||
|
||||
const fetch = React.useMemo(
|
||||
() =>
|
||||
throttle((request, callback) => {
|
||||
autocompleteService.current.getPlacePredictions(request, callback);
|
||||
|
||||
}, 200),
|
||||
[],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
let active = true;
|
||||
|
||||
if (!autocompleteService.current && window.google) {
|
||||
autocompleteService.current = new window.google.maps.places.AutocompleteService();
|
||||
// console.log('autocompleteService.current');
|
||||
// console.log(autocompleteService.current);
|
||||
}
|
||||
if (!autocompleteService.current) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (inputValue === '') {
|
||||
setOptions(value ? [value] : []);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
fetch({ input: inputValue }, (results) => {
|
||||
if (active) {
|
||||
let newOptions = [];
|
||||
|
||||
if (value) {
|
||||
newOptions = [value];
|
||||
}
|
||||
|
||||
if (results) {
|
||||
newOptions = [...newOptions, ...results];
|
||||
}
|
||||
|
||||
setOptions(newOptions);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, [value, inputValue, fetch]);
|
||||
|
||||
return (
|
||||
<Autocomplete
|
||||
id="google-map-demo"
|
||||
style={{ width: 300 }}
|
||||
getOptionLabel={(option) => (typeof option === 'string' ? option : option.description)}
|
||||
filterOptions={(x) => x}
|
||||
options={options}
|
||||
autoComplete
|
||||
includeInputInList
|
||||
filterSelectedOptions
|
||||
value={value}
|
||||
onChange={(event, newValue) => {
|
||||
setOptions(newValue ? [newValue, ...options] : options);
|
||||
setValue(newValue);
|
||||
console.log("newValue");
|
||||
// console.log(newValue);
|
||||
console.log(newValue.description)
|
||||
let geocoder = new google.maps.Geocoder();
|
||||
let addresses = {};
|
||||
geocoder.geocode({ 'address': newValue.description }, function(results, status) {
|
||||
results.map((index, value) => [
|
||||
console.log(index.geometry.location.lat()+" "+index.geometry.location.lng())
|
||||
]);
|
||||
|
||||
|
||||
});
|
||||
|
||||
}}
|
||||
onInputChange={(event, newInputValue) => {
|
||||
setInputValue(newInputValue);
|
||||
console.log('newInputValue');
|
||||
console.log(newInputValue);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="Tapez une adresse" variant="outlined" fullWidth />
|
||||
)}
|
||||
renderOption={(option) => {
|
||||
// console.log('option');
|
||||
// console.log(option);
|
||||
const matches = option.structured_formatting.main_text_matched_substrings;
|
||||
const parts = parse(
|
||||
option.structured_formatting.main_text,
|
||||
matches.map((match) => [match.offset, match.offset + match.length]),
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid container alignItems="center">
|
||||
<Grid item>
|
||||
<LocationOnIcon className={classes.icon} />
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
{parts.map((part, index) => (
|
||||
<span key={index} style={{ fontWeight: part.highlight ? 700 : 400 }}>
|
||||
{part.text}
|
||||
</span>
|
||||
))}
|
||||
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{option.structured_formatting.secondary_text}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// server.autosuggest.js
|
||||
import React from 'react';
|
||||
import Autosuggest from 'react-autosuggest';
|
||||
// import './autosuggest.css';
|
||||
|
||||
class ServerAutoSuggest extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
//Define state for value and suggestion collection
|
||||
this.state = {
|
||||
value: '',
|
||||
suggestions: []
|
||||
};
|
||||
}
|
||||
|
||||
// Filter logic
|
||||
getSuggestions = async (value) => {
|
||||
const inputValue = value.trim().toLowerCase();
|
||||
let response = await fetch("http://www.omdbapi.com/?s=" + inputValue + "&apikey=a591bb53");
|
||||
let data = await response.json()
|
||||
return data;
|
||||
};
|
||||
|
||||
// Trigger suggestions
|
||||
getSuggestionValue = suggestion => suggestion.Title;
|
||||
|
||||
// Render Each Option
|
||||
renderSuggestion = suggestion => (
|
||||
<span className="sugg-option">
|
||||
<span className="icon-wrap"><img src={suggestion.Poster} /></span>
|
||||
<span className="name">
|
||||
{suggestion.Title}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
// OnChange event handler
|
||||
onChange = (event, { newValue }) => {
|
||||
this.setState({
|
||||
value: newValue
|
||||
});
|
||||
};
|
||||
|
||||
// Suggestion rerender when user types
|
||||
onSuggestionsFetchRequested = ({ value }) => {
|
||||
this.getSuggestions(value)
|
||||
.then(data => {
|
||||
if (data.Error) {
|
||||
this.setState({
|
||||
suggestions: []
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
suggestions: data.Search
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// Triggered on clear
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.setState({
|
||||
suggestions: []
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { value, suggestions } = this.state;
|
||||
|
||||
// Option props
|
||||
const inputProps = {
|
||||
placeholder: 'Type movie name',
|
||||
value,
|
||||
onChange: this.onChange
|
||||
};
|
||||
|
||||
// Adding AutoSuggest component
|
||||
return (
|
||||
<Autosuggest
|
||||
suggestions={suggestions}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
getSuggestionValue={this.getSuggestionValue}
|
||||
renderSuggestion={this.renderSuggestion}
|
||||
inputProps={inputProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ServerAutoSuggest;
|
||||
@@ -0,0 +1,342 @@
|
||||
/* eslint-disable jsx-a11y/anchor-is-valid */
|
||||
|
||||
import React, {Fragment} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Layout from "../components/templates/Layout"
|
||||
import { Typography } from '@material-ui/core';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Router from 'next/router'
|
||||
import { connect } from 'react-redux'
|
||||
import Loader from './../components/templates/loader'
|
||||
import { isEmpty } from "lodash"
|
||||
import NoResult from './../components/atoms/NoResult';
|
||||
import Head from 'next/head'
|
||||
import dynamic from 'next/dynamic'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
import getConfig from 'next/config'
|
||||
|
||||
import Autosuggest from 'react-autosuggest';
|
||||
|
||||
// const VideoSlider = dynamic(() => import('../components/organisms/ShortVideoHooker'), {
|
||||
// ssr: false
|
||||
// });
|
||||
const HorizontalScroller = dynamic(() => import('../components/organisms/HorizontalScroller'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const TileCompany = dynamic(() => import('../components/organisms/TileCompany'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const TileOffre = dynamic(() => import('../components/organisms/TileOffre'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const Footer = dynamic(() => import('../components/organisms/Footer'), {
|
||||
ssr: false
|
||||
});
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
textAlign: 'center',
|
||||
paddingTop: theme.spacing(20),
|
||||
justifyContent: 'center',
|
||||
},
|
||||
primary: {
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
},
|
||||
scrollerSection: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
paddingBottom: theme.spacing(6),
|
||||
'&>div': {
|
||||
paddingBottom: theme.spacing(3),
|
||||
},
|
||||
[theme.breakpoints.up('md')]: {
|
||||
padding: theme.spacing(2, 10),
|
||||
paddingBottom: theme.spacing(9),
|
||||
},
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
padding: theme.spacing(2, 30),
|
||||
paddingBottom: theme.spacing(9),
|
||||
},
|
||||
[theme.breakpoints.up('xl')]: {
|
||||
padding: theme.spacing(2, 55),
|
||||
},
|
||||
},
|
||||
scrollerSectionOffer: {
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
scrollerSectionCompany: {
|
||||
backgroundColor: theme.palette.background.grey,
|
||||
},
|
||||
card: {
|
||||
margin: theme.spacing(1),
|
||||
width: '96%',
|
||||
height: '100%',
|
||||
maxWidth: '640px',
|
||||
maxheight: '360px',
|
||||
|
||||
},
|
||||
HorizontalScroller: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
paper: {
|
||||
margin: theme.spacing(1),
|
||||
width: '96%',
|
||||
height: '100%',
|
||||
},
|
||||
media: {
|
||||
},
|
||||
svg: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
polygon: {
|
||||
fill: theme.palette.common.white,
|
||||
stroke: theme.palette.divider,
|
||||
strokeWidth: 4,
|
||||
},
|
||||
img: {
|
||||
maxWidth: '100%',
|
||||
|
||||
},
|
||||
titleContainer: {
|
||||
marginTop: theme.spacing(4),
|
||||
marginBottom: theme.spacing(3),
|
||||
},
|
||||
beforeTitle: {
|
||||
fontSize: '0.8em',
|
||||
fontWeight: '300',
|
||||
textAlign: 'center',
|
||||
textTransform: 'uppercase',
|
||||
color: theme.palette.secondary.text,
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Dosis',
|
||||
fontSize: '1.5em',
|
||||
fontWeight: '600',
|
||||
textAlign: 'center',
|
||||
},
|
||||
white: {
|
||||
color: theme.palette.common.white
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
margin: theme.spacing(0, 8),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
margin: 'auto',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
class Index extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
//Define state for value and suggestion collection
|
||||
this.state = {
|
||||
value: '',
|
||||
suggestions: [],
|
||||
valueMetier: '',
|
||||
suggestionsMetier: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem("loginRedirect", "/")
|
||||
|
||||
}
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// Filter logic
|
||||
getSuggestions = async (value) => {
|
||||
const inputValue = value.trim().toLowerCase();
|
||||
let response = await fetch(publicRuntimeConfig.symphonyUrl+"/api/getCompetences?q=" + inputValue );
|
||||
// let response = await fetch("http://www.omdbapi.com/?s=" + inputValue + "&apikey=a591bb53");
|
||||
let data = await response.json()
|
||||
return data;
|
||||
};
|
||||
|
||||
// Trigger suggestions
|
||||
getSuggestionValue = suggestion => suggestion.libelle;
|
||||
// Render Each Option
|
||||
renderSuggestion = suggestion => (
|
||||
<span className="sugg-option">
|
||||
|
||||
<span className="name">
|
||||
{suggestion.libelle} ({suggestion.code})
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
// OnChange event handler
|
||||
onChange = (event, { newValue }) => {
|
||||
this.setState({
|
||||
value: newValue
|
||||
});
|
||||
};
|
||||
|
||||
// Suggestion rerender when user types
|
||||
onSuggestionsFetchRequested = ({ value }) => {
|
||||
this.getSuggestions(value)
|
||||
.then(data => {
|
||||
if (data.Error) {
|
||||
this.setState({
|
||||
suggestions: []
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
suggestions: data
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// Triggered on clear
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.setState({
|
||||
suggestions: []
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// METIER
|
||||
// Filter logic
|
||||
getSuggestionsMetier = async (valueMetier) => {
|
||||
const inputValue = valueMetier.trim().toLowerCase();
|
||||
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;
|
||||
};
|
||||
|
||||
// Trigger suggestions
|
||||
getSuggestionMetierValue = suggestion => suggestion.libelle;
|
||||
// Render Each Option
|
||||
renderSuggestionMetier = suggestion => (
|
||||
<span className="sugg-option">
|
||||
|
||||
<span className="name">
|
||||
{suggestion.libelle} ({suggestion.code})
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
// OnChange event handler
|
||||
onChangeMetier = (event, { newValue }) => {
|
||||
this.setState({
|
||||
valueMetier: newValue
|
||||
});
|
||||
};
|
||||
|
||||
// Suggestion rerender when user types
|
||||
onSuggestionsMetierFetchRequested = ({ value }) => {
|
||||
this.getSuggestionsMetier(value)
|
||||
.then(data => {
|
||||
if (data.Error) {
|
||||
this.setState({
|
||||
suggestionsMetier: []
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
suggestionsMetier: data
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// Triggered on clear
|
||||
onSuggestionsMetierClearRequested = () => {
|
||||
this.setState({
|
||||
suggestionsMetier: []
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { value, suggestions, valueMetier, suggestionsMetier } = this.state;
|
||||
// Option props
|
||||
const inputProps = {
|
||||
placeholder: 'Saisir une compétence',
|
||||
value,
|
||||
onChange: this.onChange
|
||||
};
|
||||
|
||||
const inputPropsMetier = {
|
||||
placeholder: 'Saisir un métier',
|
||||
value:valueMetier,
|
||||
onChange: this.onChangeMetier
|
||||
};
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl ;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl
|
||||
return (
|
||||
<Layout>
|
||||
<OgHead seo_title="Talents Tube - Plateforme de recrutement en vidéo"
|
||||
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}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
<div className={classes.container}>
|
||||
|
||||
{/* <VideoSlider /> */}
|
||||
|
||||
<section className={classes.scrollerSection + ' ' + classes.scrollerSectionOffer}>
|
||||
|
||||
|
||||
|
||||
<Autosuggest
|
||||
suggestions={suggestions}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
getSuggestionValue={this.getSuggestionValue}
|
||||
renderSuggestion={this.renderSuggestion}
|
||||
inputProps={inputProps}
|
||||
/>
|
||||
<Autosuggest
|
||||
suggestions={suggestionsMetier}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsMetierFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsMetierClearRequested}
|
||||
getSuggestionValue={this.getSuggestionMetierValue}
|
||||
renderSuggestion={this.renderSuggestionMetier}
|
||||
inputProps={inputPropsMetier}
|
||||
/>
|
||||
</section>
|
||||
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Index.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default (connect(mapStateToProps, { })(withStyles(styles)(Index)));
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "Talents Tube",
|
||||
"short_name": "Talents Tube",
|
||||
"lang": "fr",
|
||||
"orientation":"portrait",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco16x16.png",
|
||||
"sizes": "16x16",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco32x32.png",
|
||||
"sizes": "32x32",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco57x57.png",
|
||||
"sizes": "57x57",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco114x114.png",
|
||||
"sizes": "114x114",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco180x180.png",
|
||||
"sizes": "180x180",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1689FB",
|
||||
"theme_color": "#1689FB",
|
||||
"gcm_sender_id":"103953800507"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,35 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="73.762" height="69.644" viewBox="0 0 73.762 69.644">
|
||||
<g id="Import" transform="translate(0 13.219)">
|
||||
<g id="Groupe_7895" data-name="Groupe 7895" transform="translate(53.502 2.911) rotate(131)">
|
||||
<rect id="Rectangle_316" data-name="Rectangle 316" width="37.465" height="23.87" transform="translate(0.976 1.838)"/>
|
||||
<rect id="Rectangle_321" data-name="Rectangle 321" width="4.656" height="4.656" transform="translate(2.783 18.724)" fill="#fff"/>
|
||||
<rect id="Rectangle_398" data-name="Rectangle 398" width="1.656" height="12.656" transform="translate(2.781 4.725)" fill="#fff"/>
|
||||
<rect id="Rectangle_399" data-name="Rectangle 399" width="1.656" height="8.656" transform="translate(5.781 8.725)" fill="#fff"/>
|
||||
<rect id="Rectangle_400" data-name="Rectangle 400" width="1.656" height="18.656" transform="translate(10.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_396" data-name="Tracé 396" d="M0-3H1.656V8.656H0Z" transform="translate(13.781 14.724)" fill="#fff"/>
|
||||
<rect id="Rectangle_401" data-name="Rectangle 401" width="1.656" height="18.656" transform="translate(17.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_397" data-name="Tracé 397" d="M0-3H1.656V15.656H0Z" transform="translate(20.781 7.725)" fill="#fff"/>
|
||||
<path id="Tracé_398" data-name="Tracé 398" d="M0-3H1.656V10.788H0Z" transform="translate(23.781 12.593)" fill="#fff"/>
|
||||
<rect id="Rectangle_402" data-name="Rectangle 402" width="1.656" height="18.656" transform="translate(27.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_399" data-name="Tracé 399" d="M0,9H1.656v6.656H0Z" transform="translate(33.781 7.725)" fill="#fff"/>
|
||||
<path id="Tracé_400" data-name="Tracé 400" d="M0-3H1.656V10.788H0Z" transform="translate(30.781 12.593)" fill="#fff"/>
|
||||
</g>
|
||||
<path id="Tracé_279" data-name="Tracé 279" d="M217.367,282.859l-6.93,6.93-48.507-6.93L155,275.93l6.93-6.93h55.437Z" transform="translate(-155 -233.363)" fill="#155ee4"/>
|
||||
<path id="Tracé_280" data-name="Tracé 280" d="M173,269v6.93h48.507l6.93-6.93Z" transform="translate(-166.07 -233.363)" opacity="0.25"/>
|
||||
<g id="Groupe_7897" data-name="Groupe 7897" transform="translate(28.442 19.099)">
|
||||
<g id="Groupe_7896" data-name="Groupe 7896" transform="translate(3.551)">
|
||||
<path id="Tracé_281" data-name="Tracé 281" d="M239.065,257.45a.488.488,0,0,1-.231-.039.939.939,0,0,1-.693-1.155,50.925,50.925,0,0,0,1.463-12.088,51.857,51.857,0,0,0-.346-6.006.969.969,0,1,1,1.925-.231,55.915,55.915,0,0,1,.346,6.237,52.807,52.807,0,0,1-1.5,12.55A.952.952,0,0,1,239.065,257.45Z" transform="translate(-238.104 -232.827)" fill="#25d89a"/>
|
||||
<path id="Tracé_282" data-name="Tracé 282" d="M240.5,229.337a1.021,1.021,0,0,1-.962-.808c-.077-.462-.154-.885-.27-1.347a.944.944,0,0,1,1.848-.385c.077.462.192.924.269,1.386a.969.969,0,0,1-.77,1.116A.141.141,0,0,1,240.5,229.337Z" transform="translate(-238.804 -226.042)" fill="#25d89a"/>
|
||||
</g>
|
||||
<path id="Tracé_283" data-name="Tracé 283" d="M233.084,279.525l-4.042-6.237a.972.972,0,1,1,1.617-1.078l3,4.62,4.62-3a.972.972,0,0,1,1.078,1.617Z" transform="translate(-228.879 -254.171)" fill="#25d89a"/>
|
||||
</g>
|
||||
<path id="Tracé_284" data-name="Tracé 284" d="M316.393,300.545h-9.008a.385.385,0,1,1,0-.77h8.7l5.505-5.659a.381.381,0,1,1,.539.539Z" transform="translate(-248.483 -248.739)" fill="#25d89a"/>
|
||||
<path id="Tracé_285" data-name="Tracé 285" d="M317.93,299.2h-6.545a.385.385,0,0,1,0-.77h6.237l4.2-4.312a.381.381,0,1,1,.539.539Z" transform="translate(-250.943 -248.739)" fill="#fa6362"/>
|
||||
<g id="Groupe_7899" data-name="Groupe 7899" transform="translate(30.144 40.641)">
|
||||
<g id="Groupe_7898" data-name="Groupe 7898" transform="translate(0 0)">
|
||||
<path id="Tracé_286" data-name="Tracé 286" d="M233.3,282l2.5,3.811,5.89-3.811h-3.542l-.654.423a1.636,1.636,0,0,0,.077-.423H233.3Z" transform="translate(-233.3 -282)" fill="#21b77e"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="Rectangle_325" data-name="Rectangle 325" width="55.437" height="13.859" transform="translate(0 42.566)" fill="#1689fb"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="73.762" height="56.426" viewBox="0 0 73.762 56.426"><defs><style>.a{fill:#fff;}.b{fill:#155ee4;}.c{opacity:0.25;}.d{fill:#25d89a;}.e{fill:#fa6362;}.f{fill:#21b77e;}.g{fill:#1689fb;}</style></defs><g transform="translate(0 0)"><g transform="translate(9.499)"><rect width="42.463" height="23.869" transform="translate(0 3.769) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(1.401 6.158) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(1.866 11.472) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(2.327 16.747) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(2.826 22.019) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(38.67 2.848) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(39.131 8.123) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(39.633 13.433) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(40.094 18.708) rotate(-5.093)"/><path class="a" d="M229.4,202.9l6.275,3.311-5.582,4.35Z" transform="translate(-210.257 -192.71)"/></g><path class="b" d="M217.367,282.859l-6.93,6.93-48.507-6.93L155,275.93l6.93-6.93h55.437Z" transform="translate(-155 -233.363)"/><path class="c" d="M173,269v6.93h48.507l6.93-6.93Z" transform="translate(-166.07 -233.363)"/><g transform="translate(28.442 19.099)"><g transform="translate(3.551)"><path class="d" d="M239.065,257.45a.488.488,0,0,1-.231-.039.939.939,0,0,1-.693-1.155,50.925,50.925,0,0,0,1.463-12.088,51.857,51.857,0,0,0-.346-6.006.969.969,0,0,1,1.925-.231,55.915,55.915,0,0,1,.346,6.237,52.807,52.807,0,0,1-1.5,12.55A.952.952,0,0,1,239.065,257.45Z" transform="translate(-238.104 -232.827)"/><path class="d" d="M240.5,229.337a1.021,1.021,0,0,1-.962-.808c-.077-.462-.154-.885-.27-1.347a.944.944,0,0,1,1.848-.385c.077.462.192.924.269,1.386a.969.969,0,0,1-.77,1.116A.141.141,0,0,1,240.5,229.337Z" transform="translate(-238.804 -226.042)"/></g><path class="d" d="M233.084,279.525l-4.042-6.237a.972.972,0,1,1,1.617-1.078l3,4.62,4.62-3a.972.972,0,0,1,1.078,1.617Z" transform="translate(-228.879 -254.171)"/></g><path class="d" d="M316.393,300.545h-9.008a.385.385,0,1,1,0-.77h8.7l5.505-5.659a.381.381,0,1,1,.539.539Z" transform="translate(-248.483 -248.739)"/><path class="e" d="M317.93,299.2h-6.545a.385.385,0,0,1,0-.77h6.237l4.2-4.312a.381.381,0,1,1,.539.539Z" transform="translate(-250.943 -248.739)"/><g transform="translate(30.144 40.641)"><g transform="translate(0 0)"><path class="f" d="M233.3,282l2.5,3.811,5.89-3.811h-3.542l-.654.423a1.636,1.636,0,0,0,.077-.423H233.3Z" transform="translate(-233.3 -282)"/></g></g><rect class="g" width="55.437" height="13.859" transform="translate(0 42.566)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="65.694" height="55" viewBox="0 0 65.694 55"><defs><style>.a{fill:#fff;}.b{fill:#fa6362;}.c{fill:#25d89a;}.d{fill:#d0e7fe;}.e{fill:#f8fcff;}</style></defs><g transform="translate(6.99 12.604)"><rect class="a" width="0.382" height="6.302" transform="translate(8.135)"/><rect class="b" width="0.382" height="6.302" transform="translate(8.25 10.503)"/><rect class="b" width="6.302" height="0.382" transform="translate(0 8.288)"/><rect class="a" width="6.302" height="0.382" transform="translate(10.503 8.135)"/><rect class="a" width="0.382" height="4.125" transform="translate(4.324 4.686) rotate(-45)"/><rect class="a" width="0.382" height="4.125" transform="translate(9.254 9.481) rotate(-45)"/><rect class="b" width="4.125" height="0.382" transform="translate(4.392 12.164) rotate(-45)"/><rect class="a" width="4.125" height="0.382" transform="translate(9.186 7.288) rotate(-45)"/></g><path class="c" d="M249.806,254.569H236.819A3.831,3.831,0,0,1,233,250.75v-9.931A3.831,3.831,0,0,1,236.819,237h12.986a3.831,3.831,0,0,1,3.819,3.819v9.931A3.831,3.831,0,0,1,249.806,254.569Z" transform="translate(-206.646 -214.465)"/><path class="d" d="M235.875,281.75,229,288.625l-48.125-6.875L174,274.875,180.875,268h55Z" transform="translate(-170.181 -233.625)"/><rect class="a" width="55" height="13.75" transform="translate(3.819 41.25)"/><path class="d" d="M185.58,296.5h-9.549a3.748,3.748,0,0,1-2.483-.917c-.8-.687.382-8.441.382-9.587H189.4v6.684A3.831,3.831,0,0,1,185.58,296.5Z" transform="translate(-169.73 -244.75)"/><path d="M177.368,258.556h-9.549A3.831,3.831,0,0,1,164,254.736V231.819A3.831,3.831,0,0,1,167.819,228h9.549a3.831,3.831,0,0,1,3.819,3.819v22.917A3.831,3.831,0,0,1,177.368,258.556Z" transform="translate(-164 -208.903)"/><path class="a" d="M178.533,259.028h-9.778c-2.1,0-3.056-1.719-3.056-3.819V233.819c0-2.1.955-3.819,3.056-3.819h9.778c2.1,0,3.056,1.719,3.056,3.819v21.389C181.589,257.309,180.634,259.028,178.533,259.028Z" transform="translate(-165.051 -210.139)"/><circle class="c" cx="6.875" cy="6.875" r="6.875" transform="translate(29.792 6.875)"/><path class="c" d="M180.042,279h-1.3A3.749,3.749,0,0,1,175,275.254v-6.111a3.749,3.749,0,0,1,3.743-3.743h1.3a3.749,3.749,0,0,1,3.743,3.743v6.111A3.749,3.749,0,0,1,180.042,279Z" transform="translate(-170.799 -232.018)"/><circle class="c" cx="2.941" cy="2.941" r="2.941" transform="translate(5.653 26.736)"/><path d="M181.589,282.1v5.309c0,2.1-.955,3.819-3.056,3.819h-9.778c-2.1,0-3.056-1.719-3.056-3.819V282.1Z" transform="translate(-165.051 -242.34)"/><circle class="a" cx="1.91" cy="1.91" r="1.91" transform="translate(6.875 42.396)"/><circle class="b" cx="1.26" cy="1.26" r="1.26" transform="translate(7.524 43.045)"/><g transform="translate(48.15)"><path class="e" d="M303.981,180.368a8.149,8.149,0,0,0-12.069,10.924,3.012,3.012,0,0,1-1.3,1.49.77.77,0,0,0,.229,1.451,2.89,2.89,0,0,0,.573.038h0a5.282,5.282,0,0,0,2.941-.955,8.018,8.018,0,0,0,3.858.955,8.183,8.183,0,0,0,5.767-2.368,7.961,7.961,0,0,0,2.368-5.767A8.183,8.183,0,0,0,303.981,180.368Zm-.649,10.885a7.129,7.129,0,0,1-5.118,2.1,7.236,7.236,0,0,1-3.667-.993.543.543,0,0,0-.229-.076.552.552,0,0,0-.267.076,4.7,4.7,0,0,1-2.559.955,4.748,4.748,0,0,0,1.375-1.91.48.48,0,0,0-.076-.5,7.219,7.219,0,0,1,.306-9.892,7.129,7.129,0,0,1,5.118-2.1,7.219,7.219,0,0,1,5.118,12.337Z" transform="translate(-290.064 -178)"/><path class="e" d="M308.557,192.3h-6.8a.458.458,0,1,0,0,.917h6.8a.458.458,0,1,0,0-.917Z" transform="translate(-297.009 -186.838)"/><path class="e" d="M308.557,198.1h-6.8a.458.458,0,1,0,0,.917h6.8a.458.458,0,1,0,0-.917Z" transform="translate(-297.009 -190.423)"/><path class="e" d="M306.265,203.9h-4.507a.458.458,0,1,0,0,.917h4.507a.441.441,0,0,0,.458-.458A.464.464,0,0,0,306.265,203.9Z" transform="translate(-297.009 -194.008)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="61.875" height="67.637" viewBox="0 0 61.875 67.637">
|
||||
<g id="capture" transform="translate(-3.819 12.637)">
|
||||
<path id="Tracé_267" data-name="Tracé 267" d="M249.806,254.569H236.819A3.831,3.831,0,0,1,233,250.75v-9.931A3.831,3.831,0,0,1,236.819,237h12.986a3.831,3.831,0,0,1,3.819,3.819v9.931A3.831,3.831,0,0,1,249.806,254.569Z" transform="translate(-206.646 -214.465)" fill="#25d89a"/>
|
||||
<path id="Tracé_268" data-name="Tracé 268" d="M235.875,281.75,229,288.625l-48.125-6.875L174,274.875,180.875,268h55Z" transform="translate(-170.181 -233.625)" fill="#d0e7fe"/>
|
||||
<rect id="Rectangle_315" data-name="Rectangle 315" width="55" height="13.75" transform="translate(3.819 41.25)" fill="#fff"/>
|
||||
<circle id="Ellipse_117" data-name="Ellipse 117" cx="6.875" cy="6.875" r="6.875" transform="translate(29.792 6.875)" fill="#25d89a"/>
|
||||
<text id="_" data-name="?" transform="matrix(0.921, 0.391, -0.391, 0.921, 45.851, 8.063)" fill="#ff5a5f" font-size="11" font-family="Roboto-Black, Roboto" font-weight="800"><tspan x="-2.801" y="0">?</tspan></text>
|
||||
<text id="_2" data-name="?" transform="translate(39.881 3.168) rotate(-20)" fill="#ff5a5f" font-size="16" font-family="Roboto-Black, Roboto" font-weight="800"><tspan x="-4.074" y="0">?</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,12 @@
|
||||
<svg id="Groupe_8099" data-name="Groupe 8099" xmlns="http://www.w3.org/2000/svg" width="65.497" height="40.618" viewBox="0 0 65.497 40.618">
|
||||
<path id="Tracé_401" data-name="Tracé 401" d="M0,0H62.62V35.2H0Z" transform="translate(0 5.559) rotate(-5.093)"/>
|
||||
<rect id="Rectangle_317" data-name="Rectangle 317" width="3.917" height="3.917" transform="translate(2.066 9.081) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_318" data-name="Rectangle 318" width="3.917" height="3.917" transform="translate(2.751 16.917) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_319" data-name="Rectangle 319" width="3.917" height="3.917" transform="translate(3.431 24.696) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_320" data-name="Rectangle 320" width="3.917" height="3.917" transform="translate(4.167 32.47) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_321" data-name="Rectangle 321" width="3.917" height="3.917" transform="translate(57.023 4.199) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_322" data-name="Rectangle 322" width="3.917" height="3.917" transform="translate(57.703 11.978) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_323" data-name="Rectangle 323" width="3.917" height="3.917" transform="translate(58.444 19.809) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_324" data-name="Rectangle 324" width="3.917" height="3.917" transform="translate(59.124 27.588) rotate(-5.093)" fill="#fff"/>
|
||||
<text id="_" data-name="?" transform="matrix(0.996, -0.087, 0.087, 0.996, 26.298, 31.189)" fill="#fff" font-size="29" font-family="Roboto-Bold, Roboto" font-weight="700"><tspan x="0" y="0">?</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F3F9FF;}
|
||||
.st1{fill:#1689FB;}
|
||||
</style>
|
||||
<g>
|
||||
<circle class="st0" cx="200.32" cy="200.12" r="194.12"/>
|
||||
<circle class="st1" cx="200.32" cy="144.75" r="69.37"/>
|
||||
<path class="st1" d="M265.84,233.39H134.8c-21.2,0-38.54,17.34-38.54,38.54v92.09c30.08,19.14,65.77,30.22,104.06,30.22
|
||||
s73.98-11.09,104.06-30.22v-92.09C304.38,250.73,287.04,233.39,265.84,233.39z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 755 B |
@@ -0,0 +1,42 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080">
|
||||
<defs>
|
||||
<radialGradient id="radial-gradient" cx="0.403" cy="0.395" r="1.057" gradientTransform="translate(0.146 -0.002) scale(0.637 1.004)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#155ee4"/>
|
||||
<stop offset="1" stop-color="#8dc6ff"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radial-gradient-2" cx="0.319" cy="0.609" r="1.639" gradientTransform="matrix(0.358, 0.411, -0.161, 0.912, 0.303, -0.077)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#1689fb"/>
|
||||
<stop offset="1" stop-color="#54d7e6"/>
|
||||
</radialGradient>
|
||||
<filter id="Tracé_105" x="781.117" y="346.457" width="822.06" height="723.468" filterUnits="userSpaceOnUse">
|
||||
<feOffset dy="-27" input="SourceAlpha"/>
|
||||
<feGaussianBlur stdDeviation="43" result="blur"/>
|
||||
<feFlood flood-opacity="0.161"/>
|
||||
<feComposite operator="in" in2="blur"/>
|
||||
<feComposite in="SourceGraphic"/>
|
||||
</filter>
|
||||
<radialGradient id="radial-gradient-3" cx="0.524" cy="0.704" r="0.76" gradientTransform="matrix(-0.323, -0.938, 0.872, -0.347, 0.079, 1.439)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#1689fb" stop-opacity="0.6"/>
|
||||
<stop offset="1" stop-color="#54d7e6" stop-opacity="0.6"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radial-gradient-4" cx="0.447" cy="0.416" r="1.057" gradientTransform="translate(0.162 -0.002) scale(0.637 1.004)" xlink:href="#radial-gradient-2"/>
|
||||
<radialGradient id="radial-gradient-5" cx="0.915" cy="0.609" r="1.568" gradientTransform="matrix(0.184, 0.259, -0.081, 1.582, 0.795, -0.591)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity="0.475"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip-Youtube_4">
|
||||
<rect width="1920" height="1080"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="Youtube_4" data-name="Youtube – 4" clip-path="url(#clip-Youtube_4)">
|
||||
<rect width="1920" height="1080" fill="#fff"/>
|
||||
<path id="Tracé_106" data-name="Tracé 106" d="M12369.043,2300.3s-141.664-1034.519,765.283-1034.519c214.947,0,511.67,196.543,697.428,58.283,408.648-304.154,352.379-1089.441,934.215-1425.363,574.066-331.437,1213.727-72.058,1566.926,55.155s-251.332,2385.215-251.332,2385.215" transform="translate(-14153.795 -949.145)" fill="url(#radial-gradient)"/>
|
||||
<path id="Tracé_101" data-name="Tracé 101" d="M11762.942,398.383s55.409-341.747,332.711-280.328,290.146,146.232,543.427,0,251.155-350.119,595.736-131.889,887.4,587.9,856.8,724.362-2328.67,85.529-2328.67,85.529Z" transform="translate(-11803 322)" fill="url(#radial-gradient-2)"/>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" filter="url(#Tracé_105)">
|
||||
<path id="Tracé_105-2" data-name="Tracé 105" d="M12760.129,408.192c118.317,8.328,220.3,90.749,319.038-145.828s198.01,114.584,198.01,114.584l-493.051,268.977S12641.812,399.864,12760.129,408.192Z" transform="translate(-11803 322)" fill="#fff"/>
|
||||
</g>
|
||||
<path id="Tracé_102" data-name="Tracé 102" d="M534.949,72.539C818.824,72.539,1028,230.126,1028,514s-230.126,514-514,514S0,797.874,0,514,251.075,72.539,534.949,72.539Z" transform="translate(-200 201)" fill="url(#radial-gradient-3)"/>
|
||||
<path id="Tracé_103" data-name="Tracé 103" d="M12364.285,780.991s-57.706-421.407,311.735-421.407c87.558,0,208.426,80.061,284.094,23.741,166.461-123.9,143.54-443.779,380.548-580.615,233.844-135.01,494.406-29.353,638.281,22.467s-102.379,971.607-102.379,971.607" transform="translate(-11803 322)" fill="url(#radial-gradient-4)"/>
|
||||
<path id="Tracé_107" data-name="Tracé 107" d="M11779.612,537.613s427.922-55.028,1287.072,146.785,1121.613,162.176,1983.9-332.047,198.711,587.6,198.711,587.6L11739.1,909.484Z" transform="translate(-12748.872 179.263)" fill="url(#radial-gradient-5)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="277.043" height="328" viewBox="0 0 277.043 328">
|
||||
<g id="Groupe_7859" data-name="Groupe 7859" transform="translate(-4.489 -11.849)">
|
||||
<circle id="Ellipse_105" data-name="Ellipse 105" cx="40.594" cy="40.594" r="40.594" transform="translate(119.489 270.847) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_106" data-name="Ellipse 106" cx="40.594" cy="40.594" r="40.594" transform="translate(119.554 163.329) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_107" data-name="Ellipse 107" cx="48.799" cy="48.799" r="48.799" transform="translate(5.344 225.063) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_108" data-name="Ellipse 108" cx="48.799" cy="48.799" r="48.799" transform="matrix(-0.008, -1, 1, -0.008, 5.253, 110.195)"/>
|
||||
<circle id="Ellipse_109" data-name="Ellipse 109" cx="48.799" cy="48.799" r="48.799" transform="translate(5.235 339.849) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_110" data-name="Ellipse 110" cx="33.901" cy="33.901" r="33.901" transform="translate(213.73 210.028) rotate(-90.438)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 370 B |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 709 B |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.1 KiB |