{"version":3,"sources":["store/Configuration.ts","RestHelper.ts","store/Login.ts","store/ChallengeList.ts","store/ChallengeDetails.ts","store/UploadChallengeGpx.ts","store/UploadEffortGpx.ts","store/index.ts","components/LogoutButton.tsx","components/GetUserDetails.tsx","components/Layout.tsx","components/ChallengeList.tsx","components/Home.tsx","components/EffortList.tsx","components/UploadChallengeGpx.tsx","components/NoEffortList.tsx","components/UploadEffortGpx.tsx","shared/Modal.tsx","shared/EventHelpers.ts","shared/WithQueryParams.tsx","components/ChallengeDetails.tsx","components/StravaLoginButton.tsx","components/LoginPage.tsx","components/NotFound.tsx","components/SignUpPage.tsx","App.tsx","registerServiceWorker.ts","index.tsx","store/configureStore.ts"],"names":["initialState","siteTitle","apiBaseUrl","hasContent","response","headers","get","generateErrorMessage","resource","status","statusText","detail","getLoggedInUser","id_token","name","cookies","decodeURIComponent","document","cookie","split","trimLeft","indexOf","substring","length","getCookie","loggedInUser","jwt","decode","user_data","JSON","parse","LoginActions","actionCreators","usernamePasswordLogin","credentials","dispatch","getState","appState","console","log","email","fetch","config","method","body","stringify","then","a","ok","RestHelper","type","message","signUp","profile","json","problem","setUserProfile","text","error","catch","undefined","toChallenge","data","startDate","Date","endDate","ChallengeType","requestChallengeList","challengeList","requestPending","challenges","map","ChallengeDetailActions","getSelectedChallenge","selectedChallenge","filter","c","fetchRegistrationStatus","challengeDetails","fetchingRegistrationStatusFor","FetchingRegistrationStatus","selectedChallengeName","RegistrationStatusReceived","registrationStatus","registered","ServerRequestError","onSelectedChallengeChanged","SelectedChallengeChanged","CurrentChallengeChanged","currentChallenge","ChallengeListStore","login","AgeGroupsReceived","ageGroups","SpecialCategoriesReceived","specialCategories","EffortsReceived","efforts","AthletesReceived","athletes","refreshRegistrationStatus","selectedCategoryChanged","selectedCategory","SelectedCategoryChanged","inviteCodeChanged","inviteCode","InviteCodeChanged","joinChallenge","requiresInviteCode","SpecifyInviteCode","Registering","url","InvalidInviteCode","cancelJoin","CancelJoin","description","UploadChallengeGpxActions","onFileSelected","event","target","files","ChallengeGpxFileSelected","selectedFile","uploadFile","uploadChallengeGpx","ChallengeGpxFileUploadStarted","formData","FormData","append","ChallengeGpxFileUploaded","cancelUpload","ChallengeGpxFileUploadCanceled","UploadEffortGpxActions","onAthleteIdChanged","value","EffortGpxAthleteIdChanged","athleteId","EffortGpxFileSelected","uploadEffortGpx","EffortGpxFileUploadStarted","sub","EffortGpxFileUploaded","EffortGpxFileUploadCanceled","reducers","state","action","isLoggedInAction","loginError","signUpError","isLoggedOutAction","isErrorLoggingIn","isErrorSigningUp","isErrorSettingProfileAction","errorSettingProfile","isSetConfigurationAction","incomingAction","requestError","registrationStatusReceived","isAthleteRegistered","waitingForInviteCode","registrationError","ageGroupsReceivedAction","specialCategoriesReceivedAction","effortsReceivedAction","allEfforts","athletesReceivedAction","allAthletes","registering","LoggedOut","errorMessage","uploading","uploaded","connect","props","href","className","months","maxBirthYear","getFullYear","minBirthYear","yearArray","y","push","GetUserDetails","React","constructor","super","birthDateString","birth_date","birthDateUtc","this","year","getUTCFullYear","month","getUTCMonth","day","getUTCDate","gender","isEmailReadonly","handleYearChanged","bind","handleMonthChanged","handleDayChanged","handleGenderChanged","handleEmailChanged","render","onChange","m","i","Array","getDate","_","title","readOnly","id","disabled","onClick","saveProfile","setState","Number","birthDate","LoginStore","to","siteLogo","src","width","height","alt","children","siteFooter","ChallengeList","componentDidMount","renderChallengeListTable","renderLoadingIndicator","challenge","displayName","moment","format","fromNow","toTimeFormat","duration","str","seconds","slice","asMinutes","minutes","asHours","hours","asDays","Math","floor","EffortList","renderEffortListTable","byCategory","challengeType","showLapCount","MostLaps","renderCategoryResults","categoryName","categoryEfforts","columns","colSpan","effort","ix","athleteName","is_admin","lapCount","elapsedTime","resultsByCategory","cat","getCategory","athleteAge","athleteGender","specialCategoryId","Object","keys","showCategory","maximumAge","isKOM","category","ageGroup","UploadChallengeGpx","sectionBody","e","UploadChallengeGpxStore","NoEffortList","renderNoEffortListTable","athletesWithEffort","Set","athletesWithNoEfforts","has","athlete","age","UploadEffortGpx","fileInputRow","UploadEffortGpxStore","Modal","open","closeModal","onEnterKey","fn","key","withQueryParams","Component","location","useLocation","queryParams","URLSearchParams","search","ChallengeDetails","match","params","challengeName","componentDidUpdate","bestEffort","encodeURIComponent","pathname","hash","join","renderChallengeDetails","renderNotFound","segmentId","getMonth","hasRouteMap","displayResultsByTime","displayResultsByCategory","autoFocus","onKeyPress","registrationLink","ChallengeDetailStore","returnUrl","signup","LoginPage","userEmail","password","loggingIn","handlePasswordChanged","performLogin","SignUpPage","confirmPassword","username","firstName","lastName","handleConfirmPasswordChanged","handleUsernameChanged","handleFirstNameChanged","handleLastNameChanged","exact","path","component","Home","NotFound","isLocalhost","Boolean","window","hostname","register","navigator","URL","process","toString","origin","addEventListener","swUrl","contentType","serviceWorker","ready","registration","unregister","reload","registerValidSW","checkValidServiceWorker","onupdatefound","installingWorker","installing","onstatechange","controller","baseUrl","getElementsByTagName","getAttribute","history","createBrowserHistory","basename","resp","startsWith","warn","err","stack","REACT_APP_SITE_TITLE","REACT_APP_SITE_LOGO","REACT_APP_SITE_FOOTER","REACT_APP_API_BASE_URL","store","middleware","thunk","routerMiddleware","rootReducer","combineReducers","router","connectRouter","enhancers","windowIfDefined","__REDUX_DEVTOOLS_EXTENSION__","createStore","compose","applyMiddleware","configureStore","ReactDOM","App","getElementById","registerServiceWorker"],"mappings":"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","file":"static/js/main.c70cefe1.chunk.js","sourcesContent":["import {Action, AnyAction, Reducer} from 'redux';\n\nexport interface ConfigurationState {\n siteTitle: string,\n siteLogo?: string,\n siteFooter?: string,\n apiBaseUrl: string\n}\n\nexport interface SetConfigurationAction {\n type: 'SET_CONFIGURATION',\n config: ConfigurationState\n}\n\nfunction isSetConfigurationAction(action: Action): action is SetConfigurationAction {\n return action.type === 'SET_CONFIGURATION';\n}\n\nconst initialState = { siteTitle: 'Strava Segment Challenge', apiBaseUrl: '' } as ConfigurationState;\n\nexport const reducer: Reducer = (state: ConfigurationState | undefined, action: AnyAction) => {\n state = state || initialState;\n\n if (isSetConfigurationAction(action)) {\n return { ...state, config: action.config };\n }\n\n return state;\n};\n","import jwt from \"jwt-simple\";\n\nexport function hasContent(response: Response) {\n return !!response.headers.get('Content-Type');\n}\n\nexport function generateErrorMessage(resource: string, status: number, statusText: string, detail: string) {\n if (status >= 500 && status < 600) {\n return `The ${resource} is currently unavailable. Please try again later or contact the webmaster if the problem persists. Error detail: ${detail}`;\n } else {\n return `An error occurred fetching or setting the ${resource}. Please contact the webmaster. Error detail: ${detail}`;\n }\n}\n\nfunction getCookie(name: string): string | undefined {\n let cookies = decodeURIComponent(document.cookie);\n for (let cookie of cookies.split(';')) {\n cookie = cookie.trimLeft();\n if (cookie.indexOf(name) === 0) {\n return cookie.substring(name.length + 1, cookie.length);\n }\n }\n\n return undefined;\n}\n\nexport function getLoggedInUser() {\n const id_token = getCookie('id_token');\n let loggedInUser = undefined;\n if (id_token) {\n loggedInUser = jwt.decode(id_token, '', true);\n\n if (typeof loggedInUser.user_data === \"string\") {\n loggedInUser.user_data = JSON.parse(loggedInUser.user_data);\n }\n }\n return loggedInUser;\n}\n","import { Action, AnyAction, Reducer } from 'redux';\nimport { AppThunkAction } from \"./index\";\nimport { generateErrorMessage, hasContent } from \"../RestHelper\";\nimport * as RestHelper from '../RestHelper';\n\nexport interface LoginInfo {\n sub: string,\n name: string,\n user_data: { profile_picture?: string, birth_date?: string, gender?: string, email?: string, is_admin?: boolean },\n nbf: number,\n exp: number,\n iat: number,\n iss: string,\n aud: string\n}\n\nexport interface LoginState {\n loggedInUser?: LoginInfo,\n loginError?: string,\n signUpError?: string,\n errorSettingProfile?: string\n}\n\nexport interface LoggedInAction {\n type: 'LOGGED_IN',\n loggedInUser: LoginInfo\n}\n\nexport interface LoggedOutAction {\n type: 'LOGGED_OUT'\n}\n\nexport interface ErrorLoggingIn {\n type: 'ERROR_LOGGING_IN',\n message: string\n}\n\nexport interface ErrorSigningUp {\n type: 'ERROR_SIGNING_UP',\n message: string\n}\n\nexport interface ErrorSettingProfileAction {\n type: 'ERROR_SETTING_USER_PROFILE',\n message: string\n}\n\nexport enum LoginActions {\n LoggedIn = 'LOGGED_IN',\n LoggedOut = 'LOGGED_OUT',\n ErrorLoggingIn = 'ERROR_LOGGING_IN',\n ErrorSigningUp = 'ERROR_SIGNING_UP',\n ErrorSettingProfile = 'ERROR_SETTING_USER_PROFILE'\n}\n\nexport interface UserProfile {\n birthDate: Date;\n gender: string;\n email?: string;\n}\n\nexport interface UserSignUp {\n email: string;\n password: string;\n username: string;\n firstName?: string;\n lastName?: string;\n birthDate: Date;\n gender: string;\n}\n\nfunction isLoggedInAction(action: Action): action is LoggedInAction {\n return action.type === 'LOGGED_IN';\n}\n\nfunction isLoggedOutAction(action: Action): action is LoggedInAction {\n return action.type === 'LOGGED_OUT';\n}\n\nfunction isErrorLoggingIn(action: Action): action is ErrorLoggingIn {\n return action.type === 'ERROR_LOGGING_IN';\n}\n\nfunction isErrorSigningUp(action: Action): action is ErrorSigningUp {\n return action.type === 'ERROR_SIGNING_UP';\n}\n\nfunction isErrorSettingProfileAction(action: Action): action is ErrorSettingProfileAction {\n return action.type === 'ERROR_SETTING_USER_PROFILE';\n}\n\ntype KnownAction = LoggedInAction | ErrorLoggingIn | ErrorSigningUp | ErrorSettingProfileAction\n\nexport const actionCreators = {\n usernamePasswordLogin: (credentials: { email: string, password: string }): AppThunkAction =>\n ((dispatch, getState) => {\n let appState = getState();\n console.log('performing username and password login for: ' + credentials.email);\n fetch(\n `${appState.config.apiBaseUrl}api/auth/login`,\n {\n method: 'POST',\n body: JSON.stringify(credentials),\n headers: { 'Content-Type': 'application/json' }\n })\n .then(async response => {\n if (response.ok) {\n // check cookie\n let loggedInUser = RestHelper.getLoggedInUser();\n\n if (loggedInUser) {\n dispatch({\n type: 'LOGGED_IN',\n loggedInUser\n });\n } else {\n dispatch({\n type: 'ERROR_LOGGING_IN',\n message: 'Unexpected error attempting to log in'\n });\n }\n } else {\n console.log('Error logging in: ' + response.status);\n dispatch({\n type: 'ERROR_LOGGING_IN',\n message: response.status >= 400 && response.status < 500 ?\n 'Invalid Email Address or Password' :\n 'Unexpected error attempting to log in'\n });\n }\n });\n }),\n signUp: (profile: UserSignUp): AppThunkAction =>\n ((dispatch, getState) => {\n\n let appState = getState();\n fetch(\n `${appState.config.apiBaseUrl}api/auth/signup`,\n {\n method: 'POST',\n body: JSON.stringify(profile),\n headers: { 'Content-Type': 'application/json' }\n })\n .then(async response => {\n if (response.ok) {\n // check cookie\n let loggedInUser = RestHelper.getLoggedInUser();\n\n if (loggedInUser) {\n dispatch({\n type: 'LOGGED_IN',\n loggedInUser\n });\n } else {\n dispatch({\n type: 'ERROR_SIGNING_UP',\n message: 'Unexpected error attempting to sign up.'\n });\n }\n } else if (response.status === 400) {\n let problem = await response.json();\n dispatch({\n type: 'ERROR_SIGNING_UP',\n message: problem.detail\n });\n } else {\n dispatch({\n type: 'ERROR_SIGNING_UP',\n message: 'Unexpected error attempting to sign up.'\n });\n }\n });\n }),\n setUserProfile: (profile: { birthDate: Date, gender: string, email?: string }): AppThunkAction =>\n ((dispatch, getState) => {\n let appState = getState();\n fetch(\n `${appState.config.apiBaseUrl}api/athletes/self`,\n {\n method: 'POST',\n credentials: 'same-origin',\n body: JSON.stringify(profile),\n headers: { 'Content-Type': 'application/json' }\n })\n .then(async response => {\n if (response.ok) {\n // check cookie\n let loggedInUser = RestHelper.getLoggedInUser();\n\n if (loggedInUser) {\n dispatch({\n type: 'LOGGED_IN',\n loggedInUser\n });\n } else {\n dispatch({\n type: 'ERROR_SETTING_USER_PROFILE',\n message: 'Failed to update user profile.'\n });\n }\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error updating user profile. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: 'ERROR_SETTING_USER_PROFILE',\n message: generateErrorMessage('user profile', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: 'ERROR_SETTING_USER_PROFILE',\n message: error\n })\n });\n })\n};\n\nconst initialState = { loggedInUser: undefined } as LoginState;\n\nexport const reducer: Reducer = (state: LoginState | undefined, action: AnyAction) => {\n state = state || initialState;\n\n if (isLoggedInAction(action)) {\n return { ...state, loggedInUser: action.loggedInUser, loginError: undefined, signUpError: undefined };\n } else if (isLoggedOutAction(action)) {\n return { ...state, loggedInUser: undefined, loginError: undefined, signUpError: undefined };\n } else if (isErrorLoggingIn(action)) {\n console.log('Error logging in: ' + action.message);\n return { ...state, loggedInUser: undefined, loginError: action.message };\n } else if (isErrorSigningUp(action)) {\n return { ...state, signUpError: action.message };\n } else if (isErrorSettingProfileAction(action)) {\n return { ...state, errorSettingProfile: action.message };\n }\n\n return state;\n};\n","import { AnyAction, Reducer } from 'redux';\nimport { AppThunkAction } from './index';\nimport { generateErrorMessage, hasContent } from '../RestHelper'\n\nexport interface Challenge {\n id: number;\n name: string;\n displayName: string;\n description: string;\n segmentId: string;\n startDate: Date;\n endDate: Date;\n type: ChallengeType;\n useMovingTime: boolean;\n requiresInviteCode: boolean;\n registrationLink: string;\n hasRouteMap: boolean;\n}\n\nfunction toChallenge(data: any) {\n return {\n ...data,\n startDate: new Date(data.startDate),\n endDate: new Date(data.endDate),\n type: data.type as ChallengeType,\n };\n}\n\nexport enum ChallengeType {\n Fastest = 0,\n MostLaps = 1\n}\n\nexport interface ChallengeListState {\n challenges?: Challenge[];\n requestPending: boolean;\n requestError?: string;\n}\n\nexport interface RequestChallengeListAction {\n type: 'REQUEST_CHALLENGE_LIST';\n}\n\nexport interface ReceiveChallengeListAction {\n type: 'RECEIVE_CHALLENGE_LIST';\n challenges: Challenge[];\n}\n\nexport interface ErrorFetchingChallengeListAction {\n type: 'ERROR_FETCHING_CHALLENGE_LIST';\n message: string;\n}\n\ntype KnownAction = RequestChallengeListAction | ReceiveChallengeListAction | ErrorFetchingChallengeListAction;\n\nexport const actionCreators = {\n requestChallengeList: (): AppThunkAction => (dispatch, getState) => {\n const appState = getState();\n // If there is no request pending, and we have not previously fetched challenges, fetch the challenge list\n if (appState && (!appState.challengeList || (!appState.challengeList.requestPending && !appState.challengeList.challenges))) {\n fetch(`${appState.config.apiBaseUrl}api/challenges`)\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({ type: 'RECEIVE_CHALLENGE_LIST', challenges: (data as unknown[]).map(toChallenge) });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching challenge list. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: 'ERROR_FETCHING_CHALLENGE_LIST',\n message: generateErrorMessage('challenge list', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: 'ERROR_FETCHING_CHALLENGE_LIST',\n message: error\n })\n });\n\n dispatch({ type: 'REQUEST_CHALLENGE_LIST' });\n }\n }\n};\n\nconst initialState: ChallengeListState = { requestPending: false };\n\nexport const reducer: Reducer = (state: ChallengeListState | undefined, incomingAction: AnyAction): ChallengeListState => {\n state = state || initialState;\n\n const action = incomingAction as KnownAction;\n switch (action.type) {\n case 'REQUEST_CHALLENGE_LIST':\n if (!state.requestPending && !state.challenges) {\n return { ...state, requestPending: true };\n } else {\n // Ignore redundant requests\n return state;\n }\n case 'RECEIVE_CHALLENGE_LIST':\n return {\n ...state,\n requestPending: false,\n challenges: (incomingAction as ReceiveChallengeListAction).challenges\n };\n case 'ERROR_FETCHING_CHALLENGE_LIST':\n return {\n ...state,\n requestPending: false,\n challenges: [],\n requestError: (incomingAction as ErrorFetchingChallengeListAction).message\n };\n default:\n return state;\n }\n};\n","import * as ChallengeListStore from \"./ChallengeList\";\nimport { ApplicationState, AppThunkAction } from \"./index\";\nimport { AnyAction, Reducer } from \"redux\";\nimport { generateErrorMessage, hasContent } from \"../RestHelper\";\nimport { LoggedInAction, LoggedOutAction, LoginActions } from \"./Login\";\n\nexport interface AgeGroup {\n maximumAge: number,\n description: string\n}\n\nexport interface SpecialCategory {\n specialCategoryId: number,\n categoryName: string\n}\n\nexport interface Effort {\n id: number,\n athleteId: number,\n athleteName: number\n athleteGender: string,\n athleteAge: number,\n activityId: number,\n lapCount: number,\n elapsedTime: number,\n isKOM: boolean,\n specialCategoryId: number | null\n}\n\nexport interface Athlete {\n id: number,\n displayName: string,\n gender: string,\n age: number,\n specialCategoryId: number | null\n}\n\nexport type Category = { minimumAge?: number, maximumAge?: number, gender?: string, description: string };\n\nexport interface ChallengeDetailsState {\n selectedChallengeName?: string,\n currentChallenge?: ChallengeListStore.Challenge,\n isAthleteRegistered?: boolean,\n inviteCode?: string,\n waitingForInviteCode?: boolean,\n registering?: boolean,\n registrationError?: string,\n selectedCategory: Category | null,\n ageGroups?: AgeGroup[],\n specialCategories?: SpecialCategory[],\n allEfforts?: Effort[],\n allAthletes?: Athlete[],\n errorMessage?: string,\n fetchingRegistrationStatusFor?: string,\n}\n\nexport enum ChallengeDetailActions {\n SelectedChallengeChanged = 'SELECTED_CHALLENGE_CHANGED',\n CurrentChallengeChanged = 'CURRENT_CHALLENGE_CHANGED',\n SelectedCategoryChanged = 'SELECTED_CATEGORY_CHANGED',\n FetchingRegistrationStatus = 'FETCHING_REGISTRATION_STATUS',\n RegistrationStatusReceived = 'REGISTRATION_STATUS_RECEIVED',\n AgeGroupsReceived = 'AGE_GROUPS_RECEIVED',\n SpecialCategoriesReceived = 'SPECIAL_CATEGORIES_RECEIVED',\n EffortsReceived = 'EFFORTS_RECEIVED',\n AthletesReceived = 'ATHLETES_RECEIVED',\n SpecifyInviteCode = 'SPECIFY_INVITE_CODE',\n Registering = 'REGISTERING',\n InviteCodeChanged= 'INVITE_CODE_CHANGED',\n InvalidInviteCode = 'INVALID_INVITE_CODE',\n CancelJoin = 'CANCEL_JOIN',\n ServerRequestError = 'ERROR_FETCHING_DATA'\n}\n\nexport interface SelectedChallengeChanged {\n type: ChallengeDetailActions.SelectedChallengeChanged,\n selectedChallengeName: string | undefined\n}\n\nexport interface SelectedCategoryChanged {\n type: ChallengeDetailActions.SelectedCategoryChanged,\n selectedCategory: Category\n}\n\nexport interface CurrentChallengeChanged {\n type: ChallengeDetailActions.CurrentChallengeChanged,\n currentChallenge: ChallengeListStore.Challenge | undefined\n}\n\nexport interface FetchingRegistrationStatus {\n type: ChallengeDetailActions.FetchingRegistrationStatus,\n selectedChallengeName: string,\n}\n\nexport interface RegistrationStatusReceived {\n type: ChallengeDetailActions.RegistrationStatusReceived,\n selectedChallengeName: string,\n registrationStatus: boolean\n}\n\nexport interface AgeGroupsReceived {\n type: ChallengeDetailActions.AgeGroupsReceived,\n selectedChallengeName: string,\n ageGroups: AgeGroup[]\n}\n\nexport interface SpecialCategoriesReceived {\n type: ChallengeDetailActions.SpecialCategoriesReceived,\n selectedChallengeName: string,\n specialCategories: SpecialCategory[]\n}\n\nexport interface EffortsReceived {\n type: ChallengeDetailActions.EffortsReceived,\n selectedChallengeName: string,\n efforts: Effort[]\n}\n\nexport interface AthletesReceived {\n type: ChallengeDetailActions.AthletesReceived,\n selectedChallengeName: string,\n athletes: Athlete[]\n}\n\nexport interface SpecifyInviteCode {\n type: ChallengeDetailActions.SpecifyInviteCode\n}\n\nexport interface Registering {\n type: ChallengeDetailActions.Registering\n}\n\nexport interface InviteCodeChanged {\n type: ChallengeDetailActions.InviteCodeChanged;\n inviteCode: string;\n}\n\nexport interface InvalidInviteCode {\n type: ChallengeDetailActions.InvalidInviteCode\n}\n\nexport interface CancelJoin {\n type: ChallengeDetailActions.CancelJoin\n}\n\nexport interface HasMessage {\n message: string\n}\n\nexport interface ServerRequestError extends HasMessage {\n type: ChallengeDetailActions.ServerRequestError\n}\n\ntype KnownAction =\n SelectedChallengeChanged\n | CurrentChallengeChanged\n | SelectedCategoryChanged\n | FetchingRegistrationStatus\n | RegistrationStatusReceived\n | AgeGroupsReceived\n | SpecialCategoriesReceived\n | EffortsReceived\n | AthletesReceived\n | SpecifyInviteCode\n | Registering\n | InviteCodeChanged\n | InvalidInviteCode\n | CancelJoin\n | ServerRequestError\n | ChallengeListStore.RequestChallengeListAction\n | ChallengeListStore.ReceiveChallengeListAction\n | ChallengeListStore.ErrorFetchingChallengeListAction\n | LoggedInAction\n | LoggedOutAction;\n\nfunction getSelectedChallenge(challenges: ChallengeListStore.Challenge[], selectedChallenge: string): ChallengeListStore.Challenge | undefined {\n return challenges.filter(c => c.name === selectedChallenge)[0];\n}\n\nfunction fetchRegistrationStatus(appState: ApplicationState, selectedChallenge: string, dispatch: (action: KnownAction) => void) {\n if (appState.challengeDetails?.fetchingRegistrationStatusFor === selectedChallenge) {\n // Don't fetch multiple times\n return;\n }\n\n // Fetch Registration Status\n dispatch({\n type: ChallengeDetailActions.FetchingRegistrationStatus,\n selectedChallengeName: selectedChallenge\n })\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge}/registration`, { credentials: 'same-origin' })\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.RegistrationStatusReceived,\n selectedChallengeName: selectedChallenge,\n registrationStatus: data.registered\n });\n } else if (response.status === 401) {\n dispatch({\n type: 'LOGGED_OUT'\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching registration status. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('registration status', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n}\n\nexport const actionCreators = {\n onSelectedChallengeChanged: (selectedChallenge: string): AppThunkAction => (dispatch, getState) => {\n let appState = getState();\n\n if (appState) {\n if (!appState.challengeDetails || selectedChallenge !== appState.challengeDetails.selectedChallengeName) {\n dispatch({\n type: ChallengeDetailActions.SelectedChallengeChanged,\n selectedChallengeName: selectedChallenge\n });\n\n if (!appState.challengeList || !appState.challengeList.challenges) {\n // Need to wait for challenge list\n ChallengeListStore.actionCreators.requestChallengeList()(dispatch, getState);\n } else {\n // The easy way, we already have the challenge list\n dispatch({\n type: ChallengeDetailActions.CurrentChallengeChanged,\n currentChallenge: getSelectedChallenge(appState.challengeList.challenges, selectedChallenge)\n });\n }\n\n if (appState.login?.loggedInUser) {\n fetchRegistrationStatus(appState, selectedChallenge, dispatch);\n }\n\n // Fetch Age Groups\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge}/age_groups`)\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.AgeGroupsReceived,\n selectedChallengeName: selectedChallenge,\n ageGroups: data\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching age groups. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('challenge age groups', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n\n // Fect Special Categories\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge}/special_categories`)\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.SpecialCategoriesReceived,\n selectedChallengeName: selectedChallenge,\n specialCategories: data\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching special categories. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('challenge categories', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n\n // Fetch Efforts\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge}/efforts`)\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.EffortsReceived,\n selectedChallengeName: selectedChallenge,\n efforts: data\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching efforts. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('efforts', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n\n // Fetch Athletes\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge}/athletes`)\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.AthletesReceived,\n selectedChallengeName: selectedChallenge,\n athletes: data\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error fetching athletes. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('athletes', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n }\n }\n },\n refreshRegistrationStatus: (selectedChallenge: string): AppThunkAction => (dispatch, getState) => {\n let appState = getState();\n\n if (appState.login?.loggedInUser) {\n fetchRegistrationStatus(appState, selectedChallenge, dispatch);\n }\n },\n selectedCategoryChanged: (selectedCategory: Category) => ({\n type: ChallengeDetailActions.SelectedCategoryChanged,\n selectedCategory: selectedCategory\n } as SelectedCategoryChanged),\n inviteCodeChanged: (inviteCode: string): AppThunkAction => (dispatch, getState) => {\n dispatch({\n type: ChallengeDetailActions.InviteCodeChanged,\n inviteCode\n });\n },\n joinChallenge: (inviteCode?: string): AppThunkAction => (dispatch, getState) => {\n let appState = getState();\n\n if (appState) {\n const selectedChallenge = appState.challengeDetails?.currentChallenge;\n if (selectedChallenge && appState.login?.loggedInUser) {\n if (selectedChallenge.requiresInviteCode && !inviteCode) {\n dispatch({\n type: ChallengeDetailActions.SpecifyInviteCode\n });\n return;\n }\n\n dispatch({\n type: ChallengeDetailActions.Registering\n });\n\n let url = `${appState.config.apiBaseUrl}api/challenges/${selectedChallenge.name}/register`;\n if (inviteCode) {\n url = `${url}?inviteCode=${inviteCode}`;\n }\n fetch(url, { method: 'POST', credentials: 'same-origin' })\n .then(async response => {\n if (response.ok) {\n const data = await response.json();\n dispatch({\n type: ChallengeDetailActions.RegistrationStatusReceived,\n selectedChallengeName: selectedChallenge.name,\n registrationStatus: data.registered\n });\n\n // Immediately initiate a refresh\n fetch(`${appState.config.apiBaseUrl}api/challenges/${selectedChallenge.name}/refresh`, {\n method: 'POST',\n credentials: 'same-origin'\n })\n .then(response => {\n if (response.ok) {\n console.log('Refresh started.');\n } else {\n console.log(`Refresh failed to start: ${response.status}`)\n }\n });\n } else if (response.status === 400 && hasContent(response)) {\n let problem = await response.json();\n if (problem.type === \"urn:segment-challenge-app:invalid-invite-code\") {\n dispatch({\n type: ChallengeDetailActions.InvalidInviteCode\n });\n } else {\n console.error(`Error updating registration status. Status: ${response.status}, Status Description: ${response.statusText}, Detail: Unknown`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('registration status', response.status, response.statusText, 'Unknown')\n });\n }\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error updating registration status. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: generateErrorMessage('registration status', response.status, response.statusText, detail)\n });\n }\n })\n .catch(error => {\n dispatch({\n type: ChallengeDetailActions.ServerRequestError,\n message: error\n })\n });\n }\n }\n },\n cancelJoin: (): AppThunkAction => (dispatch, getState) => {\n dispatch({\n type: ChallengeDetailActions.CancelJoin\n });\n }\n};\n\nconst initialState: ChallengeDetailsState = { selectedCategory: { description: 'Overall' } };\n\nexport const reducer: Reducer =\n (state: ChallengeDetailsState | undefined, incomingAction: AnyAction) => {\n state = state || initialState;\n\n const action = incomingAction as KnownAction;\n\n switch (action.type) {\n case ChallengeDetailActions.SelectedChallengeChanged:\n // Is this ok? Do we have to null out things individually?\n return {\n ...initialState,\n selectedChallengeName: (action as SelectedChallengeChanged).selectedChallengeName,\n };\n case ChallengeDetailActions.CurrentChallengeChanged:\n return { ...state, currentChallenge: (action as CurrentChallengeChanged).currentChallenge };\n case 'RECEIVE_CHALLENGE_LIST':\n if (state.selectedChallengeName) {\n return {\n ...state,\n currentChallenge:\n getSelectedChallenge(\n (action as ChallengeListStore.ReceiveChallengeListAction).challenges,\n state.selectedChallengeName\n )\n };\n }\n\n break;\n case ChallengeDetailActions.FetchingRegistrationStatus:\n return {\n ...state,\n fetchingRegistrationStatusFor: (action as FetchingRegistrationStatus).selectedChallengeName\n };\n case ChallengeDetailActions.RegistrationStatusReceived:\n const registrationStatusReceived = action as RegistrationStatusReceived;\n if (registrationStatusReceived.selectedChallengeName === state.selectedChallengeName) {\n return {\n ...state,\n isAthleteRegistered: registrationStatusReceived.registrationStatus,\n waitingForInviteCode: state.waitingForInviteCode && !registrationStatusReceived.registrationStatus,\n registrationError: undefined,\n fetchingRegistrationStatusFor:\n (state.fetchingRegistrationStatusFor === registrationStatusReceived.selectedChallengeName) ?\n undefined :\n state.fetchingRegistrationStatusFor,\n };\n }\n\n break;\n case ChallengeDetailActions.AgeGroupsReceived:\n const ageGroupsReceivedAction = action as AgeGroupsReceived;\n if (ageGroupsReceivedAction.selectedChallengeName === state.selectedChallengeName) {\n return { ...state, ageGroups: ageGroupsReceivedAction.ageGroups };\n }\n\n break;\n case ChallengeDetailActions.SpecialCategoriesReceived:\n const specialCategoriesReceivedAction = action as SpecialCategoriesReceived;\n if (specialCategoriesReceivedAction.selectedChallengeName === state.selectedChallengeName) {\n return { ...state, specialCategories: specialCategoriesReceivedAction.specialCategories };\n }\n\n break;\n case ChallengeDetailActions.EffortsReceived:\n const effortsReceivedAction = action as EffortsReceived;\n if (effortsReceivedAction.selectedChallengeName === state.selectedChallengeName) {\n return { ...state, allEfforts: effortsReceivedAction.efforts };\n }\n\n break;\n case ChallengeDetailActions.AthletesReceived:\n const athletesReceivedAction = action as AthletesReceived;\n if (athletesReceivedAction.selectedChallengeName === state.selectedChallengeName) {\n return { ...state, allAthletes: athletesReceivedAction.athletes };\n }\n\n break;\n case ChallengeDetailActions.SpecifyInviteCode:\n return { ...state, waitingForInviteCode: true };\n case ChallengeDetailActions.Registering:\n return { ...state, registering: true };\n case ChallengeDetailActions.InviteCodeChanged:\n return { ...state, inviteCode: (action as InviteCodeChanged).inviteCode };\n case ChallengeDetailActions.InvalidInviteCode:\n return { ...state, registering: false, registrationError: 'Invalid invite code.', waitingForInviteCode: true };\n case ChallengeDetailActions.CancelJoin:\n return { ...state, waitingForInviteCode: false, inviteCode: undefined };\n case LoginActions.LoggedOut:\n return {\n ...state,\n registrationError: 'You have been logged out. Please login again to see your registration status.',\n fetchingRegistrationStatusFor: undefined,\n isAthleteRegistered: undefined\n };\n case ChallengeDetailActions.ServerRequestError:\n case 'ERROR_FETCHING_CHALLENGE_LIST':\n return { ...state, errorMessage: (action as HasMessage).message };\n }\n\n return state;\n };\n","import {AnyAction, Reducer} from \"redux\";\n\nimport {HasMessage} from \"./ChallengeDetails\";\nimport {ChangeEvent} from \"react\";\nimport {AppThunkAction} from \"./index\";\nimport {generateErrorMessage, hasContent} from \"../RestHelper\";\n\nexport interface UploadChallengeGpxState {\n selectedFile?: File | null,\n uploading?: boolean,\n uploaded?: boolean,\n errorMessage?: string,\n}\n\nexport enum UploadChallengeGpxActions {\n ChallengeGpxFileSelected = 'CHALLENGE_GPX_FILE_SELECTED',\n ChallengeGpxFileUploadCanceled = 'CHALLENGE_GPX_UPLOAD_CANCELED',\n ChallengeGpxFileUploadStarted = 'CHALLENGE_GPX_UPLOAD_STARTED',\n ChallengeGpxFileUploaded = 'CHALLENGE_GPX_UPLOAD_DONE',\n ServerRequestError = 'ERROR_FETCHING_DATA'\n}\n\nexport interface ChallengeGpxFileSelected {\n type: UploadChallengeGpxActions.ChallengeGpxFileSelected,\n selectedFile: File\n}\n\nexport interface ChallengeGpxFileUploadCanceled {\n type: UploadChallengeGpxActions.ChallengeGpxFileUploadCanceled\n}\n\nexport interface ChallengeGpxFileUploadStarted {\n type: UploadChallengeGpxActions.ChallengeGpxFileUploadStarted\n}\n\nexport interface ChallengeGpxFileUploaded {\n type: UploadChallengeGpxActions.ChallengeGpxFileUploaded\n}\n\nexport interface ServerRequestError extends HasMessage {\n type: UploadChallengeGpxActions.ServerRequestError\n}\n\nexport const actionCreators = {\n onFileSelected: (event: ChangeEvent): AppThunkAction => (dispatch, getState) => {\n if (event.target.files && event.target.files.length === 1) {\n dispatch({\n type: UploadChallengeGpxActions.ChallengeGpxFileSelected,\n selectedFile: event.target.files[0]\n });\n }\n },\n uploadFile: (): AppThunkAction => (dispatch, getState) => {\n let appState = getState();\n\n if (appState.uploadChallengeGpx?.selectedFile &&\n appState.challengeDetails?.selectedChallengeName) {\n\n dispatch({\n type: UploadChallengeGpxActions.ChallengeGpxFileUploadStarted\n });\n\n let formData = new FormData();\n formData.append('gpxFile', appState.uploadChallengeGpx.selectedFile);\n\n fetch(\n `${appState.config.apiBaseUrl}api/challenges/${appState.challengeDetails.selectedChallengeName}/set_gpx`,\n {method: 'POST', credentials: 'same-origin', body: formData})\n .then(async response => {\n if (response.ok) {\n dispatch({\n type: UploadChallengeGpxActions.ChallengeGpxFileUploaded\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error uploading GPX data. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: UploadChallengeGpxActions.ServerRequestError,\n message: generateErrorMessage('registration status', response.status, response.statusText, detail)\n });\n }\n });\n } else {\n console.log('Unable to process uploadFile action. selectedFile is not available in app state.');\n }\n },\n cancelUpload: (): AppThunkAction => (dispatch, getState) => {\n dispatch({\n type: UploadChallengeGpxActions.ChallengeGpxFileUploadCanceled\n });\n }\n};\n\ntype KnownAction =\n ChallengeGpxFileSelected |\n ChallengeGpxFileUploadCanceled |\n ChallengeGpxFileUploadStarted |\n ChallengeGpxFileUploaded |\n ServerRequestError;\n\nconst initialState: UploadChallengeGpxState = {};\n\nexport const reducer: Reducer =\n (state: UploadChallengeGpxState | undefined, incomingAction: AnyAction) => {\n state = state || initialState;\n\n const action = incomingAction as KnownAction;\n\n switch (action.type) {\n case UploadChallengeGpxActions.ChallengeGpxFileSelected:\n return {\n ...state,\n selectedFile: (action as ChallengeGpxFileSelected).selectedFile,\n };\n\n case UploadChallengeGpxActions.ChallengeGpxFileUploadCanceled:\n return {\n ...state,\n selectedFile: null\n };\n\n case UploadChallengeGpxActions.ChallengeGpxFileUploadStarted:\n return {\n ...state,\n uploading: true\n };\n\n case UploadChallengeGpxActions.ChallengeGpxFileUploaded:\n return {\n ...state,\n uploading: false,\n uploaded: true\n };\n\n case UploadChallengeGpxActions.ServerRequestError:\n return {\n ...state,\n errorMessage: (action as HasMessage).message,\n selectedFile: null,\n uploading: false\n };\n }\n\n return state;\n };\n","import {AnyAction, Reducer} from \"redux\";\n\nimport {HasMessage} from \"./ChallengeDetails\";\nimport {ChangeEvent} from \"react\";\nimport {AppThunkAction} from \"./index\";\nimport {generateErrorMessage, hasContent} from \"../RestHelper\";\n\nexport interface UploadEffortGpxState {\n selectedFile?: File | null,\n athleteId?: string,\n uploading?: boolean,\n uploaded?: boolean,\n errorMessage?: string,\n}\n\nexport enum UploadEffortGpxActions {\n EffortGpxFileSelected = 'EFFORT_GPX_FILE_SELECTED',\n EffortGpxAthleteIdChanged = 'EFFORT_GPX_ATHLETE_ID_CHANGED',\n EffortGpxFileUploadCanceled = 'EFFORT_GPX_UPLOAD_CANCELED',\n EffortGpxFileUploadStarted = 'EFFORT_GPX_UPLOAD_STARTED',\n EffortGpxFileUploaded = 'EFFORT_GPX_UPLOAD_DONE',\n ServerRequestError = 'ERROR_FETCHING_DATA'\n}\n\nexport interface EffortGpxFileSelected {\n type: UploadEffortGpxActions.EffortGpxFileSelected,\n selectedFile: File\n}\n\nexport interface EffortGpxAthleteIdChanged {\n type: UploadEffortGpxActions.EffortGpxAthleteIdChanged,\n athleteId: string\n}\n\nexport interface EffortGpxFileUploadCanceled {\n type: UploadEffortGpxActions.EffortGpxFileUploadCanceled\n}\n\nexport interface EffortGpxFileUploadStarted {\n type: UploadEffortGpxActions.EffortGpxFileUploadStarted\n}\n\nexport interface EffortGpxFileUploaded {\n type: UploadEffortGpxActions.EffortGpxFileUploaded\n}\n\nexport interface ServerRequestError extends HasMessage {\n type: UploadEffortGpxActions.ServerRequestError\n}\n\nexport const actionCreators = {\n onAthleteIdChanged: (event: ChangeEvent): AppThunkAction => (dispatch, getState) => {\n console.log(`athlete id changing: ${event.target.value}`);\n dispatch({\n type: UploadEffortGpxActions.EffortGpxAthleteIdChanged,\n athleteId: event.target.value\n });\n },\n onFileSelected: (event: ChangeEvent): AppThunkAction => (dispatch, getState) => {\n if (event.target.files && event.target.files.length === 1) {\n dispatch({\n type: UploadEffortGpxActions.EffortGpxFileSelected,\n selectedFile: event.target.files[0]\n });\n }\n },\n uploadFile: (): AppThunkAction => (dispatch, getState) => {\n let appState = getState();\n\n if (appState.uploadEffortGpx?.selectedFile &&\n appState.challengeDetails?.selectedChallengeName) {\n\n dispatch({\n type: UploadEffortGpxActions.EffortGpxFileUploadStarted\n });\n\n let formData = new FormData();\n formData.append('gpxFile', appState.uploadEffortGpx.selectedFile);\n\n let athleteId = appState.uploadEffortGpx.athleteId ?? appState.login?.loggedInUser?.sub;\n console.log(`upload gpx for: ${athleteId}`)\n fetch(\n `${appState.config.apiBaseUrl}api/challenges/${appState.challengeDetails.selectedChallengeName}/upload_activity?athlete=${athleteId}`,\n {method: 'POST', credentials: 'same-origin', body: formData})\n .then(async response => {\n if (response.ok) {\n dispatch({\n type: UploadEffortGpxActions.EffortGpxFileUploaded\n });\n } else {\n let detail: string;\n if (hasContent(response)) {\n detail = await response.text();\n } else {\n detail = 'Unknown';\n }\n\n console.error(`Error uploading GPX data. Status: ${response.status}, Status Description: ${response.statusText}, Detail: ${detail}`);\n\n dispatch({\n type: UploadEffortGpxActions.ServerRequestError,\n message: generateErrorMessage('registration status', response.status, response.statusText, detail)\n });\n }\n });\n } else {\n console.log('Unable to process uploadFile action. selectedFile is not available in app state.');\n }\n },\n cancelUpload: (): AppThunkAction => (dispatch, getState) => {\n dispatch({\n type: UploadEffortGpxActions.EffortGpxFileUploadCanceled\n });\n }\n};\n\ntype KnownAction =\n EffortGpxFileSelected |\n EffortGpxAthleteIdChanged |\n EffortGpxFileUploadCanceled |\n EffortGpxFileUploadStarted |\n EffortGpxFileUploaded |\n ServerRequestError;\n\nconst initialState: UploadEffortGpxState = {};\n\nexport const reducer: Reducer =\n (state: UploadEffortGpxState | undefined, incomingAction: AnyAction) => {\n state = state || initialState;\n\n const action = incomingAction as KnownAction;\n\n switch (action.type) {\n case UploadEffortGpxActions.EffortGpxFileSelected:\n return {\n ...state,\n selectedFile: (action as EffortGpxFileSelected).selectedFile,\n };\n\n case UploadEffortGpxActions.EffortGpxAthleteIdChanged:\n console.log(`athlete id changed: ${(action as EffortGpxAthleteIdChanged).athleteId}`);\n return {\n ...state,\n athleteId: (action as EffortGpxAthleteIdChanged).athleteId\n }\n\n case UploadEffortGpxActions.EffortGpxFileUploadCanceled:\n return {\n ...state,\n selectedFile: null\n };\n\n case UploadEffortGpxActions.EffortGpxFileUploadStarted:\n return {\n ...state,\n uploading: true\n };\n\n case UploadEffortGpxActions.EffortGpxFileUploaded:\n return {\n ...state,\n uploading: false,\n uploaded: true\n };\n\n case UploadEffortGpxActions.ServerRequestError:\n return {\n ...state,\n errorMessage: (action as HasMessage).message,\n selectedFile: null,\n uploading: false\n };\n }\n\n return state;\n };\n","import * as Configuration from './Configuration';\nimport * as Login from './Login';\nimport * as ChallengeList from \"./ChallengeList\";\nimport * as ChallengeDetails from \"./ChallengeDetails\";\nimport * as UploadChallengeGpx from \"./UploadChallengeGpx\";\nimport * as UploadEffortGpx from \"./UploadEffortGpx\";\n\n// The top-level state object\nexport interface ApplicationState {\n login?: Login.LoginState;\n config: Configuration.ConfigurationState;\n challengeList?: ChallengeList.ChallengeListState;\n challengeDetails?: ChallengeDetails.ChallengeDetailsState;\n uploadChallengeGpx?: UploadChallengeGpx.UploadChallengeGpxState;\n uploadEffortGpx?: UploadEffortGpx.UploadEffortGpxState;\n}\n\nexport const reducers = {\n login: Login.reducer,\n config: Configuration.reducer,\n challengeList: ChallengeList.reducer,\n challengeDetails: ChallengeDetails.reducer,\n uploadChallengeGpx: UploadChallengeGpx.reducer,\n uploadEffortGpx: UploadEffortGpx.reducer,\n};\n\n// This type can be used as a hint on action creators so that its 'dispatch' and 'getState' params are\n// correctly typed to match your store.\nexport interface AppThunkAction {\n (dispatch: (action: TAction) => void, getState: () => ApplicationState): void;\n}\n","import * as React from 'react';\nimport { connect } from 'react-redux';\nimport { ApplicationState } from \"../store\";\nimport { ConfigurationState } from \"../store/Configuration\";\n\nconst LogoutButton = (props: { config: ConfigurationState }) => (\n Logout\n);\n\nexport default connect((state: ApplicationState, props) =>\n ({ ...props, config: state.config }))(LogoutButton);\n","import * as React from 'react';\nimport { connect } from \"react-redux\";\nimport * as LoginStore from \"../store/Login\";\nimport { ApplicationState } from \"../store\";\nimport LogoutButton from \"./LogoutButton\";\nimport { ChangeEvent } from \"react\";\n\ntype GetUserDetailsProps =\n { login?: LoginStore.LoginState } &\n { setUserProfile: (profile: { birthDate: Date, gender: string, email?: string }) => void };\n\ntype GetUserDetailsState = {\n year?: number,\n // Index by 1 month. Fuck javascript.\n month?: number,\n day?: number,\n gender?: string,\n email?: string,\n isEmailReadonly: boolean\n};\n\nconst months = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n];\n\nconst maxBirthYear = new Date().getFullYear() - 13;\nconst minBirthYear = maxBirthYear - (99 - 13);\nlet yearArray: number[] = [];\nfor (let y = maxBirthYear; y >= minBirthYear; y--) {\n yearArray.push(y);\n}\n\nfunction getDaysPerMonth(year: number | undefined, month: number | undefined) {\n if (month) {\n // Note month here is index by 1, where as javascript is index by zero, which is why this works.\n if (year) {\n return new Date(year, month, 0).getDate();\n } else {\n // Intentionally choosing a leap year, since we want to include 29 for february\n return new Date(2020, month, 0).getDate();\n }\n } else {\n return 31;\n }\n}\n\nclass GetUserDetails extends React.PureComponent {\n constructor(props: GetUserDetailsProps) {\n super(props);\n\n const birthDateString = props.login?.loggedInUser?.user_data?.birth_date;\n const birthDateUtc = birthDateString ? new Date(birthDateString) : undefined;\n\n console.log(props.login?.loggedInUser);\n\n let email = props.login?.loggedInUser?.user_data?.email;\n this.state = {\n year: birthDateUtc?.getUTCFullYear(),\n month: birthDateUtc ? birthDateUtc.getUTCMonth() + 1 : undefined,\n day: birthDateUtc?.getUTCDate(),\n gender: props.login?.loggedInUser?.user_data?.gender,\n email: email ?? '',\n isEmailReadonly: !!email\n };\n\n this.handleYearChanged = this.handleYearChanged.bind(this);\n this.handleMonthChanged = this.handleMonthChanged.bind(this);\n this.handleDayChanged = this.handleDayChanged.bind(this);\n this.handleGenderChanged = this.handleGenderChanged.bind(this);\n this.handleEmailChanged = this.handleEmailChanged.bind(this);\n }\n\n public render() {\n console.log(this.state);\n return (\n
\n
\n

Complete Profile

\n

In order to participate in challenges we need your birth date and gender.

\n
\n \n \n \n
\n
\n \n
\n
\n \n
\n
\n \n \n
\n
\n
\n );\n }\n\n private handleYearChanged(event: ChangeEvent) {\n this.setState({ year: Number(event.target.value) });\n }\n\n private handleMonthChanged(event: ChangeEvent) {\n this.setState({ month: Number(event.target.value) });\n }\n\n private handleDayChanged(event: ChangeEvent) {\n this.setState({ day: Number(event.target.value) });\n }\n\n private handleGenderChanged(event: ChangeEvent) {\n this.setState({ gender: event.target.value });\n }\n\n private handleEmailChanged(event: ChangeEvent) {\n if (!this.state.isEmailReadonly) {\n this.setState({ email: event.target.value });\n }\n }\n\n private saveProfile() {\n if (this.state.year && this.state.month && this.state.day && this.state.gender) {\n this.props.setUserProfile({\n birthDate: new Date(this.state.year, this.state.month - 1, this.state.day),\n gender: this.state.gender,\n email: this.state.email\n });\n }\n }\n}\n\nexport default connect((state: ApplicationState) => ({ login: state.login }), LoginStore.actionCreators)(GetUserDetails);\n","import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport { Link } from \"react-router-dom\";\nimport LogoutButton from \"./LogoutButton\";\nimport GetUserDetails from \"./GetUserDetails\";\nimport { ApplicationState } from \"../store\";\nimport { ConfigurationState } from \"../store/Configuration\";\nimport { LoginState } from \"../store/Login\";\n\nconst Layout = (props: { children?: React.ReactNode, config: ConfigurationState, login?: LoginState }) => (\n \n
\n
\n

