Ajout de briques pour l'économie collaborative

pull/507/head
Johan Girod 2019-04-12 19:09:27 +02:00
parent dcbbca149d
commit 60fb652df3
17 changed files with 366 additions and 212 deletions

View File

@ -1,5 +1,5 @@
.ui__.inverted-button:not(:disabled):active,
.ui__.button:not(:disabled):active {
.ui__.inverted-button:not(:disabled):not(.disabled):active,
.ui__.button:not(:disabled):not(.disabled):active {
animation: push-button-down 0.1s ease-out alternate-reverse 2;
}
@ -23,7 +23,9 @@
}
.ui__.button:disabled,
.ui__.inverted-button:disabled {
.ui__.button.disabled,
.ui__.inverted-button:disabled,
.ui__.inverted-button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
@ -64,7 +66,7 @@
);
color: white;
}
.ui__.button:not(:disabled):not(.simple):hover,
.ui__.button:not(:disabled):not(.disabled):not(.simple):hover,
.ui__.button.selected {
background-position-x: 0%;
border-color: white;
@ -93,8 +95,8 @@
color: white;
border-color: white;
}
.ui__.inverted-button:not(:disabled):hover,
.ui__.inverted-button:not(:disabled).selected {
.ui__.inverted-button:not(:disabled):not(.disabled):hover,
.ui__.inverted-button:not(:disabled):not(.disabled).selected {
background-color: rgba(255, 255, 255, 1);
color: rgb(41, 117, 209);
color: var(--colour);
@ -142,12 +144,12 @@
padding: 0.15em 0em;
}
.ui__.link-button:not(:disabled):hover,
.ui__.text-button:not(:disabled):hover,
.ui__.dashed-button:not(:disabled):hover,
.ui__.link-button:not(:disabled).selected,
.ui__.text-button:not(:disabled).selected,
.ui__.dashed-button:not(:disabled).selected {
.ui__.link-button:not(:disabled):not(.disabled):hover,
.ui__.text-button:not(:disabled):not(.disabled):hover,
.ui__.dashed-button:not(:disabled):not(.disabled):hover,
.ui__.link-button:not(:disabled):not(.disabled).selected,
.ui__.text-button:not(:disabled):not(.disabled).selected,
.ui__.dashed-button:not(:disabled):not(.disabled).selected {
opacity: 0.8;
}
@ -162,11 +164,11 @@
will-change: transform;
}
.ui__.skip.button:not(:disabled):hover {
.ui__.skip.button:not(:disabled):not(.disabled):hover {
opacity: 0.8;
transform: translateX(3px);
}
.ui__.skip.button.left:not(:disabled):hover {
.ui__.skip.button.left:not(:disabled):not(.disabled):hover {
transform: translateX(-3px);
}

View File

@ -0,0 +1,62 @@
.ui__.checkbox {
cursor: pointer;
position: relative;
margin: auto;
width: 18px;
line-height: 18px;
height: 18px;
-webkit-tap-highlight-color: transparent;
transform: translate3d(0, 0, 0);
outline: none !important;
}
.ui__.checkbox:before {
content: '';
position: absolute;
top: -11px;
left: -11px;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(34, 50, 84, 0.03);
opacity: 0;
transition: opacity 0.2s ease;
}
.ui__.checkbox svg {
position: relative;
z-index: 1;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke: #c8ccd4;
stroke: var(--colour);
stroke-width: 1.5;
transform: translate3d(0, 0, 0);
transition: all 0.2s ease;
}
.ui__.checkbox svg path {
stroke-dasharray: 60;
stroke-dashoffset: 0;
}
.ui__.checkbox svg polyline {
stroke-dasharray: 22;
stroke-dashoffset: 66;
}
.ui__.checkbox:hover:before,
.ui__.checkbox:focus:before {
opacity: 1;
}
.ui__.checkbox:hover svg {
stroke: var(--colour);
}
.ui__.checkbox-input:checked + .ui__.checkbox svg {
stroke: var(--colour);
}
.ui__.checkbox-input:checked + .ui__.checkbox svg path {
stroke-dashoffset: 60;
transition: all 0.3s linear;
}
.ui__.checkbox-input:checked + .ui__.checkbox svg polyline {
stroke-dashoffset: 42;
transition: all 0.2s linear;
transition-delay: 0.15s;
}

View File

@ -0,0 +1,21 @@
import React from 'react'
import './index.css'
export default function Checkbox(props) {
return (
<>
<input
type="checkbox"
className="ui__ checkbox-input"
style={{ display: 'none' }}
{...props}
/>
<label htmlFor={props.id} className="ui__ checkbox" tabIndex="0">
<svg width="18px" height="18px" viewBox="0 0 18 18">
<path d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z" />
<polyline points="1 9 7 14 15 4" />
</svg>
</label>
</>
)
}

View File

@ -1,66 +1,3 @@
.ui__.checkbox {
cursor: pointer;
position: relative;
margin: auto;
width: 18px;
line-height: 18px;
height: 18px;
-webkit-tap-highlight-color: transparent;
transform: translate3d(0, 0, 0);
outline: none !important;
}
.ui__.checkbox:before {
content: '';
position: absolute;
top: -11px;
left: -11px;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(34, 50, 84, 0.03);
opacity: 0;
transition: opacity 0.2s ease;
}
.ui__.checkbox svg {
position: relative;
z-index: 1;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke: #c8ccd4;
stroke: var(--colour);
stroke-width: 1.5;
transform: translate3d(0, 0, 0);
transition: all 0.2s ease;
}
.ui__.checkbox svg path {
stroke-dasharray: 60;
stroke-dashoffset: 0;
}
.ui__.checkbox svg polyline {
stroke-dasharray: 22;
stroke-dashoffset: 66;
}
.ui__.checkbox:hover:before,
.ui__.checkbox:focus:before {
opacity: 1;
}
.ui__.checkbox:hover svg {
stroke: var(--colour);
}
.ui__.checkbox-input:checked + .ui__.checkbox svg {
stroke: var(--colour);
}
.ui__.checkbox-input:checked + .ui__.checkbox svg path {
stroke-dashoffset: 60;
transition: all 0.3s linear;
}
.ui__.checkbox-input:checked + .ui__.checkbox svg polyline {
stroke-dashoffset: 42;
transition: all 0.2s linear;
transition-delay: 0.15s;
}
ul.ui__.checklist {
padding-left: 0.3rem;
}

View File

@ -4,6 +4,7 @@ import { ScrollToElement } from 'Components/utils/Scroll'
import withTracker from 'Components/utils/withTracker'
import React, { Component } from 'react'
import Animate from 'Ui/animate'
import Checkbox from '../Checkbox'
import './index.css'
import type { Tracker } from 'Components/utils/withTracker'
import type { ChildrenArray, Node, Element } from 'react'
@ -51,24 +52,13 @@ class CheckItemComponent extends Component<CheckItemProps, CheckItemState> {
<ScrollToElement onlyIfNotVisible when={this.state.displayExplanations}>
<div className="ui__ checkItemLabel">
{/* TODO ACCESSIBILITY: impossible to tick the checkbox with keyboard ? */}
<input
type="checkbox"
className="ui__ checkbox-input"
style={{ display: 'none' }}
<Checkbox
name={this.props.name}
id={this.props.name}
defaultChecked={this.props.defaultChecked}
onChange={this.handleChecked}
defaultChecked={this.props.defaultChecked}
/>
<label
htmlFor={this.props.name}
className="ui__ checkbox"
tabIndex="0">
<svg width="18px" height="18px" viewBox="0 0 18 18">
<path d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z" />
<polyline points="1 9 7 14 15 4" />
</svg>
</label>
<button
className={classnames('ui__ checklist-button', {
opened: this.state.displayExplanations

View File

@ -20,7 +20,6 @@ import ReactPiwik from '../../Tracker'
import './App.css'
import Footer from './layout/Footer/Footer'
import Navigation from './layout/Navigation/Navigation'
import ProgressHeader from './layout/ProgressHeader/ProgressHeader'
import trackSimulatorActions from './middlewares/trackSimulatorActions'
import CompanyIndex from './pages/Company'
import HiringProcess from './pages/HiringProcess'
@ -94,7 +93,6 @@ const App = compose(
{/* Passing location down to prevent update blocking */}
<Navigation location={location} />
<div className="app-content">
<ProgressHeader />
<div
className="ui__ container"
style={{ flexGrow: 1, flexShrink: 0, marginTop: '1rem' }}>

View File

@ -64,12 +64,12 @@ export default compose(
{emoji('🤝')} <T>Connaître les démarches d'embauche</T>
</Link>
<Link
className="ui__ button-choice ui__ button-choice--soon"
className="ui__ button-choice "
to={sitePaths.économieCollaborative.index}>
<span className="ui__ button-choice-label">
<T>prochainement</T>
</span>
{emoji('🏡')} <T>Déclarer mon activité d'économie collaborative</T>
{emoji('🏡')}{' '}
<T>
Déclarer mes revenus de plateforme en ligne (airbnb, leboncoin, etc.)
</T>
</Link>
{/*
<Link className="ui__ button-choice ui__ button-choice--soon" to={'/'}>

View File

@ -0,0 +1,81 @@
import classnames from 'classnames'
import withSitePaths from 'Components/utils/withSitePaths'
import { without } from 'ramda'
import React, { useState } from 'react'
import emoji from 'react-easy-emoji'
import { Link } from 'react-router-dom'
import Animate from 'Ui/animate'
import activités from './activités.yaml'
export default withSitePaths(function ActivitésSelection({ sitePaths }) {
let [itemsSelected, selectItem] = useState([])
return (
<Animate.fromBottom>
<h1>Quels types de revenus avez-vous ?</h1>
<p>
Les seuils de déclaration ne sont pas les mêmes en fonction du type
d'activité que vous exercez. Sélectionnez toutes les plateformes depuis
lesquelles vous avez reçu de l'argent durant l'année.
</p>
<ul
css={`
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
li > * {
width: 100%;
}
li {
margin: 1rem 0;
cursor: pointer;
text-align: center
width: 12em;
.title {
font-weight: 500;
}
img {
width: 2em !important;
height: 2em !important;
margin: 0.6em 0 !important;
}
p {
font-size: 95%;
font-style: italic;
text-align: center;
line-height: 1em;
}
}
li:hover, li.selected {background: var(--colour); color: white}
`}>
{activités.map(({ titre, exemples, icônes }) => {
let selected = itemsSelected.includes(titre)
return (
<li
className={classnames('ui__ card ', { selected })}
key={titre}
onClick={() =>
selectItem(
selected
? without([titre], itemsSelected)
: [...itemsSelected, titre]
)
}>
<div className="title">{titre}</div>
{emoji(icônes)}
<p>{exemples}</p>
</li>
)
})}
</ul>
<p css="text-align: right">
<Link
to={sitePaths.économieCollaborative.activités.locationMeublée}
className={classnames('ui__ plain button', {
disabled: !itemsSelected.length
})}>
Continuer
</Link>
</p>
</Animate.fromBottom>
)
})

View File

@ -0,0 +1,44 @@
import withSitePaths from 'Components/utils/withSitePaths'
import React from 'react'
import Animate from 'Ui/animate'
import { CheckItem, Checklist } from 'Ui/Checklist'
import pizzaSharing from './images/pizzaSharing.svg'
export default withSitePaths(function CoConsommation({ sitePaths }) {
return (
<Animate.fromBottom>
<h1>Co-consommation</h1>
<img
css="max-width: 100%; height: 200px; margin: 2rem auto;display:block;"
src={pizzaSharing}
/>
<p>
La co-consommation, c'est par exemple partagez votre voiture
(co-voiturage), des repas, ou encore des sorties. Le site le plus
emblématique est Blablacar.
</p>
<p>
Pour que ces revenus ne soient pas considérés comme des revenus
professionnels, vous devez confirmer ces deux conditions :
</p>
<Checklist key={'coConsommation'}>
<CheckItem
name="jeSuisBénéficiaire"
title="Je fait partie des bénéficiaires du service"
explanations="Les revenus que vous réalisez au titre du partage des frais sont perçus dans le cadre dune « co-consommation », ce qui signifie que vous bénéficiez également de la prestation de service proposée au même titre que les personnes avec lesquelles les frais sont partagés"
/>
<CheckItem
name="pasPlusCher"
title="Je ne fait pas payer les autres plus cher que cela me coute réellement (pas de bénéfice)"
explanations="Les revenus perçus nexcèdent pas le montant des coûts directs engagés à loccasion de la prestation. Ils ne doivent couvrir que les frais supportés à loccasion du service rendu (hors frais liés à lacquisition, lentretien ou lutilisation personnelle du bien partagé)"
/>
</Checklist>
<p className="ui__ answer-group">
<button className="ui__ simple button">Ce n'est pas le cas</button>
<button className="ui__ plain button" disabled>
Continuer
</button>
</p>
</Animate.fromBottom>
)
})

View File

@ -0,0 +1,41 @@
import { emoji, React } from 'Components'
import withSitePaths from 'Components/utils/withSitePaths'
import { Link } from 'react-router-dom'
import Animate from 'Ui/animate'
import illustration from './images/multitasking.svg'
export default withSitePaths(function Home({ sitePaths }) {
return (
<Animate.fromBottom>
<h1>Déclarer les revenus des plateformes en ligne</h1>
<img
css="max-width: 100%; height: 200px; margin: 2rem auto;display:block;"
src={illustration}
/>
<p>
Vous avez des revenus issus des <strong>plateformes en ligne</strong>{' '}
(Airbnb, Abritel, Drivy, Blablacar, Leboncoin, etc.), la loi vous oblige
à les déclarer. Mais il peut être parfois difficile de s'y retrouver
dans toute la documentation légale {emoji('🤔')}
</p>
<p>
C'est pourquoi nous avons conçu ce guide. En quelques clics, vous saurez
tout ce qu'il faut faire dans votre situation pour être en règle : ce
que vous devez déclarer, , et comment le faire.
</p>
<div css="text-align: center">
<Link
to={sitePaths.économieCollaborative.activités.index}
className="ui__ button plain cta">
Commencer le guide
</Link>
</div>
<p className="ui__ notice">
PS : cet outils est à but purement informatif, et non coercitif. Nous ne
stockons absolument aucune donnée utilisateur, tout ce que vous
saisissez reste sur votre navigateur. Vous pouvez donc répondre aux
questions suivantes l'esprit léger, en toute transparence {emoji('😌')}
</p>
</Animate.fromBottom>
)
})

View File

@ -0,0 +1,41 @@
import withSitePaths from 'Components/utils/withSitePaths'
import React from 'react'
import emoji from 'react-easy-emoji'
import { Link } from 'react-router-dom'
export default withSitePaths(function LocationMeublée({ sitePaths }) {
return (
<>
<h1>{emoji('🏡')} Location meublée</h1>
<p>
Vous avez loué un logement meublé pour de courtes durées à une clientèle
de passage qui n'y élit pas domicile (hors location de chambres dhôtes
et de meublé de tourisme)
</p>
<p>Vos recettes annuelles sont :</p>
<ul>
<li>
<Link
to={sitePaths.économieCollaborative.activités.coConsommation}
className="ui__ simple button">
Inférieures à 23 000
</Link>
</li>
<li>
<Link
to={sitePaths.économieCollaborative.activités.coConsommation}
className="ui__ simple button">
Situées entre 23 000 et 70 000
</Link>
</li>
<li>
<Link
to={sitePaths.économieCollaborative.activités.coConsommation}
className="ui__ simple button">
Supérieures à 70 000
</Link>
</li>
</ul>
</>
)
})

View File

@ -1,15 +1,15 @@
- titre: Location meublée
icônes: 🏠🛋️
icônes: 🏠 🛋
exemples: Airbnb, Abritel, chambre d'hôte...
- titre: Location de biens
icônes: 🔑🚗 🔧🌱
icônes: 🔑 🚗 🔧 🌱
exemples: Drivy, outils de jardinage, bricolage...
- titre: Services
icônes: 🚴🚕👩‍💻🍼
icônes: 🚴 🚕 👩‍💻 🍼
exemples: Deliveroo, Uber, sites internet, nounous...
- titre: Vente de biens
icônes: 📦🧶
icônes: 📦 🧶
exemples: Leboncoin, eBay, Etsy...
- titre: Co-consommation
icônes: 👥🚗
icônes: 👥 🚗
exemples: Blablacar, ...

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -1,110 +1,33 @@
import { React, emoji } from 'Components'
import { useState } from 'react'
import activités from './activités.yaml'
import { without } from 'ramda'
import classNames from 'classnames'
export default () => {
let [itemsSelected, selectItem] = useState([])
import withSitePaths from 'Components/utils/withSitePaths'
import React from 'react'
import { Route } from 'react-router'
import ActivitésSelection from './ActivitésSelection'
import CoConsommation from './CoConsommation'
import Home from './Home'
import LocationMeublée from './LocationMeublée'
export default withSitePaths(function ÉconomieCollaborative({ sitePaths }) {
return (
<div css="margin-top: 1em; ">
<p>
J'ai des revenus issus des <strong>plateformes en ligne</strong> :
Airbnb, Abritel, Drivy, Blablacar, Leboncoin, ...
</p>
<div css="display: flex; align-items: center ; margin: 0em 0 4em">
<span
css={`
margin-top: 0.6em;
img {
width: 2em !important;
height: 2em !important;
margin-right: 1em !important;
}
`}>
{emoji('🤔')}
</span>
<h1 css="font-size: 200%; ">
Comment être en règle ? <br />
Quelles cotisations et impôt ?
</h1>
</div>
<div>
<p>{emoji('✔️')} Sélectionnez vos revenus :</p>
<ul
css={`
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
li > * {
width: 100%;
}
li {
margin: 1em;
cursor: pointer;
text-align: center
width: 12em;
.title {
font-weight: 500;
}
img {
width: 2em !important;
height: 2em !important;
margin: 0.6em 0 !important;
}
p {
font-size: 95%;
font-style: italic;
text-align: center;
line-height: 1em;
}
}
li:hover, li.selected {background: var(--colour); color: white}
`}>
{activités.map(({ titre, exemples, icônes }) => {
let selected = itemsSelected.includes(titre)
return (
<li
className={classNames('ui__ card ', { selected })}
key={titre}
onClick={() =>
selectItem(
selected
? without([titre], itemsSelected)
: [...itemsSelected, titre]
)
}>
<div className="title">{titre}</div>
{emoji(icônes)}
<p>{exemples}</p>
{selected && (
<div
css={`
display: flex;
align-items: center;
justify-content: space-evenly;
`}>
<input
onClick={e => e.stopPropagation()}
css={`
width: 8em;
font-size: 100%;
border: none;
border-radius: 0.3em;
padding: 0.3em;
`}
placeholder="votre revenu"
/>
&nbsp;
</div>
)}
</li>
)
})}
</ul>
</div>
</div>
<>
<Route
exact
path={sitePaths.économieCollaborative.index}
component={Home}
/>
<Route
exact
path={sitePaths.économieCollaborative.activités.index}
component={ActivitésSelection}
/>
<Route
exact
path={sitePaths.économieCollaborative.activités.locationMeublée}
component={LocationMeublée}
/>
<Route
exact
path={sitePaths.économieCollaborative.activités.coConsommation}
component={CoConsommation}
/>
</>
)
}
})

View File

@ -107,7 +107,18 @@ export const constructLocalizedSitePath = (language: string) => {
index: t('path.démarcheEmbauche.index', '/démarches-embauche')
},
économieCollaborative: {
index: t('path.économieCollaborative.index', '/économie-collaborative')
index: t('path.économieCollaborative.index', '/économie-collaborative'),
activités: {
index: t('path.économieCollaborative.activitésSelection', '/activités'),
locationMeublée: t(
'path.économieCollaborative.locationMeublée',
'/location-meublée'
),
coConsommation: t(
'path.économieCollaborative.coConsommation',
'/co-consommation'
)
}
},
documentation: {
index: t('path.documentation.index', '/documentation')