{"version":3,"sources":["stores/LoadingState.ts","hocs/useStore.tsx","stores/AuthenticationStore.ts","stores/ApplicationStorage.ts","stores/ActionsStore.ts","stores/UserLocationStore.ts","stores/AnalyticsStore.ts","stores/RootStore.ts","components/Button/Button.tsx","hooks/useStores.ts","components/ErrorLabel.tsx","components/Page.tsx","assets/img/Icon.tsx","components/ColumnPage.tsx","pages/startup/Email.tsx","pages/startup/CodeConfirmation.tsx","components/Spinner/Spinner.tsx","pages/actions/ActionsCard.tsx","assets/img/geolocationCardBackground.tsx","pages/actions/geolocation/GeolocationCard.tsx","components/Title.tsx","pages/actions/workflows/WorkflowResult.tsx","components/ModalContainer.tsx","pages/actions/workflows/WorkflowDetail.tsx","pages/actions/workflows/useWorkflowDetail.ts","pages/actions/workflows/WorkflowCard.tsx","pages/actions/workflows/WorkflowCardDefault.tsx","pages/actions/workflows/useGeolocalizedWorkflow.ts","pages/actions/workflows/GeolocalizedWorkflowCard.tsx","pages/actions/workflows/useGeolocalizedWorkflowCard.ts","assets/img/ScanQRCodeIcon.tsx","pages/actions/scanner/ScannerCard.tsx","pages/actions/Actions.tsx","stores/entities/Action.ts","components/QRScanner.tsx","components/PaddedPage.tsx","pages/actions/scanner/ScannerDetail.tsx","pages/Router.tsx","common/Formatter.ts","index.tsx","hooks/useConfigLoader.ts","common/errors/ApiErrors.ts","common/ApplicationInfo.ts","services/ProovrApi.ts","services/models/WorkflowResponse.ts"],"names":["LoadingState","StoreContext","createContext","StoreProvider","children","store","Provider","value","AuthenticationStore","proovrApi","applicationStorage","analyticsStore","loadingState","Loaded","email","authenticationState","isUserAuthenticated","makeAutoObservable","this","a","refreshIsAuthenticated","jwt","get","runInAction","post","type","authenticated","generateAuthenticationState","Loading","requestEmailVerification","Error","code","verifyEmail","emailResponse","set","emailCredential","authenticationSucceeded","require","v4","clear","ApplicationStorage","remove","key","localStorage","getItem","e","setItem","console","log","removeItem","ActionsStore","userLocationStore","actions","reaction","locationEnabled","populateActions","refresh","fetchWorkflows","workflows","isMobile","push","actionType","items","map","workflowResponse","forEach","UserLocationStore","userLocation","geolocationHandlerId","registerGeolocationHandler","navigator","geolocation","watchPosition","location","clearWatch","AnalyticsStore","baseURL","analyticsUserId","client","axios","create","authenticationTimer","uuid","Cookies","DateTime","local","secondsPassed","diff","seconds","duration","body","agentType","httpBody","source","RootStore","config","authenticationStore","actionsStore","ApiBaseUrl","ProovrApi","ProovrApiBaseUrl","reset","logout","Button","React","forwardRef","props","ref","className","size","buttonSize","isLoading","outline","disabled","onClick","data-test-id","testId","href","useStores","useContext","ErrorLabel","message","Page","style","minHeight","Icon","width","height","viewBox","fill","xmlns","rx","d","filter","id","x","y","filterUnits","colorInterpolationFilters","floodOpacity","result","in","values","dy","stdDeviation","mode","in2","x1","y1","x2","y2","gradientUnits","stopColor","offset","ColumnPage","IconHeader","t","useTranslation","Email","observer","history","useHistory","useState","error","setError","input","setInput","autoSubmit","setAutoSubmit","buttonRef","useRef","useEffect","emailParameter","URLSearchParams","window","search","authenticationStarted","current","click","onSubmit","preventDefault","RoutePath","codeConfirmation","htmlFor","onChange","event","target","required","placeholder","CodeConfirmation","SpinnerIcon","CenteredSpinner","SpinnerWithBorder","ActionsCard","isActive","opacity","position","GeolocationCardBackground","marginLeft","stroke","strokeWidth","GeolocationCard","left","top","right","bottom","overflow","borderRadius","Title","title","WorkflowResult","isSucceeded","resultMessage","onTap","buttonTitle","src","SuccessIcon","FailureIcon","modalStyles","overlay","backgroundColor","zIndex","content","padding","inset","ModalContainer","isOpen","setIsOpen","document","onClose","WorkflowDetail","setIsLoading","initialWorkflowResultState","showResult","setResult","shouldRedirect","url","webViewNavigationHandler","handleWebViewNavigation","redirect","setRedirect","workflow","credentials","Map","requestedCredentials","Object","entries","startWorkflow","startUrl","response","status","redirectToUrl","redirectIdentityToUrl","NetworkError","setFailedResult","resultParam","searchParams","messageParam","red","res","useWorkflowDetail","onMessage","dataURL","data","resultValue","URL","toString","close","addEventListener","removeEventListener","frameBorder","onLoad","WorkflowCard","workflowDetail","setWorkflowDetail","workflowId","alt","logoUrl","name","description","WorkflowCardDefault","translationBasePath","localizationKey","enabled","translationInterpolations","variables","useWorkflowCardDefault","TIMERS_KEY","useGeolocalizedWorkflow","gpsLocation","geoLocationCondition","allowInside","allowOutside","isGeolocationAuthorized","userToLocationRadiusDistance","userWasPreviouslyInRange","userLocationObject","latitude","coords","longitude","distanceInMeters","getDistance","Math","max","radius","timers","timersJSON","JSON","parse","toISO","stringify","Array","from","saveTimerWithId","isExpired","activationTime","fromISO","isTimerExpired","delete","clearTimer","GeolocalizedWorkflowCard","workflowGeolocalizationPath","distanceDescriptionTranslationKey","undefined","distance","useGeolocalizedWorkflowCard","ScanQRCodeIcon","cx","cy","r","fill-rule","clip-rule","ScannerCard","qrCodeScanner","Actions","workflowURL","ActionsCards","action","isActionGeolocation","actionGeolocation","isActionWorkFlow","actionWorkFlow","Header","rootStore","confirm","styles","relative","viewFinder","boxSizing","border","boxShadow","QRScanner","qrCodeOnError","setQrCodeOnError","onQrCodeOnError","showViewFinder","delay","onError","onScan","setQRCodeData","PaddedPage","ScannerDetail","setWorkflow","errorMessage","setErrorMessage","processData","getWorkflowFromUrl","replace","useScannerDetail","state","Scanner","path","indexOf","Router","pathName","pathname","urlParameters","workflowParameter","workflowURLParameter","isAuthenticatedPath","isUnAuthenticatedPath","analyticsURLParameters","parameter","slice","component","Formatter","userLanguageCode","countryCode","format","metersToCurrentLengthUnit","formattedDate","dateStringForValue","meters","lengthUnit","feet","round","date","moment","ISO_8601","isValid","locale","find","v","toLowerCase","configure","enforceActions","reactionRequiresObservable","observableRequiresReaction","Application","setConfig","fetch","json","useConfigLoader","formatter","i18n","use","initReactI18next","LanguageDetector","Backend","init","load","backend","backends","LocalStorageBackend","BackendAdapter","HttpBackend","loadPath","allowMultiLoading","crossDomain","backendOptions","expirationTime","prefix","versions","fallbackLng","ns","interpolation","escapeValue","_","interpolate","then","StrictMode","fallback","HeaderAndRouter","Helmet","ReactDOM","render","getElementById","EmailError","ConfirmationCodeError","InvalidWorkflowError","language","substring","global","Buffer","baseUrl","headers","unauthorizedErrorHandler","interceptors","Promise","reject","statusText","State","logHttpSuccess","logHttpError","emailErrors","errors","split","Token","codeError","params","page","pageSize","authenticatedHeaders","isWorkflowResponse","jsonCredentials","fromMapToObj","Credentials","installationId","match","Authorization","obj","w"],"mappings":"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","file":"static/js/main.6f3b8b19.chunk.js","sourcesContent":["export enum LoadingState {\r\n Loading,\r\n Loaded,\r\n Error,\r\n}\r\n","import React, { FC, createContext, ReactNode, ReactElement } from \"react\";\r\nimport { RootStore } from \"../stores/RootStore\";\r\n\r\nexport const StoreContext = createContext({} as RootStore);\r\n\r\nexport type StoreComponent = FC<{\r\n store: RootStore;\r\n children: ReactNode;\r\n}>;\r\n\r\nexport const StoreProvider: StoreComponent = ({\r\n children,\r\n store,\r\n}): ReactElement => {\r\n return (\r\n {children}\r\n );\r\n};\r\n","import { makeAutoObservable, runInAction } from \"mobx\";\r\nimport { LoadingState } from \"./LoadingState\";\r\nimport { ProovrApi } from \"../services/ProovrApi\";\r\nimport { VerifyEmailResponse } from \"../services/models/VerifyEmailResponse\";\r\nimport { ApplicationStorage } from \"./ApplicationStorage\";\r\nimport { AnalyticsStore } from \"./AnalyticsStore\";\r\n\r\nexport class AuthenticationStore {\r\n public loadingState: LoadingState = LoadingState.Loaded;\r\n public email: string = \"\";\r\n private authenticationState: string | null = null;\r\n public isUserAuthenticated: boolean = false;\r\n\r\n constructor(\r\n private proovrApi: ProovrApi,\r\n private applicationStorage: ApplicationStorage,\r\n private analyticsStore: AnalyticsStore\r\n ) {\r\n makeAutoObservable(this);\r\n (async () => {\r\n await this.refreshIsAuthenticated();\r\n })();\r\n }\r\n\r\n public refreshIsAuthenticated() {\r\n // consider user being authenticated if we have a jwt\r\n const jwt = this.applicationStorage.get(\"auth_jwt\");\r\n runInAction(() => {\r\n this.isUserAuthenticated = !!jwt;\r\n this.analyticsStore.post({\r\n type: \"user-status\",\r\n authenticated: this.isUserAuthenticated,\r\n });\r\n });\r\n }\r\n\r\n public async requestEmailVerification(email: string): Promise {\r\n this.authenticationState = this.generateAuthenticationState();\r\n runInAction(() => {\r\n this.loadingState = LoadingState.Loading;\r\n });\r\n\r\n try {\r\n await this.proovrApi.requestEmailVerification(\r\n email,\r\n this.authenticationState\r\n );\r\n runInAction(() => {\r\n this.email = email;\r\n this.loadingState = LoadingState.Loaded;\r\n });\r\n } catch (error) {\r\n runInAction(() => {\r\n this.loadingState = LoadingState.Error;\r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n public async verifyEmail(code: string): Promise {\r\n runInAction(() => {\r\n this.loadingState = LoadingState.Loading;\r\n });\r\n try {\r\n let emailResponse: VerifyEmailResponse = await this.proovrApi.verifyEmail(\r\n this.email,\r\n this.authenticationState,\r\n code\r\n );\r\n this.applicationStorage.set(emailResponse.emailCredential, \"auth_jwt\");\r\n await this.refreshIsAuthenticated();\r\n this.analyticsStore.authenticationSucceeded();\r\n runInAction(() => {\r\n this.loadingState = LoadingState.Loaded;\r\n });\r\n } catch (error) {\r\n runInAction(() => {\r\n this.isUserAuthenticated = false;\r\n this.loadingState = LoadingState.Error;\r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n private generateAuthenticationState(): string {\r\n const uuid = require(\"uuid\");\r\n return uuid.v4();\r\n }\r\n\r\n public logout() {\r\n this.applicationStorage.clear();\r\n this.refreshIsAuthenticated();\r\n }\r\n}\r\n","export type ApplicationStorageKey =\r\n | \"auth_jwt\"\r\n | \"analyticsUserId\"\r\n | \"workflowNavigationParameter\"\r\n | \"workflowURLNavigationParameter\";\r\n\r\nexport class ApplicationStorage {\r\n public clear() {\r\n this.remove(\"auth_jwt\");\r\n this.remove(\"workflowNavigationParameter\");\r\n this.remove(\"workflowURLNavigationParameter\");\r\n }\r\n\r\n public get(key: ApplicationStorageKey): string | null {\r\n try {\r\n return localStorage.getItem(key);\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n\r\n public set(value: string | null, key: ApplicationStorageKey) {\r\n try {\r\n if (value) {\r\n localStorage.setItem(key, value);\r\n } else {\r\n this.remove(key);\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n }\r\n\r\n public remove(key: ApplicationStorageKey) {\r\n try {\r\n localStorage.removeItem(key);\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n}\r\n","import { makeAutoObservable, reaction, runInAction } from \"mobx\";\r\nimport { LoadingState } from \"./LoadingState\";\r\nimport { ProovrApi } from \"../services/ProovrApi\";\r\nimport { Action, ActionScanner, ActionWorkFlow } from \"./entities/Action\";\r\nimport { isMobile } from \"react-device-detect\";\r\nimport { UserLocationStore } from \"./UserLocationStore\";\r\nimport { AnalyticsStore } from \"./AnalyticsStore\";\r\n\r\nexport class ActionsStore {\r\n public loadingState: LoadingState = LoadingState.Loading;\r\n public actions: Action[] = [];\r\n\r\n constructor(\r\n private proovrApi: ProovrApi,\r\n private userLocationStore: UserLocationStore,\r\n private analyticsStore: AnalyticsStore\r\n ) {\r\n makeAutoObservable(this);\r\n\r\n // reacts on changes of locationEnabled to display the proper cell\r\n reaction(\r\n () => userLocationStore.locationEnabled,\r\n (locationEnabled) => {\r\n (async () => {\r\n await this.populateActions();\r\n })();\r\n }\r\n );\r\n }\r\n\r\n public async refresh() {\r\n await this.userLocationStore.refresh();\r\n await this.populateActions();\r\n }\r\n\r\n public async populateActions() {\r\n const locationEnabled = this.userLocationStore.locationEnabled;\r\n if (locationEnabled !== null) {\r\n this.analyticsStore.post({\r\n type: \"actions-page-started\",\r\n \"authorized-location\": locationEnabled ? \"true\" : \"false\",\r\n });\r\n }\r\n\r\n const workflows = await this.proovrApi.fetchWorkflows();\r\n\r\n let actions: Action[] = [];\r\n // scanner\r\n if (isMobile) {\r\n actions.push({ actionType: \"scanner\" } as ActionScanner);\r\n }\r\n\r\n // geolocation not authorized\r\n if (locationEnabled !== null && !locationEnabled) {\r\n actions.push({ actionType: \"geo\" });\r\n }\r\n\r\n // workflows\r\n let actionWorkFlows = workflows.items.map((workflowResponse) => {\r\n return {\r\n actionType: \"workflow\",\r\n workflowResponse: workflowResponse,\r\n };\r\n }) as ActionWorkFlow[];\r\n actionWorkFlows.forEach((a) => actions.push(a));\r\n\r\n runInAction(() => {\r\n this.actions = actions;\r\n this.loadingState = LoadingState.Loaded;\r\n });\r\n }\r\n\r\n reset() {\r\n runInAction(() => {\r\n this.actions = [];\r\n this.loadingState = LoadingState.Loading;\r\n });\r\n }\r\n}\r\n","import { makeAutoObservable, runInAction } from \"mobx\";\r\n\r\nexport class UserLocationStore {\r\n public userLocation: Position | null = null;\r\n public locationEnabled: boolean | null = null;\r\n private geolocationHandlerId: number = 0;\r\n\r\n constructor() {\r\n makeAutoObservable(this);\r\n }\r\n\r\n private registerGeolocationHandler = () => {\r\n return navigator.geolocation.watchPosition(\r\n (location) => {\r\n runInAction(() => {\r\n this.userLocation = location;\r\n this.locationEnabled = true;\r\n });\r\n },\r\n () => {\r\n runInAction(() => {\r\n this.userLocation = null;\r\n this.locationEnabled = false;\r\n });\r\n console.log(\r\n \"Retrieving user location failed. Most likely location access permission is denied.\"\r\n );\r\n }\r\n );\r\n };\r\n\r\n public refresh() {\r\n if (this.geolocationHandlerId !== 0) {\r\n navigator.geolocation.clearWatch(this.geolocationHandlerId);\r\n }\r\n this.geolocationHandlerId = this.registerGeolocationHandler();\r\n }\r\n}\r\n","import * as axios from \"axios\";\r\nimport { DateTime } from \"luxon\";\r\nimport { isMobile } from \"react-device-detect\";\r\nimport { ApplicationStorage } from \"./ApplicationStorage\";\r\nimport Cookies from \"js-cookie\";\r\n\r\ntype bodyAuthorization = \"undefined\" | \"true\" | \"false\";\r\ninterface AnalyticsBody {\r\n type: string;\r\n url?: string;\r\n \"page-name\"?: string;\r\n \"url-parameters\"?: string;\r\n duration?: number;\r\n \"http-response-status\"?: number;\r\n \"http-response-message\"?: number;\r\n \"http-response-success\"?: boolean;\r\n \"authorized-location\"?: bodyAuthorization;\r\n \"authorized-camera\"?: bodyAuthorization;\r\n authenticated?: boolean;\r\n}\r\n\r\nexport class AnalyticsStore {\r\n private readonly analyticsUserId: string;\r\n\r\n private client: axios.AxiosInstance = axios.default.create({\r\n baseURL: this.baseURL,\r\n });\r\n\r\n constructor(\r\n private applicationStorage: ApplicationStorage,\r\n private baseURL: string\r\n ) {\r\n const uuid = require(\"uuid\");\r\n this.analyticsUserId =\r\n applicationStorage.get(\"analyticsUserId\") ?? uuid.v4();\r\n applicationStorage.set(this.analyticsUserId, \"analyticsUserId\");\r\n if (!Cookies.get(\"session\")) {\r\n Cookies.set(\"session\", uuid.v4());\r\n }\r\n }\r\n\r\n private authenticationTimer: DateTime | null = null;\r\n public authenticationStarted() {\r\n this.authenticationTimer = DateTime.local();\r\n this.post({ type: \"authentication-started\" });\r\n }\r\n\r\n public authenticationSucceeded() {\r\n const secondsPassed = DateTime.local().diff(\r\n this.authenticationTimer ?? DateTime.local(),\r\n \"seconds\"\r\n ).seconds;\r\n this.post({\r\n type: \"authentication-succeeded\",\r\n duration: secondsPassed,\r\n });\r\n }\r\n\r\n public post(body: AnalyticsBody) {\r\n const agentType = isMobile ? \"mobile\" : \"desktop\";\r\n const httpBody = {\r\n source: \"proovr-web\",\r\n \"agent-type\": agentType,\r\n \"session-id\": Cookies.get(\"session\"),\r\n \"user-id\": this.analyticsUserId,\r\n ...body,\r\n };\r\n //console.log(\"### Analytics.post\", body);\r\n (async () => {\r\n try {\r\n await this.client.post(\"/stats\", httpBody);\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n })();\r\n }\r\n}\r\n","import { ProovrApi } from \"../services/ProovrApi\";\r\nimport { AuthenticationStore } from \"./AuthenticationStore\";\r\nimport { ApplicationStorage } from \"./ApplicationStorage\";\r\nimport { ActionsStore } from \"./ActionsStore\";\r\nimport { Config } from \"../hooks/useConfigLoader\";\r\nimport { UserLocationStore } from \"./UserLocationStore\";\r\nimport { AnalyticsStore } from \"./AnalyticsStore\";\r\n\r\nexport class RootStore {\r\n public applicationStorage: ApplicationStorage = new ApplicationStorage();\r\n public proovrApi: ProovrApi;\r\n public authenticationStore: AuthenticationStore;\r\n public userLocationStore: UserLocationStore;\r\n public actionsStore: ActionsStore;\r\n public analyticsStore: AnalyticsStore;\r\n\r\n constructor(config: Config) {\r\n this.analyticsStore = new AnalyticsStore(\r\n this.applicationStorage,\r\n config.ApiBaseUrl\r\n );\r\n this.proovrApi = new ProovrApi(\r\n config.ProovrApiBaseUrl,\r\n this.applicationStorage,\r\n this.analyticsStore\r\n );\r\n this.authenticationStore = new AuthenticationStore(\r\n this.proovrApi,\r\n this.applicationStorage,\r\n this.analyticsStore\r\n );\r\n this.userLocationStore = new UserLocationStore();\r\n this.actionsStore = new ActionsStore(\r\n this.proovrApi,\r\n this.userLocationStore,\r\n this.analyticsStore\r\n );\r\n }\r\n\r\n public logout() {\r\n this.analyticsStore.post({ type: \"log-out\" });\r\n this.actionsStore.reset();\r\n this.authenticationStore.logout();\r\n }\r\n}\r\n","import React, { PropsWithChildren } from \"react\";\r\n\r\nexport interface ButtonProps extends React.HTMLProps {\r\n isLoading?: boolean;\r\n disabled?: boolean;\r\n onClick?: () => void;\r\n buttonSize?: \"s\" | \"m\" | \"l\";\r\n outline?: boolean;\r\n type?: \"submit\" | \"reset\" | \"button\";\r\n className?: string;\r\n testId?: string;\r\n}\r\nexport const Button = React.forwardRef(\r\n (props: PropsWithChildren, ref) => {\r\n let className = \"c-button c-button--fluid\";\r\n if (props.size || props.buttonSize !== \"m\") {\r\n className += ` c-button--${props.buttonSize}`;\r\n }\r\n if (props.isLoading) {\r\n className += \" is-loading\";\r\n }\r\n\r\n if (!props.outline) {\r\n className += \" c-button--primary\";\r\n }\r\n if (props.className) {\r\n className += \" \" + props.className;\r\n }\r\n\r\n return (\r\n \r\n {props.isLoading && (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {props.children}\r\n \r\n );\r\n }\r\n);\r\n","import { useContext } from \"react\";\r\nimport { RootStore } from \"../stores/RootStore\";\r\nimport { StoreContext } from \"../hocs/useStore\";\r\n\r\nexport const useStores = (): RootStore => useContext(StoreContext);\r\n","import React from \"react\";\r\n\r\ninterface Props {\r\n message: string;\r\n className?: string;\r\n}\r\n\r\nexport const ErrorLabel = (props: Props) => {\r\n return (\r\n \r\n {props.message}\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\n\r\ninterface Props {}\r\nexport const Page = (props: React.PropsWithChildren) => {\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n","import React from \"react\";\r\n\r\ninterface Props {\r\n width?: number;\r\n}\r\n\r\nexport const Icon = (props: Props) => {\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { Page } from \"./Page\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Icon } from \"../assets/img/Icon\";\r\n\r\ninterface Props {}\r\n\r\nexport const ColumnPage = (props: React.PropsWithChildren) => {\r\n return (\r\n \r\n
\r\n \r\n
{props.children}
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const IconHeader = () => {\r\n const { t } = useTranslation(\"mobile\");\r\n return (\r\n
\r\n \r\n \r\n \r\n {t(\"onboarding.welcome\")}\r\n \r\n
\r\n \r\n );\r\n};\r\n","import { observer } from \"mobx-react-lite\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport React, { useEffect, useRef, useState } from \"react\";\r\nimport { Button } from \"../../components/Button/Button\";\r\nimport { useHistory } from \"react-router-dom\";\r\nimport { useStores } from \"../../hooks/useStores\";\r\nimport { LoadingState } from \"../../stores/LoadingState\";\r\nimport { ErrorLabel } from \"../../components/ErrorLabel\";\r\nimport { RoutePath } from \"../Router\";\r\nimport { ColumnPage } from \"../../components/ColumnPage\";\r\n\r\nexport const Email = observer(() => {\r\n const { t } = useTranslation(\"mobile\");\r\n const { authenticationStore, analyticsStore } = useStores();\r\n const history = useHistory();\r\n const [error, setError] = useState(\"\");\r\n const [input, setInput] = useState(\"\");\r\n const [autoSubmit, setAutoSubmit] = useState(false);\r\n const buttonRef = useRef(null);\r\n\r\n useEffect(() => {\r\n const urlParameters = new URLSearchParams(window.location.search);\r\n const emailParameter: string | null = urlParameters.get(\"email\");\r\n if (emailParameter) {\r\n setInput(emailParameter);\r\n setAutoSubmit(true);\r\n }\r\n analyticsStore.authenticationStarted();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (autoSubmit) {\r\n buttonRef?.current?.click();\r\n }\r\n }, [autoSubmit]);\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n await authenticationStore.requestEmailVerification(input);\r\n history.push(RoutePath.codeConfirmation);\r\n } catch (e: any) {\r\n console.error(error);\r\n setError(e.message);\r\n }\r\n };\r\n\r\n const onChange = (event: React.ChangeEvent) => {\r\n setInput(event.target.value);\r\n };\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"email.instruction\")}\r\n \r\n
\r\n {error !== \"\" && (\r\n \r\n )}\r\n \r\n
\r\n
\r\n \r\n {t(\"common.verify\")}\r\n \r\n
\r\n \r\n
\r\n );\r\n});\r\n","import { observer } from \"mobx-react-lite\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport React, { useState } from \"react\";\r\nimport { Button } from \"../../components/Button/Button\";\r\nimport { LoadingState } from \"../../stores/LoadingState\";\r\nimport { useStores } from \"../../hooks/useStores\";\r\nimport { useHistory } from \"react-router-dom\";\r\nimport { ErrorLabel } from \"../../components/ErrorLabel\";\r\nimport { RoutePath } from \"../Router\";\r\nimport { ColumnPage } from \"../../components/ColumnPage\";\r\n\r\nexport const CodeConfirmation = observer(() => {\r\n const { t } = useTranslation(\"mobile\");\r\n const { authenticationStore } = useStores();\r\n const history = useHistory();\r\n const [error, setError] = useState(\"\");\r\n const [input, setInput] = useState(\"\");\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n try {\r\n await authenticationStore.verifyEmail(input);\r\n history.push(RoutePath.actions);\r\n } catch (e: any) {\r\n console.error(e);\r\n setError(e.message);\r\n }\r\n };\r\n\r\n const onChange = (event: React.ChangeEvent) => {\r\n setInput(event.target.value);\r\n };\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"confirmation_code.instruction\")}\r\n \r\n
\r\n {error !== \"\" && (\r\n \r\n )}\r\n \r\n
\r\n
\r\n \r\n {t(\"common.verify\")}\r\n \r\n
\r\n \r\n
\r\n );\r\n});\r\n","import React from \"react\";\r\n\r\nconst SpinnerIcon = () => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const CenteredSpinner = () => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const SpinnerWithBorder = () => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import React, { MouseEventHandler, PropsWithChildren } from \"react\";\r\n\r\ninterface Props {\r\n isActive?: boolean;\r\n onClick: MouseEventHandler;\r\n}\r\n\r\nexport const ActionsCard = (props: PropsWithChildren) => {\r\n const isActive = props.isActive ?? true;\r\n return (\r\n {}}\r\n >\r\n \r\n {props.children}\r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nexport const GeolocationCardBackground = () => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import { observer } from \"mobx-react-lite\";\r\nimport React, { MouseEventHandler } from \"react\";\r\nimport { ActionsCard } from \"../ActionsCard\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { GeolocationCardBackground } from \"../../../assets/img/geolocationCardBackground\";\r\n\r\ninterface Props {\r\n onClick: MouseEventHandler;\r\n}\r\n\r\nexport const GeolocationCard = observer((props: Props) => {\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n
\r\n {t(\"permissions.geolocalization_not_authorized_description\")}\r\n
\r\n
\r\n {t(\"permissions.geolocalization_not_authorized_subtitle\")}\r\n
\r\n
\r\n \r\n );\r\n});\r\n","import React from \"react\";\r\n\r\ninterface Props {\r\n title: string;\r\n className?: string;\r\n}\r\n\r\nexport const Title = (props: Props) => {\r\n return (\r\n \r\n {props.title}\r\n \r\n );\r\n};\r\n","import React, { CSSProperties } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport SuccessIcon from \"@proxyclick/hello-icons/dist/svg/checkmark-circle--color-32.svg\";\r\nimport FailureIcon from \"@proxyclick/hello-icons/dist/svg/danger--color-24.svg\";\r\nimport { Button } from \"../../../components/Button/Button\";\r\nimport { Title } from \"../../../components/Title\";\r\n\r\ninterface Props {\r\n isSucceeded: boolean;\r\n resultMessage: string | null;\r\n onTap(): void;\r\n}\r\n\r\nexport const WorkflowResult = (props: Props) => {\r\n const { isSucceeded, resultMessage, onTap } = props;\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n const buttonTitle = isSucceeded ? t(\"common.done\") : t(\"common.cancel\");\r\n const title = isSucceeded\r\n ? t(\"workflow.result_title_succeeded\")\r\n : t(\"workflow.result_title_failed\");\r\n return (\r\n \r\n \r\n <div\r\n className={\r\n \"u-flex u-flex-auto u-flex-grow1 u-flex-align-items-center u-flex-justify-center\"\r\n }\r\n >\r\n <div className={\"u-align-center\"}>\r\n <img\r\n src={isSucceeded ? SuccessIcon : FailureIcon}\r\n style={{ width: 80 }}\r\n />\r\n <div className={\"u-color-neutral-medium u-text-l\"}>\r\n {resultMessage}\r\n </div>\r\n </div>\r\n </div>\r\n <Button onClick={onTap}>{buttonTitle}</Button>\r\n </div>\r\n );\r\n};\r\n","import React, { useEffect, useState } from \"react\";\r\nimport Modal from \"react-modal\";\r\n\r\nexport interface Props {\r\n onClose(): void;\r\n}\r\n\r\nconst modalStyles = {\r\n overlay: {\r\n backgroundColor: \"rgba(0, 0, 0, 0.45)\",\r\n zIndex: 1000,\r\n },\r\n content: {\r\n padding: 0,\r\n backgroundColor: \"#f3f3f6\",\r\n inset: 0,\r\n borderRadius: 0,\r\n },\r\n};\r\n\r\nexport const ModalContainer = (props: React.PropsWithChildren<Props>) => {\r\n const [isOpen, setIsOpen] = useState(true);\r\n\r\n useEffect(() => {\r\n document.body.style.overflow = \"hidden\";\r\n return () => {\r\n document.body.style.overflow = \"unset\";\r\n };\r\n }, []);\r\n\r\n return (\r\n <Modal isOpen={isOpen} style={modalStyles}>\r\n <div\r\n className={\"u-flex u-flex-col u-flex-auto\"}\r\n style={{ height: \"100%\" }}\r\n >\r\n <div\r\n className={\r\n \"u-flex u-align-right u-padding-right-s u-padding-top-s u-flex-justify-end\"\r\n }\r\n >\r\n <div\r\n onClick={() => {\r\n setIsOpen(false);\r\n props.onClose();\r\n }}\r\n >\r\n <svg className=\"c-icon__svg u-cursor-pointer\">\r\n <use href={\"#close-circle-24\"}></use>\r\n </svg>\r\n </div>\r\n </div>\r\n {props.children}\r\n </div>\r\n </Modal>\r\n );\r\n};\r\n","import React, { useEffect } from \"react\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { useWorkflowDetail } from \"./useWorkflowDetail\";\r\nimport { CenteredSpinner } from \"../../../components/Spinner/Spinner\";\r\nimport { WorkflowResult } from \"./WorkflowResult\";\r\nimport { ModalContainer } from \"../../../components/ModalContainer\";\r\n\r\nexport interface Props {\r\n workflow: WorkflowResponse | null;\r\n onClose(): void;\r\n}\r\n\r\nexport const WorkflowDetail = (props: Props) => {\r\n const { result, redirect, isLoading, startWorkflow } = useWorkflowDetail();\r\n\r\n const onMessage = (event: MessageEvent) => {\r\n const dataURL = event.data?.data?.url;\r\n if (dataURL) {\r\n const url = new URL(dataURL, document.location.toString());\r\n const resultValue = url.searchParams.get(\"ProovrResult\");\r\n if (resultValue && resultValue === \"OK\") {\r\n close();\r\n }\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n // listen to onMessage calls from the workflows we visit\r\n window.addEventListener(\"message\", onMessage, false);\r\n return () => {\r\n window.removeEventListener(\"message\", onMessage);\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n const workflow = props.workflow;\r\n if (workflow !== null) {\r\n (async () => {\r\n await startWorkflow(workflow);\r\n })();\r\n }\r\n }, [props.workflow]);\r\n\r\n const close = () => {\r\n props.onClose();\r\n };\r\n\r\n return (\r\n <ModalContainer onClose={close}>\r\n {isLoading && <CenteredSpinner />}\r\n {result.showResult && (\r\n <WorkflowResult\r\n isSucceeded={result.isSucceeded}\r\n resultMessage={result.message}\r\n onTap={close}\r\n />\r\n )}\r\n {redirect.shouldRedirect && !result.showResult && (\r\n // for the iframe to expand to 100% height all its parents must be 100% height\r\n <div style={{ height: \"100%\" }}>\r\n <iframe\r\n title={\"proovr web\"}\r\n width={\"100%\"}\r\n height={\"100%\"}\r\n frameBorder={0}\r\n src={redirect.url}\r\n onLoad={() => {}}\r\n />\r\n </div>\r\n )}\r\n </ModalContainer>\r\n );\r\n};\r\n","import { useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { NetworkError } from \"../../../common/errors/ApiErrors\";\r\nimport { useStores } from \"../../../hooks/useStores\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\n\r\nexport interface WorkflowRedirectState {\r\n shouldRedirect: boolean;\r\n url: string;\r\n webViewNavigationHandler: (url: URL) => void;\r\n}\r\n\r\nexport interface WorkflowResultState {\r\n showResult: boolean;\r\n isSucceeded: boolean;\r\n message: string | null;\r\n}\r\n\r\nexport const useWorkflowDetail = () => {\r\n const { proovrApi, applicationStorage } = useStores();\r\n const [isLoading, setIsLoading] = useState(true);\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n const initialWorkflowResultState = {\r\n showResult: false,\r\n isSucceeded: false,\r\n message: \"\",\r\n };\r\n const [result, setResult] = useState<WorkflowResultState>(\r\n initialWorkflowResultState\r\n );\r\n const [redirect, setRedirect] = useState<WorkflowRedirectState>({\r\n shouldRedirect: false,\r\n url: \"\",\r\n webViewNavigationHandler: handleWebViewNavigation,\r\n });\r\n\r\n async function startWorkflow(workflow: WorkflowResponse): Promise<void> {\r\n setResult(initialWorkflowResultState);\r\n setIsLoading(true);\r\n try {\r\n const credentials = new Map<string, string>();\r\n const jwt = applicationStorage.get(\"auth_jwt\");\r\n if (workflow.requestedCredentials && jwt) {\r\n for (const [key] of Object.entries(workflow.requestedCredentials)) {\r\n if (key === \"Email\" && jwt) {\r\n credentials.set(key, jwt);\r\n }\r\n }\r\n }\r\n\r\n const response = await proovrApi.startWorkflow(\r\n workflow.startUrl,\r\n credentials\r\n );\r\n\r\n if (response?.status === \"REDIRECT\" || response?.status === 2) {\r\n redirectToUrl(response.redirectIdentityToUrl);\r\n } else {\r\n setResult({\r\n isSucceeded: response.status === \"OK\",\r\n showResult: true,\r\n message: response.message,\r\n });\r\n }\r\n } catch (error) {\r\n if (error instanceof NetworkError) {\r\n setFailedResult(error.message);\r\n } else {\r\n setFailedResult(t(\"common.error_generic\"));\r\n }\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }\r\n\r\n function redirectToUrl(url: string | undefined): void {\r\n if (url) {\r\n setRedirect({\r\n shouldRedirect: true,\r\n url: url,\r\n webViewNavigationHandler: handleWebViewNavigation,\r\n });\r\n } else {\r\n setFailedResult(t(\"workflow.could_not_redirect\"));\r\n }\r\n }\r\n\r\n function setFailedResult(message: string): void {\r\n setResult({\r\n showResult: true,\r\n isSucceeded: false,\r\n message: message,\r\n });\r\n }\r\n\r\n function handleWebViewNavigation(url: URL) {\r\n const resultParam = url.searchParams.get(\"ProovrResult\");\r\n const messageParam = url.searchParams.get(\"ProovrMessage\");\r\n if (resultParam && messageParam) {\r\n setResult({\r\n showResult: true,\r\n isSucceeded: resultParam === \"OK\",\r\n message: messageParam,\r\n });\r\n setRedirect((red) => {\r\n red.shouldRedirect = false;\r\n return red;\r\n });\r\n } else if (resultParam && !messageParam) {\r\n setResult((res) => {\r\n res.showResult = false;\r\n return res;\r\n });\r\n }\r\n }\r\n\r\n return {\r\n result,\r\n redirect,\r\n isLoading,\r\n startWorkflow,\r\n };\r\n};\r\n","import { observer } from \"mobx-react-lite\";\r\nimport React, { useEffect, useState } from \"react\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { ActionsCard } from \"../ActionsCard\";\r\nimport { WorkflowDetail } from \"./WorkflowDetail\";\r\nimport { useStores } from \"../../../hooks/useStores\";\r\n\r\ninterface Props {\r\n workflowResponse: WorkflowResponse;\r\n name: string;\r\n description: string;\r\n isActive: boolean;\r\n}\r\n\r\nexport const WorkflowCard = observer((props: Props) => {\r\n const { applicationStorage, actionsStore } = useStores();\r\n const [workflowDetail, setWorkflowDetail] = useState<WorkflowResponse | null>(\r\n null\r\n );\r\n\r\n useEffect(() => {\r\n const workflow = applicationStorage.get(\"workflowNavigationParameter\");\r\n if (workflow && workflow === props.workflowResponse.workflowId) {\r\n setWorkflowDetail(props.workflowResponse);\r\n applicationStorage.remove(\"workflowNavigationParameter\");\r\n }\r\n }, []);\r\n\r\n return (\r\n <>\r\n {workflowDetail !== null && (\r\n <WorkflowDetail\r\n workflow={workflowDetail}\r\n onClose={async () => {\r\n setWorkflowDetail(null);\r\n await actionsStore.refresh();\r\n }}\r\n />\r\n )}\r\n <ActionsCard\r\n isActive={props.isActive}\r\n onClick={() => {\r\n setWorkflowDetail(props.workflowResponse);\r\n }}\r\n >\r\n <div className=\"u-width-50 u-margin-bottom-xs\">\r\n <div className=\"c-image-fit c-image-fit--square c-image-fit--cover\">\r\n <img\r\n alt=\"logo\"\r\n src={props.workflowResponse.logoUrl}\r\n style={{ borderRadius: \"25px\" }}\r\n />\r\n </div>\r\n </div>\r\n <div className=\"c-heading c-heading--xl u-margin-bottom-none u-margin-bottom-2xs@medium\">\r\n {props.name}\r\n </div>\r\n <div className=\"u-text-s u-text-m@medium u-color-neutral-dark\">\r\n {props.description}\r\n </div>\r\n </ActionsCard>\r\n </>\r\n );\r\n});\r\n","import React from \"react\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { WorkflowCard } from \"./WorkflowCard\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\ninterface Props {\r\n workflowResponse: WorkflowResponse;\r\n}\r\n\r\nexport const useWorkflowCardDefault = (workflow: WorkflowResponse) => {\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n const translationBasePath = `workflows:${\r\n workflow.localizationKey ?? \"\"\r\n }.action.${workflow.enabled ? \"enabled\" : \"disabled\"}`;\r\n let translationInterpolations = workflow.variables;\r\n const name = t(translationBasePath + \".title\", translationInterpolations);\r\n\r\n return {\r\n name,\r\n description: t(\r\n translationBasePath + \".subtitle\",\r\n translationInterpolations\r\n ),\r\n isActive: workflow.enabled,\r\n };\r\n};\r\n\r\nexport const WorkflowCardDefault = (props: Props) => {\r\n const { name, description, isActive } = useWorkflowCardDefault(\r\n props.workflowResponse\r\n );\r\n\r\n return (\r\n <WorkflowCard\r\n name={name}\r\n description={description}\r\n isActive={isActive}\r\n workflowResponse={props.workflowResponse}\r\n />\r\n );\r\n};\r\n","import getDistance from \"geolib/es/getDistance\";\r\nimport { DateTime } from \"luxon\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { useStores } from \"../../../hooks/useStores\";\r\n\r\nexport interface WorkflowGeolocationState {\r\n userWasPreviouslyInRange: boolean;\r\n userToLocationRadiusDistance: number | null;\r\n}\r\n\r\nconst TIMERS_KEY = \"@WorkflowTimerKey\";\r\nconst TIMER_ACTIVE_IN_SECONDS = 300;\r\n\r\nfunction saveTimerWithId(id: string) {\r\n let timersJSON = localStorage.getItem(TIMERS_KEY);\r\n let timers: Map<string, string>;\r\n if (timersJSON) {\r\n timers = new Map(JSON.parse(timersJSON));\r\n } else {\r\n timers = new Map<string, string>();\r\n }\r\n timers.set(id, DateTime.local().toISO());\r\n localStorage.setItem(\r\n TIMERS_KEY,\r\n JSON.stringify(Array.from(timers.entries()))\r\n );\r\n}\r\n\r\nfunction clearTimer(id: string) {\r\n let timersJSON = localStorage.getItem(TIMERS_KEY);\r\n if (timersJSON) {\r\n const timers: Map<string, string> = new Map(JSON.parse(timersJSON));\r\n timers.delete(id);\r\n localStorage.setItem(\r\n TIMERS_KEY,\r\n JSON.stringify(Array.from(timers.entries()))\r\n );\r\n }\r\n}\r\n\r\nfunction isTimerExpired(id: string) {\r\n let isExpired = true;\r\n\r\n let activationTime: string | undefined;\r\n let timersJSON = localStorage.getItem(TIMERS_KEY);\r\n if (timersJSON) {\r\n const timers: Map<string, string> = new Map(JSON.parse(timersJSON));\r\n activationTime = timers.get(id);\r\n }\r\n\r\n if (activationTime) {\r\n isExpired =\r\n DateTime.local().diff(DateTime.fromISO(activationTime), \"seconds\")\r\n .seconds > TIMER_ACTIVE_IN_SECONDS;\r\n }\r\n return isExpired;\r\n}\r\ninterface Props {\r\n workflow: WorkflowResponse;\r\n}\r\n\r\nexport const useGeolocalizedWorkflow = (props: Props) => {\r\n const { workflow } = props;\r\n const { userLocationStore } = useStores();\r\n\r\n const gpsLocation = workflow.geoLocationCondition?.gpsLocation;\r\n const allowInside = workflow.geoLocationCondition?.allowInside;\r\n const allowOutside = workflow.geoLocationCondition?.allowOutside;\r\n\r\n let isGeolocationAuthorized = false;\r\n let userToLocationRadiusDistance: number | null = null;\r\n let userWasPreviouslyInRange = false;\r\n let userLocationObject = userLocationStore.userLocation;\r\n if (userLocationObject) {\r\n isGeolocationAuthorized = true;\r\n\r\n let userLocation = {\r\n latitude: userLocationObject.coords.latitude,\r\n longitude: userLocationObject.coords.longitude,\r\n };\r\n\r\n let location = {\r\n latitude: gpsLocation?.latitude!,\r\n longitude: gpsLocation?.longitude!,\r\n };\r\n\r\n const distanceInMeters = getDistance(userLocation, location);\r\n\r\n if (allowInside && allowOutside) {\r\n userToLocationRadiusDistance = 0;\r\n } else if (allowInside) {\r\n userToLocationRadiusDistance = Math.max(\r\n distanceInMeters - gpsLocation!.radius,\r\n 0\r\n );\r\n } else if (allowOutside) {\r\n userToLocationRadiusDistance = Math.max(\r\n gpsLocation!.radius - distanceInMeters,\r\n 0\r\n );\r\n }\r\n if (\r\n userToLocationRadiusDistance !== null &&\r\n userToLocationRadiusDistance === 0\r\n ) {\r\n // as long as you're in the zone, restart WorkflowActivationTimer to avoid displaying notification if the user\r\n // don't go outside the region\r\n saveTimerWithId(workflow.workflowId);\r\n } else {\r\n const isExpired = isTimerExpired(workflow.workflowId);\r\n userWasPreviouslyInRange = !isExpired;\r\n if (isExpired) {\r\n clearTimer(workflow.workflowId);\r\n }\r\n }\r\n }\r\n return {\r\n isGeolocationAuthorized,\r\n userWasPreviouslyInRange,\r\n userToLocationRadiusDistance,\r\n };\r\n};\r\n","import { observer } from \"mobx-react-lite\";\r\nimport React from \"react\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { useGeolocalizedWorkflowCard } from \"./useGeolocalizedWorkflowCard\";\r\nimport { WorkflowCard } from \"./WorkflowCard\";\r\n\r\ninterface Props {\r\n workflowResponse: WorkflowResponse;\r\n}\r\n\r\nexport const GeolocalizedWorkflowCard = observer((props: Props) => {\r\n const { name, description, isActive } = useGeolocalizedWorkflowCard(\r\n props.workflowResponse\r\n );\r\n return (\r\n <WorkflowCard\r\n name={name}\r\n description={description}\r\n isActive={isActive}\r\n workflowResponse={props.workflowResponse}\r\n />\r\n );\r\n});\r\n","import { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useGeolocalizedWorkflow } from \"./useGeolocalizedWorkflow\";\r\n\r\nexport const useGeolocalizedWorkflowCard = (workflow: WorkflowResponse) => {\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n const translationBasePath = `workflows:${\r\n workflow.localizationKey ?? \"\"\r\n }.action.${workflow.enabled ? \"enabled\" : \"disabled\"}`;\r\n let translationInterpolations = workflow.variables;\r\n const name = t(translationBasePath + \".title\", translationInterpolations);\r\n\r\n const {\r\n isGeolocationAuthorized,\r\n userWasPreviouslyInRange,\r\n userToLocationRadiusDistance,\r\n } = useGeolocalizedWorkflow({\r\n workflow: workflow,\r\n });\r\n\r\n let isActive = true;\r\n\r\n let workflowGeolocalizationPath = `workflows:${\r\n workflow.localizationKey ?? \"\"\r\n }.action.geolocalization.`;\r\n let distanceDescriptionTranslationKey = \"\";\r\n if (userWasPreviouslyInRange) {\r\n distanceDescriptionTranslationKey =\r\n workflowGeolocalizationPath + \"inRange.subtitle\";\r\n } else if (!isGeolocationAuthorized) {\r\n isActive = false;\r\n distanceDescriptionTranslationKey =\r\n \"workflow.geolocalization_not_authorized_description\";\r\n } else if (\r\n userToLocationRadiusDistance !== null &&\r\n userToLocationRadiusDistance !== undefined\r\n ) {\r\n const locationExtraRadius = 1000;\r\n if (userToLocationRadiusDistance <= 0) {\r\n distanceDescriptionTranslationKey =\r\n workflowGeolocalizationPath + \"inRange.subtitle\";\r\n } else if (userToLocationRadiusDistance < locationExtraRadius) {\r\n isActive = false;\r\n translationInterpolations.distance = userToLocationRadiusDistance.toString();\r\n distanceDescriptionTranslationKey =\r\n workflowGeolocalizationPath + \"inLongRange.subtitle\";\r\n } else {\r\n isActive = false;\r\n distanceDescriptionTranslationKey =\r\n workflowGeolocalizationPath + \"outOfRange.subtitle\";\r\n }\r\n }\r\n\r\n return {\r\n name,\r\n description: t(\r\n distanceDescriptionTranslationKey,\r\n translationInterpolations\r\n ),\r\n isActive,\r\n };\r\n};\r\n","import React from \"react\";\r\n\r\nexport const ScanQRCodeIcon = () => {\r\n return (\r\n <svg\r\n width=\"50\"\r\n height=\"50\"\r\n viewBox=\"0 0 50 50\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"25\" cy=\"25\" r=\"25\" fill=\"#F3F3F6\" />\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n d=\"M15 24H24V15H15V24ZM22 22H17V17H22V22ZM26 35H29V33H28V31H26V35ZM26 29V26H30V28H28V29H26ZM35 32V35H31V33H33V32H35ZM35 26H32V28H33V30H35V26ZM29 29H32V32H29V29ZM31 30H30V31H31V30ZM21 18H18V21H21V18ZM26 24H35V15H26V24ZM33 22H28V17H33V22ZM32 18H29V21H32V18ZM15 35H24V26H15V35ZM22 33H17V28H22V33ZM21 29H18V32H21V29Z\"\r\n fill=\"#39396A\"\r\n />\r\n </svg>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { observer } from \"mobx-react-lite\";\r\nimport { ActionsCard } from \"../ActionsCard\";\r\nimport { useHistory } from \"react-router-dom\";\r\nimport { RoutePath } from \"../../Router\";\r\nimport { ScanQRCodeIcon } from \"../../../assets/img/ScanQRCodeIcon\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\nexport const ScannerCard = observer(() => {\r\n const history = useHistory();\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n return (\r\n <>\r\n <ActionsCard\r\n onClick={() => {\r\n history.push(RoutePath.qrCodeScanner);\r\n }}\r\n >\r\n <div className=\"u-width-50 u-margin-bottom-xs\">\r\n <ScanQRCodeIcon />\r\n </div>\r\n <div className=\"c-heading c-heading--xl u-line-height-6u u-margin-bottom-2xs u-margin-bottom-2xs@medium\">\r\n {t(\"actions.card_scan_title\")}\r\n </div>\r\n <div className=\"u-text-s u-text-m@medium u-color-neutral-dark\">\r\n {t(\"actions.card_scan_description\")}\r\n </div>\r\n </ActionsCard>\r\n </>\r\n );\r\n});\r\n","import { observer } from \"mobx-react-lite\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport React, { useEffect } from \"react\";\r\nimport { useStores } from \"../../hooks/useStores\";\r\nimport { CenteredSpinner } from \"../../components/Spinner/Spinner\";\r\nimport { LoadingState } from \"../../stores/LoadingState\";\r\nimport { GeolocationCard } from \"./geolocation/GeolocationCard\";\r\nimport {\r\n ActionWorkFlow,\r\n isActionGeolocation,\r\n isActionScanner,\r\n isActionWorkFlow,\r\n} from \"../../stores/entities/Action\";\r\nimport { WorkflowCardDefault } from \"./workflows/WorkflowCardDefault\";\r\nimport { GeolocalizedWorkflowCard } from \"./workflows/GeolocalizedWorkflowCard\";\r\nimport { ScannerCard } from \"./scanner/ScannerCard\";\r\nimport { Page } from \"../../components/Page\";\r\nimport { Icon } from \"../../assets/img/Icon\";\r\nimport { RoutePath } from \"../Router\";\r\nimport { useHistory } from \"react-router-dom\";\r\n\r\nexport const Actions = observer(() => {\r\n const history = useHistory();\r\n const rootStore = useStores();\r\n const { actionsStore } = rootStore;\r\n\r\n useEffect(() => {\r\n (async () => {\r\n await actionsStore.refresh();\r\n })();\r\n }, []);\r\n\r\n const { applicationStorage } = useStores();\r\n\r\n useEffect(() => {\r\n const workflowURL = applicationStorage.get(\r\n \"workflowURLNavigationParameter\"\r\n );\r\n if (workflowURL) {\r\n history.push(RoutePath.qrCodeScanner, { workflowURL: workflowURL });\r\n applicationStorage.remove(\"workflowURLNavigationParameter\");\r\n }\r\n }, []);\r\n\r\n const ActionsCards = observer(() => {\r\n return (\r\n <>\r\n {actionsStore.actions.map((action) => {\r\n if (isActionScanner(action)) {\r\n return (\r\n <ScannerCard\r\n key={action.actionType}\r\n data-test-id={action.actionType}\r\n />\r\n );\r\n } else if (isActionGeolocation(action)) {\r\n const actionGeolocation: ActionWorkFlow = action;\r\n return (\r\n <GeolocationCard\r\n key={actionGeolocation.actionType}\r\n data-test-id={actionGeolocation.actionType}\r\n onClick={() => actionsStore.refresh()}\r\n />\r\n );\r\n }\r\n if (isActionWorkFlow(action)) {\r\n const actionWorkFlow: ActionWorkFlow = action;\r\n if (actionWorkFlow.workflowResponse.geoLocationCondition === null) {\r\n return (\r\n <WorkflowCardDefault\r\n key={actionWorkFlow.workflowResponse.workflowId}\r\n data-test-id={actionWorkFlow.workflowResponse.workflowId}\r\n workflowResponse={actionWorkFlow.workflowResponse}\r\n />\r\n );\r\n } else {\r\n return (\r\n <GeolocalizedWorkflowCard\r\n key={actionWorkFlow.workflowResponse.workflowId}\r\n data-test-id={actionWorkFlow.workflowResponse.workflowId}\r\n workflowResponse={actionWorkFlow.workflowResponse}\r\n />\r\n );\r\n }\r\n } else {\r\n return <div />;\r\n }\r\n })}\r\n </>\r\n );\r\n });\r\n\r\n return (\r\n <Page>\r\n <Header />\r\n <main className={\"u-flex u-flex-auto\"}>\r\n {actionsStore.loadingState === LoadingState.Loading && (\r\n <div className={\"u-flex u-flex-grow1\"}>\r\n <CenteredSpinner />\r\n </div>\r\n )}\r\n {actionsStore.loadingState === LoadingState.Loaded && (\r\n <div className=\"l-container u-padding-h-outer u-margin-v-outer u-margin-v-xl@medium u-max-width-700@medium\">\r\n <div className=\"l-grid l-grid--stretch\">\r\n <ActionsCards />\r\n </div>\r\n </div>\r\n )}\r\n </main>\r\n </Page>\r\n );\r\n});\r\n\r\nconst Header = () => {\r\n const { t } = useTranslation(\"mobile\");\r\n const rootStore = useStores();\r\n\r\n return (\r\n <header\r\n className=\"l-container u-padding-h-outer u-color-bg-white u-border-bottom\"\r\n style={{ position: \"sticky\", top: 0, zIndex: 500 }}\r\n >\r\n <div className=\"u-flex u-flex-align-items-center u-padding-v-gutter\">\r\n <div className=\"u-flex u-flex-nowrap u-flex-align-items-center u-text-ellipsis\">\r\n <Icon width={40} />\r\n <h1 className=\"c-heading c-heading--m u-margin-left-xs u-text-ellipsis\">\r\n {t(\"onboarding.welcome\")}\r\n </h1>\r\n </div>\r\n <div className=\"u-margin-left-auto\">\r\n <a\r\n className=\"c-link c-link--primary c-link--no-underline u-text-weight-medium u-flex u-flex-align-items-center u-flex-nowrap\"\r\n onClick={() => {\r\n if (window.confirm(t(\"settings.log_out_question\"))) {\r\n rootStore.logout();\r\n }\r\n }}\r\n >\r\n <svg className=\"icon-arrow-right-24\">\r\n <use href=\"#arrow-right-24\"></use>\r\n </svg>\r\n <span className=\"u-text-nowrap\">{t(\"settings.log_out\")}</span>\r\n </a>\r\n </div>\r\n </div>\r\n </header>\r\n );\r\n};\r\n","import { WorkflowResponse } from \"../../services/models/WorkflowResponse\";\r\n\r\nexport interface Action {\r\n actionType: \"scanner\" | \"geo\" | \"workflow\";\r\n}\r\n\r\nexport function isActionScanner(input: Action): input is ActionGeolocation {\r\n return input.actionType === \"scanner\";\r\n}\r\n\r\nexport function isActionGeolocation(input: Action): input is ActionGeolocation {\r\n return input.actionType === \"geo\";\r\n}\r\n\r\nexport function isActionWorkFlow(input: Action): input is ActionWorkFlow {\r\n return input.actionType === \"workflow\";\r\n}\r\n\r\nexport interface ActionScanner extends Action {}\r\n\r\nexport interface ActionGeolocation extends Action {}\r\n\r\nexport interface ActionWorkFlow extends Action {\r\n workflowResponse: WorkflowResponse;\r\n}\r\n","import React, { CSSProperties, useEffect, useState } from \"react\";\r\nimport QrReader from \"react-qr-reader\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { SpinnerWithBorder } from \"./Spinner/Spinner\";\r\n\r\ninterface Props {\r\n isLoading?: boolean;\r\n showViewFinder?: boolean;\r\n setQRCodeData(data: string | null): void;\r\n onQrCodeOnError(value: string): void;\r\n}\r\n\r\nconst styles: { [key: string]: CSSProperties } = {\r\n relative: {\r\n position: \"relative\",\r\n },\r\n viewFinder: {\r\n top: 0,\r\n left: 0,\r\n zIndex: 1,\r\n boxSizing: \"border-box\",\r\n border: \"50px solid rgba(0, 0, 0, 0.4)\",\r\n boxShadow: \"inset 0 0 0 2px rgba(255, 255, 255, 1)\",\r\n position: \"absolute\",\r\n width: \"100%\",\r\n height: \"100%\",\r\n },\r\n};\r\n\r\nexport const QRScanner = (props: Props) => {\r\n const [qrCodeOnError, setQrCodeOnError] = useState<string | null>(null);\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n useEffect(() => {\r\n if (qrCodeOnError) {\r\n props.onQrCodeOnError(qrCodeOnError);\r\n }\r\n }, [qrCodeOnError]);\r\n\r\n const Error = () => {\r\n return (\r\n <>\r\n <div className={\"u-padding-all-m u-align-center u-text-xl\"}>\r\n {t(\"permissions.camera_not_authorized_title\")}\r\n </div>\r\n </>\r\n );\r\n };\r\n\r\n return (\r\n <div>\r\n <div style={styles.relative}>\r\n {(props.isLoading ?? false) && <SpinnerWithBorder />}\r\n {(props.showViewFinder ?? true) && (\r\n <div\r\n style={styles.viewFinder}\r\n className={\r\n \"u-flex u-flex-col u-flex-align-items-center u-flex-justify-center\"\r\n }\r\n >\r\n {qrCodeOnError !== null && <Error />}\r\n </div>\r\n )}\r\n <QrReader\r\n style={styles.relative}\r\n delay={300}\r\n onError={(error) => {\r\n const domError = error as DOMException;\r\n if (domError) {\r\n setQrCodeOnError(domError.name);\r\n } else {\r\n setQrCodeOnError(\"error\");\r\n }\r\n }}\r\n onScan={(data: string | null) => props.setQRCodeData(data)}\r\n showViewFinder={false}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { Page } from \"./Page\";\r\n\r\ninterface Props {\r\n className?: string;\r\n}\r\n\r\nexport const PaddedPage = (props: React.PropsWithChildren<Props>) => {\r\n return (\r\n <Page>\r\n <div\r\n className={\r\n \"u-padding-right-m u-padding-left-m u-padding-top-m \" +\r\n props.className ?? \"\"\r\n }\r\n >\r\n {props.children}\r\n </div>\r\n </Page>\r\n );\r\n};\r\n","import React, { useEffect, useState } from \"react\";\r\nimport { QRScanner } from \"../../../components/QRScanner\";\r\nimport { useHistory, useLocation } from \"react-router-dom\";\r\nimport { useStores } from \"../../../hooks/useStores\";\r\nimport { WorkflowResult } from \"../workflows/WorkflowResult\";\r\nimport { WorkflowDetail } from \"../workflows/WorkflowDetail\";\r\nimport { WorkflowResponse } from \"../../../services/models/WorkflowResponse\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Title } from \"../../../components/Title\";\r\nimport { Button } from \"../../../components/Button/Button\";\r\nimport { PaddedPage } from \"../../../components/PaddedPage\";\r\nimport { ModalContainer } from \"../../../components/ModalContainer\";\r\nimport { RoutePath} from \"../../Router\";\r\n\r\nconst useScannerDetail = () => {\r\n const history = useHistory();\r\n const { proovrApi, analyticsStore } = useStores();\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [workflow, setWorkflow] = useState<WorkflowResponse | null>(null);\r\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\r\n\r\n const { t } = useTranslation(\"mobile\");\r\n\r\n const close = () => {\r\n history.replace(RoutePath.actions);\r\n };\r\n\r\n const processData = async (data: string | null) => {\r\n if (data !== null && !isLoading) {\r\n setIsLoading(true);\r\n try {\r\n const workflow = await proovrApi.getWorkflowFromUrl(data);\r\n setErrorMessage(null);\r\n setWorkflow(workflow);\r\n analyticsStore.post({ type: \"scanning-succeeded\" });\r\n } catch (e) {\r\n setWorkflow(null);\r\n setErrorMessage(t(\"workflow.invalid_workflow_exception\"));\r\n analyticsStore.post({ type: \"scanning-failed\" });\r\n }\r\n setIsLoading(false);\r\n }\r\n };\r\n return { isLoading, workflow, errorMessage, processData, close };\r\n};\r\n\r\nexport const ScannerDetail = (props: any) => {\r\n const { isLoading, workflow, errorMessage, processData, close } =\r\n useScannerDetail();\r\n const { t } = useTranslation(\"mobile\");\r\n const { analyticsStore } = useStores();\r\n\r\n useEffect(() => {\r\n analyticsStore.post({\r\n type: \"scanning-started\",\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n (async () => {\r\n const workflowURL = props.location.state?.workflowURL;\r\n if (workflowURL) {\r\n await processData(workflowURL);\r\n }\r\n })();\r\n }, []);\r\n\r\n const Scanner = () => (\r\n <>\r\n <Title title={t(\"scanner.title\")} />\r\n <div\r\n style={{\r\n position: \"relative\",\r\n }}\r\n >\r\n <QRScanner\r\n isLoading={isLoading}\r\n showViewFinder={workflow === null}\r\n setQRCodeData={(data) => processData(data)}\r\n onQrCodeOnError={(error) => {\r\n analyticsStore.post({\r\n type: \"scanning-loaded\",\r\n \"authorized-camera\": \"false\",\r\n });\r\n }}\r\n />\r\n </div>\r\n {workflow && !isLoading && (\r\n <WorkflowDetail workflow={workflow} onClose={close} />\r\n )}\r\n <Button onClick={close} className={\"u-margin-top-m u-margin-bottom-m\"}>\r\n {t(\"common.cancel\")}\r\n </Button>\r\n </>\r\n );\r\n\r\n return (\r\n <PaddedPage className={\"u-color-bg-neutral-off u-padding-top-m\"}>\r\n {errorMessage === null && <Scanner />}\r\n {errorMessage && (\r\n <ModalContainer\r\n onClose={() => {\r\n close();\r\n }}\r\n >\r\n <WorkflowResult\r\n isSucceeded={false}\r\n resultMessage={errorMessage}\r\n onTap={close}\r\n />\r\n </ModalContainer>\r\n )}\r\n </PaddedPage>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { Route, Switch, useHistory } from \"react-router-dom\";\r\nimport { Email } from \"./startup/Email\";\r\nimport { CodeConfirmation } from \"./startup/CodeConfirmation\";\r\nimport { Actions } from \"./actions/Actions\";\r\nimport { useStores } from \"../hooks/useStores\";\r\nimport { observer } from \"mobx-react-lite\";\r\nimport { ScannerDetail } from \"./actions/scanner/ScannerDetail\";\r\n\r\nexport class RoutePath {\r\n static email = \"/email\";\r\n static codeConfirmation = \"/code_confirmation\";\r\n static actions = \"/actions\";\r\n static qrCodeScanner = \"/qrcode_scanner\";\r\n static isAuthenticatedPath(path: string): boolean {\r\n return [RoutePath.actions].indexOf(path) >= 0;\r\n }\r\n static isUnAuthenticatedPath(path: string): boolean {\r\n return [RoutePath.email, RoutePath.codeConfirmation].indexOf(path) >= 0;\r\n }\r\n}\r\n\r\nexport const Router = observer(() => {\r\n let history = useHistory();\r\n const {\r\n authenticationStore,\r\n applicationStorage,\r\n analyticsStore,\r\n } = useStores();\r\n\r\n const pathName = window.location.pathname;\r\n const urlParameters = new URLSearchParams(window.location.search);\r\n\r\n if (pathName === \"/\") {\r\n const workflowParameter = urlParameters.get(\"workflow\");\r\n if (workflowParameter) {\r\n applicationStorage.set(workflowParameter, \"workflowNavigationParameter\");\r\n }\r\n const workflowURLParameter = urlParameters.get(\"workflowURL\");\r\n if (workflowURLParameter) {\r\n applicationStorage.set(\r\n workflowURLParameter,\r\n \"workflowURLNavigationParameter\"\r\n );\r\n }\r\n }\r\n\r\n if (authenticationStore.isUserAuthenticated) {\r\n // if user tries to visit an unauthenticated route, bring him back to default authenticated route\r\n if (!RoutePath.isAuthenticatedPath(pathName)) {\r\n history.replace(RoutePath.actions);\r\n }\r\n } else if (\r\n pathName === RoutePath.codeConfirmation &&\r\n authenticationStore.email === \"\"\r\n ) {\r\n //to go back to email if the code confirmation is refreshed and no email is saved in authenticaiton store\r\n history.replace(RoutePath.email);\r\n } else if (!RoutePath.isUnAuthenticatedPath(pathName)) {\r\n // prevent user from accessing authenticated routes\r\n history.replace(RoutePath.email);\r\n }\r\n\r\n let analyticsURLParameters = \"\";\r\n urlParameters.forEach((value, parameter) => {\r\n analyticsURLParameters += parameter + \",\";\r\n });\r\n analyticsURLParameters = analyticsURLParameters.slice(0, -1);\r\n analyticsStore.post({\r\n type: \"pageview\",\r\n url: pathName,\r\n \"page-name\": pathName.replace(\"/\", \"\"),\r\n \"url-parameters\": analyticsURLParameters,\r\n });\r\n\r\n return (\r\n <>\r\n <Switch>\r\n <Route path={RoutePath.email} component={Email} />\r\n <Route path={RoutePath.codeConfirmation} component={CodeConfirmation} />\r\n <Route path={RoutePath.actions} component={Actions} />\r\n <Route path={RoutePath.qrCodeScanner} component={ScannerDetail} />\r\n </Switch>\r\n </>\r\n );\r\n});\r\n","import moment from 'moment';\r\n\r\ntype LengthUnit = 'metric' | 'imperial';\r\n\r\nexport class Formatter {\r\n constructor(private userLanguageCode: string, private countryCode: string) {}\r\n\r\n interpolate(value: any, format: string | undefined) {\r\n if (format === 'distanceInMeters' && value) {\r\n return this.metersToCurrentLengthUnit(value);\r\n } else {\r\n const formattedDate = this.dateStringForValue(value, format);\r\n if (formattedDate) {\r\n return formattedDate;\r\n }\r\n }\r\n return value;\r\n }\r\n\r\n metersToCurrentLengthUnit(meters: number): string {\r\n if (this.lengthUnit() === 'imperial') {\r\n const feet = meters / 0.3048;\r\n // display feet for distances < than 100m\r\n if (meters < 100) {\r\n return Math.round(feet) + 'ft';\r\n } else {\r\n return Math.round(feet / 3) + 'yds';\r\n }\r\n } else {\r\n return Math.round(meters).toString() + 'm';\r\n }\r\n }\r\n\r\n dateStringForValue(value: any, format: any): string | null {\r\n if (value && format) {\r\n let date = moment(value, moment.ISO_8601, true);\r\n if (date.isValid()) {\r\n return date.locale(this.userLanguageCode).format(format);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n lengthUnit(): LengthUnit {\r\n const isImperial = ['US', 'MMR', 'LBR'].find(v => v.toLowerCase() === this.countryCode.toLowerCase());\r\n return isImperial ? 'imperial' : 'metric';\r\n }\r\n}\r\n","import React, { Suspense } from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\nimport { StoreProvider } from \"./hocs/useStore\";\r\nimport \"./index.scss\";\r\nimport i18n from \"i18next\";\r\nimport { configure } from \"mobx\";\r\nimport { RootStore } from \"./stores/RootStore\";\r\nimport { initReactI18next, useTranslation } from \"react-i18next\";\r\nimport BackendAdapter from \"i18next-multiload-backend-adapter\";\r\nimport HttpBackend from \"i18next-http-backend\";\r\nimport Backend from \"i18next-chained-backend\";\r\nimport { BrowserRouter } from \"react-router-dom\";\r\nimport { Router } from \"./pages/Router\";\r\nimport LanguageDetector from \"i18next-browser-languagedetector\";\r\nimport { CenteredSpinner } from \"./components/Spinner/Spinner\";\r\nimport { useConfigLoader } from \"./hooks/useConfigLoader\";\r\nimport LocalStorageBackend from \"i18next-localstorage-backend\";\r\nimport { Formatter } from \"./common/Formatter\"; // primary use cache\r\nimport { countryCode, userLanguageCode } from \"./common/ApplicationInfo\";\r\nimport { Helmet } from \"react-helmet\";\r\n\r\n// don't allow state modifications outside actions\r\nconfigure({\r\n enforceActions: \"observed\",\r\n reactionRequiresObservable: true,\r\n observableRequiresReaction: true,\r\n});\r\n\r\nconst Application = () => {\r\n const { config } = useConfigLoader();\r\n const formatter = new Formatter(userLanguageCode(), countryCode());\r\n\r\n if (config) {\r\n i18n\r\n .use(initReactI18next)\r\n .use(LanguageDetector)\r\n .use(Backend)\r\n .init({\r\n load: \"languageOnly\",\r\n backend: {\r\n backends: [\r\n LocalStorageBackend,\r\n new BackendAdapter(null, {\r\n backend: new HttpBackend(null, {\r\n //{{lng}} returns lng+fallbackLng\r\n //{{ns}} returns all namespaces values\r\n loadPath:\r\n config.ProovrApiBaseUrl +\r\n \"/v1/localization.json?languages={{lng}}&namespaces={{ns}}\",\r\n allowMultiLoading: true,\r\n crossDomain: true,\r\n }),\r\n }),\r\n ],\r\n backendOptions: [\r\n { expirationTime: 7 * 24 * 60 * 60 * 1000 },\r\n {\r\n prefix: \"i18next_res_\",\r\n versions: {},\r\n },\r\n ],\r\n },\r\n fallbackLng: \"en\",\r\n ns: [\"mobile\", \"workflows\", \"web\"],\r\n interpolation: {\r\n escapeValue: false,\r\n format: (value, format, _) => formatter.interpolate(value, format),\r\n },\r\n })\r\n .then();\r\n\r\n const store = new RootStore(config);\r\n\r\n return (\r\n <React.StrictMode>\r\n <StoreProvider store={store}>\r\n <Suspense fallback={<CenteredSpinner />}>\r\n <BrowserRouter>\r\n <HeaderAndRouter />\r\n </BrowserRouter>\r\n </Suspense>\r\n </StoreProvider>\r\n </React.StrictMode>\r\n );\r\n } else {\r\n return <CenteredSpinner />;\r\n }\r\n};\r\n\r\nconst HeaderAndRouter = () => {\r\n const { t } = useTranslation(\"web\");\r\n return (\r\n <>\r\n <Helmet>\r\n <title>{t(\"meta.title\")}\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nReactDOM.render(, document.getElementById(\"root\"));\r\n","import { useEffect, useState } from \"react\";\r\n\r\nexport interface Config {\r\n ProovrApiBaseUrl: string;\r\n ApiBaseUrl: string;\r\n}\r\n\r\nexport const useConfigLoader = () => {\r\n const [config, setConfig] = useState(null);\r\n\r\n useEffect(() => {\r\n (async () => {\r\n try {\r\n let result = await fetch(\"config.json\");\r\n let json = await result.json();\r\n setConfig(json);\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n })();\r\n }, []);\r\n\r\n return { config };\r\n};\r\n","import i18n from \"i18next\";\r\n\r\nexport class EmailError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n }\r\n}\r\n\r\nexport class ConfirmationCodeError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n }\r\n}\r\n\r\nexport class NetworkError extends Error {\r\n constructor() {\r\n super(i18n.t(\"common.no_internet_connection\"));\r\n }\r\n}\r\n\r\nexport class InvalidWorkflowError extends Error {\r\n constructor() {\r\n super(i18n.t(\"workflow.invalid_workflow_exception\"));\r\n }\r\n}\r\n","export function userLanguageCode(): string {\r\n return window.navigator.language;\r\n}\r\n\r\nexport function userLanguageCodeShort(): string {\r\n return userLanguageCode().substring(0, 2);\r\n}\r\n\r\nexport function countryCode(): string {\r\n return userLanguageCodeShort().toLowerCase() === \"en\" ? \"US\" : \"BE\";\r\n}\r\n","// import * as ApplicationInfo from \"../common/ApplicationInfo\";\r\nimport * as axios from \"axios\";\r\nimport { AxiosResponse } from \"axios\";\r\nimport {\r\n ConfirmationCodeError,\r\n EmailError,\r\n InvalidWorkflowError,\r\n NetworkError,\r\n} from \"../common/errors/ApiErrors\";\r\nimport { PaginatedResponse } from \"./models/PaginatedResponse\";\r\nimport { VerifyEmailResponse } from \"./models/VerifyEmailResponse\";\r\nimport {\r\n isWorkflowResponse,\r\n WorkflowResponse,\r\n} from \"./models/WorkflowResponse\";\r\nimport { StartWorkflowResponse } from \"./models/StartWorkflowResponse\";\r\nimport { ApplicationStorage } from \"../stores/ApplicationStorage\";\r\nimport { userLanguageCode } from \"../common/ApplicationInfo\";\r\nimport { AnalyticsStore } from \"../stores/AnalyticsStore\";\r\n\r\n//used to use the buffer to download image as base 64 with axios.\r\nglobal.Buffer = global.Buffer || require(\"buffer\").Buffer;\r\nexport class ProovrApi {\r\n private client: axios.AxiosInstance = axios.default.create({\r\n baseURL: this.baseUrl,\r\n headers: this.headers,\r\n });\r\n\r\n public unauthorizedErrorHandler: (() => void) | null = null;\r\n constructor(\r\n private baseUrl: string,\r\n private applicationStorage: ApplicationStorage,\r\n private analyticsStore: AnalyticsStore\r\n ) {\r\n this.client.interceptors.response.use(\r\n (res) => {\r\n return res;\r\n },\r\n\r\n (error) => {\r\n if (error.response?.status === 401) {\r\n // Analytics.reportError(\"API UnauthorizedError\", error.request.url);\r\n if (this.unauthorizedErrorHandler) {\r\n this.unauthorizedErrorHandler();\r\n }\r\n } else if (error.message === \"Network Error\") {\r\n return Promise.reject(new NetworkError());\r\n }\r\n return Promise.reject(error);\r\n }\r\n );\r\n }\r\n\r\n private get headers(): any {\r\n return {\r\n \"Content-Type\": \"application/json\",\r\n \"Accept-Language\": userLanguageCode(),\r\n // that doesn't work, so we set a custom header \"application-agent\"\r\n // \"user-agent\": \"Proovr\",\r\n \"application-agent\": \"Proovr\",\r\n };\r\n }\r\n\r\n private logHttpSuccess(response: AxiosResponse, type: string) {\r\n this.analyticsStore.post({\r\n type: type,\r\n \"http-response-status\": response.status,\r\n \"http-response-success\": true,\r\n });\r\n }\r\n\r\n private logHttpError(error: any, type: string) {\r\n this.analyticsStore.post({\r\n type: type,\r\n \"http-response-status\": error.response?.status,\r\n \"http-response-message\": error.response?.statusText,\r\n \"http-response-success\": false,\r\n });\r\n }\r\n\r\n public get authenticatedHeaders(): any {\r\n const jwt = this.applicationStorage.get(\"auth_jwt\");\r\n if (jwt === null) {\r\n throw \"null JWT\";\r\n }\r\n return {\r\n Authorization: `Bearer ${jwt}`,\r\n };\r\n }\r\n\r\n public async requestEmailVerification(\r\n email: string,\r\n authenticationState: string\r\n ): Promise {\r\n const url: string = `${this.baseUrl}/v0.1/credentials/email/request`;\r\n try {\r\n const response = await this.client.post(url, {\r\n Email: email,\r\n State: authenticationState,\r\n });\r\n this.logHttpSuccess(response, \"authentication-email-http-request\");\r\n } catch (error) {\r\n this.logHttpError(error, \"authentication-code-http-request\");\r\n const emailErrors = error?.response?.data?.errors[\"Email\"];\r\n if (emailErrors && emailErrors[0]) {\r\n throw new EmailError(emailErrors[0].split(\"|\")[0]);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n public async verifyEmail(\r\n email: string | null,\r\n authenticationState: string | null,\r\n code: string\r\n ): Promise {\r\n const url: string = `${this.baseUrl}/v0.1/credentials/email/verify`;\r\n try {\r\n const response = await this.client.post(url, {\r\n Email: email,\r\n State: authenticationState,\r\n Token: code,\r\n });\r\n this.logHttpSuccess(response, \"authentication-code-http-request\");\r\n return response.data;\r\n } catch (error) {\r\n this.logHttpError(error, \"authentication-code-http-request\");\r\n const codeError = error?.response?.data?.errors[\"Token\"];\r\n if (codeError && codeError[0]) {\r\n throw new ConfirmationCodeError(codeError[0].split(\"|\")[0]);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n public async fetchWorkflows(): Promise> {\r\n const url: string = `${this.baseUrl}/v0.1/identities/me/workflows`;\r\n const response = await this.client.get>(\r\n url,\r\n {\r\n params: { page: 1, pageSize: 100 },\r\n headers: this.authenticatedHeaders,\r\n }\r\n );\r\n return response.data;\r\n }\r\n\r\n public async getWorkflowFromUrl(url: string): Promise {\r\n let response: AxiosResponse = await this.client.get(url);\r\n const isResponseValid = isWorkflowResponse(response.data);\r\n if (!isResponseValid) {\r\n throw new InvalidWorkflowError();\r\n } else {\r\n return response.data;\r\n }\r\n }\r\n\r\n public async startWorkflow(\r\n startUrl: string,\r\n requestedCredentials: Map\r\n ): Promise {\r\n try {\r\n const jsonCredentials = fromMapToObj(\r\n requestedCredentials\r\n );\r\n const response = await this.client.post(startUrl, {\r\n Credentials: jsonCredentials,\r\n });\r\n this.logHttpSuccess(response, \"start-workflow-http-request\");\r\n return response.data;\r\n } catch (error) {\r\n this.logHttpError(error, \"start-workflow-http-request\");\r\n throw error;\r\n }\r\n }\r\n\r\n public async unRegisterDevice(installationId: string): Promise {\r\n const url: string = `${this.baseUrl}/v0.1/identities/me/devices/${installationId}`;\r\n try {\r\n return await this.client.delete(url, {\r\n headers: this.authenticatedHeaders,\r\n });\r\n } catch (error) {\r\n // Analytics.reportError(\"unRegisterDevice\", error.message);\r\n if (error.message === \"Network Error\") {\r\n throw new NetworkError();\r\n } else {\r\n throw new Error(error.message);\r\n }\r\n }\r\n }\r\n\r\n public async translationReportMissingKey(\r\n language: string,\r\n key: string\r\n ): Promise {\r\n const url: string = `${this.baseUrl}/v1/localization/errors/keys`;\r\n try {\r\n return await this.client.post(url, { language: language, key: key });\r\n } catch (error) {\r\n // Analytics.reportError(\"translationReportMissingKey\", error.message);\r\n if (error.message === \"Network Error\") {\r\n throw new NetworkError();\r\n } else {\r\n throw new Error(error.message);\r\n }\r\n }\r\n }\r\n\r\n public async translationReportMissingValue(\r\n language: string,\r\n value: string,\r\n match: string\r\n ): Promise {\r\n const url: string = `${this.baseUrl}/v1/localization/errors/values`;\r\n try {\r\n return await this.client.post(url, {\r\n language: language,\r\n source: value,\r\n match: match,\r\n });\r\n } catch (error) {\r\n // Analytics.reportError(\"translationReportMissingValue\", error.message);\r\n if (error.message === \"Network Error\") {\r\n throw new NetworkError();\r\n } else {\r\n throw new Error(error.message);\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport function fromMapToObj(map: Map): any {\r\n const obj = Object.create(null);\r\n map.forEach((value, key) => {\r\n obj[key] = value;\r\n });\r\n\r\n return obj;\r\n}\r\n","export interface WorkflowResponse {\r\n workflowId: string;\r\n logoUrl: string;\r\n startUrl: string;\r\n // todo: verify if that works instead of requestedCredentials?: Map;\r\n requestedCredentials?: { [key: string]: any };\r\n geoLocationCondition?: GeoLocationConditionResponse;\r\n\r\n notifications: WorkflowResponseNotifications;\r\n localizationKey: string;\r\n enabled: boolean;\r\n variables: { [key: string]: any };\r\n}\r\n\r\nexport interface WorkflowResponseNotifications {\r\n enter: boolean;\r\n exit: boolean;\r\n}\r\n\r\nexport interface GeoLocationConditionResponse {\r\n allowInside?: boolean;\r\n allowOutside?: boolean;\r\n gpsLocation?: GpsLocation;\r\n}\r\n\r\nexport interface GpsLocation {\r\n latitude: number;\r\n longitude: number;\r\n radius: number;\r\n}\r\n\r\nexport function isWorkflowResponse(\r\n workflow: WorkflowResponse\r\n): workflow is WorkflowResponse {\r\n const w = workflow as WorkflowResponse;\r\n return w.workflowId !== undefined && w.startUrl !== undefined;\r\n}\r\n"],"sourceRoot":""}