\n \n {props.config.siteLogo &&\n \"logo\"}\n {props.config.siteTitle}\n \n

\n
\n
\n {(props.login && props.login.loggedInUser) ?\n Welcome, {props.login.loggedInUser.name} :\n \n Log in\n Sign up\n }\n
\n
\n
\n {props.children}\n
\n {props.config.siteFooter &&
{props.config.siteFooter}
}\n {/* If the user is logged in, but has not yet set their birth date and email, display the user profile dialog. */}\n {props.login?.loggedInUser && !(props.login.loggedInUser.user_data.birth_date && props.login.loggedInUser.user_data.email) &&\n }\n
\n);\n\nexport default connect(\n (state: ApplicationState, props) =>\n ({ ...props, config: state.config, login: state.login }))(Layout);\n","import * as React from 'react';\nimport {connect, Matching} from 'react-redux';\nimport {Link} from \"react-router-dom\";\nimport moment from \"moment\";\nimport * as ChallengeListStore from '../store/ChallengeList'\nimport {ApplicationState} from \"../store\";\n\ntype ChallengeListProps =\n ChallengeListStore.ChallengeListState &\n { requestChallengeList: () => void };\n\nclass ChallengeList extends React.PureComponent> {\n public componentDidMount() {\n this.props.requestChallengeList();\n }\n\n public render() {\n return (\n \n {this.props.requestError &&\n {this.props.requestError}}\n {this.props.challenges ?\n ChallengeList.renderChallengeListTable(this.props.challenges) :\n ChallengeList.renderLoadingIndicator()}\n \n );\n }\n\n private static renderChallengeListTable(challenges: ChallengeListStore.Challenge[]) {\n return (\n \n \n \n \n \n \n \n \n \n {challenges.map((challenge: ChallengeListStore.Challenge) =>\n new Date()) ? 'active-challenge' : 'inactive-challenge'}>\n \n \n \n \n )}\n \n
SegmentStart DateEnd Date
{challenge.displayName}{moment(challenge.startDate).fromNow()} ({moment(challenge.startDate).format('MMMM Do YYYY')}){moment(challenge.endDate).fromNow()}
\n );\n }\n\n private static renderLoadingIndicator() {\n return (\n
Loading ...
\n )\n }\n}\n\nexport default connect(\n (state: ApplicationState) => state.challengeList,\n ChallengeListStore.actionCreators\n)(ChallengeList);\n","import * as React from 'react';\nimport {connect} from 'react-redux';\nimport {ApplicationState} from \"../store\";\nimport ChallengeList from \"./ChallengeList\";\n\nconst Home = (state: ApplicationState) => (\n
\n

Challenges

\n \n
\n);\n\nexport default connect((state: ApplicationState) => state)(Home);\n","import * as React from 'react';\nimport { connect, Matching } from \"react-redux\";\nimport moment from \"moment\";\nimport * as ChallengeDetailsStore from \"../store/ChallengeDetails\";\nimport { ApplicationState } from \"../store\";\nimport { ChallengeType } from \"../store/ChallengeList\";\nimport { LoginState } from \"../store/Login\";\n\ntype EffortListProps =\n ChallengeDetailsStore.ChallengeDetailsState &\n {\n byCategory: boolean,\n login?: LoginState\n };\n\nfunction toTimeFormat(duration: moment.Duration) {\n let str = ('0' + duration.seconds()).slice(-2);\n\n if (duration.asMinutes() >= 1.0) {\n str = `${('0' + duration.minutes()).slice(-2)}:${str}`;\n\n if (duration.asHours() >= 1.0) {\n str = `${('0' + duration.hours()).slice(-2)}:${str}`;\n\n if (duration.asDays() >= 1.0) {\n str = `${Math.floor(duration.asDays())} days ${str}`;\n }\n }\n } else {\n str += ' seconds';\n }\n\n return str;\n}\n\nclass EffortList extends React.PureComponent> {\n public render() {\n return (\n \n {this.props.errorMessage &&\n {this.props.errorMessage}}\n {this.props.allEfforts ?\n this.renderEffortListTable(this.props.allEfforts, this.props.currentChallenge?.type, this.props.byCategory) :\n EffortList.renderLoadingIndicator()}\n \n );\n }\n\n private renderEffortListTable(\n efforts: ChallengeDetailsStore.Effort[],\n challengeType: ChallengeType | undefined,\n byCategory: boolean) {\n // TODO filter by category\n const showLapCount = challengeType === ChallengeType.MostLaps;\n\n let renderCategoryResults = (categoryName: string, categoryEfforts: ChallengeDetailsStore.Effort[]) => {\n const columns = showLapCount ? 4 : 3;\n return (\n \n \n {categoryName}\n \n \n Place\n Athlete\n {showLapCount && Lap Count}\n Time\n \n {categoryEfforts.map((effort, ix) =>\n \n {ix + 1}\n {effort.athleteName}{this.props.login?.loggedInUser?.user_data.is_admin && (` (${effort.athleteId})`)}\n {showLapCount && {effort.lapCount}}\n {toTimeFormat(moment.duration(effort.elapsedTime, 'seconds'))}\n \n )}\n \n );\n }\n\n if (byCategory) {\n let resultsByCategory: any = {};\n for (const effort of efforts) {\n const cat = this.getCategory(effort.athleteAge, effort.athleteGender, effort.specialCategoryId);\n if (!resultsByCategory[cat]) {\n resultsByCategory[cat] = [effort];\n } else {\n resultsByCategory[cat].push(effort);\n }\n }\n return (\n \n {Object.keys(resultsByCategory).map(cat => renderCategoryResults(cat, resultsByCategory[cat]))}\n
\n );\n } else {\n const showCategory = !(this.props.selectedCategory?.maximumAge && this.props.selectedCategory?.gender);\n return (\n \n \n \n \n {showCategory && }\n {showLapCount && }\n \n \n \n \n {efforts.map((effort: ChallengeDetailsStore.Effort) =>\n \n \n {showCategory && }\n {showLapCount && }\n \n \n )}\n \n
AthleteCategoryLap CountTime
{effort.athleteName}{this.props.login?.loggedInUser?.user_data.is_admin && (` (${effort.athleteId})`)}{this.getCategory(effort.athleteAge, effort.athleteGender, effort.specialCategoryId)}{effort.lapCount}{toTimeFormat(moment.duration(effort.elapsedTime, 'seconds'))}
\n );\n }\n }\n\n private getCategory(athleteAge: number, athleteGender: string, specialCategoryId: number | null): string {\n if (this.props.ageGroups && this.props.specialCategories) {\n let gender = 'Other';\n switch (athleteGender) {\n case 'm':\n case 'M':\n gender = 'Men';\n break;\n case 'f':\n case 'F':\n gender = 'Women';\n break;\n }\n\n let category;\n if (specialCategoryId != null) {\n const cat = this.props.specialCategories.filter(c => c.specialCategoryId === specialCategoryId)[0];\n if (cat) {\n category = cat.categoryName;\n }\n } else if (this.props.ageGroups) {\n const ageGroup = this.props.ageGroups.filter(a => a.maximumAge >= athleteAge)[0];\n if (ageGroup) {\n category = ageGroup.description ;\n }\n }\n\n if (category) {\n return `${gender}, ${category}`\n } else {\n return gender;\n }\n\n } else {\n return 'Unknown';\n }\n }\n\n private static renderLoadingIndicator() {\n return (\n
Loading ...
\n )\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({...state.challengeDetails, login: state.login})\n)(EffortList);\n","import * as React from \"react\";\nimport {connect, Matching} from \"react-redux\";\nimport {UploadChallengeGpxState} from \"../store/UploadChallengeGpx\";\nimport * as ChallengeDetailStore from \"../store/ChallengeDetails\";\nimport * as UploadChallengeGpxStore from \"../store/UploadChallengeGpx\";\nimport {LoginState} from \"../store/Login\";\nimport {ApplicationState} from \"../store\";\nimport {ChangeEvent} from \"react\";\n\ntype UploadChallengeProps =\n UploadChallengeGpxStore.UploadChallengeGpxState &\n ChallengeDetailStore.ChallengeDetailsState &\n { login?: LoginState } &\n {\n onFileSelected: (event: ChangeEvent) => void,\n uploadFile: () => void,\n cancelUpload: () => void\n };\n\nclass UploadChallengeGpx extends React.PureComponent, UploadChallengeGpxState> {\n constructor(props: UploadChallengeProps) {\n super(props);\n\n this.state = {};\n }\n\n public render() {\n let sectionBody;\n\n if (this.props.uploaded) {\n sectionBody = (\n
\n GPX data successfully uploaded.\n
\n );\n } else if (this.props.uploading) {\n sectionBody = (\n
\n Uploading File: {this.props.selectedFile?.name || \"unknown\"}\n
\n );\n } else if (this.props.errorMessage) {\n sectionBody = (\n
\n An error occurred: {this.props.errorMessage}\n
\n );\n } else if (this.props.selectedFile) {\n sectionBody = (\n
\n File selected: {this.props.selectedFile?.name}\n \n \n\n
\n );\n } else {\n sectionBody = (\n
\n this.props.onFileSelected(e)}/>\n
\n );\n }\n\n return (\n
\n

\n Upload Segment GPX Data\n

\n {sectionBody}\n
\n );\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({...state.uploadChallengeGpx, ...state.challengeDetails, login: state.login}),\n UploadChallengeGpxStore.actionCreators\n)(UploadChallengeGpx);\n","import * as React from 'react';\nimport {connect, Matching} from \"react-redux\";\nimport * as ChallengeDetailsStore from \"../store/ChallengeDetails\";\nimport {ApplicationState} from \"../store\";\nimport {LoginState} from \"../store/Login\";\n\ntype NoEffortListProps =\n ChallengeDetailsStore.ChallengeDetailsState &\n { login?: LoginState };\n\nclass NoEffortList extends React.PureComponent> {\n public render() {\n return (\n \n {this.props.errorMessage &&\n {this.props.errorMessage}}\n {this.props.allAthletes && this.props.allEfforts ?\n this.renderNoEffortListTable(this.props.allAthletes, this.props.allEfforts) :\n NoEffortList.renderLoadingIndicator()}\n \n );\n }\n\n private renderNoEffortListTable(athletes: ChallengeDetailsStore.Athlete[], efforts: ChallengeDetailsStore.Effort[]) {\n const showCategory = !(this.props.selectedCategory?.maximumAge && this.props.selectedCategory?.gender);\n const athletesWithEffort = new Set(efforts.map(e => e.athleteId));\n const athletesWithNoEfforts = athletes.filter(a => !athletesWithEffort.has(a.id));\n if (athletesWithNoEfforts.length > 0) {\n return (\n \n

