Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/llle_project/ecolyo
1 result
Show changes
Commits on Source (37)
Showing
with 552 additions and 186 deletions
<svg width="101" height="23" viewBox="0 0 101 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.81215 12.9224C7.39405 13.427 6.88879 13.833 6.32645 14.1163C5.76411 14.3995 5.15621 14.5542 4.53892 14.5711C3.92164 14.588 3.30761 14.4667 2.7334 14.2146C2.15919 13.9625 1.63653 13.5846 1.19656 13.1034C0.0191753 11.7958 0 10.5266 0 7.28739C0 4.04822 0.0230104 2.77683 1.19656 1.46924C1.62081 1.00088 2.12406 0.630018 2.6775 0.377874C3.23094 0.125731 3.82371 -0.0027462 4.4219 -0.000207232C6.68846 -0.000207232 8.42769 1.65026 8.8323 4.18665H7.85434C7.47083 2.21461 6.1688 0.966645 4.42765 0.966645C3.97438 0.962018 3.5248 1.05754 3.10507 1.24766C2.68534 1.43777 2.30384 1.71868 1.98276 2.07405C1.05274 3.10905 0.981792 4.20794 0.981792 7.28739C0.981792 10.3668 1.05466 11.4742 1.97893 12.4986C2.29994 12.8541 2.68143 13.135 3.10117 13.3252C3.52092 13.5153 3.97053 13.6107 4.42382 13.606C4.93588 13.6092 5.44221 13.4864 5.90641 13.2463C6.3706 13.0062 6.78111 12.6548 7.10841 12.2175C7.66642 11.4529 7.88502 10.6075 7.88502 9.38081V8.09239H4.4219V7.12554H8.86298V9.46813C8.86298 10.9589 8.57343 12.0237 7.81215 12.9309" fill="white"/>
<path d="M17.0893 1.08766H13.2829V6.88451H17.0893C18.7384 6.88451 19.9349 5.95812 19.9349 3.98609C19.9349 2.01405 18.7384 1.08766 17.0893 1.08766ZM19.9157 14.4532L16.8342 7.85136H13.2829V14.4532H12.3049V0.127197H17.2158C19.3251 0.127197 20.9129 1.47525 20.9129 3.97118C20.9129 6.10081 19.7527 7.49358 17.9406 7.83645L21.0567 14.4596L19.9157 14.4532Z" fill="white"/>
<path d="M27.6724 1.56896L24.9725 10.0023H30.3724L27.6724 1.56896ZM31.8048 14.4511L30.6811 10.9691H24.6638L23.5401 14.4511H22.4893L27.2371 0.127197H28.1077L32.8556 14.4596L31.8048 14.4511Z" fill="white"/>
<path d="M43.5439 14.4508L36.0961 1.99248V14.4508H35.1182V0.118408H36.0961L43.5439 12.5384V0.118408H44.5238V14.4508H43.5439Z" fill="white"/>
<path d="M55.3753 2.19294C54.6332 1.34109 53.6361 1.08766 52.6025 1.08766H49.4846V13.4842H52.6006C53.6342 13.4842 54.6313 13.2223 55.3734 12.3768C56.405 11.2098 56.3322 8.6734 56.3322 7.0847C56.3322 5.49599 56.4031 3.3621 55.3734 2.18655L55.3753 2.19294ZM56.0618 13.1371C55.2948 13.989 54.1788 14.4447 52.8365 14.4447H48.5066V0.127197H52.8384C54.1807 0.127197 55.3024 0.591457 56.0637 1.43692C57.3696 2.88507 57.314 5.15951 57.314 7.09321C57.314 9.02692 57.3696 11.6932 56.0637 13.1435L56.0618 13.1371Z" fill="white"/>
<path d="M60.3035 14.4508V0.118408H62.8231V11.9549H68.6775V14.4508H60.3035Z" fill="white"/>
<path d="M74.202 8.57304V14.4508H71.7015V8.57304L67.8223 0.118408H70.5586L72.969 5.89822L75.3449 0.118408H78.0793L74.202 8.57304Z" fill="white"/>
<path d="M85.3987 3.26031C85.1955 3.01071 84.9458 2.81309 84.6671 2.68109C84.3883 2.54909 84.0871 2.48586 83.7841 2.49577C83.4787 2.48591 83.1749 2.54907 82.8934 2.68098C82.6118 2.81288 82.3591 3.01046 82.1523 3.26031C81.6633 3.86299 81.5368 4.53809 81.5368 7.28531C81.5368 10.0325 81.6633 10.7055 82.1523 11.3103C82.3592 11.56 82.6119 11.7575 82.8934 11.8894C83.175 12.0213 83.4787 12.0846 83.7841 12.0748C84.087 12.0846 84.3882 12.0213 84.667 11.8893C84.9457 11.7573 85.1954 11.5598 85.3987 11.3103C85.8877 10.7055 86.0335 10.0325 86.0335 7.28531C86.0335 4.53809 85.8896 3.86299 85.3987 3.26031ZM87.2722 13.0034C86.3373 14.0107 85.0858 14.5741 83.7832 14.5741C82.4805 14.5741 81.2291 14.0107 80.2942 13.0034C78.9902 11.5552 79.0247 9.76207 79.0247 7.28744C79.0247 4.81281 78.9902 3.02818 80.2942 1.57151C81.2291 0.564137 82.4805 0.000732422 83.7832 0.000732422C85.0858 0.000732422 86.3373 0.564137 87.2722 1.57151C88.5781 3.01966 88.5589 4.81068 88.5589 7.28744C88.5589 9.7642 88.5704 11.5552 87.2722 13.0034Z" fill="white"/>
<path d="M98.7506 14.4508L93.6403 5.65545V14.4508H91.1226V0.118408H93.37L98.4803 8.89461V0.118408H101V14.4508H98.7506Z" fill="white"/>
<path d="M85.6326 18.9751H85.6442C85.7043 18.8383 85.7987 18.7238 85.9161 18.6452C86.0334 18.5666 86.1687 18.5274 86.3057 18.5321C86.7659 18.5321 87.2338 18.7451 87.2338 20.14C87.2338 20.9365 87.2108 21.8543 86.275 21.8543C86.1485 21.8567 86.0236 21.8223 85.9126 21.7547C85.8017 21.6871 85.7085 21.5886 85.6422 21.4689H85.625V23.0001H85.1628V18.596H85.6307L85.6326 18.9751ZM86.7448 20.14C86.7448 19.6587 86.7448 18.9559 86.1581 18.9559C85.5713 18.9559 85.6346 19.8418 85.6346 20.3295C85.6346 20.7555 85.6576 21.4306 86.1753 21.4306C86.6931 21.4306 86.7448 20.9982 86.7448 20.1464V20.14Z" fill="white"/>
<path d="M53.4347 21.3281H53.4232C53.3722 21.4924 53.2736 21.6332 53.1427 21.7284C53.0119 21.8236 52.8562 21.8679 52.7003 21.8541C52.0905 21.8541 51.9141 21.4176 51.9141 20.8042C51.9141 19.8352 52.7693 19.7927 53.4232 19.8097C53.4347 19.3838 53.4405 18.9238 52.9381 18.9238C52.872 18.9179 52.8057 18.9292 52.7443 18.9568C52.6829 18.9844 52.6282 19.0275 52.5844 19.0827C52.5407 19.1379 52.5091 19.2037 52.4923 19.2748C52.4755 19.3459 52.4738 19.4204 52.4874 19.4924H51.9889C52.0119 18.7768 52.3532 18.5298 52.963 18.5298C53.7032 18.5298 53.8968 18.9557 53.8968 19.4924V21.03C53.8988 21.2846 53.918 21.5388 53.9544 21.7902H53.4424L53.4347 21.3281ZM52.382 20.8404C52.382 21.1492 52.5181 21.4282 52.8307 21.4282C53.1432 21.4282 53.4692 21.2323 53.4232 20.1994C52.9802 20.2079 52.382 20.1653 52.382 20.8426V20.8404Z" fill="white"/>
<path d="M61.8415 21.7905V19.5756C61.8415 19.2519 61.761 18.9559 61.3851 18.9559C61.3079 18.9573 61.2318 18.977 61.1621 19.0137C61.0923 19.0505 61.0304 19.1034 60.9805 19.1689C60.9083 19.312 60.8706 19.4734 60.8712 19.6374V21.7883H60.4072V19.2605C60.4072 19.0475 60.3957 18.8175 60.3784 18.596H60.8731V18.9943H60.8847C60.9435 18.8418 61.0451 18.7145 61.1743 18.6312C61.3035 18.548 61.4534 18.5132 61.6018 18.5321C61.7378 18.5209 61.8738 18.5537 61.9933 18.6267C62.1128 18.6996 62.2106 18.8096 62.2749 18.9431C62.3386 18.8061 62.4379 18.6936 62.5601 18.6203C62.6822 18.547 62.8214 18.5162 62.9595 18.5321C63.2624 18.5321 63.7457 18.6088 63.7457 19.3606V21.7905H63.2778V19.5756C63.2778 19.2519 63.1992 18.9559 62.8214 18.9559C62.7583 18.9448 62.6937 18.9498 62.6326 18.9705C62.5715 18.9911 62.5154 19.0269 62.4686 19.0752C62.3557 19.2349 62.2991 19.4347 62.3094 19.6374V21.7883L61.8415 21.7905Z" fill="white"/>
<path d="M67.1493 20.3593C67.1493 21.2516 67.366 21.4241 67.7245 21.4241C68.0429 21.4241 68.2097 21.1387 68.225 20.8172H68.737C68.737 21.5263 68.3382 21.8479 67.7341 21.8479C67.1301 21.8479 66.6411 21.6349 66.6411 20.2336C66.6411 19.2966 66.737 18.5299 67.7341 18.5299C68.5548 18.5299 68.76 19.0304 68.76 20.0867V20.3593H67.1493ZM68.271 19.9674C68.271 19.0368 68.0371 18.9239 67.6958 18.9239C67.4005 18.9239 67.155 19.0815 67.1493 19.9674H68.271ZM68.3861 17.2202L67.6402 18.1125H67.2567L67.7648 17.2202H68.3861Z" fill="white"/>
<path d="M71.9317 18.5959V17.9826L72.3996 17.7483V18.6001H73.0266V18.992H72.3996V20.947C72.3996 21.16 72.3996 21.4091 72.8272 21.4091C72.8617 21.4091 72.9346 21.3963 73.0381 21.3836V21.7818C72.8847 21.7946 72.7294 21.8329 72.576 21.8329C72.1311 21.8329 71.9317 21.62 71.9317 21.2643V18.9877H71.46V18.5959H71.9317Z" fill="white"/>
<path d="M76.5166 19.0814H76.5338C76.7256 18.5937 76.9672 18.5383 77.4217 18.5383V19.0771L77.297 19.058C77.2558 19.0502 77.2142 19.0459 77.1724 19.0452C76.6546 19.0452 76.5223 19.4818 76.5223 19.9119V21.7988H76.0544V18.6043H76.5223L76.5166 19.0814Z" fill="white"/>
<path d="M80.0793 20.2401C80.0793 19.303 80.1752 18.5364 81.1724 18.5364C82.1695 18.5364 82.2654 19.3094 82.2654 20.2401C82.2654 21.652 81.7802 21.8543 81.1724 21.8543C80.5645 21.8543 80.0793 21.652 80.0793 20.2401ZM81.7764 20.0271C81.7764 19.154 81.531 18.9623 81.1724 18.9623C80.8138 18.9623 80.5683 19.1518 80.5683 20.0271C80.5683 21.0642 80.6891 21.4391 81.1724 21.4391C81.6556 21.4391 81.7783 21.0557 81.7783 20.0186L81.7764 20.0271Z" fill="white"/>
<path d="M90.0909 20.2401C90.0909 19.303 90.1868 18.5364 91.184 18.5364C92.1811 18.5364 92.2789 19.3094 92.2789 20.2401C92.2789 21.652 91.7938 21.8543 91.184 21.8543C90.5742 21.8543 90.0909 21.652 90.0909 20.2401ZM91.788 20.0271C91.788 19.154 91.5426 18.9623 91.184 18.9623C90.8254 18.9623 90.5799 19.1518 90.5799 20.0271C90.5799 21.0642 90.6988 21.4391 91.184 21.4391C91.6691 21.4391 91.7899 21.0557 91.7899 20.0186L91.788 20.0271Z" fill="white"/>
<path d="M95.7747 21.7905H95.3068V17.2224H95.7727L95.7747 21.7905Z" fill="white"/>
<path d="M99.2224 20.3591C99.2224 21.2515 99.4391 21.424 99.7977 21.424C100.116 21.424 100.283 21.1386 100.298 20.817H100.81C100.81 21.5262 100.411 21.8477 99.8072 21.8477C99.2032 21.8477 98.7142 21.6348 98.7142 20.2335C98.7142 19.2965 98.8101 18.5298 99.8072 18.5298C100.628 18.5298 100.833 19.0302 100.833 20.0865V20.3591H99.2224ZM100.344 19.9673C100.344 19.0366 100.11 18.9238 99.7689 18.9238C99.4736 18.9238 99.2281 19.0814 99.2224 19.9673H100.344Z" fill="white"/>
<path d="M49.2296 21.7905H48.7617V17.2224H49.2296V21.7905Z" fill="white"/>
</svg>
src/assets/png/badges/CHA00000003-0.png

