Skip to content
Snippets Groups Projects
AppContextProvider.tsx 9.29 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    import React, { useState, useEffect } from 'react'
    import { withClient, Client } from 'cozy-client'
    import { FluidType } from 'enum/fluid.enum'
    import { ScreenType } from 'enum/screen.enum'
    
    import InitDataManager from 'services/initDataManagerService'
    
    import UserProfileDataManager from 'services/userProfileDataManagerService'
    import { UserChallenge, UserProfile } from 'services/dataChallengeContracts'
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    interface AppContextProps {
      isIndexesLoading: boolean
      isIndexesLoadingSuccess: boolean | null
      isDataLoading: boolean
      isDataLoadingSuccess: boolean | null
      isFluidTypesLoading: boolean
      isFluidTypesLoadingSuccess: boolean | null
      fluidTypes: FluidType[]
      refreshFluidTypes: Function
      isCurrentChallengeUpdateLoading: boolean
      isCurrentChallengeUpdateLoadingSuccess: boolean | null
      currentChallenge: UserChallenge | null
      challengeNotification: boolean
      refreshCurrentChallenge: Function
      isContextLoaded: boolean
      isError: boolean
      screenType: ScreenType
    
      userProfile: UserProfile | null
      setWelcomeModalViewed: Function
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    }
    
    export const AppContext = React.createContext<AppContextProps>({
      isIndexesLoading: false,
      isIndexesLoadingSuccess: null,
      isDataLoading: false,
      isDataLoadingSuccess: null,
      isFluidTypesLoading: false,
      isFluidTypesLoadingSuccess: null,
      fluidTypes: [],
      refreshFluidTypes: () => null,
      isCurrentChallengeUpdateLoading: false,
      isCurrentChallengeUpdateLoadingSuccess: null,
      currentChallenge: null,
      challengeNotification: false,
      refreshCurrentChallenge: () => Promise,
      isContextLoaded: false,
      isError: false,
      screenType: ScreenType.MOBILE,
    
      userProfile: null,
      setWelcomeModalViewed: () => null,
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    })
    
    interface AppContextProviderProps {
      children: React.ReactNode
      client: Client
    }
    
    const AppContextProvider: React.FC<AppContextProviderProps> = ({
      children,
      client,
    }: AppContextProviderProps) => {
      const [isIndexesLoading, setIndexesLoading] = useState<boolean>(false)
      const [isIndexesLoadingSuccess, setIndexesLoadingSuccess] = useState<
        boolean | null
      >(null)
    
      const [isDataLoading, setDataLoading] = useState<boolean>(false)
      const [isDataLoadingSuccess, setDataLoadingSuccess] = useState<
        boolean | null
      >(null)
    
      const [isFluidTypesLoading, setFluidTypesLoading] = useState<boolean>(false)
      const [isFluidTypesLoadingSuccess, setFluidTypesLoadingSuccess] = useState<
        boolean | null
      >(null)
    
      const [fluidTypes, setFluidTypes] = useState<FluidType[]>([])
    
      const [
        isCurrentChallengeUpdateLoading,
        setCurrentChallengeUpdateLoading,
      ] = useState<boolean>(false)
      const [
        isCurrentChallengeUpdateLoadingSuccess,
        setCurrentChallengeUpdateLoadingSuccess,
      ] = useState<boolean | null>(null)
      const [
        currentChallenge,
        setCurrentChallenge,
      ] = useState<UserChallenge | null>(null)
      const [challengeNotification, setChallengeNotification] = useState<boolean>(
        false
      )
    
      const [isContextLoaded, setContextLoaded] = useState<boolean>(false)
      const [isError, setError] = useState<boolean>(false)
      const [screenType, setScreenType] = useState<ScreenType>(ScreenType.MOBILE)
    
    
      const [isUserProfileLoadingSuccess, setUserProfileLoadingSuccess] = useState<
        boolean | null
      >(null)
    
      const [userProfile, setUserProfile] = useState<UserProfile | null>(null)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
      const defineScreenType = () => {
        if (screen.width <= 768) {
          setScreenType(ScreenType.MOBILE)
        } else if (screen.width <= 1024) {
          setScreenType(ScreenType.TABLET)
        } else {
          setScreenType(ScreenType.DESKTOP)
        }
      }
    
      const refreshFluidTypes = async () => {
        const im = new InitDataManager(client)
        const resultFluidTypes = await im.checkFluidTypes()
        if (resultFluidTypes) {
          setFluidTypes(resultFluidTypes)
          const resultAchievement = await im.checkAchievement('CHA00000001')
          if (resultAchievement) {
            const resultNotificationChallenge = await im.isCurrentChallengeOver(
              resultAchievement,
              resultFluidTypes
            )
            if (resultNotificationChallenge) {
              setChallengeNotification(resultNotificationChallenge)
            }
          }
        }
      }
    
    
      const setWelcomeModalViewed = async () => {
        const upm = new UserProfileDataManager(client)
        const updatedUserProfile = await upm.updateUserProfile({
          haveSeenWelcomeModal: true,
        })
        if (updatedUserProfile) {
          setUserProfile(updatedUserProfile)
        }
      }
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
      const refreshCurrentChallenge = async (): Promise<boolean> => {
        const im = new InitDataManager(client)
        try {
          const resultUpdateChallenge = await im.checkCurrentChallenge(fluidTypes)
          setCurrentChallenge(resultUpdateChallenge)
          if (resultUpdateChallenge) {
            const resultNotificationChallenge = await im.isCurrentChallengeOver(
              resultUpdateChallenge,
              fluidTypes
            )
            if (resultNotificationChallenge) {
              setChallengeNotification(resultNotificationChallenge)
            }
          } else {
            setChallengeNotification(false)
          }
          return true
        } catch {
          setCurrentChallenge(null)
          setChallengeNotification(false)
          return false
        }
      }
    
      useEffect(() => {
        let subscribed = true
        function handleResize() {
          defineScreenType()
        }
        handleResize()
        window.addEventListener('resize', handleResize)
        const im = new InitDataManager(client)
    
        const updm = new UserProfileDataManager(client)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
        async function loadData() {
          // Create missing indexes
          setIndexesLoading(true)
          const resultIndexConsoData = await im.initIndex()
          if (subscribed && !resultIndexConsoData) {
            setIndexesLoadingSuccess(false)
            setError(true)
          }
          if (subscribed && resultIndexConsoData) {
            console.log(
              '%c Context: Indexes created',
              'background: #222; color: white'
            )
            setIndexesLoadingSuccess(true)
          }
          setIndexesLoading(false)
    
          // Load challenges, ecogestures and user profile data
          setDataLoading(true)
          const resultInitData = await im.initData()
          if (subscribed && !resultInitData) {
            setDataLoadingSuccess(false)
            setError(true)
          }
          if (subscribed && resultInitData) {
            setDataLoadingSuccess(true)
          }
          setDataLoading(false)
    
          // Load configured fluidTypes
          setFluidTypesLoading(true)
          const resultFluidTypes = await im.checkFluidTypes()
          if (subscribed && resultFluidTypes) {
            console.log(
              '%c Context: Konnectors loaded ',
              'background: #222; color: white'
            )
            setFluidTypes(resultFluidTypes)
            setFluidTypesLoadingSuccess(true)
          }
          setFluidTypesLoading(false)
    
          // Update current challenge if exists
          setCurrentChallengeUpdateLoading(true)
          try {
            const resultUpdateChallenge = await im.checkCurrentChallenge(
              resultFluidTypes ? resultFluidTypes : []
            )
            if (subscribed && resultUpdateChallenge) {
              const resultNotificationChallenge = await im.isCurrentChallengeOver(
                resultUpdateChallenge,
                resultFluidTypes ? resultFluidTypes : []
              )
              if (subscribed && resultNotificationChallenge) {
                setChallengeNotification(resultNotificationChallenge)
              }
            }
            if (subscribed) {
              console.log(
                '%c Context: Current Challenge checked',
                'background: #222; color: white'
              )
              setCurrentChallenge(resultUpdateChallenge)
              setCurrentChallengeUpdateLoadingSuccess(true)
            }
          } catch {
            setCurrentChallengeUpdateLoadingSuccess(false)
            setError(true)
          } finally {
            setCurrentChallengeUpdateLoading(false)
          }
    
    
          //Retrieve the UserProfile
          const loadedUserProfile = await updm.getUserProfile()
          if (!loadedUserProfile) {
            setError(true)
          }
          if (subscribed && loadedUserProfile) {
            console.log(
              '%c Context: UserProfile Loaded',
              'background: #222; color: white'
            )
            setUserProfile(loadedUserProfile)
    
            setUserProfileLoadingSuccess(true)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
        }
        loadData()
        return () => {
          subscribed = false
          window.removeEventListener('resize', handleResize)
        }
      }, [])
    
      useEffect(() => {
        if (
          isIndexesLoadingSuccess &&
          isDataLoadingSuccess &&
          isFluidTypesLoadingSuccess &&
          isCurrentChallengeUpdateLoadingSuccess &&
    
          isUserProfileLoadingSuccess &&
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          !isError
        ) {
          setTimeout(function() {
            setContextLoaded(true)
          }, 1000)
        }
      }, [
        isIndexesLoadingSuccess,
        isDataLoadingSuccess,
        isFluidTypesLoadingSuccess,
        isCurrentChallengeUpdateLoadingSuccess,
    
        isUserProfileLoadingSuccess,
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
        isError,
      ])
    
      return (
        <AppContext.Provider
          value={{
            isIndexesLoading,
            isIndexesLoadingSuccess,
            isDataLoading,
            isDataLoadingSuccess,
            isFluidTypesLoading,
            isFluidTypesLoadingSuccess,
            fluidTypes,
            refreshFluidTypes,
            isCurrentChallengeUpdateLoading,
            isCurrentChallengeUpdateLoadingSuccess,
            currentChallenge,
            challengeNotification,
            refreshCurrentChallenge,
            isContextLoaded,
            isError,
            screenType,
    
            userProfile,
            setWelcomeModalViewed,
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          }}
        >
          {children}
        </AppContext.Provider>
      )
    }
    
    export default withClient(AppContextProvider)