Athletes With No Times

\n \n \n \n \n {showCategory && }\n \n \n \n {athletesWithNoEfforts.map((athlete: ChallengeDetailsStore.Athlete) =>\n \n \n {showCategory && }\n \n )}\n \n
AthleteCategory
{athlete.displayName}{this.props.login?.loggedInUser?.user_data.is_admin && (` (${athlete.id})`)}{this.getCategory(athlete.age, athlete.gender, athlete.specialCategoryId)}
\n

\n Note: If you recently uploaded a ride it make take 30 minutes to an hour for your segment times to\n appear here. If it takes longer please contact support.\n

\n
\n );\n }\n }\n\n private getCategory(athleteAge: number, athleteGender: string, specialCategoryId: number | null): string {\n if (this.props.ageGroups && this.props.specialCategories) {\n let gender = 'Other';\n switch (athleteGender) {\n case 'm':\n case 'M':\n gender = 'Men';\n break;\n case 'f':\n case 'F':\n gender = 'Women';\n break;\n }\n\n let category;\n if (specialCategoryId != null) {\n const cat = this.props.specialCategories.filter(c => c.specialCategoryId === specialCategoryId)[0];\n if (cat) {\n category = cat.categoryName;\n }\n } else if (this.props.ageGroups) {\n const ageGroup = this.props.ageGroups.filter(a => a.maximumAge >= athleteAge)[0];\n if (ageGroup) {\n category = ageGroup.description ;\n }\n }\n\n if (category) {\n return `${gender}, ${category}`\n } else {\n return gender;\n }\n } else {\n return 'Unknown';\n }\n }\n\n private static renderLoadingIndicator() {\n return (\n
Loading? ...
\n )\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({...state.challengeDetails, login: state.login})\n)(NoEffortList);\n","import * as React from \"react\";\nimport { connect, Matching } from \"react-redux\";\nimport { UploadEffortGpxState } from \"../store/UploadEffortGpx\";\nimport * as ChallengeDetailStore from \"../store/ChallengeDetails\";\nimport * as UploadEffortGpxStore from \"../store/UploadEffortGpx\";\nimport { LoginInfo, LoginState } from \"../store/Login\";\nimport { ApplicationState } from \"../store\";\nimport { ChangeEvent } from \"react\";\n\ntype UploadEffortProps =\n UploadEffortGpxStore.UploadEffortGpxState &\n ChallengeDetailStore.ChallengeDetailsState &\n { loggedInUser?: LoginInfo } &\n {\n onAthleteIdChanged: (event: ChangeEvent) => void,\n onFileSelected: (event: ChangeEvent) => void,\n uploadFile: () => void,\n cancelUpload: () => void\n };\n\nclass UploadEffortGpx extends React.PureComponent, UploadEffortGpxState> {\n constructor(props: UploadEffortProps) {\n super(props);\n\n this.state = {\n athleteId: props.athleteId\n };\n }\n\n public render() {\n let fileInputRow;\n\n if (this.props.uploaded) {\n fileInputRow = (\n
\n GPX data successfully uploaded.\n
\n );\n } else if (this.props.uploading) {\n fileInputRow = (\n
\n Uploading File: {this.props.selectedFile?.name || \"unknown\"}\n
\n );\n } else if (this.props.errorMessage) {\n fileInputRow = (\n
\n An error occurred: {this.props.errorMessage}\n
\n );\n } else if (this.props.selectedFile) {\n fileInputRow = (\n
\n File selected: {this.props.selectedFile?.name}\n \n \n\n
\n );\n } else {\n fileInputRow = (\n
\n this.props.onFileSelected(e)} />\n
\n );\n }\n\n return (\n
\n

\n Upload Effort GPX Data\n

\n {this.props.loggedInUser && this.props.loggedInUser.user_data.is_admin &&\n
\n \n
}\n {fileInputRow}\n
\n );\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({ ...state.uploadEffortGpx, ...state.challengeDetails, loggedInUser: state.login?.loggedInUser }),\n UploadEffortGpxStore.actionCreators\n)(UploadEffortGpx);\n","import * as React from \"react\";\n\ntype ModalProps = {\n open: boolean,\n title?: string,\n closeModal?: () => void,\n children: any,\n};\n\nexport function Modal(props: ModalProps) {\n if (props.open) {\n return (\n
\n
\n {props.closeModal && }\n {props.title &&
{props.title}
}\n
\n {props.children}\n
\n
\n
\n );\n } else {\n return null;\n }\n}\n\n","import * as React from 'react';\n\nexport function onEnterKey(fn: (e: React.KeyboardEvent) => void): (e: React.KeyboardEvent) => void {\n return (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n fn(e);\n }\n };\n}\n","import * as React from 'react';\nimport { useLocation } from \"react-router\";\n\nexport const withQueryParams = (Component: any) => {\n return (props: any) => {\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n\n return ();\n };\n};\n\nexport interface IQueryParamsProps {\n location: Location,\n queryParams: URLSearchParams\n}\n","import * as React from 'react';\nimport { ChangeEvent } from 'react';\nimport { connect, Matching } from 'react-redux';\nimport { Redirect, RouteComponentProps } from 'react-router';\nimport { Link } from 'react-router-dom';\nimport parse from 'html-react-parser';\nimport moment from 'moment';\n\nimport EffortList from './EffortList';\nimport UploadChallengeGpx from './UploadChallengeGpx';\nimport NoEffortList from './NoEffortList';\nimport UploadEffortGpx from './UploadEffortGpx';\nimport { ApplicationState } from '../store';\nimport { Challenge } from '../store/ChallengeList';\nimport * as ChallengeDetailStore from '../store/ChallengeDetails'\nimport * as ChallengeListStore from '../store/ChallengeList'\nimport { LoginState } from '../store/Login';\nimport { Category } from '../store/ChallengeDetails';\nimport { Modal } from '../shared/Modal';\nimport { onEnterKey } from '../shared/EventHelpers';\nimport { IQueryParamsProps, withQueryParams } from '../shared/WithQueryParams';\n\ntype ChallengeDetailsProps =\n ChallengeDetailStore.ChallengeDetailsState &\n ChallengeListStore.ChallengeListState &\n { login?: LoginState } &\n {\n onSelectedChallengeChanged: (selectedChallenge: string) => void,\n refreshRegistrationStatus: (selectedChallenge: string) => void,\n selectedCategoryChanged: (selectedCategory: Category) => ChallengeDetailStore.SelectedCategoryChanged,\n joinChallenge: (inviteCode?: string) => void,\n cancelJoin: () => void,\n inviteCodeChanged: (inviteCode: string) => void,\n } &\n RouteComponentProps<{ challengeName: string }> &\n IQueryParamsProps;\n\ntype ChallengeDetailsState = {\n bestEffort?: number,\n byCategory?: boolean\n};\n\nfunction relativeUrl(location: Location) {\n return [location.pathname, location.search, location.hash].join('');\n}\n\nclass ChallengeDetails extends React.PureComponent, ChallengeDetailsState> {\n constructor(props: ChallengeDetailsProps) {\n super(props);\n\n this.state = {};\n }\n\n public componentDidMount() {\n this.props.onSelectedChallengeChanged(this.props.match.params.challengeName);\n\n // Only use the query parameter if we don't have this in our props yet.\n let inviteCode = this.props.queryParams.get('inviteCode') ?? undefined;\n if (!this.props.inviteCode && inviteCode) {\n this.props.inviteCodeChanged(inviteCode);\n }\n\n if (this.props.login?.loggedInUser && this.props.isAthleteRegistered === undefined && this.props.selectedChallengeName) {\n // console.log('refresh registration');\n this.props.refreshRegistrationStatus(this.props.selectedChallengeName);\n } /* else {\n console.log(JSON.stringify({\n loggedInUser: this.props.login?.loggedInUser?.sub,\n isAthleteRegistered: this.props.isAthleteRegistered,\n selectedChallengeName: this.props.selectedChallengeName\n }))\n } */\n }\n\n public componentDidUpdate() {\n this.props.onSelectedChallengeChanged(this.props.match.params.challengeName);\n\n if (this.props.allEfforts && this.props.login && this.props.login.loggedInUser) {\n const loggedInUser = this.props.login.loggedInUser;\n this.setState({\n bestEffort: this.props.allEfforts.filter(e => e.athleteId === Number(loggedInUser.sub))[0]?.id\n })\n }\n }\n\n public render() {\n if (this.props.inviteCode && !this.props.login?.loggedInUser) {\n // If a user is trying to register, but isn't logged in, suggest that the sign up\n return (\n \n );\n }\n\n return (\n \n {this.props.requestError &&\n {this.props.requestError}}\n {this.props.currentChallenge ?\n this.renderChallengeDetails() :\n (this.props.challenges ? ChallengeDetails.renderNotFound() : ChallengeDetails.renderLoadingIndicator())}\n \n );\n }\n\n private renderChallengeDetails() {\n return this.props.currentChallenge && (\n
\n
\n

