Maquette de la nouvelle navigation par défilement
parent
fc752be767
commit
1de78d28e8
|
@ -0,0 +1,12 @@
|
|||
|
||||
#sim .tip {
|
||||
font-style: italic;
|
||||
margin-bottom: .6em;
|
||||
text-align: center;
|
||||
}
|
||||
#sim .tip p {
|
||||
margin: 0;
|
||||
}
|
||||
#sim .tip progress {
|
||||
margin-left: 1em;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import React, { Component } from 'react'
|
||||
import { connect } from "react-redux"
|
||||
import { withRouter } from "react-router"
|
||||
import './ProgressTip.css'
|
||||
|
||||
@withRouter
|
||||
@connect(state => ({
|
||||
done: state.done,
|
||||
foldedSteps: state.foldedSteps,
|
||||
nextSteps: state.nextSteps,
|
||||
}))
|
||||
export default class ProgressTip extends Component {
|
||||
state = {
|
||||
nbFoldedStepsForFirstEstimation: null
|
||||
}
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (newProps.done && this.state.nbFoldedStepsForFirstEstimation == null)
|
||||
this.setState({
|
||||
nbFoldedStepsForFirstEstimation: newProps.foldedSteps.length
|
||||
})
|
||||
}
|
||||
render() {
|
||||
let {done, nextSteps, foldedSteps} = this.props
|
||||
if (!done) return null
|
||||
return (
|
||||
<div className="tip">
|
||||
{nextSteps.length != 0 &&
|
||||
this.state.nbFoldedStepsForFirstEstimation ===
|
||||
foldedSteps.length && (
|
||||
<p>Votre première estimation est disponible !</p>
|
||||
)}
|
||||
{nextSteps.length != 0 && (
|
||||
<p>
|
||||
Il vous reste environ {nextSteps.length}{' '}
|
||||
{nextSteps.length === 1 ? 'questions' : 'question'} pour
|
||||
affiner le calcul
|
||||
<progress
|
||||
value={foldedSteps.length}
|
||||
max={foldedSteps.length + nextSteps.length}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,20 +1,28 @@
|
|||
|
||||
#resultsWrapper {
|
||||
height: 40%;
|
||||
#resultsZone {
|
||||
height: 49%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
#results {
|
||||
width: 100%;
|
||||
}
|
||||
#resultsContent {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
padding: .1em .3em;
|
||||
width: 95%;
|
||||
padding: .6em 0;
|
||||
width: 100%;
|
||||
max-width: 45em;
|
||||
background: #2975D1;
|
||||
color: white;
|
||||
box-shadow: 0px 0px 20px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
#results button {
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
#results-actions {
|
||||
background: #333350;
|
||||
}
|
||||
|
|
|
@ -1,68 +1,71 @@
|
|||
import R from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {connect} from 'react-redux'
|
||||
import { withRouter } from 'react-router'
|
||||
import R from "ramda"
|
||||
import React, { Component } from "react"
|
||||
import classNames from "classnames"
|
||||
import { Link } from "react-router-dom"
|
||||
import { connect } from "react-redux"
|
||||
import { withRouter } from "react-router"
|
||||
|
||||
import './Results.css'
|
||||
import {clearDict} from 'Engine/traverse'
|
||||
import {encodeRuleName} from 'Engine/rules'
|
||||
import RuleValueVignette from './rule/RuleValueVignette'
|
||||
import "./Results.css"
|
||||
import { clearDict } from "Engine/traverse"
|
||||
import { encodeRuleName } from "Engine/rules"
|
||||
import RuleValueVignette from "./rule/RuleValueVignette"
|
||||
import ProgressTip from "Components/ProgressTip"
|
||||
|
||||
@withRouter
|
||||
@connect(
|
||||
state => ({
|
||||
analysis: state.analysis,
|
||||
targetName: state.targetName,
|
||||
conversationStarted: !R.isEmpty(state.form),
|
||||
conversationFirstAnswer: R.path(['form', 'conversation', 'values'])(state),
|
||||
situationGate: state.situationGate
|
||||
})
|
||||
)
|
||||
@connect(state => ({
|
||||
analysis: state.analysis,
|
||||
targetName: state.targetName,
|
||||
conversationStarted: !R.isEmpty(state.form),
|
||||
conversationFirstAnswer: R.path(["form", "conversation", "values"])(state),
|
||||
situationGate: state.situationGate,
|
||||
done: state.done,
|
||||
}))
|
||||
export default class Results extends Component {
|
||||
render() {
|
||||
let {
|
||||
analysis,
|
||||
targetName,
|
||||
conversationStarted,
|
||||
conversationFirstAnswer,
|
||||
location
|
||||
} = this.props
|
||||
render() {
|
||||
let {
|
||||
analysis,
|
||||
targetName,
|
||||
conversationStarted,
|
||||
conversationFirstAnswer,
|
||||
location,
|
||||
done
|
||||
} = this.props
|
||||
|
||||
if (!analysis) return null
|
||||
if (!analysis) return null
|
||||
|
||||
let {targets} = analysis
|
||||
let { targets } = analysis
|
||||
|
||||
let onRulePage = R.contains('/regle/')(location.pathname)
|
||||
return (
|
||||
<div id="resultsWrapper">
|
||||
<section ref={el => this.el = el} id="results">
|
||||
{onRulePage && conversationStarted ?
|
||||
<div id ="results-actions">
|
||||
<Link id="toSimulation" to={'/simu/' + encodeRuleName(targetName)}>
|
||||
<i className="fa fa-arrow-circle-left" aria-hidden="true"></i>Reprendre la simulation
|
||||
</Link>
|
||||
</div>
|
||||
: <div id="results-titles">
|
||||
<h2><i className="fa fa-calculator" aria-hidden="true"></i>{targets.length == 1 ? 'Votre objectif' : 'Vos objectifs'}</h2>
|
||||
</div>
|
||||
}
|
||||
<Link
|
||||
className="edit"
|
||||
to="/"
|
||||
>
|
||||
<i className="fa fa-pencil-square-o" aria-hidden="true" />
|
||||
{' '}
|
||||
<span>Modifier</span>
|
||||
</Link>
|
||||
<ul>
|
||||
{targets.map( rule => <li key={rule.nom}>
|
||||
<RuleValueVignette {...rule} conversationStarted={conversationStarted} />
|
||||
</li>)}
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
let onRulePage = R.contains("/regle/")(location.pathname)
|
||||
return (
|
||||
<div id="resultsZone">
|
||||
<section id="results">
|
||||
<ProgressTip />
|
||||
<div id="resultsContent">
|
||||
<div id="results-titles">
|
||||
<h2>
|
||||
<i className="fa fa-calculator" aria-hidden="true" />
|
||||
{targets.length == 1 ? "Votre objectif" : "Vos objectifs"}
|
||||
</h2>
|
||||
</div>
|
||||
<Link className="edit" to="/">
|
||||
<i className="fa fa-pencil-square-o" aria-hidden="true" />
|
||||
{" "}
|
||||
<span>Modifier</span>
|
||||
</Link>
|
||||
<ul>
|
||||
{targets.map(rule => (
|
||||
<li key={rule.nom}>
|
||||
<RuleValueVignette
|
||||
{...rule}
|
||||
conversationStarted={conversationStarted}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
{done && <button>Comprendre mes résultats</button>}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.resultsGrid {
|
||||
margin-top: 6em;
|
||||
}
|
|
@ -9,7 +9,7 @@ import { humanFigure } from './rule/RuleValueVignette'
|
|||
|
||||
import { capitalise0 } from '../utils'
|
||||
import { nameLeaf } from 'Engine/rules'
|
||||
|
||||
import './ResultsGrid.css'
|
||||
// Filtered variables and rules can't be filtered in a uniform way, for now
|
||||
let paidBy = R.pathEq(['explanation', 'cotisation', 'dû par'])
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#sim {
|
||||
margin: 3% auto;
|
||||
margin: 0 auto;
|
||||
|
||||
color: #333350;
|
||||
transition: background-color .5s;
|
||||
height: 100%;
|
||||
width: 90%;
|
||||
max-width: 45em;
|
||||
font-size: 130%;
|
||||
|
||||
|
@ -75,17 +74,3 @@
|
|||
box-shadow: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#sim .tip {
|
||||
font-style: italic;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
#sim .tip p {
|
||||
margin: 0;
|
||||
}
|
||||
#sim .tip progress {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
|
|
@ -1,87 +1,64 @@
|
|||
import React, { Component } from 'react'
|
||||
import R from 'ramda'
|
||||
import Aide from '../Aide'
|
||||
import Satisfaction from '../Satisfaction'
|
||||
import { reduxForm } from 'redux-form'
|
||||
import { scroller, Element } from 'react-scroll'
|
||||
import React, { Component } from "react"
|
||||
import R from "ramda"
|
||||
import Aide from "../Aide"
|
||||
import Satisfaction from "../Satisfaction"
|
||||
import { reduxForm } from "redux-form"
|
||||
import { scroller, Element } from "react-scroll"
|
||||
|
||||
@reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
form: "conversation",
|
||||
destroyOnUnmount: false
|
||||
})
|
||||
export default class Conversation extends Component {
|
||||
state = {
|
||||
nbFoldedStepsForFirstEstimation: null
|
||||
}
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (newProps.done && this.state.nbFoldedStepsForFirstEstimation == null)
|
||||
this.setState({
|
||||
nbFoldedStepsForFirstEstimation: newProps.foldedSteps.length
|
||||
})
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
foldedSteps,
|
||||
currentQuestion,
|
||||
reinitalise,
|
||||
textColourOnWhite,
|
||||
done,
|
||||
nextSteps
|
||||
} = this.props
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.foldedSteps.length == this.props.foldedSteps.length)
|
||||
return null
|
||||
|
||||
// scroller.scrollTo('myScrollToElement', {
|
||||
// duration: 200,
|
||||
// delay: 100,
|
||||
// smooth: true
|
||||
// })
|
||||
console.log('will scroll')
|
||||
setTimeout(
|
||||
() =>
|
||||
scroller.scrollTo("myScrollToElement", {
|
||||
duration: 200,
|
||||
delay: 0,
|
||||
smooth: true
|
||||
}),
|
||||
1
|
||||
)
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
foldedSteps,
|
||||
currentQuestion,
|
||||
reinitalise,
|
||||
textColourOnWhite,
|
||||
done,
|
||||
nextSteps
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<>
|
||||
{!R.isEmpty(foldedSteps) && (
|
||||
<div id="foldedSteps">
|
||||
<div className="header">
|
||||
<h2>
|
||||
<i className="fa fa-mouse-pointer" aria-hidden="true" />Vos
|
||||
réponses
|
||||
</h2>
|
||||
<button
|
||||
onClick={reinitalise}
|
||||
style={{ color: textColourOnWhite }}
|
||||
>
|
||||
<i className="fa fa-trash" aria-hidden="true" />
|
||||
Tout effacer
|
||||
</button>
|
||||
</div>
|
||||
{foldedSteps}
|
||||
</div>
|
||||
)}
|
||||
<Element name="myScrollToElement" id="myScrollToElement">
|
||||
{done && (
|
||||
<div className="tip">
|
||||
{nextSteps.length != 0 &&
|
||||
this.state.nbFoldedStepsForFirstEstimation ===
|
||||
foldedSteps.length && (
|
||||
<p>Votre première estimation est disponible !</p>
|
||||
)}
|
||||
{nextSteps.length != 0 && (
|
||||
<p>
|
||||
Il vous reste environ {nextSteps.length}{' '}
|
||||
{nextSteps.length === 1 ? 'questions' : 'question'} pour
|
||||
affiner le calcul
|
||||
<progress
|
||||
value={foldedSteps.length}
|
||||
max={foldedSteps.length + nextSteps.length}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div id="currentQuestion">
|
||||
{currentQuestion || <Satisfaction simu={this.props.simu} />}
|
||||
</div>
|
||||
</Element>
|
||||
<Aide />
|
||||
</>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{!R.isEmpty(foldedSteps) && (
|
||||
<div id="foldedSteps">
|
||||
<div className="header">
|
||||
<button
|
||||
onClick={reinitalise}
|
||||
style={{ color: textColourOnWhite }}
|
||||
>
|
||||
<i className="fa fa-trash" aria-hidden="true" />
|
||||
Tout effacer
|
||||
</button>
|
||||
</div>
|
||||
{foldedSteps}
|
||||
</div>
|
||||
)}
|
||||
<Element name="myScrollToElement" id="myScrollToElement">
|
||||
{foldedSteps.length != 0 && <button>↑ Modifier mes réponses</button>}
|
||||
<div id="currentQuestion">
|
||||
{currentQuestion || <Satisfaction simu={this.props.simu} />}
|
||||
</div>
|
||||
</Element>
|
||||
<Aide />
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,26 @@
|
|||
height: 55%;
|
||||
}
|
||||
|
||||
#myScrollToElement button {
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
|
||||
#myScrollToElement, #foldedSteps {
|
||||
padding: 1em 1em;
|
||||
}
|
||||
|
||||
#foldedSteps {
|
||||
margin: 3em .3em;
|
||||
margin-bottom: 6em;
|
||||
}
|
||||
|
||||
#foldedSteps .header button {
|
||||
font-size: 80%;
|
||||
color: #2975D1;
|
||||
border: none;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#foldedSteps .header button i {
|
||||
margin-right: .3em;
|
||||
|
|
|
@ -1,67 +1,45 @@
|
|||
import React, { Component } from 'react'
|
||||
import './Layout.css'
|
||||
import './reset.css'
|
||||
import './ribbon.css'
|
||||
import React, { Component } from "react"
|
||||
import "./Layout.css"
|
||||
import "./reset.css"
|
||||
import "./ribbon.css"
|
||||
|
||||
import { Link, Route, Router, Switch, Redirect } from 'react-router-dom'
|
||||
import { Link, Route, Router, Switch, Redirect } from "react-router-dom"
|
||||
|
||||
import Home from 'Components/Home'
|
||||
import Rule from 'Components/rule/Rule'
|
||||
import Route404 from 'Components/Route404'
|
||||
import Contact from 'Components/Contact'
|
||||
import Simulateur from 'Components/Simulateur'
|
||||
import RulesList from 'Components/RulesList'
|
||||
import Home from "Components/Home"
|
||||
import Rule from "Components/rule/Rule"
|
||||
import Route404 from "Components/Route404"
|
||||
import Contact from "Components/Contact"
|
||||
import Simulateur from "Components/Simulateur"
|
||||
import RulesList from "Components/RulesList"
|
||||
|
||||
import ReactPiwik from 'Components/Tracker'
|
||||
import createHistory from 'history/createBrowserHistory'
|
||||
import ReactPiwik from "Components/Tracker"
|
||||
import createHistory from "history/createBrowserHistory"
|
||||
|
||||
const piwik = new ReactPiwik({
|
||||
url: 'stats.data.gouv.fr',
|
||||
siteId: 39,
|
||||
trackErrors: true
|
||||
url: "stats.data.gouv.fr",
|
||||
siteId: 39,
|
||||
trackErrors: true
|
||||
})
|
||||
|
||||
export default class Layout extends Component {
|
||||
history = createHistory()
|
||||
render() {
|
||||
let displayWarning = ['/simu/', '/regle/', '/regles'].find(
|
||||
t => window.location.href.toString().indexOf(t) > -1
|
||||
)
|
||||
history = createHistory()
|
||||
render() {
|
||||
// track the initial pageview
|
||||
ReactPiwik.push(["trackPageView"])
|
||||
|
||||
// track the initial pageview
|
||||
ReactPiwik.push(['trackPageView'])
|
||||
|
||||
return (
|
||||
<Router history={piwik.connectToHistory(this.history)}>
|
||||
<>
|
||||
<div id="header">
|
||||
{displayWarning && (
|
||||
<span id="ribbon">
|
||||
<Link to="/contact">
|
||||
<em>version beta</em>{' '}
|
||||
<i className="fa fa-flask" aria-hidden="true" />
|
||||
</Link>
|
||||
</span>
|
||||
)}
|
||||
{
|
||||
// this.props.location.pathname != '/' &&
|
||||
// <Link to="/">
|
||||
// <img id="site-logo" src={require('../images/logo.png')} />
|
||||
// </Link>
|
||||
}
|
||||
</div>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/contact" component={Contact} />
|
||||
<Route path="/regle/:name" component={Rule} />
|
||||
<Route path="/regles" component={RulesList} />
|
||||
<Route path="/simu/:targets" component={Simulateur} />
|
||||
<Redirect from="/simu/" to="/" />
|
||||
<Redirect from="/simu/:name/intro" to="/simu/:name" />
|
||||
<Route component={Route404} />
|
||||
</Switch>
|
||||
</>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Router history={piwik.connectToHistory(this.history)}>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/contact" component={Contact} />
|
||||
<Route path="/regle/:name" component={Rule} />
|
||||
<Route path="/regles" component={RulesList} />
|
||||
<Route path="/simu/:targets" component={Simulateur} />
|
||||
<Redirect from="/simu/" to="/" />
|
||||
<Redirect from="/simu/:name/intro" to="/simu/:name" />
|
||||
<Route component={Route404} />
|
||||
</Switch>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue