instantjob-recruiter-client
Version:
a set of tools for creating an instantjob recruiter react client
344 lines (314 loc) • 9.81 kB
JSX
import React, {Component} from 'react'
import classNames from 'classnames/bind'
import {MdDone, MdFace, MdCheckBox, MdCheckBoxOutlineBlank} from 'react-icons/lib/md'
import Button from 'components/utils/button'
import ExclusiveField from 'components/exclusive_field'
import {color} from 'common/styles'
import {array_contains, array_from_hash, property_toggler, create_hash} from 'common/utilities'
import store from 'common/store'
import auto_bind from 'common/auto_bind'
import {alert_warning} from 'actions/display'
import {show_popover, dismiss_popover} from 'actions/display'
const examples = {
user: {
comment: `Ex: Numéro de dossier, Commentaire suite à l'entretien, Date de naissance ...`,
non_exclusive: `Ex: Langue, Compétences, Établissement préféré ...`,
exclusive: `Ex: Équipe, Dossier validé, Qualification ...`,
file: `Ex: Titre de séjour, Carte vitale, RIB ...`,
},
mission: {
comment: `Ex: Référence de la mission, Précisions sur l'accès au lieu, Données de contact ...`,
non_exclusive: `Ex: Matériel requis, Personnes à contacter ...`,
exclusive: `Ex: Client, Tenue vestimentaire ...`,
computed: `Ex: Montant HT, Montant TTC ...`,
},
mission_proposal: {
comment: `Ex: Chiffre d'affaire réalisé, Appréciation suite à la mission ...`,
non_exclusive: `Ex: Compétences validées ...`,
exclusive: `Ex: Note sur la mission, Tenue ...`,
template: `Ex: Contrat de travail, Autorisation d'accès au lieu de la mission ...`,
computed: `Ex: Nom du contact, Salaire, ...`,
},
shift: {
comment: `Ex: Commentaire, Nombre de clients servis, Bonus ...`,
non_exclusive: `Ex: Pause, Primes ...`,
exclusive: `Ex: Panier repas ...`,
computed: `Ex: Salaire, Prime de dimanche, ...`,
},
value: {
comment: `Ex: Numéro de téléphone ...`,
non_exclusive: `Ex: Matériel demandé ...`,
exclusive: `Ex: Type de client ...`,
computed: `Ex: Adresse complète ...`,
},
workplace: {
comment: `Ex: Numéro de téléphone ...`,
non_exclusive: `Ex: Équipements présents ...`,
exclusive: `Ex: Client ...`,
},
deal: {
computed: `Ex: Total HT, Total TTC ...`,
template: `Ex: Devis, Facture ...`
},
}
let cx = classNames.bind(require('styles/new_field_form.scss'))
class NewFieldForm extends Component {
constructor(props) {
super(props)
this.state = {
kind: this.props.type == "mission" && array_from_hash(this.props.existing_fields).length > 0 ? "" : "new"
}
auto_bind(this)
}
render() {
switch (this.state.kind) {
case "new":
return (
<New {...this.props} />
)
case "recycled":
return (
<Recycled {...this.props} />
)
default:
return (
<div className={cx('new-field-form')}>
<div className={cx('new-field-form__mission', 'new-field-form__mission_choice')}>
<span>Quel genre de champ voulez-vous créer ?</span>
<div className={cx('new-field-form__mission__buttons')}>
<div className={cx('new-field-form__mission__buttons__button')}>
<Button onClick={() => this.setState({kind: "new"})}>
Créer un champ mission spécifique
</Button>
</div>
<div className={cx('new-field-form__mission__buttons__description')}>
Vous pourrez ainsi renseigner des informations sur vos missions et choisir de les partager avec les candidats.
</div>
</div>
<div className={cx('new-field-form__mission__buttons')}>
<div className={cx('new-field-form__mission__buttons__button')}>
<Button onClick={() => this.setState({kind: "recycled"})}>
Réutiliser un champ candidat
</Button>
</div>
<div className={cx('new-field-form__mission__buttons__description')}>
Cela permet de réutiliser dans la fiche descriptive de la mission un champ utilisé pour filtrer vos candidats
</div>
</div>
</div>
</div>
)
}
}
}
class Recycled extends Component {
constructor(props) {
super(props)
this.state = {
id: false,
shared_with_user: false,
}
auto_bind(this)
}
toggle_shared_with_user() {
this.setState(property_toggler("shared_with_user"))
}
create_field() {
this.props.recycle_field(this.state)
}
render() {
return (
<div className={cx('new-field-form__mission')}>
<div>
<ExclusiveField
values={array_from_hash(this.props.existing_fields)}
selected={this.state.id}
on_clear={() => this.setState({id: false})}
name={"Quel champ voulez-vous réutiliser ?"}
on_select_value={(id) => this.setState({id})}
allow_creating_values={false}
/>
</div>
<Setting
label="Visible par le candidat"
toggle={this.toggle_shared_with_user}
/>
<div className={cx('new-field-form__create-button')}>
<Button disabled={!this.state.id} onClick={this.create_field} icon={MdDone}>
Créer le nouveau champ
</Button>
</div>
</div>
)
}
}
class New extends Component {
constructor(props) {
super(props)
this.state = {
name: "",
category: "non_exclusive",
shared_with_user: true,
shared_by_user: true,
}
auto_bind(this)
}
componentDidMount() {
this.name_input.focus()
}
create_field() {
this.props.create_field(this.state)
}
update_field(state) {
this.setState(state)
}
get_settings() {
switch (this.props.type) {
case "user":
return [{
label: "Renseigné par le candidat",
initial: this.state.shared_by_user,
toggle: () => this.setState(property_toggler("shared_by_user")),
}]
case "mission":
return [{
label: "Visible par le candidat",
initial: this.state.shared_with_user,
toggle: () => this.setState(property_toggler("shared_with_user")),
}]
default:
return []
}
}
render_setting(setting, index) {
return <Setting key={index} {...setting} />
}
render() {
let {type} = this.props
let {name, category} = this.state
return (
<div className={cx('new-field-form', 'new-field-form_new')}>
<div className={cx('new-field-form__parameters')}>
<FieldNameInput ref={(name_input) => this.name_input = name_input} on_change={this.update_field} />
<FieldCategorySelection
on_change={this.update_field}
options={Object.keys(examples[type])}
examples={examples[type][category]}
/>
</div>
{this.get_settings().map(this.render_setting)}
<div className={cx('new-field-form__create-button')}>
<Button disabled={name.trim().length == 0} onClick={this.create_field} icon={MdDone}>
Créer le nouveau champ
</Button>
</div>
</div>
)
}
}
class FieldNameInput extends Component {
constructor(props) {
super(props)
this.state = {
name: ""
}
auto_bind(this)
}
focus() {
this.input.focus()
}
onChange({target: {value: name}}) {
let state = {name}
this.setState(state)
this.props.on_change(state)
}
render() {
return (
<input
ref={(input) => this.input = input}
className={cx('new-field-form__name-input')}
type="text"
placeholder={"Nom"}
value={this.state.name}
onChange={this.onChange}
/>
)
}
}
class FieldCategorySelection extends Component {
constructor(props) {
super(props)
this.state = {
category: 'non_exclusive',
}
auto_bind(this)
}
on_change(category) {
let state = {category}
this.setState(state)
this.props.on_change(state)
}
make_option(id) {
let names = {
comment: 'Texte libre',
non_exclusive: 'Multi-valeur à choix multiples',
exclusive: 'Multi-valeur à choix unique',
file: 'Document stocké',
template: `Document généré à partir d'un modèle`,
computed: 'Valeur calculée',
}
return {id, name: names[id]}
}
render() {
let {options, examples} = this.props
return (
<div className={cx('new-field-form__category-selection')}>
<ExclusiveField
values={options.map(this.make_option)}
selected={this.state.category}
name={"Catégorie"}
on_select_value={this.on_change}
allow_creating_values={false}
searchable={false}
/>
<div className={cx('new-field-form__category-selection-examples')}>
{examples}
</div>
</div>
)
}
}
class Setting extends Component {
constructor(props) {
super(props)
this.state = {
checked: props.initial,
}
auto_bind(this)
}
toggle() {
this.setState(property_toggler('checked'))
this.props.toggle()
}
render() {
let {label} = this.props
return (
<div onClick={this.toggle} className={cx('new-field-form__setting', {'new-field-form__setting_checked': this.state.checked})}>
{this.state.checked ? (
<MdCheckBox />
) : (
<MdCheckBoxOutlineBlank />
)}
<div className={cx('new-field-form__setting-label')}>
{label}
</div>
</div>
)
}
}
NewFieldForm.defaultProps = {
create_field() {},
existing_fields: {},
type: 'mission',
}
export default NewFieldForm