{this.props.currentChallenge.displayName}

\n {(this.props.isAthleteRegistered === false) &&\n }\n {this.state.bestEffort ?\n \n Your Effort\n :\n (this.props.isAthleteRegistered === true &&\n You have joined. Check back later for your efforts.)}\n
\n
    \n
  • Start Date/Time: {moment(this.props.currentChallenge.startDate).format('MMMM Do YYYY, h:mm a')}
  • \n {(this.props.currentChallenge.startDate.getDate() !== this.props.currentChallenge.endDate.getDate() ||\n this.props.currentChallenge.startDate.getMonth() !== this.props.currentChallenge.endDate.getMonth()) ?\n
  • End Date/Time: {moment(this.props.currentChallenge.endDate).format('MMMM Do YYYY, h:mm a')}
  • :\n
  • End Time: {moment(this.props.currentChallenge.endDate).format('h:mm a')}
  • }\n
\n {this.props.currentChallenge.hasRouteMap &&\n \n \"A\n }\n

{parse(this.props.currentChallenge.description)}

\n
\n

\n {!this.state.byCategory ?\n By Time :\n this.displayResultsByTime()} className=\"alternate-results-display clickable\">By Time}\n | \n {this.state.byCategory ?\n By Category :\n this.displayResultsByCategory()} className=\"alternate-results-display clickable\">By Category}\n

\n
\n \n {/*
*/}\n {/* */}\n {/*
*/}\n
\n
\n \n
\n
\n {this.props.login?.loggedInUser?.user_data.is_admin && }\n {this.props.isAthleteRegistered &&\n this.props.currentChallenge.startDate < new Date() &&\n }\n\n this.props.cancelJoin()}>\n
\n \n

