diff --git a/src/components/Season/SeasonCard.tsx b/src/components/Season/SeasonCard.tsx index 511aaa34d2f5ac29063c4adf6056c41276d6efe3..a989d17118a6d7694b0005e6da0fba9a887f225b 100644 --- a/src/components/Season/SeasonCard.tsx +++ b/src/components/Season/SeasonCard.tsx @@ -9,33 +9,33 @@ import SeasonCardUnlocked from './SeasonCardUnlocked' import './season.scss' interface SeasonCardProps { - season: UserSeason + userSeason: UserSeason indexSlider: number index: number cardWitdh: number } -const SeasonCard = ({ - season, +const SeasonCard: React.FC<SeasonCardProps> = ({ + userSeason, indexSlider, index, cardWitdh, }: SeasonCardProps) => { const renderCard = () => { - const { state } = season + const { state } = userSeason switch (state) { case UserSeasonState.LOCKED: - return <SeasonCardLocked season={season} /> + return <SeasonCardLocked userSeason={userSeason} /> case UserSeasonState.UNLOCKED: - return <SeasonCardUnlocked season={season} /> + return <SeasonCardUnlocked userSeason={userSeason} /> case UserSeasonState.DONE: - return <SeasonCardDone season={season} /> + return <SeasonCardDone userSeason={userSeason} /> case UserSeasonState.ONGOING: - return <SeasonCardOnGoing season={season} /> + return <SeasonCardOnGoing userSeason={userSeason} /> case UserSeasonState.BOSS: - return <SeasonCardBoss season={season} /> + return <SeasonCardBoss userSeason={userSeason} /> default: - return <SeasonCardLocked season={season} /> + return <SeasonCardLocked userSeason={userSeason} /> } } return ( diff --git a/src/components/Season/SeasonCardBoss.tsx b/src/components/Season/SeasonCardBoss.tsx index bd5a764a26970d2cae0ca30850183fda2ecb46d8..1be2373ba2e7b4fe1a9b6a5233053884b60af1fb 100644 --- a/src/components/Season/SeasonCardBoss.tsx +++ b/src/components/Season/SeasonCardBoss.tsx @@ -1,11 +1,13 @@ -import { UserSeason } from 'models' import React from 'react' import './season.scss' +import { UserSeason } from 'models' interface SeasonCardBossProps { - season: UserSeason + userSeason: UserSeason } -const SeasonCardBoss = ({ season }: SeasonCardBossProps) => { +const SeasonCardBoss: React.FC<SeasonCardBossProps> = ({ + userSeason, +}: SeasonCardBossProps) => { return <></> } diff --git a/src/components/Season/SeasonCardDone.tsx b/src/components/Season/SeasonCardDone.tsx index d3f531e50cd81706eb112dd2b421014883976b12..008311b7d0fb3b3f30b421bcd5f69236cc742b1c 100644 --- a/src/components/Season/SeasonCardDone.tsx +++ b/src/components/Season/SeasonCardDone.tsx @@ -1,12 +1,14 @@ -import { UserSeason } from 'models' import React from 'react' import './season.scss' +import { UserSeason } from 'models' interface SeasonCardDoneProps { - season: UserSeason + userSeason: UserSeason } -const SeasonCardDone = ({ season }: SeasonCardDoneProps) => { +const SeasonCardDone: React.FC<SeasonCardDoneProps> = ({ + userSeason, +}: SeasonCardDoneProps) => { return <></> } diff --git a/src/components/Season/SeasonCardLocked.tsx b/src/components/Season/SeasonCardLocked.tsx index 0767a59b81e4d47059698ace92eee454c8ca794d..d79453ceb777b33113d72b37a0776b72961140e8 100644 --- a/src/components/Season/SeasonCardLocked.tsx +++ b/src/components/Season/SeasonCardLocked.tsx @@ -1,15 +1,17 @@ -import { UserSeason } from 'models' import React from 'react' import './season.scss' +import { UserSeason } from 'models' interface SeasonCardLockedProps { - season: UserSeason + userSeason: UserSeason } -const SeasonCardLocked = ({ season }: SeasonCardLockedProps) => { +const SeasonCardLocked: React.FC<SeasonCardLockedProps> = ({ + userSeason, +}: SeasonCardLockedProps) => { return ( <div className="cardContent"> <p className="title">Saison</p> - <span className="seasonTitle">{season.title}</span> + <span className="seasonTitle">{userSeason.title}</span> <span>Locked</span> </div> ) diff --git a/src/components/Season/SeasonCardOnGoing.tsx b/src/components/Season/SeasonCardOnGoing.tsx index 6f1309797d97369efe20556e69a792be790deff0..dd6d345f8b83b627f769f184c17461f0e025f67b 100644 --- a/src/components/Season/SeasonCardOnGoing.tsx +++ b/src/components/Season/SeasonCardOnGoing.tsx @@ -1,15 +1,17 @@ -import { UserSeason } from 'models' import React from 'react' import './season.scss' +import { UserSeason } from 'models' interface SeasonCardOnGoingProps { - season: UserSeason + userSeason: UserSeason } -const SeasonCardOnGoing = ({ season }: SeasonCardOnGoingProps) => { +const SeasonCardOnGoing: React.FC<SeasonCardOnGoingProps> = ({ + userSeason, +}: SeasonCardOnGoingProps) => { return ( <div className="cardContent"> <p className="title">Saison</p> - <span className="seasonTitle">{season.title}</span> + <span className="seasonTitle">{userSeason.title}</span> </div> ) } diff --git a/src/components/Season/SeasonCardUnlocked.tsx b/src/components/Season/SeasonCardUnlocked.tsx index 24e69098135b7de1810190fff74e0b7d87376dd7..50642f81229cd4f381650184312c083f40edefc5 100644 --- a/src/components/Season/SeasonCardUnlocked.tsx +++ b/src/components/Season/SeasonCardUnlocked.tsx @@ -1,18 +1,35 @@ -import StyledButtonValid from 'components/CommonKit/Button/StyledButtonValid' -import { UserSeason } from 'models' -import React from 'react' +import React, { useCallback } from 'react' +import { Client, useClient } from 'cozy-client' +import { useDispatch } from 'react-redux' import './season.scss' +import { UserSeason } from 'models' +import SeasonService from 'services/season.service' +import StyledButtonValid from 'components/CommonKit/Button/StyledButtonValid' +import { updateUserSeasonList } from 'store/season/season.actions' interface SeasonCardUnlockedProps { - season: UserSeason + userSeason: UserSeason } -const SeasonCardUnlocked = ({ season }: SeasonCardUnlockedProps) => { +const SeasonCardUnlocked: React.FC<SeasonCardUnlockedProps> = ({ + userSeason, +}: SeasonCardUnlockedProps) => { + const client: Client = useClient() + const dispatch = useDispatch() + + const launchSeason = useCallback(async () => { + const seasonService = new SeasonService(client) + const updatedSeason = await seasonService.startUserSeason(userSeason) + dispatch(updateUserSeasonList(updatedSeason)) + }, [client, dispatch, userSeason]) + return ( <div className="cardContent"> <p className="title">Saison</p> - <span className="seasonTitle">{season.title}</span> + <span className="seasonTitle">{userSeason.title}</span> <span>Icon</span> - <StyledButtonValid>Lancer la saison</StyledButtonValid> + <StyledButtonValid onClick={launchSeason}> + Lancer la saison + </StyledButtonValid> </div> ) } diff --git a/src/components/Season/SeasonView.tsx b/src/components/Season/SeasonView.tsx index 2ba6bc821cb152b99a1fc73cdf99bb41ffcd7b24..085f29f55434e9cd46e077a2affd14f401621b74 100644 --- a/src/components/Season/SeasonView.tsx +++ b/src/components/Season/SeasonView.tsx @@ -1,19 +1,18 @@ import React, { useState } from 'react' -import SeasonCard from './SeasonCard' +import './season.scss' +import { useSelector } from 'react-redux' +import { EcolyoState } from 'store' import CozyBar from 'components/Header/CozyBar' import Content from 'components/Content/Content' import Header from 'components/Header/Header' +import SeasonCard from './SeasonCard' import StyledIconbutton from 'components/CommonKit/IconButton/StyledIconButton' import LeftArrowIcon from 'assets/icons/ico/left-arrow.svg' import RightArrowIcon from 'assets/icons/ico/right-arrow.svg' -import './season.scss' - -import { UserSeason } from 'models' -import { userSeasonData } from '../../../test/__mocks__/userSeasonData.mock' -import { useSelector } from 'react-redux' -import { EcolyoState } from 'store' const SeasonView: React.FC = () => { + const { userSeasonList } = useSelector((state: EcolyoState) => state.season) + const marginPx = 16 const cardWitdh = window.outerWidth < 500 ? window.outerWidth - marginPx * 6 : 285 @@ -28,9 +27,6 @@ const SeasonView: React.FC = () => { setHeaderHeight(height) } - const [userSeasonLists, setUserSeasonList] = useState<UserSeason[]>( - userSeasonData - ) const resetValues = () => { //Method used to cancel a swipe on a simple click setTouchEnd(0) @@ -38,7 +34,7 @@ const SeasonView: React.FC = () => { } const moveSliderRight = () => { - if (index < userSeasonLists.length - 1) { + if (index < userSeasonList.length - 1) { if (index === 0) setcontainerTranslation( (prev: number) => prev - cardWitdh - marginPx * 1.2 @@ -88,8 +84,7 @@ const SeasonView: React.FC = () => { setTouchEnd(e.targetTouches[0].clientX) if (e.nativeEvent instanceof MouseEvent) setTouchEnd(e.clientX) } - const { userSeasonList } = useSelector((state: EcolyoState) => state.season) - // console.log('seasons', userSeasonList) + return ( <> <CozyBar titleKey={'COMMON.APP_OPTIONS_TITLE'} /> @@ -114,10 +109,10 @@ const SeasonView: React.FC = () => { transform: `translateX(${containerTranslation}px)`, }} > - {userSeasonLists.map((season, i) => ( + {userSeasonList.map((userSeason, i) => ( <SeasonCard key={i} - season={season} + userSeason={userSeason} indexSlider={index} index={i} cardWitdh={cardWitdh} diff --git a/src/db/seasons/bossEntity.json b/src/db/bossEntity.json similarity index 100% rename from src/db/seasons/bossEntity.json rename to src/db/bossEntity.json diff --git a/src/db/seasons/quizData.json b/src/db/quizData.json similarity index 100% rename from src/db/seasons/quizData.json rename to src/db/quizData.json diff --git a/src/db/seasons/seasonEntity.json b/src/db/seasonEntity.json similarity index 89% rename from src/db/seasons/seasonEntity.json rename to src/db/seasonEntity.json index c8cc651684947e0a692c9ad1c260521d9fd816d6..18ab7aff9699922d306886ff7281d0a69d31bc4b 100644 --- a/src/db/seasons/seasonEntity.json +++ b/src/db/seasonEntity.json @@ -3,7 +3,6 @@ "_id": "SEASON0001", "title": "Nicolas Hublot", "description": "foobar", - "duration": { "days": 3 }, "target": 40, "relationships": { "boss": { @@ -16,7 +15,6 @@ "_id": "SEASON0002", "title": "Tata", "description": "foobar", - "duration": { "days": 3 }, "target": 40, "relationships": { "boss": { @@ -29,7 +27,6 @@ "_id": "SEASON0003", "title": "Titi", "description": "foobar", - "duration": { "days": 3 }, "target": 40, "relationships": { "boss": { diff --git a/src/models/boss.model.ts b/src/models/boss.model.ts index b1265acc20488409bcb58e41bb2fdc7cec6012ce..c444fc8830e40e0402d25a114b4819a019ed5d66 100644 --- a/src/models/boss.model.ts +++ b/src/models/boss.model.ts @@ -14,7 +14,7 @@ export interface Boss { description: string duration: Duration treshold: number - state: UserBossState // Todo enum + state: UserBossState startDate: DateTime | null consumption: number } diff --git a/src/models/index.ts b/src/models/index.ts index 5f427d46b94742555b05d71bfad086a9a0304ff7..ab6b25d84fbeb5ffa908cbd570a2d171aff80706 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -11,6 +11,7 @@ export * from './indicator.model' export * from './konnector.model' export * from './modal.model' export * from './profile.model' +export * from './relation.model' export * from './report.model' export * from './season.model' export * from './boss.model' diff --git a/src/models/relation.model.ts b/src/models/relation.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..6045092d586ffd72e17e36df1d87a1630547a254 --- /dev/null +++ b/src/models/relation.model.ts @@ -0,0 +1,4 @@ +export interface Relation { + _id: string + _type: string +} diff --git a/src/models/season.model.ts b/src/models/season.model.ts index 3b62f0c21d7270159e58556b5243dd9841096993..18738cc1b8cffb1bfc592969e5cc424a51a3f116 100644 --- a/src/models/season.model.ts +++ b/src/models/season.model.ts @@ -10,7 +10,6 @@ export interface SeasonEntity { id: string title: string description: string - duration: Duration target: number boss: BossEntity quizType: string @@ -22,7 +21,6 @@ export interface UserSeason { title: string description: string state: UserSeasonState - duration: Duration target: number progress: number boss: Boss diff --git a/src/services/boss.service.ts b/src/services/boss.service.ts index 1d31b4b1e516744c05e4bfea719cc78380e52c0c..1f84976f3d6ec6cbc07a97d52911220567ebe83e 100644 --- a/src/services/boss.service.ts +++ b/src/services/boss.service.ts @@ -2,6 +2,7 @@ import { Client, QueryDefinition, QueryResult, Q } from 'cozy-client' import { BOSS_DOCTYPE } from 'doctypes/com-grandlyon-ecolyo-boss' import { Boss, BossEntity } from 'models/boss.model' import { UserBossState } from 'enum/userBoss.enum' +import { Duration } from 'luxon' export default class BossService { private readonly _client: Client @@ -18,13 +19,9 @@ export default class BossService { return bosses } public async getBossEntityById(bossId: string): Promise<BossEntity> { - const query: QueryDefinition = Q(BOSS_DOCTYPE) - const { - data: [boss], - }: QueryResult<BossEntity> = await this._client.query( - query.where({ _id: bossId }) - ) - return boss + const query: QueryDefinition = Q(BOSS_DOCTYPE).where({ _id: bossId }) + const { data }: QueryResult<BossEntity[]> = await this._client.query(query) + return data && data[0] } public async deleteAllBossEntities(): Promise<boolean> { @@ -50,8 +47,6 @@ export default class BossService { } public formatToUserBoss(boss: BossEntity): Boss { - console.log('boss', boss) - const userBoss: Boss = { id: boss.id, title: boss.title, @@ -64,6 +59,7 @@ export default class BossService { } return userBoss } + public uptadeUserBossConsumption( boss: Boss, newConsumptionValue: number @@ -74,4 +70,30 @@ export default class BossService { } return userBoss } + + public getBossfromBossEntities( + bossEntityList: BossEntity[], + searchId: string + ): Boss { + let boss: Boss = { + id: '', + title: '', + description: '', + duration: Duration.fromObject({ day: 0 }), + treshold: 15, + state: UserBossState.LOCKED, + startDate: null, + consumption: 0, + } + if (bossEntityList.length > 0) { + const bossEntityIndex = bossEntityList.findIndex( + entity => entity.id === searchId + ) + if (bossEntityIndex >= 0) { + const bossEntity: BossEntity = bossEntityList[bossEntityIndex] + boss = this.formatToUserBoss(bossEntity) + } + } + return boss + } } diff --git a/src/services/initialization.service.ts b/src/services/initialization.service.ts index bbc452881bbbc8dba6b0b3d8b5f42adc4fda0530..a6d565bc19bfa674cf668564edbb718de84ddc8d 100644 --- a/src/services/initialization.service.ts +++ b/src/services/initialization.service.ts @@ -24,8 +24,8 @@ import { FluidStatus, Profile } from 'models' import EcogestureService from 'services/ecogesture.service' import SeasonService from 'services/season.service' import ecogestureData from 'db/ecogestureData.json' -import seasonEntityData from 'db/seasons/seasonEntity.json' -import bossEntityData from 'db/seasons/bossEntity.json' +import seasonEntityData from 'db/seasonEntity.json' +import bossEntityData from 'db/bossEntity.json' import ProfileService from 'services/profile.service' import profileData from 'db/profileData.json' diff --git a/src/services/season.service.ts b/src/services/season.service.ts index 9b4969ff46c51b84ac8b95cff3a924eb0e810fb9..d11f554d19ba42ee224179d9b00f70c2b4a6c21f 100644 --- a/src/services/season.service.ts +++ b/src/services/season.service.ts @@ -2,16 +2,13 @@ import { Client, QueryDefinition, QueryResult, Q } from 'cozy-client' import { SEASON_DOCTYPE, USERSEASON_DOCTYPE } from 'doctypes' import { SeasonEntity, UserSeason } from 'models/season.model' import { Boss, BossEntity } from 'models/boss.model' -import get from 'lodash/get' import { UserSeasonState, UserSeasonSuccess } from 'enum/userSeason.enum' import BossService from './boss.service' import { UpdateUserSeason } from 'enum/updateUserSeason.enum' - -export interface Relation { - _id: string - _type: string -} +import { DateTime } from 'luxon' +import { Relation } from 'models' +import { getRelationship } from 'utils/utils' export default class SeasonService { private readonly _client: Client @@ -29,26 +26,11 @@ export default class SeasonService { return userSeasons } - /** - * Get one relation in doc - * - * @param {object} doc - DocumentEntity - * @param {string} relName - Name of the relation - */ - public getRelationship<D>(doc: D, relName: string): Relation { - return get(doc, `relationships.${relName}[0]`, []) - } - public formatToUserSeason(season: SeasonEntity, boss: Boss): UserSeason { - // const bossService = new BossService(this._client) - // const seasonBoss: Relation = this.getRelationship(season, 'boss') - // const bossEntity = await bossService.getBossEntityById(seasonBoss._id) - const userSeason: UserSeason = { id: season.id, title: season.title, description: season.description, - duration: season.duration, target: season.target, boss: boss, state: UserSeasonState.LOCKED, @@ -58,8 +40,6 @@ export default class SeasonService { endingDate: null, quiz: null, } - console.log('userSeason', userSeason) - return userSeason } @@ -70,57 +50,53 @@ export default class SeasonService { * else Push new UserSeason into list * return UserSeason List */ - const bossService = new BossService(this._client) - console.log('include') - const querySeasonEntity: QueryDefinition = Q(SEASON_DOCTYPE) - .where({}) - .include(['boss']) - console.log('include2') - // const { - // data: seasonEntity, - // }: QueryResult<SeasonEntity[]> = await this._client.query(querySeasonEntity) - const result = await this._client.query(querySeasonEntity) - console.log('result', result) - console.log('include3') + const querySeasonEntity: QueryDefinition = Q(SEASON_DOCTYPE).include([ + 'boss', + ]) + const { + data: seasonEntityList, + included: bossEntityList, + }: QueryResult<SeasonEntity[], BossEntity[]> = await this._client.query( + querySeasonEntity + ) + const queryUserSeason: QueryDefinition = Q(USERSEASON_DOCTYPE) const { - data: userSeason, + data: userSeasonList, }: QueryResult<UserSeason[]> = await this._client.query(queryUserSeason) - console.log('seasonEntity', seasonEntity) - console.log('relationships', relationships) + const bossService = new BossService(this._client) let buildList: UserSeason[] = [] - - if (seasonEntity.length > 0 && userSeason.length === 0) { - seasonEntity.forEach(async season => { - console.log('season', season) - - // const seasonBoss: Relation = this.getRelationship(season, 'boss') - // const bossEntity = await bossService.getBossEntityById(seasonBoss._id) - - // console.log('bossEntity', bossEntity) - // const userBoss: Boss = bossService.formatToUserBoss(bossEntity) - // buildList.push(this.formatToUserSeason(season, userBoss)) + if (seasonEntityList.length > 0 && userSeasonList.length === 0) { + seasonEntityList.forEach(async season => { + console.log(season) + const bossEntityRelation: Relation = getRelationship(season, 'boss') + const boss: Boss = bossService.getBossfromBossEntities( + bossEntityList || [], + bossEntityRelation._id + ) + const userSeason = this.formatToUserSeason(season, boss) + buildList.push(userSeason) }) buildList = this.isAllSeasonLocked(buildList) - console.log('buildList', buildList) - return buildList - } - if (userSeason.length !== 0 && seasonEntity.length !== 0) { - seasonEntity.forEach(season => { - if (userSeason.some(found => found.id === season.id)) { - const foundSeason = userSeason.find(s => s.id === season.id) - if (foundSeason) { - buildList.push(foundSeason) - } + } else if (seasonEntityList.length > 0 && userSeasonList.length > 0) { + seasonEntityList.forEach(season => { + const userSeasonIndex = userSeasonList.findIndex( + entity => entity.id === season.id + ) + if (userSeasonIndex >= 0) { + const userSeason: UserSeason = userSeasonList[userSeasonIndex] + buildList.push(userSeason) } else { - // format seasonEntity to fit userSeason array - // buildList.push(this.formatToUserSeason(season)) + const bossEntityRelation: Relation = getRelationship(season, 'boss') + const boss: Boss = bossService.getBossfromBossEntities( + bossEntityList || [], + bossEntityRelation._id + ) + buildList.push(this.formatToUserSeason(season, boss)) } }) buildList = this.isAllSeasonLocked(buildList) - - return buildList } return buildList } @@ -155,7 +131,7 @@ export default class SeasonService { return userSeasons } - public async startUserSeason(userSeason: UserSeason): Promise<boolean> { + public async startUserSeason(userSeason: UserSeason): Promise<UserSeason> { /* Passer une selected userSeason ONGOING 0 Progress @@ -164,7 +140,20 @@ export default class SeasonService { Quizz . create userSeason en base */ - return true + userSeason.state = UserSeasonState.ONGOING + userSeason.progress = 0 + userSeason.startDate = DateTime.local() + userSeason.success = UserSeasonSuccess.ONGOING + try { + const { data: updatedUserSeason } = await this._client.create( + USERSEASON_DOCTYPE, + userSeason + ) + return updatedUserSeason + } catch (error) { + console.log('Initialization error: ', error) + throw error + } } public async updateUserSeason( diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a9358f18d3b6faced558538cb57f1a3b3836c782..60918c44f033c707df919c78fe7f543c5b64d87d 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,3 +1,5 @@ +import get from 'lodash/get' +import { Relation } from 'models' import { FluidType } from '../enum/fluid.enum' import { KonnectorUpdate } from '../enum/konnectorUpdate.enum' @@ -41,3 +43,13 @@ export function formatNumberValues( return '--,--' } } + +/** + * Get one relation in doc + * + * @param {object} doc - DocumentEntity + * @param {string} relName - Name of the relation + */ +export function getRelationship<D>(doc: D, relName: string): Relation { + return get(doc, `relationships.${relName}.data`, []) +} diff --git a/test/__mocks__/userSeasonData.mock.ts b/test/__mocks__/userSeasonData.mock.ts index 911d311d46c9ca68a2b66dbeda2348be6e1b262a..39910106234e70abffa02d2fce52e6bba149810f 100644 --- a/test/__mocks__/userSeasonData.mock.ts +++ b/test/__mocks__/userSeasonData.mock.ts @@ -9,7 +9,6 @@ export const userSeasonData: UserSeason[] = [ title: 'Nicolas Hublot', description: 'foobar', state: UserSeasonState.UNLOCKED, - duration: Duration.fromObject({ days: 30 }), target: 40, progress: 0, boss: bossData, @@ -23,7 +22,6 @@ export const userSeasonData: UserSeason[] = [ title: 'Tata', description: 'foobar', state: UserSeasonState.LOCKED, - duration: Duration.fromObject({ days: 30 }), target: 40, progress: 0, boss: bossData, @@ -37,7 +35,6 @@ export const userSeasonData: UserSeason[] = [ title: 'Toto', description: 'foobar', state: UserSeasonState.ONGOING, - duration: Duration.fromObject({ days: 30 }), target: 40, progress: 0, boss: bossData,