Commit b1696d7a authored by Guilhem CARRON's avatar Guilhem CARRON
Browse files

Merge branch 'feat/US749-reinit-ecogesture-selection' into 'dev'

Feat/us749 reinit ecogesture selection

See merge request web-et-numerique/llle_project/ecolyo!605
parents 49b74c78 7556c498
......@@ -11,10 +11,12 @@ import { Link } from '@material-ui/core/'
interface EcogestureCardProps {
ecogesture: Ecogesture
selectionCompleted: boolean
}
const EcogestureCard: React.FC<EcogestureCardProps> = ({
ecogesture,
selectionCompleted,
}: EcogestureCardProps) => {
const [ecogestureIcon, setEcogestureIcon] = useState<string>('')
useEffect(() => {
......@@ -33,7 +35,10 @@ const EcogestureCard: React.FC<EcogestureCardProps> = ({
return (
<Link
to={`/ecogesture/${ecogesture.id}`}
to={{
pathname: `/ecogesture/${ecogesture.id}`,
state: { selectionCompleted },
}}
component={RouterLink}
className="ecogesture-list-item"
>
......
......@@ -12,11 +12,13 @@ interface EcogestureEmptyListProps {
setTab: React.Dispatch<React.SetStateAction<number>>
isObjective: boolean
isSelectionDone: boolean
handleReinitClick: () => void
}
const EcogestureEmptyList: React.FC<EcogestureEmptyListProps> = ({
setTab,
isObjective,
isSelectionDone,
handleReinitClick,
}: EcogestureEmptyListProps) => {
const { t } = useI18n()
const history = useHistory()
......@@ -57,6 +59,20 @@ const EcogestureEmptyList: React.FC<EcogestureEmptyListProps> = ({
>
{t('ecogesture.emptyList.btn1')}
</Button>
{isSelectionDone && (
<Button
aria-label={t('ecogesture.emptyList.reinit')}
onClick={handleReinitClick}
classes={{
root: 'reinit-button btn-profile-next rounded',
label: 'text-16-bold',
}}
>
{t('ecogesture.reinit')}
</Button>
)}
{!isSelectionDone && (
<Button
aria-label={t('ecogesture.emptyList.btn2')}
......
......@@ -11,13 +11,15 @@ import EcogestureCard from 'components/Ecogesture/EcogestureCard'
import StyledIcon from 'components/CommonKit/Icon/StyledIcon'
import Button from '@material-ui/core/Button'
import './ecogestureList.scss'
import { Usage } from 'enum/ecogesture.enum'
import { EcogestureStatus, Usage } from 'enum/ecogesture.enum'
interface EcogestureListProps {
list: Ecogesture[]
displaySelection: boolean
selectionTotal: number
selectionViewed: number
index: number
handleReinitClick: () => void
}
const EcogestureList: React.FC<EcogestureListProps> = ({
......@@ -25,6 +27,8 @@ const EcogestureList: React.FC<EcogestureListProps> = ({
displaySelection,
selectionTotal,
selectionViewed,
index,
handleReinitClick,
}: EcogestureListProps) => {
const { t } = useI18n()
const history = useHistory()
......@@ -50,7 +54,10 @@ const EcogestureList: React.FC<EcogestureListProps> = ({
.filter(ecogesture => Usage[ecogesture.usage] === activeFilter)
.map((ecogesture, index) => (
<div key={index} className="ecogesture-list-item">
<EcogestureCard ecogesture={ecogesture} />
<EcogestureCard
ecogesture={ecogesture}
selectionCompleted={selectionViewed === selectionTotal}
/>
</div>
))
if (filtered.length > 0) {
......@@ -163,23 +170,30 @@ const EcogestureList: React.FC<EcogestureListProps> = ({
)}
</div>
<div className="ecogesture-content">
{list.length > 0 && activeFilter === Usage[Usage.ALL] ? (
list.map((ecogesture, index) => (
<EcogestureCard ecogesture={ecogesture} key={index} />
))
) : list.length > 0 && activeFilter !== Usage[Usage.ALL] ? (
filterEcogesture(list)
) : !displaySelection ? (
<div className="ec-filter-error">
<div className="text-20-normal">
{t('ecogesture.no_ecogesture_filter.text1')}
</div>
<div className="text-16-italic">
{t('ecogesture.no_ecogesture_filter.text2')}
</div>
</div>
) : (
''
{list.length > 0 && activeFilter === Usage[Usage.ALL]
? list.map((ecogesture, index) => (
<EcogestureCard
ecogesture={ecogesture}
key={index}
selectionCompleted={selectionViewed === selectionTotal}
/>
))
: list.length > 0 && activeFilter !== Usage[Usage.ALL]
? filterEcogesture(list)
: !displaySelection && (
<div className="ec-filter-error">
<div className="text-20-normal">
{t('ecogesture.no_ecogesture_filter.text1')}
</div>
<div className="text-16-italic">
{t('ecogesture.no_ecogesture_filter.text2')}
</div>
</div>
)}
{!displaySelection && index !== EcogestureStatus.ALL && (
<button className="reinit-button" onClick={handleReinitClick}>
<span>{t('ecogesture.reinit')}</span>
</button>
)}
</div>
</div>
......
import React from 'react'
import { mount } from 'enzyme'
import toJson from 'enzyme-to-json'
import configureStore from 'redux-mock-store'
import { globalStateData } from '../../../tests/__mocks__/globalStateData.mock'
import { challengeStateData } from '../../../tests/__mocks__/challengeStateData.mock'
import { Provider } from 'react-redux'
import EcogestureReinitModal from './EcogestureReinitModal'
jest.mock('cozy-ui/transpiled/react/I18n', () => {
return {
useI18n: jest.fn(() => {
return {
t: (str: string) => str,
}
}),
}
})
const mockImportIconbyId = jest.fn()
jest.mock('utils/utils', () => {
return {
importIconbyId: jest.fn(() => {
return mockImportIconbyId
}),
}
})
const mockStore = configureStore([])
describe('EcogestureReinitModal component', () => {
it('should be rendered correctly', async () => {
const store = mockStore({
ecolyo: {
global: globalStateData,
challenge: challengeStateData,
},
})
const wrapper = mount(
<Provider store={store}>
<EcogestureReinitModal
open={true}
handleCloseClick={jest.fn()}
handleLaunchReinit={jest.fn()}
/>
</Provider>
)
expect(toJson(wrapper)).toMatchSnapshot()
})
})
import React from 'react'
import Dialog from '@material-ui/core/Dialog'
import { Button, IconButton } from '@material-ui/core'
import Icon from 'cozy-ui/transpiled/react/Icon'
import { useI18n } from 'cozy-ui/transpiled/react/I18n'
import CloseIcon from 'assets/icons/ico/close.svg'
import './ecogestureReinitModal.scss'
import warningIcon from 'assets/icons/ico/warn-orange.svg'
interface EcogestureReinitModalProps {
open: boolean
handleCloseClick: () => void
handleLaunchReinit: () => void
}
const EcogestureReinitModal: React.FC<EcogestureReinitModalProps> = ({
open,
handleCloseClick,
handleLaunchReinit,
}: EcogestureReinitModalProps) => {
const { t } = useI18n()
return (
<Dialog
open={open}
onClose={handleCloseClick}
aria-labelledby={'accessibility-title'}
classes={{
root: 'modal-root',
paper: 'modal-paper',
}}
>
<div id={'accessibility-title'}>
{t('feedback.accessibility.window_title')}
</div>
<IconButton
aria-label={t('feedback.accessibility.button_close')}
className="modal-paper-close-button"
onClick={handleCloseClick}
>
<Icon icon={CloseIcon} size={16} />
</IconButton>
<div className="eg-reinit-modal">
<Icon icon={warningIcon} size={63} />
<div className="title text-20-bold">
{t('ecogesture.reinitModal.title_part1')}
<span className="warn-title">
{t('ecogesture.reinitModal.title_part2')}
</span>
{t('ecogesture.reinitModal.title_part3')}
<span className="warn-title">
{t('ecogesture.reinitModal.title_part4')}
</span>
{t('ecogesture.reinitModal.title_part5')}
<span className="warn-title">
{t('ecogesture.reinitModal.title_part6')}
</span>
</div>
<div className="text-16-normal text">
{t('ecogesture.reinitModal.text1')}
</div>
<div className="text-16-bold text">
{t('ecogesture.reinitModal.text2')}
</div>
<div className="buttons-container">
<Button
aria-label={t('ecogesture.reinitModal.btn1')}
onClick={handleCloseClick}
className="btn1"
classes={{
root: 'btn-secondary-negative',
label: 'text-16-bold',
}}
>
{t('ecogesture.reinitModal.btn1')}
</Button>
<Button
aria-label={t('ecogesture.reinitModal.btn2')}
onClick={handleLaunchReinit}
classes={{
root: 'btn-profile-next rounded',
label: 'text-16-bold',
}}
>
{t('ecogesture.reinitModal.btn2')}
</Button>
</div>
</div>
</Dialog>
)
}
export default EcogestureReinitModal
......@@ -18,6 +18,7 @@ import { FluidType } from 'enum/fluid.enum'
import EcogestureEmptyList from './EcogestureEmptyList'
import { EcogestureStatus } from 'enum/ecogesture.enum'
import EcogestureInitModal from './EcogestureInitModal'
import EcogestureReinitModal from './EcogestureReinitModal'
import { updateProfile } from 'store/profile/profile.actions'
import { useHistory, useLocation } from 'react-router-dom'
import { ProfileEcogesture } from 'models/profileEcogesture.model'
......@@ -79,6 +80,13 @@ const EcogestureView: React.FC = () => {
const [openEcogestureInitModal, setOpenEcogestureInitModal] = useState<
boolean
>(!haveSeenEcogestureModal)
const [openEcogestureReinitModal, setOpenEcogestureReinitModal] = useState<
boolean
>(false)
const handleReinitClick = useCallback(() => {
setOpenEcogestureReinitModal(true)
}, [])
const handleLaunchForm = useCallback(async () => {
dispatch(updateProfile({ haveSeenEcogestureModal: true }))
......@@ -91,6 +99,22 @@ const EcogestureView: React.FC = () => {
setOpenEcogestureInitModal(false)
}, [dispatch])
const handleLaunchReinit = useCallback(async () => {
setOpenEcogestureReinitModal(false)
setIsLoaded(false)
const ecogestureService = new EcogestureService(client)
const reset = await ecogestureService.reinitAllEcogestures()
if (reset) {
setOpenEcogestureReinitModal(false)
setIsLoaded(true)
history.push('/ecogesture-form?modal=true')
}
}, [client, history])
const handleCloseEcogestureReinitModal = useCallback(() => {
setOpenEcogestureReinitModal(false)
}, [])
const handleChange = useCallback(
(event: React.ChangeEvent<{}>, newValue: any) => {
event.preventDefault()
......@@ -197,6 +221,7 @@ const EcogestureView: React.FC = () => {
})}
{...tabProps(EcogestureStatus.DOING)}
></Tab>
<Tab
label={getLabel(EcogestureStatus.ALL)}
className={classNames('single-tab', {
......@@ -215,6 +240,7 @@ const EcogestureView: React.FC = () => {
setTab={setTabValue}
isObjective={true}
isSelectionDone={true}
handleReinitClick={handleReinitClick}
/>
) : (
<EcogestureList
......@@ -222,6 +248,8 @@ const EcogestureView: React.FC = () => {
displaySelection={totalAvailable !== totalViewed}
selectionTotal={totalAvailable}
selectionViewed={totalViewed}
index={EcogestureStatus.OBJECTIVE}
handleReinitClick={handleReinitClick}
/>
)
) : (
......@@ -229,6 +257,7 @@ const EcogestureView: React.FC = () => {
setTab={setTabValue}
isObjective={true}
isSelectionDone={false}
handleReinitClick={handleReinitClick}
/>
)}
</TabPanel>
......@@ -241,6 +270,7 @@ const EcogestureView: React.FC = () => {
setTab={setTabValue}
isObjective={false}
isSelectionDone={true}
handleReinitClick={handleReinitClick}
/>
) : (
<EcogestureList
......@@ -248,6 +278,8 @@ const EcogestureView: React.FC = () => {
displaySelection={totalAvailable !== totalViewed}
selectionTotal={totalAvailable}
selectionViewed={totalViewed}
index={EcogestureStatus.DOING}
handleReinitClick={handleReinitClick}
/>
)
) : (
......@@ -255,9 +287,11 @@ const EcogestureView: React.FC = () => {
setTab={setTabValue}
isObjective={false}
isSelectionDone={false}
handleReinitClick={handleReinitClick}
/>
)}
</TabPanel>
<TabPanel value={tabValue} index={EcogestureStatus.ALL}>
{allEcogestureList.length && (
<EcogestureList
......@@ -265,6 +299,8 @@ const EcogestureView: React.FC = () => {
displaySelection={false}
selectionTotal={totalAvailable}
selectionViewed={totalViewed}
index={EcogestureStatus.ALL}
handleReinitClick={handleReinitClick}
/>
)}
</TabPanel>
......@@ -278,6 +314,13 @@ const EcogestureView: React.FC = () => {
handleLaunchForm={handleLaunchForm}
/>
)}
{openEcogestureReinitModal && (
<EcogestureReinitModal
open={openEcogestureReinitModal}
handleCloseClick={handleCloseEcogestureReinitModal}
handleLaunchReinit={handleLaunchReinit}
/>
)}
</>
)
}
......
......@@ -52,6 +52,12 @@ jest.mock('services/ecogesture.service', () => {
const mockStore = configureStore([])
jest.mock('react-router-dom', () => ({
useLocation: jest.fn().mockReturnValue({
state: { selectionCompleted: true },
}),
}))
describe('SingleEcogesture component', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
......
......@@ -24,6 +24,8 @@ import { useClient } from 'cozy-client'
import ErrorPage from 'components/CommonKit/ErrorPage/ErrorPage'
import StyledSpinner from 'components/CommonKit/Spinner/StyledSpinner'
import { FluidType } from 'enum/fluid.enum'
import { useLocation } from 'react-router-dom'
import { Location } from 'history'
interface SingleEcogestureProps {
match: { params: { id: string } }
......@@ -34,6 +36,7 @@ const SingleEcogesture: React.FC<SingleEcogestureProps> = ({
}: SingleEcogestureProps) => {
const { t } = useI18n()
const client = useClient()
const location: Location<any> = useLocation<any>()
const [ecogesture, setEcogesture] = useState<Ecogesture>()
const [ecogestureIcon, setEcogestureIcon] = useState<string>('')
const [isMoreDetail, setIsMoreDetail] = useState<boolean>(false)
......@@ -41,6 +44,7 @@ const SingleEcogesture: React.FC<SingleEcogestureProps> = ({
const [isObjective, setIsObjective] = useState<boolean>(false)
const [isLoading, setIsLoading] = useState<boolean>(true)
const ecogestureID: string = match.params.id
const selectionCompleted = location.state.selectionCompleted
const ecogestureService = useMemo(() => new EcogestureService(client), [
client,
......@@ -132,6 +136,7 @@ const SingleEcogesture: React.FC<SingleEcogestureProps> = ({
</Content>
)
}
return ecogesture ? (
<>
<CozyBar
......@@ -182,41 +187,44 @@ const SingleEcogesture: React.FC<SingleEcogestureProps> = ({
: t('ecogesture_modal.show_more')}
</div>
</div>
<div className="buttons-selection">
<IconButton
aria-label={t('ecogesture.objective')}
onClick={toggleObjective}
classes={{
root: `btn-secondary-negative objective-btn ${isObjective &&
'active'}`,
label: 'text-15-normal',
}}
>
<Icon
className="status-icon"
icon={
isObjective ? objectiveEnabledIcon : objectiveDisabledIcon
}
size={40}
/>
<span>{t('ecogesture.objective')}</span>
</IconButton>
<IconButton
aria-label={t('ecogesture.doing')}
onClick={toggleDoing}
classes={{
root: `btn-secondary-negative doing-btn ${isDoing && 'active'}`,
label: 'text-15-normal',
}}
>
<Icon
className="status-icon"
icon={isDoing ? doingEnabledIcon : doingDisabledIcon}
size={40}
/>
<span>{t('ecogesture.doing')}</span>
</IconButton>
</div>
{selectionCompleted && (
<div className="buttons-selection">
<IconButton
aria-label={t('ecogesture.objective')}
onClick={toggleObjective}
classes={{
root: `btn-secondary-negative objective-btn ${isObjective &&
'active'}`,
label: 'text-15-normal',
}}
>
<Icon
className="status-icon"
icon={
isObjective ? objectiveEnabledIcon : objectiveDisabledIcon
}
size={40}
/>
<span>{t('ecogesture.objective')}</span>
</IconButton>
<IconButton
aria-label={t('ecogesture.doing')}
onClick={toggleDoing}
classes={{
root: `btn-secondary-negative doing-btn ${isDoing &&
'active'}`,
label: 'text-15-normal',
}}
>
<Icon
className="status-icon"
icon={isDoing ? doingEnabledIcon : doingDisabledIcon}
size={40}
/>
<span>{t('ecogesture.doing')}</span>
</IconButton>
</div>
)}
</div>
</Content>
</>
......
......@@ -87,7 +87,14 @@ exports[`EcogestureCard component should be rendered correctly 1`] = `
"render": [Function],
}
}
to="/ecogesture/ECOGESTURE001"
to={
Object {
"pathname": "/ecogesture/ECOGESTURE001",
"state": Object {
"selectionCompleted": undefined,
},
}
}
>
<ForwardRef(Link)
className="ecogesture-list-item"
......@@ -115,7 +122,14 @@ exports[`EcogestureCard component should be rendered correctly 1`] = `
"render": [Function],
}
}
to="/ecogesture/ECOGESTURE001"
to={
Object {
"pathname": "/ecogesture/ECOGESTURE001",
"state": Object {
"selectionCompleted": undefined,
},
}
}
>
<WithStyles(ForwardRef(Typography))
className="MuiLink-root MuiLink-underlineHover ecogesture-list-item"
......@@ -136,7 +150,14 @@ exports[`EcogestureCard component should be rendered correctly 1`] = `
}
onBlur={[Function]}
onFocus={[Function]}
to="/ecogesture/ECOGESTURE001"
to={
Object {
"pathname": "/ecogesture/ECOGESTURE001",
"state": Object {
"selectionCompleted": undefined,
},
}
}
variant="inherit"
>
<ForwardRef(Typography)
......@@ -192,14 +213,28 @@ exports[`EcogestureCard component should be rendered correctly 1`] = `
}
onBlur={[Function]}
onFocus={[Function]}
to="/ecogesture/ECOGESTURE001"
to={
Object {
"pathname": "/ecogesture/ECOGESTURE001",
"state": Object {
"selectionCompleted": undefined,
},
}
}