\n If you do not yet have an invite code, you may need to register\n for the event or contact the challenge organizer.\n

\n {this.props.registrationError &&\n

\n {this.props.registrationError}\n

}\n
\n \n \n
\n
\n
\n
\n );\n }\n\n private displayResultsByCategory() {\n this.setState({ byCategory: true });\n }\n\n private displayResultsByTime() {\n this.setState({ byCategory: false });\n }\n\n private static renderLoadingIndicator() {\n return (\n
Loading ...
\n )\n }\n\n private static renderNotFound() {\n return (\n
\n The Challenge you are looking for was not found.\n
\n )\n }\n\n private static getSelectedChallenge(challenges: Challenge[], challengeName: string): Challenge | undefined {\n return challenges.filter(c => c.name === challengeName)[0];\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({ ...state.challengeList, ...state.challengeDetails, login: state.login }),\n ChallengeDetailStore.actionCreators\n)(withQueryParams(ChallengeDetails));\n","import * as React from 'react';\nimport { connect } from 'react-redux';\nimport { ConfigurationState } from \"../store/Configuration\";\nimport { ApplicationState } from \"../store\";\n\nconst StravaLoginButton = (props: { config: ConfigurationState, signup?: boolean, returnUrl?: string }) => {\n let url = (props.returnUrl ?\n `${props.config.apiBaseUrl}api/connect/login?returnUrl=${encodeURIComponent(props.returnUrl)}` :\n `${props.config.apiBaseUrl}api/connect/login`);\n return (\n \n {props.signup ? 'Sign up' : 'Log in'} with Strava\n \n );\n};\n\nexport default connect((state: ApplicationState, props) =>\n ({ ...props, config: state.config }))(StravaLoginButton);\n","import * as React from \"react\";\nimport { ChangeEvent } from \"react\";\nimport { connect } from \"react-redux\";\nimport { ApplicationState } from \"../store\";\nimport * as LoginStore from \"../store/Login\";\nimport StravaLoginButton from \"./StravaLoginButton\";\nimport { Redirect } from \"react-router\";\nimport { onEnterKey } from \"../shared/EventHelpers\";\nimport { IQueryParamsProps, withQueryParams } from \"../shared/WithQueryParams\";\n\ntype LoginPageProps = {\n userEmail?: string,\n loginError?: string,\n loggedInUser?: LoginStore.LoginInfo\n} & {\n usernamePasswordLogin: (credentials: { email: string, password: string }) => void\n} & IQueryParamsProps;\n\ntype LoginPageState = {\n email: string,\n password: string,\n loggingIn: boolean,\n returnUrl?: string\n};\n\nclass LoginPage extends React.PureComponent {\n constructor(props: LoginPageProps) {\n super(props);\n\n this.state = {\n email: props.userEmail ?? '',\n password: '',\n loggingIn: false,\n returnUrl: props.queryParams.get('returnUrl') ?? undefined,\n };\n\n this.handleEmailChanged = this.handleEmailChanged.bind(this);\n this.handlePasswordChanged = this.handlePasswordChanged.bind(this);\n }\n\n public render() {\n if (this.props.loggedInUser) {\n console.log(`Logged in. Redirecting to ${this.state.returnUrl || '/'}`);\n return ;\n } else {\n return (\n
\n {/* TODO: Add Login with Google, Facebook */}\n \n
\n
\n \n \n {this.props.loginError &&
{this.props.loginError}
}\n \n
\n
\n );\n }\n }\n\n private handleEmailChanged(event: ChangeEvent) {\n this.setState({ email: event.target.value });\n }\n\n private handlePasswordChanged(event: ChangeEvent) {\n this.setState({ password: event.target.value });\n }\n\n private performLogin() {\n this.setState({ loggingIn: true });\n this.props.usernamePasswordLogin({ email: this.state.email, password: this.state.password });\n }\n}\n\n// TODO: track last login email via cookie or local storage\nexport default connect(\n (state: ApplicationState) => ({\n loggedInUser: state.login?.loggedInUser,\n loginError: state.login?.loginError\n }),\n LoginStore.actionCreators\n)(withQueryParams(LoginPage));\n","import * as React from \"react\";\n\nexport default () => (\n
\n
Page Not Found
\n