174 KiB

src/assets/png/badges/CHA00000003-1.png

193 KiB

......@@ -46,6 +46,10 @@ const PrimaryButton = withStyles({
color: '#000000',
fontWeight: 'bold',
},
disabled: {
background: 'var(--multiColorRadialGradient) !important',
opacity: '0.6',
},
})(BaseButton)
const SecondaryButton = withStyles({
......
......@@ -42,6 +42,10 @@ const PrimaryButton = withStyles({
root: {
background: 'var(--multiColorRadialGradient)',
},
disabled: {
background: 'var(--multiColorRadialGradient) !important',
opacity: '0.6',
},
label: {
color: '#000000',
fontWeight: 'bold',
......
......@@ -4,7 +4,6 @@ import { history } from 'components/ContainerComponents/ViewContainer/ViewContai
import { withClient, Client } from 'cozy-client'
import { ScreenType } from 'enum/screen.enum'
import { AppContext } from 'components/Contexts/AppContextProvider'
import useInstanceSettings from 'components/Hooks/userInstanceSettings'
import BackArrowIcon from 'assets/icons/ico/back-arrow.svg'
import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
......@@ -29,7 +28,6 @@ const Header: React.FC<HeaderProps> = ({
}: HeaderProps) => {
const header = useRef(null)
const { screenType } = useContext(AppContext)
const { data: instanceSettings } = useInstanceSettings(client)
const cozyBarHeight = 48
const headerBottomHeight = 8
......
......@@ -37,10 +37,15 @@ const FinishedChallengeDetailsViewContainer: React.FC<FinishedChallengeDetailsVi
const { screenType } = useContext(AppContext)
async function importRightBadge(id: string, badgeStatus: number) {
// Les svg doivent être au format idchallenge-badgestate.svg
const importedBadge = await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
// Les png doivent être au format idchallenge-badgestate.png
const importedBadge =
id === 'CHA00000001'
? await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-1.png`
)
: await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
setBadgeIcon(importedBadge.default)
}
......@@ -111,20 +116,26 @@ const FinishedChallengeDetailsViewContainer: React.FC<FinishedChallengeDetailsVi
</div>
)
) : null}
<div className="cp-win-badge-star">
<img
className="cp-win-badge"
src={badgeIcon}
width={screenType === ScreenType.MOBILE ? 200 : 300}
></img>
{challenge.badge === BadgeState.SUCCESS ? (
{challenge.badge === BadgeState.SUCCESS ? (
<div className="cp-win-badge-star">
<img
className="cp-win-badge"
src={badgeIcon}
width={screenType === ScreenType.MOBILE ? 200 : 300}
></img>
<img
className="cp-win-star"
src={StarIcon}
width={screenType === ScreenType.MOBILE ? 380 : 480}
></img>
) : null}
</div>
</div>
) : (
<img
className="cp-win-badge"
src={badgeIcon}
width={screenType === ScreenType.MOBILE ? 200 : 300}
></img>
)}
<div className="cp-description text-16-bold">
{challenge.challengeType &&
challenge.challengeType.description}
......
......@@ -65,7 +65,9 @@ const LockedChallengeDetailsViewContainer: React.FC<LockedChallengeDetailsViewPr
width={screenType === ScreenType.MOBILE ? 180 : 220}
></img>
<div className="cp-description text-16-bold">
{t('CHALLENGE.LOCKED')}
{challenge.level < 900
? t('CHALLENGE.LOCKED')
: t('CHALLENGE.FULLY_LOCKED')}
</div>
</div>
<div className="cp-valid-locked">
......
......@@ -3,7 +3,7 @@ import { withClient, Client } from 'cozy-client'
import Modal from 'components/CommonKit/Modal/Modal'
import StyledButton from 'components/CommonKit/Button/StyledButton'
import { translate } from 'cozy-ui/react/I18n'
import useInstanceSettings from 'components/Hooks/userInstanceSettings'
import userInstanceSettings from 'components/Hooks/userInstanceSettings'
interface WelcomeModalContainerProps {
handleClose: () => void
......@@ -16,7 +16,7 @@ const WelcomeModalContainer: React.FC<WelcomeModalContainerProps> = ({
t,
client,
}: WelcomeModalContainerProps) => {
const { data: instanceSettings } = useInstanceSettings(client)
const { data: instanceSettings } = userInstanceSettings(client)
return (
<React.Fragment>
......
......@@ -35,12 +35,42 @@ const FollowChallengeTimeline: React.FC<FollowChallengeTimelineViewProps> = ({
const startingDate = DateTime.fromISO(challenge.startingDate.toString())
const listOfChallengeDays = []
let i = 0
while (challenge.challengeType.duration.days > i) {
if (challenge.challengeType.duration.days === 7) {
while (challenge.challengeType.duration.days > i) {
listOfChallengeDays.push({
letter: startingDate
.plus({ days: i })
.weekdayShort[0].toUpperCase(),
date: startingDate.plus({ days: i }).day,
})
i++
}
} else {
while (challenge.challengeType.duration.days >= i) {
listOfChallengeDays.push({
letter: '',
date: startingDate.plus({ days: i }).toFormat('dd/MM'),
})
i += 7
}
}
return listOfChallengeDays
} else {
return []
}
}
const getListOfWeeks = () => {
if (challenge && challenge.challengeType) {
const startingDate = DateTime.fromISO(challenge.startingDate.toString())
const listOfChallengeDays = []
let i = 0
while (challenge.challengeType.duration.days >= i) {
listOfChallengeDays.push({
letter: startingDate.plus({ days: i }).weekdayShort[0].toUpperCase(),
date: startingDate.plus({ days: i }).day,
letter: '',
date: startingDate.plus({ days: i }).toFormat('dd/MM'),
})
i++
i += 7
}
return listOfChallengeDays
} else {
......@@ -58,36 +88,75 @@ const FollowChallengeTimeline: React.FC<FollowChallengeTimelineViewProps> = ({
return 0
}
} else {
return 0
if (challenge) {
return -Interval.fromDateTimes(DateTime.local(), viewingDate()).count(
'days'
)
} else {
return 0
}
}
}
const generateTimelinePart = (
index: number,
dayCount: number,
className: string
) => {
return (
<div
className={`${className} ${
(index === 0 && dayCount > 0) ||
(index === getListOfWeeks().length - 1 && dayCount < 0)
? 'none'
: index * 7 < getListOfPastDays() + dayCount
? 'past'
: 'futur'
}`}
></div>
)
}
const monthChallenge = () => {
return getListOfWeeks().map((day, index) => (
<div key={index} className="day-solo">
<div className="day-line-label">
{generateTimelinePart(index, 3, 'date-dash')}
{generateTimelinePart(index, 2, 'date-dash')}
{generateTimelinePart(index, 1, 'date-dash')}
{generateTimelinePart(index, 0, 'date-label')}
{generateTimelinePart(index, -1, 'date-dash')}
{generateTimelinePart(index, -2, 'date-dash')}
{generateTimelinePart(index, -3, 'date-dash')}
</div>
<div className="day-letter">{day.letter}</div>
<div className="day-date">{day.date}</div>
</div>
))
}
const weekChallenge = () => {
return getListOfDays().map((day, index) => (
<div key={index} className="day-solo">
<div className="day-line-label">
{generateTimelinePart(index, 0, 'date-dash')}
{generateTimelinePart(index, 0, 'date-label')}
{generateTimelinePart(index + 1, 0, 'date-dash')}
</div>
<div className="day-letter">{day.letter}</div>
<div className="day-date">{day.date}</div>
</div>
))
}
return (
<React.Fragment>
<div className="list-of-days-duration">
{getListOfDays().map((day, index) => (
<div key={index} className="day-solo">
<div className="day-line-label">
<div
className={`date-dash ${
index < getListOfPastDays() ? 'past' : 'futur'
}`}
></div>
<div
className={`date-label ${
index < getListOfPastDays() ? 'past' : 'futur'
}`}
></div>
<div
className={`date-dash ${
index + 1 < getListOfPastDays() ? 'past' : 'futur'
}`}
></div>
</div>
<div className="day-letter">{day.letter}</div>
<div className="day-date">{day.date}</div>
</div>
))}
{challenge &&
challenge.challengeType &&
challenge.challengeType.duration.days === 7
? weekChallenge()
: monthChallenge()}
</div>
</React.Fragment>
)
......
......@@ -33,10 +33,15 @@ const ChallengeListItem: React.FC<ChallengeListItemProps> = ({
const [badgeIcon, setBadgeIcon] = useState<any | null>(null)
async function importRightBadge(id: string, badgeStatus: number) {
// Les svg doivent être au format idchallenge-badgestate.svg
const importedBadge = await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
// Les png doivent être au format idchallenge-badgestate.png
const importedBadge =
id === 'CHA00000001'
? await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-1.png`
)
: await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
setBadgeIcon(importedBadge.default)
}
......
......@@ -36,6 +36,7 @@ const ChallengesList: React.FC<ChallengesListProps> = ({
const [openChallengeModal, setOpenChallengeModal] = useState(false)
const [scroll, setScroll] = useState(0)
const [paddingBottom, setPaddingBottom] = useState(0)
const [userLevel, setUserLevel] = useState<null | number>(null)
const handleCloseClick = () => {
setOngoingChallenge(null)
......@@ -87,8 +88,8 @@ const ChallengesList: React.FC<ChallengesListProps> = ({
fluidTypes
)
const dataAllUC = await challengeManager.getAllUserChallenges()
if (subscribed && dataAllCT && dataAllUC) {
const levelOfUser = await challengeManager.getUserLevel()
if (subscribed && dataAllCT && dataAllUC && levelOfUser) {
const ongoingChallengeTmp = dataAllUC.filter(
challenge => challenge.state === ChallengeState.ONGOING
)[0]
......@@ -96,7 +97,7 @@ const ChallengesList: React.FC<ChallengesListProps> = ({
setChallengesType(dataAllCT)
setUserChallenges(dataAllUC)
setOngoingChallenge(ongoingChallengeTmp)
setUserLevel(levelOfUser)
if (
await challengeManager.isChallengeOver(
ongoingChallengeTmp,
......@@ -122,10 +123,12 @@ const ChallengesList: React.FC<ChallengesListProps> = ({
fluidTypes
)
const dataAllUC = await challengeManager.getAllUserChallenges()
if (subscribed && dataAllCT && dataAllUC) {
const levelOfUser = await challengeManager.getUserLevel()
if (subscribed && dataAllCT && dataAllUC && levelOfUser) {
setChallengesType(dataAllCT)
setUserChallenges(dataAllUC)
setRightChallengeInTheMiddle(dataAllCT, dataAllUC)
setUserLevel(levelOfUser)
}
}
loadNewChallengesType()
......@@ -154,7 +157,10 @@ const ChallengesList: React.FC<ChallengesListProps> = ({
style={{ paddingBottom: paddingBottom }}
>
{challengesType.map((challenge, index) =>
index === challengesType.length - 1 && !ongoingChallenge ? (
index === challengesType.length - 1 &&
!ongoingChallenge &&
userLevel ===
challengesType[challengesType.length - 1].level ? (
<ChallengeListItem
key={index}
challenge={challenge}
......
......@@ -29,10 +29,15 @@ const ChallengeModal: React.FC<ChallengeModalProps> = ({
const { screenType } = useContext(AppContext)
async function importRightBadge(id: string, badgeStatus: number) {
// Les svg doivent être au format idchallenge-badgestate.svg
const importedBadge = await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
// Les png doivent être au format idchallenge-badgestate.png
const importedBadge =
id === 'CHA00000001'
? await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-1.png`
)
: await import(
/* webpackMode: "eager" */ `assets/png/badges/${id}-${badgeStatus}.png`
)
setBadgeIcon(importedBadge.default)
}
......@@ -56,10 +61,20 @@ const ChallengeModal: React.FC<ChallengeModalProps> = ({
{t('CHALLENGE.CONGRATULATION')}
</div>
<div className="cm-result text-18-bold">
<div>{t('CHALLENGE.RESULT_POSITIF')}</div>
<div className="cm-result-positif text-18-normal">{`${result} €`}</div>
{challengeId !== 'CHA00000001' ? (
<>
<div>{t('CHALLENGE.RESULT_POSITIF')}</div>
<div className="cm-result-positif text-18-normal">{`${result} €`}</div>
</>
) : null}
</div>
<div className="cm-win-badge-star">
<div
className={
challengeId !== 'CHA00000001'
? 'cm-win-badge-star'
: 'cm-win-badge-star --ecolyo-royal'
}
>
<img
className="cm-win-badge"
src={badgeIcon}
......
......@@ -2,105 +2,49 @@ import React from 'react'
import { translate } from 'cozy-ui/react/I18n'
import IFluidConfig from 'services/IFluidConfig'
import { Konnector, Trigger } from 'doctypes'
import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
import StyledButton from 'components/CommonKit/Button/StyledButton'
import TrailingIcon from 'assets/icons/ico/trailing-icon.svg'
import KonnectorLoginForm from 'components/ContentComponents/Konnector/KonnectorLoginForm'
import KonnectorOAuthForm from 'components/ContentComponents/Konnector/KonnectorOAuthForm'
interface KonnectorFormProps {
fluidConfig: IFluidConfig
login: string
setLogin: Function
password: string
setPassword: Function
loading: boolean
error: string
handleSubmit: Function
t: Function
konnector: Konnector
account: Account | null
trigger: Trigger | null
handleSuccessForm: Function
}
const KonnectorForm: React.FC<KonnectorFormProps> = ({
fluidConfig,
login,
setLogin,
password,
setPassword,
loading,
error,
handleSubmit,
t,
konnector,
account,
trigger,
handleSuccessForm,
}: KonnectorFormProps) => {
const konnectorName: string = fluidConfig.konnectorConfig.name
const konnectorType: string = fluidConfig.konnectorConfig.type
const siteLink: string = fluidConfig.siteLink
const oAuth: boolean = fluidConfig.konnectorConfig.oauth
function revealPassword(idInput: string) {
const input = document.getElementById(idInput)
if (input) {
if (input.getAttribute('type') === 'password') {
input.setAttribute('type', 'text')
} else {
input.setAttribute('type', 'password')
}
}
const handleSuccess = (_account: Account, _trigger: Trigger) => {
handleSuccessForm(_account, _trigger)
}
return (
<form
className="form"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => handleSubmit(e)}
>
{t('KONNECTORCONFIG.LABEL_FILLIN')} {konnectorName}
<div className="form-group">
<div className="form-message">{error}</div>
<input
id={'idFieldLogin' + konnectorType}
type="text"
className="form-control form-input"
aria-describedby="emailHelp"
placeholder="Adresse e-mail"
name="login"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setLogin(e.target.value)
}
value={login}
></input>
</div>
<div className="form-group">
<div className="form-message">{error}</div>
<input
id={'idFieldPassword' + konnectorType}
type="password"
className="form-control form-input"
aria-describedby="PasswordHelp"
placeholder="Mot de passe"
name="password"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setPassword(e.target.value)
}
value={password}
<>
{!oAuth ? (
<KonnectorLoginForm
fluidConfig={fluidConfig}
onSuccess={handleSuccess}
account={account}
trigger={trigger}
/>
<span>
<StyledIconButton
icon={TrailingIcon}
className="form-trailing-icon"
size={22}
onClick={() => revealPassword('idFieldPassword' + konnectorType)}
/>
</span>
</div>
<StyledButton type="submit" color="primary" disabled={loading}>
{t('KONNECTORCONFIG.BTN_CONNECTION')}
</StyledButton>
<StyledButton
type="button"
color="secondary"
disabled={loading}
onClick={() => window.open(siteLink, '_blank')}
>
{t('KONNECTORCONFIG.BTN_NOACCOUNT')}
</StyledButton>
</form>
) : (
<KonnectorOAuthForm
konnector={konnector}
siteLink={fluidConfig.siteLink}
onSuccess={handleSuccess}
/>
)}
</>
)
}
......
import React, { useEffect, useState } from 'react'
import { withClient, Client } from 'cozy-client'
import { translate } from 'cozy-ui/react/I18n'
import { isKonnectorRunning } from 'cozy-harvest-lib/dist/helpers/triggers'
import {
KonnectorJob,
ERROR_EVENT,
LOGIN_SUCCESS_EVENT,
SUCCESS_EVENT,
} from 'cozy-harvest-lib/dist/models/KonnectorJob'
import { Trigger } from 'doctypes'
import Lottie from 'react-lottie'
import * as loadingData from 'assets/anims/bounceloading.json'
import StyledButton from 'components/CommonKit/Button/StyledButton'
const loadingOptions = {
loop: true,
autoplay: true,
animationData: loadingData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
}
interface KonnectorLaunchProps {
trigger: Trigger
handleKonnectorLaunch: Function
client: Client
t: Function
}
const KonnectorLaunch: React.FC<KonnectorLaunchProps> = ({
trigger,
handleKonnectorLaunch,
client,
t,
}: KonnectorLaunchProps) => {
const [state, setState] = useState<string | null>(null)
const callbackResponse = (_state: string) => {
setState(_state)
}
const handleClick = () => {
handleKonnectorLaunch()
}
useEffect(() => {
let subscribed = true
async function getData() {
if (subscribed && !isKonnectorRunning(trigger)) {
const konnectorJob = new KonnectorJob(client, trigger)
await konnectorJob.launch()
konnectorJob.jobWatcher.on(ERROR_EVENT, () => {
callbackResponse(ERROR_EVENT)
})
konnectorJob.jobWatcher.on(LOGIN_SUCCESS_EVENT, () => {
callbackResponse(LOGIN_SUCCESS_EVENT)
})
konnectorJob.jobWatcher.on(SUCCESS_EVENT, () => {
callbackResponse(SUCCESS_EVENT)
})
}
}
getData()
return () => {
subscribed = false
}
}, [])
return (
<div className="klaunch-content">
{!state ? (
<>
<Lottie options={loadingOptions} height={50} width={50} />
<div className="klaunch-content-text klaunch-content-text-center text-16-normal">
<div>{t('KONNECTORCONFIG.PLZ_WAIT')}</div>
</div>
<div className="klaunch-content-text text-16-normal">
<div>{t('KONNECTORCONFIG.LOADING_DATA')}</div>
</div>
</>
) : (
<>
<div className="klaunch-info-txt">
{state === ERROR_EVENT
? t('KONNECTORCONFIG.ERROR_DATA')
: t('KONNECTORCONFIG.SUCCESS')}
<StyledButton type="button" color="primary" onClick={handleClick}>
<div>{t('KONNECTORCONFIG.OK')}</div>
</StyledButton>
</div>
</>
)}
</div>
)
}
export default translate()(withClient(KonnectorLaunch))
import React from 'react'
import { translate } from 'cozy-ui/react/I18n'
import Lottie from 'react-lottie'
import * as loadingData from 'assets/anims/bounceloading.json'
const loadingOptions = {
loop: true,
autoplay: true,
animationData: loadingData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
}
interface KonnectorLoadingProps {
t: Function
}
const KonnectorLoading: React.FC<KonnectorLoadingProps> = ({
t,
}: KonnectorLoadingProps) => {
return (
<div className="kload-content">
<Lottie options={loadingOptions} height={50} width={50} />
<div className="kload-content-text kload-content-text-center text-16-normal">
<div>{t('KONNECTORCONFIG.PLZ_WAIT')}</div>
</div>
<div className="kload-content-text text-16-normal">
<div>{t('KONNECTORCONFIG.LOADING_DATA')}</div>
</div>
</div>
)
}
export default translate()(KonnectorLoading)
import React, { useState, useEffect } from 'react'
import { withClient, Client } from 'cozy-client'
import { translate } from 'cozy-ui/react/I18n'
import IFluidConfig from 'services/IFluidConfig'
import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
import StyledButton from 'components/CommonKit/Button/StyledButton'
import TrailingIcon from 'assets/icons/ico/trailing-icon.svg'
import { ConnectionService } from 'services/connectionService'
import { AccountService } from 'services/accountService'
import { Account, AuthLoginData, Trigger } from 'doctypes'
interface KonnectorLoginFormProps {
fluidConfig: IFluidConfig
onSuccess: Function
account: Account
trigger: Trigger
client: Client
t: Function
}
const KonnectorLoginForm: React.FC<KonnectorLoginFormProps> = ({
fluidConfig,
onSuccess,
account,
trigger,
client,
t,
}: KonnectorLoginFormProps) => {
const konnectorName: string = fluidConfig.konnectorConfig.name
const konnectorType: string = fluidConfig.konnectorConfig.type
const siteLink: string = fluidConfig.siteLink
const [login, setLogin] = useState<string>('')
const [password, setPassword] = useState<string>('')
const [error, setError] = useState<string>('')
const [loading, setLoading] = useState<boolean>(false)
function revealPassword(idInput: string) {
const input = document.getElementById(idInput)
if (input) {
if (input.getAttribute('type') === 'password') {
input.setAttribute('type', 'text')
} else {
input.setAttribute('type', 'password')
}
}
}
const connect = async () => {
const connectionService = new ConnectionService(
client,
fluidConfig.konnectorConfig.slug,
login,
password
)
const { account, trigger } = await connectionService.connectNewUser()
if (!trigger) {
setError(t('KONNECTORCONFIG.ERROR_ACCOUNT_CREATION'))
setLoading(false)
return null
}
onSuccess(account, trigger)
}
const update = async () => {
const auth = {
login: login,
password: password,
}
account.auth = auth
const updatedAccount = await AccountService.updateAccount(client, account)
onSuccess(updatedAccount, trigger)
}
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
try {
setError('')
setLoading(true)
if (!login || !password) {
setError(t('KONNECTORCONFIG.ERROR_NO_LOGIN_PASSWORD'))
setLoading(false)
return null
}
if (!account) {
await connect()
} else {
await update()
}
} catch (error) {
setLoading(false)
}
}
useEffect(() => {
if (account) {
const auth: AuthLoginData = account.auth
if (auth.login) {
setLogin(auth.login)
}
setError(t('KONNECTORCONFIG.ERROR_LOGIN_FAILED'))
}
}, [])
return (
<form
className="form"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => handleSubmit(e)}
>
{t('KONNECTORCONFIG.LABEL_FILLIN')} {konnectorName}
<div className="form-group">
<input
id={'idFieldLogin' + konnectorType}
type="text"
className="form-control form-input"
aria-describedby="emailHelp"
placeholder="Adresse e-mail"
name="login"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setLogin(e.target.value)
}
value={login}
></input>
</div>
<div className="form-group">
<input
id={'idFieldPassword' + konnectorType}
type="password"
className="form-control form-input"
aria-describedby="PasswordHelp"
placeholder="Mot de passe"
name="password"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setPassword(e.target.value)
}
value={password}
/>
<span>
<StyledIconButton
icon={TrailingIcon}
className="form-trailing-icon"
size={22}
onClick={() => revealPassword('idFieldPassword' + konnectorType)}
/>
</span>
<div className="form-message">{error}</div>
</div>
<StyledButton
className="form-button"
type="submit"
color="primary"
disabled={loading}
>
{t('KONNECTORCONFIG.BTN_CONNECTION')}
</StyledButton>
<StyledButton
type="button"
color="secondary"
disabled={loading}
onClick={() => window.open(siteLink, '_blank')}
>
{t('KONNECTORCONFIG.BTN_NOACCOUNT')}
</StyledButton>
</form>
)
}
export default translate()(withClient(KonnectorLoginForm))
import React from 'react'
import { translate } from 'cozy-ui/react/I18n'
import StyledButton from 'components/CommonKit/Button/StyledButton'
interface KonnectorNotFoundProps {
konnectorSlug: string
t: Function
}
const KonnectorNotFound: React.FC<KonnectorNotFoundProps> = ({
konnectorSlug,
t,
}: KonnectorNotFoundProps) => {
const openKonnectorURL = () => {
// TODO - Use getstoreinstallationurl from client - https://docs.cozy.io/en/cozy-client/api/cozy-client/#getstoreinstallationurl-string
const hostname = window.location.origin.replace('ecolyo', 'store')
const url = hostname + '/#/discover/' + konnectorSlug
window.open(url, '_blank')
}
return (
<div className="knotfound">
<div className="knotfound-text">
{' '}
{t('KONNECTORCONFIG.NOT_INSTALLED')}
</div>
<div className="knotfound-button">
<StyledButton type="button" color="primary" onClick={openKonnectorURL}>
{t('KONNECTORCONFIG.BTN_INSTALL')}
</StyledButton>
</div>
</div>
)
}
export default translate()(KonnectorNotFound)
import React from 'react'
import { Client, withClient } from 'cozy-client'
import { translate } from 'cozy-ui/react/I18n'
import { Konnector } from 'doctypes'
import { Konnector, Trigger } from 'doctypes'
import OAuthForm from 'components/ContentComponents/OAuth/OAuthForm'
import StyledButton from 'components/CommonKit/Button/StyledButton'
import { AccountService } from 'services/accountService'
import { TriggerService } from 'services/triggersService'
interface KonnectorOAuthFormProps {
konnector: Konnector
siteLink: string
onSuccess: Function
loading: boolean
client: Client
t: Function
}
......@@ -18,15 +22,25 @@ const KonnectorOAuthForm: React.FC<KonnectorOAuthFormProps> = ({
siteLink,
onSuccess,
loading,
client,
t,
}: KonnectorOAuthFormProps) => {
const handleSuccess = async (accountId: string) => {
const account = await AccountService.getAccount(client, accountId)
if (!account) {
onSuccess(null, null)
}
const triggersServices = new TriggerService(client, account, konnector)
const trigger: Trigger = await triggersServices.createTrigger()
onSuccess(account, trigger)
}
return (
<div className="koauthform">
<div className="koauthform-text text-16-normal">
{t('oauth.connect.' + konnector.slug + '.info')}
</div>
<div className="koauthform-button">
<OAuthForm konnector={konnector} onSuccess={onSuccess} />
<OAuthForm konnector={konnector} onSuccess={handleSuccess} />
</div>
<div className="koauthform-text text-16-bold">
<div className="text-16-bold">
......@@ -50,4 +64,4 @@ const KonnectorOAuthForm: React.FC<KonnectorOAuthFormProps> = ({
)
}
export default translate()(KonnectorOAuthForm)
export default translate()(withClient(KonnectorOAuthForm))