The page you are trying to view could not be found.

\n
\n);\n","import * as React from \"react\";\nimport { ChangeEvent } from \"react\";\nimport { connect } from \"react-redux\";\nimport { ApplicationState } from \"../store\";\nimport * as LoginStore from \"../store/Login\";\nimport StravaLoginButton from \"./StravaLoginButton\";\nimport { Redirect } from \"react-router\";\nimport { Link } from \"react-router-dom\";\nimport { IQueryParamsProps, withQueryParams } from \"../shared/WithQueryParams\";\n\ntype SignUpPageProps = {\n signUpError?: string,\n loggedInUser?: LoginStore.LoginInfo\n} & {\n signUp: (profile: LoginStore.UserSignUp) => void\n} & IQueryParamsProps;\n\ntype SignUpPageState = {\n email?: string,\n password?: string,\n confirmPassword?: string,\n username?: string,\n firstName?: string,\n lastName?: string,\n year?: number,\n month?: number,\n day?: number,\n gender?: string,\n returnUrl?: string,\n}\n\nconst months = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n];\n\nconst maxBirthYear = new Date().getFullYear() - 13;\nconst minBirthYear = maxBirthYear - (99 - 13);\nlet yearArray: number[] = [];\nfor (let y = maxBirthYear; y >= minBirthYear; y--) {\n yearArray.push(y);\n}\n\nfunction getDaysPerMonth(year: number | undefined, month: number | undefined) {\n if (month) {\n // Note month here is index by 1, where as javascript is index by zero, which is why this works.\n if (year) {\n return new Date(year, month, 0).getDate();\n } else {\n // Intentionally choosing a leap year, since we want to include 29 for february\n return new Date(2020, month, 0).getDate();\n }\n } else {\n return 31;\n }\n}\n\nclass SignUpPage extends React.PureComponent {\n constructor(props: SignUpPageProps) {\n super(props);\n\n this.state = {\n email: '',\n password: '',\n confirmPassword: '',\n username: '',\n firstName: '',\n lastName: '',\n year: undefined,\n month: undefined,\n day: undefined,\n gender: undefined,\n returnUrl: props.queryParams.get('returnUrl') ?? undefined\n };\n\n this.handleEmailChanged = this.handleEmailChanged.bind(this);\n this.handlePasswordChanged = this.handlePasswordChanged.bind(this);\n this.handleConfirmPasswordChanged = this.handleConfirmPasswordChanged.bind(this);\n this.handleUsernameChanged = this.handleUsernameChanged.bind(this);\n this.handleFirstNameChanged = this.handleFirstNameChanged.bind(this);\n this.handleLastNameChanged = this.handleLastNameChanged.bind(this);\n this.handleYearChanged = this.handleYearChanged.bind(this);\n this.handleMonthChanged = this.handleMonthChanged.bind(this);\n this.handleDayChanged = this.handleDayChanged.bind(this);\n this.handleGenderChanged = this.handleGenderChanged.bind(this);\n }\n\n public render() {\n if (this.props.loggedInUser) {\n console.log('sign up successful. Redirecting.');\n return ;\n } else {\n return (\n
\n
\n

Option 1. Strava

\n

If you have a Strava account please use this button to sign up using Strava. You will be redirected to the Strava website or app and prompted to authorize ASBRA to access your activity information. Once you click the authorize button you will be redirected back to this page where you will be prompted to enter some additional information.

\n \n
\n

Option 2. Email Address & Password

\n

Only fill out and submit the form below if you do not have a Strava account.

\n
\n

In order to participate in challenges we need to know a little bit about you.

\n
\n \n

You will use your Email to log in.

\n
\n
\n \n

= 7) ? '' : 'error'}`}>Your\n password must be at least 7 characters.

\n
\n
\n \n {this.state.confirmPassword &&\n this.state.confirmPassword != this.state.password &&\n

The passwords must match exactly.

}\n\n
\n
\n \n

This name will be displayed in leader boards.

\n
\n
\n \n
\n
\n \n
\n
\n

Birthdate

\n \n \n \n
\n
\n \n
\n {this.props.signUpError &&\n

{this.props.signUpError}

}\n \n
\n
\n
\n Already signed up? Log in instead.\n
\n
\n );\n }\n }\n\n private handleEmailChanged(event: ChangeEvent) {\n this.setState({ email: event.target.value });\n }\n\n private handlePasswordChanged(event: ChangeEvent) {\n this.setState({ password: event.target.value });\n }\n\n private handleConfirmPasswordChanged(event: ChangeEvent) {\n this.setState({ confirmPassword: event.target.value });\n }\n\n private handleUsernameChanged(event: ChangeEvent) {\n this.setState({ username: event.target.value });\n }\n\n private handleFirstNameChanged(event: ChangeEvent) {\n this.setState({ firstName: event.target.value });\n }\n\n private handleLastNameChanged(event: ChangeEvent) {\n this.setState({ lastName: event.target.value });\n }\n\n private handleYearChanged(event: ChangeEvent) {\n this.setState({ year: Number(event.target.value) });\n }\n\n private handleMonthChanged(event: ChangeEvent) {\n this.setState({ month: Number(event.target.value) });\n }\n\n private handleDayChanged(event: ChangeEvent) {\n this.setState({ day: Number(event.target.value) });\n }\n\n private handleGenderChanged(event: ChangeEvent) {\n this.setState({ gender: event.target.value });\n }\n\n private signUp() {\n if (this.state.email &&\n this.state.password &&\n this.state.password === this.state.confirmPassword &&\n this.state.username &&\n this.state.year &&\n this.state.month &&\n this.state.day &&\n this.state.gender) {\n this.props.signUp({\n email: this.state.email,\n password: this.state.password,\n username: this.state.username,\n firstName: this.state.firstName,\n lastName: this.state.lastName,\n birthDate: new Date(this.state.year, this.state.month - 1, this.state.day),\n gender: this.state.gender,\n });\n }\n }\n}\n\nexport default connect(\n (state: ApplicationState) => ({ loggedInUser: state.login?.loggedInUser, signUpError: state.login?.signUpError }),\n LoginStore.actionCreators)(withQueryParams(SignUpPage));\n","import React from \"react\";\nimport { Route, Switch } from \"react-router\";\nimport Layout from \"./components/Layout\";\nimport Home from \"./components/Home\";\nimport ChallengeDetails from \"./components/ChallengeDetails\";\nimport LoginPage from \"./components/LoginPage\";\nimport NotFound from \"./components/NotFound\";\nimport SignUpPage from \"./components/SignUpPage\";\n\nimport \"./site.scss\"\n\nexport default () => (\n \n \n \n \n \n \n \n \n \n);\n","// In production, we register a service worker to serve assets from local cache.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\n// cached resources are updated in the background.\n\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\n// This link also includes instructions on opting out of this behavior.\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport default function register() {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const url = process.env.PUBLIC_URL as string;\n const publicUrl = new URL(url, window.location.toString());\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Lets check if a service worker still exists or not.\n checkValidServiceWorker(swUrl);\n } else {\n // Is not local host. Just register service worker\n registerValidSW(swUrl);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl: string) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing as ServiceWorker;\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the old content will have been purged and\n // the fresh content will have been added to the cache.\n // It's the perfect time to display a \"New content is\n // available; please refresh.\" message in your web app.\n console.log('New content is available; please refresh.');\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl: string) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (response.status === 404 || (contentType && contentType.indexOf('javascript') === -1)) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl);\n }\n })\n .catch(() => {\n console.log('No internet connection found. App is running in offline mode.');\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport { Provider } from 'react-redux';\nimport { ConnectedRouter } from 'connected-react-router';\nimport { createBrowserHistory } from 'history';\nimport configureStore from './store/configureStore';\nimport App from './App';\nimport registerServiceWorker from './registerServiceWorker';\nimport * as RestHelper from './RestHelper';\n\n// Create browser history to use in the Redux store\nconst baseUrl = document.getElementsByTagName('base')[0].getAttribute('href') as string;\nconst history = createBrowserHistory({ basename: baseUrl });\n\n// Check user login state\nlet loggedInUser = RestHelper.getLoggedInUser();\n\nfetch('/config/env.json')\n .then(resp => {\n if (resp.status === 200) {\n const contentType = resp.headers.get('Content-Type');\n if (contentType && (contentType.startsWith('application/json') || contentType.startsWith('text/json'))) {\n return resp.json();\n } else {\n console.warn(`Unexpected content type for /config/env.json: ${contentType}`);\n }\n } else {\n console.warn(`Unexpected status code for /config/env.json: ${resp.status}`);\n }\n\n return {};\n })\n .catch(err => {\n console.warn('Error fetching config json: ' + (err.stack || err.message));\n return {};\n })\n .then((config: any) => {\n // Get the application-wide store instance, prepopulating with state from the server where available.\n const initialState = {\n login: { loggedInUser },\n config: {\n siteTitle: config.siteTitle ?? process.env.REACT_APP_SITE_TITLE ?? 'Strava Segment Challenge',\n siteLogo: config.siteLogo ?? process.env.REACT_APP_SITE_LOGO,\n siteFooter: config.siteFooter ?? process.env.REACT_APP_SITE_FOOTER,\n apiBaseUrl: config.apiBaseUrl ?? process.env.REACT_APP_API_BASE_URL ?? ''\n }\n };\n\n document.title = initialState.config.siteTitle;\n\n const store = configureStore(history, initialState);\n\n ReactDOM.render(\n \n \n \n \n ,\n document.getElementById('root')\n );\n\n registerServiceWorker();\n });\n","import {applyMiddleware, combineReducers, compose, createStore} from 'redux';\nimport thunk from 'redux-thunk';\nimport {connectRouter, routerMiddleware} from 'connected-react-router';\nimport {History} from 'history';\nimport {reducers, ApplicationState} from \"./index\";\n\nexport default function configureStore(history: History, initialState?: ApplicationState) {\n const middleware = [\n thunk,\n routerMiddleware(history)\n ];\n\n const rootReducer = combineReducers({\n ...reducers,\n router: connectRouter(history)\n });\n\n const enhancers = [];\n const windowIfDefined = typeof window === 'undefined' ? null : window as any;\n if (windowIfDefined && windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__) {\n enhancers.push(windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__());\n }\n\n return createStore(\n rootReducer,\n initialState,\n compose(applyMiddleware(...middleware), ...enhancers)\n );\n}\n"],"sourceRoot":""}