{"version":3,"sources":["AppContext.tsx","Component/TopNav.tsx","Component/Login.tsx","State/ActionRegistry.ts","State/Actions/setDrawerState.ts","Model/DrawerType.ts","Component/SideDrawer.tsx","Utility/LoginTokenStore.ts","State/Actions/setLoginToken.ts","Component/LoginDrawer.tsx","Model/ClassType.ts","Model/CheckpointRating.ts","Component/Filter.tsx","Utility/FilterParamsHelper.ts","State/Actions/setFilterParams.ts","Component/FilterDrawer.tsx","Utility/CoordinateHelper.ts","Component/AddCheckpoint.tsx","State/Actions/setBusy.ts","State/Actions/setCheckpoints.ts","State/Actions/setErrorMessage.ts","State/Actions/setCameraLocation.ts","Utility/CheckpointStore.ts","Utility/CheckpointHelper.ts","State/Actions/addCheckpoint.ts","Component/AddCheckpointDrawer.tsx","Component/CheckpointProperties.tsx","State/Actions/removeCheckpoint.ts","Component/CheckpointPropertiesDrawer.tsx","Component/Drawers.tsx","Component/CheckpointMap/GoogleMapWrapper.ts","Component/CheckpointMap/index.tsx","State/Actions/setSelectedCheckpoint.ts","App.tsx","State/Actions/initializeApp.ts","State/useAppState.ts","index.tsx"],"names":["AppContext","React","createContext","TopNav","props","Box","sx","display","flexDirection","width","justifyContent","items","map","item","Button","onClick","value","name","Login","useState","token","localToken","setLocalToken","Stack","m","direction","alignItems","spacing","TextField","label","variant","size","onChange","event","target","color","onLogin","ActionRegistry","type","reducer","this","reducers","set","dispatch","args","get","dispatcher","dispatchers","Map","DrawerType","setDrawerState","addReducer","state","drawer","open","newState","drawerState","SideDrawer","useContext","Drawer","anchor","onClose","children","StorageKey","LoginTokenStore","localStorage","getItem","setItem","setLoginToken","loginToken","save","LoginDrawer","ClassType","CheckpointRating","renderClasses","selectedClasses","params","handleClassChange","newClasses","Set","checked","add","delete","newParams","Typography","FormControlLabel","FourByFour","control","Checkbox","has","e","XCross","renderRatings","selectedRatings","handleRatingChange","newRatings","Basecamp","Green","Blue","Black","renderYears","selectedYears","yearsArray","Array","from","allYears","sort","yearElements","year","index","newYears","handleYearChange","Filter","AllRatings","AllClasses","FilterParamsHelper","checkpoints","allYearsSet","c","allClassesSet","class","allClasses","forEach","filter","checkpoint","rating","setFilterParams","filterParams","filteredCheckpoints","allCheckpoints","FilterDrawer","CoordinateHelper","latStr","longStr","lat","tryParseCoordinate","undefined","lng","latLng","distanceKm","heading","startLatRads","degToRad","angularDistance","headingRads","Math","asin","sin","cos","radToDeg","atan2","degrees","PI","radians","str","cleanStr","trim","toLocaleLowerCase","length","parts","split","parseInt","isNaN","sign","abs","minutesDecimal","parseFloat","floor","StateKey","EmptyState","competitionDay","distance","AddCheckpoint","json","JSON","parse","setState","useEffect","stringify","errors","setErrors","FormControl","fullWidth","InputLabel","id","Select","labelId","MenuItem","required","placeholder","error","coord","tryConvert","NaN","validDistance","validHeading","move","nanoid","tryCreateCheckpoint","onAdd","setBusy","busy","setCheckpoints","newFilterParams","update","setErrorMessage","message","errorMessage","setCameraLocation","location","cameraLocation","CheckpointsEndpoint","CheckpointStore","axios","result","data","config","headers","Authorization","post","CheckpointHelper","point","dlat","dlng","sqrt","Number","EPSILON","a","isDuplicate","AddItem","newCheckpoints","addCheckpoint","addDispatcher","AddCheckpointDrawer","InputProps","readOnly","CheckpointProperties","onRemove","Properties","removeCheckpoint","CheckpointPropertiesDrawer","onCheckpointRemove","selectedCheckpoint","Drawers","GoogleMapWrapper","zoom","center","onCheckpointClicked","markers","google","maps","setZoom","setCenter","markerIdsToRemove","keys","marker","url","Marker","position","icon","labelOrigin","Point","title","createMarker","addListener","setMap","CheckpointMap","ref","useRef","current","updateMarkers","style","flexGrow","setSelectedCheckpoint","TopNavItems","App","height","LinearProgress","Snackbar","anchorOrigin","vertical","horizontal","autoHideDuration","Alert","severity","AlertTitle","load","create","initializeApp","DefaultState","createDefault","action","reducerForType","getReducer","useAppState","useReducer","baseDispatch","useMemo","dispatcherForType","getDispatcher","dispatchMiddleware","AppContainer","StrictMode","Provider","ReactDOM","render","document","getElementById"],"mappings":"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","file":"static/js/main.e0f4c5d9.chunk.js","sourcesContent":["import React from \"react\";\n\nimport { Action } from \"./State/Action\";\nimport { IAppState } from \"./Model/IAppState\";\n\ninterface IAppContext {\n readonly state: IAppState;\n readonly dispatch: React.Dispatch;\n}\n\nexport const AppContext = React.createContext(null!);","import React from \"react\";\n\nimport { Box, Button } from \"@mui/material\";\n\nexport interface IProps {\n readonly items: { name: string, value: any }[];\n\n readonly onClick: (value: any) => void;\n}\n\nexport function TopNav(props: IProps): React.ReactElement {\n return (\n \n {props.items.map((item) => )}\n \n );\n}","import React from \"react\";\n\nimport { Button } from \"@mui/material\";\nimport { Stack, TextField } from \"@mui/material\";\n\nexport interface IProps {\n readonly token: string;\n readonly onLogin: (token: string) => void;\n}\n\nexport function Login(props: IProps): React.ReactElement {\n const [localToken, setLocalToken] = React.useState(props.token);\n\n const onChange = (event: React.ChangeEvent) => {\n setLocalToken(event.target.value);\n };\n\n return (\n \n \n\n \n \n );\n}\n","import React from \"react\";\n\nimport { Action } from \"./Action\";\n\nimport { IAppState } from \"../Model/IAppState\";\n\ntype Reducer = (state: IAppState, ...args: any[]) => IAppState;\ntype Dispatcher = (dispatch: React.Dispatch, ...args: any[]) => void;\n\ntype ReducerParameters =\n T extends (state: IAppState, ...args: infer P) => any ? P : never;\n\ntype DispatchParameters =\n T extends (dispatch: React.Dispatch, ...args: infer P) => any ? P : never;\n\nexport class ActionRegistry {\n private static readonly reducers = new Map();\n private static readonly dispatchers = new Map();\n\n public static addReducer(type: string, reducer: T): (dispatch: React.Dispatch, ...args: ReducerParameters) => void {\n this.reducers.set(type, reducer);\n \n return (dispatch: React.Dispatch, ...args: ReducerParameters): void => {\n dispatch({ type, args });\n };\n }\n\n public static getReducer(type: string): Reducer | undefined {\n return this.reducers.get(type);\n }\n\n public static addDispatcher(type: string, dispatcher: T): (dispatch: React.Dispatch, ...args: DispatchParameters) => void {\n this.dispatchers.set(type, dispatcher);\n\n return (dispatch: React.Dispatch, ...args: DispatchParameters): void => {\n dispatch({ type, args });\n };\n }\n\n public static getDispatcher(type: string): Dispatcher | undefined {\n return this.dispatchers.get(type);\n }\n}","import { IAppState } from \"../../Model/IAppState\";\nimport { DrawerType } from \"../../Model/DrawerType\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nfunction reducer(state: IAppState, drawer: DrawerType, open: boolean): IAppState {\n const newState = new Map(state.drawerState);\n\n newState.set(drawer, open);\n\n return {\n ...state,\n drawerState: newState\n };\n}\n\nexport const setDrawerState = ActionRegistry.addReducer(\"setDrawerState\", reducer);","export enum DrawerType {\n AddItem,\n Filter,\n Login,\n Properties\n}","import React from \"react\";\n\nimport { Drawer } from \"@mui/material\";\n\nimport { AppContext } from \"../AppContext\";\n\nimport { DrawerType } from \"../Model/DrawerType\";\n\nimport { setDrawerState } from \"../State/Actions/setDrawerState\";\n\ninterface IProps {\n readonly type: DrawerType;\n}\n\nexport function SideDrawer(props: React.PropsWithChildren): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n return (\n setDrawerState(dispatch, props.type, false)}>\n {props.children}\n \n );\n}\n","const StorageKey = \"rebellemaps-login\"\n\nexport class LoginTokenStore {\n public static load(): string {\n return localStorage.getItem(StorageKey) ?? \"\"\n }\n\n public static save(token: string): void {\n localStorage.setItem(StorageKey, token);\n }\n}","import { IAppState } from \"../../Model/IAppState\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { LoginTokenStore } from \"../../Utility/LoginTokenStore\";\n\nfunction reducer(state: IAppState, loginToken: string): IAppState {\n LoginTokenStore.save(loginToken);\n\n return {\n ...state,\n loginToken\n };\n}\n\nexport const setLoginToken = ActionRegistry.addReducer(\"setLoginToken\", reducer);","import React from \"react\";\n\nimport { Login } from \"./Login\";\nimport { SideDrawer } from \"./SideDrawer\";\n\nimport { AppContext } from \"../AppContext\";\n\nimport { DrawerType } from \"../Model/DrawerType\";\n\nimport { setLoginToken } from \"../State/Actions/setLoginToken\";\nimport { setDrawerState } from \"../State/Actions/setDrawerState\";\n\nexport function LoginDrawer(): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n const onLogin = (token: string) => {\n setDrawerState(dispatch, DrawerType.Login, false);\n setLoginToken(dispatch, token);\n };\n\n return (\n \n \n \n );\n}","export enum ClassType {\n FourByFour = \"4x4\",\n XCross = \"X-Cross\"\n}\n","export enum CheckpointRating {\n Basecamp = \"Basecamp\",\n Green = \"Green\",\n Blue = \"Blue\",\n Black = \"Black\"\n}","import { Box, Checkbox, FormControlLabel, Stack, Typography } from \"@mui/material\";\n\nimport { ClassType } from \"../Model/ClassType\";\nimport { IFilterParams } from \"../Model/IFilterParams\";\nimport { CheckpointRating } from \"../Model/CheckpointRating\";\n\nexport interface IProps {\n readonly params: IFilterParams;\n\n readonly onChange: (params: IFilterParams) => void;\n}\n\nfunction renderClasses(props: IProps): React.ReactElement {\n const selectedClasses = props.params.selectedClasses;\n\n const handleClassChange = (event: React.ChangeEvent, type: ClassType) => {\n const newClasses = new Set(selectedClasses);\n\n if (event.target.checked) {\n newClasses.add(type);\n } else {\n newClasses.delete(type);\n }\n\n const newParams: IFilterParams = {\n ...props.params,\n selectedClasses: newClasses\n };\n\n props.onChange(newParams);\n };\n\n return (\n <>\n Classes\n handleClassChange(e, ClassType.FourByFour)} />\n }/>\n\n handleClassChange(e, ClassType.XCross)} />\n }/>\n \n )\n}\n\nfunction renderRatings(props: IProps): React.ReactElement {\n const selectedRatings = props.params.selectedRatings;\n\n const handleRatingChange = (event: React.ChangeEvent, type: CheckpointRating) => {\n const newRatings = new Set(selectedRatings);\n\n if (event.target.checked) {\n newRatings.add(type);\n } else {\n newRatings.delete(type);\n }\n\n const newParams: IFilterParams = {\n ...props.params,\n selectedRatings: newRatings\n };\n\n props.onChange(newParams);\n };\n\n return (\n <>\n Ratings\n handleRatingChange(e, CheckpointRating.Basecamp)} />\n }/>\n\n handleRatingChange(e, CheckpointRating.Green)} />\n }/>\n\n handleRatingChange(e, CheckpointRating.Blue)} />\n }/>\n\n handleRatingChange(e, CheckpointRating.Black)} />\n }/>\n \n )\n}\n\nfunction renderYears(props: IProps): React.ReactElement {\n const selectedYears = props.params.selectedYears;\n\n const handleYearChange = (event: React.ChangeEvent, year: number) => {\n const newYears = new Set(selectedYears);\n\n if (event.target.checked) {\n newYears.add(year);\n } else {\n newYears.delete(year);\n }\n\n const newParams: IFilterParams = {\n ...props.params,\n selectedYears: newYears\n };\n\n props.onChange(newParams);\n };\n\n const yearsArray = Array.from(props.params.allYears);\n\n yearsArray.sort();\n\n const yearElements = yearsArray.map((year, index) => (\n handleYearChange(e, year)} />\n }/>\n ));\n\n return (\n <>\n Years\n {yearElements}\n \n )\n}\n\nexport function Filter(props: IProps): React.ReactElement {\n return (\n \n \n {renderClasses(props)}\n {renderRatings(props)}\n {renderYears(props)}\n \n \n )\n}","import { ClassType } from \"../Model/ClassType\";\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\nimport { IFilterParams } from \"../Model/IFilterParams\";\nimport { CheckpointRating } from \"../Model/CheckpointRating\";\n\nconst AllRatings = new Set([\n CheckpointRating.Basecamp,\n CheckpointRating.Green,\n CheckpointRating.Blue,\n CheckpointRating.Black\n]);\n\nconst AllClasses = new Set([ClassType.XCross, ClassType.FourByFour]);\n\nexport class FilterParamsHelper {\n public static createDefault(): IFilterParams {\n return {\n allYears: new Set(),\n selectedYears: new Set(),\n selectedRatings: AllRatings,\n selectedClasses: AllClasses\n }\n }\n\n public static create(checkpoints: ReadonlyArray): IFilterParams {\n const allYearsSet = new Set(checkpoints.map(c => c.year));\n const allClassesSet = new Set(checkpoints.map(c => c.class ?? ClassType.FourByFour));\n\n return {\n allYears: allYearsSet,\n selectedYears: allYearsSet,\n selectedRatings: AllRatings,\n selectedClasses: allClassesSet\n }\n }\n\n public static update(params: IFilterParams, checkpoints: ReadonlyArray): IFilterParams {\n const allYears = new Set(checkpoints.map(c => c.year));\n const selectedYears = new Set(params.selectedYears);\n\n const allClasses = new Set(checkpoints.map(c => c.class ?? ClassType.FourByFour));\n const selectedClasses = new Set(params.selectedClasses);\n\n // If we get a new year add it to the selected years\n if (params.allYears.size < allYears.size) {\n allYears.forEach(year => {\n if (!params.allYears.has(year)) {\n selectedYears.add(year);\n }\n });\n }\n\n // If we get a new class add it to the selected classes\n if (params.selectedClasses.size < allClasses.size) {\n allClasses.forEach(c => {\n if (!params.selectedClasses.has(c)) {\n selectedClasses.add(c);\n }\n });\n }\n\n return {\n ...params,\n allYears,\n selectedYears,\n selectedClasses\n };\n }\n\n public static filter(params: IFilterParams, checkpoints: ReadonlyArray): ICheckpoint[] {\n return checkpoints.filter(checkpoint =>\n params.selectedRatings.has(checkpoint.rating) && params.selectedYears.has(checkpoint.year));\n }\n}","import { IAppState } from \"../../Model/IAppState\";\nimport { IFilterParams } from \"../../Model/IFilterParams\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { FilterParamsHelper } from \"../../Utility/FilterParamsHelper\";\n\nfunction reducer(state: IAppState, params: IFilterParams): IAppState {\n return {\n ...state,\n filterParams: params,\n filteredCheckpoints: FilterParamsHelper.filter(params, state.allCheckpoints)\n };\n}\n\nexport const setFilterParams = ActionRegistry.addReducer(\"setFilterParams\", reducer);","import React from \"react\";\n\nimport { Filter } from \"./Filter\";\n\nimport { SideDrawer } from \"./SideDrawer\";\n\nimport { AppContext } from \"../AppContext\";\n\nimport { DrawerType } from \"../Model/DrawerType\";\nimport { setFilterParams } from \"../State/Actions/setFilterParams\";\n\nexport function FilterDrawer(): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n return (\n \n setFilterParams(dispatch, params)}/>\n \n );\n}","export class CoordinateHelper {\n public static tryConvert(latStr: string, longStr: string): google.maps.LatLngLiteral | undefined {\n const lat = CoordinateHelper.tryParseCoordinate(latStr);\n if (lat === undefined) {\n return undefined;\n }\n \n if (lat < -90 || lat > 90) {\n return undefined;\n }\n \n const lng = CoordinateHelper.tryParseCoordinate(longStr);\n if (lng === undefined) {\n return undefined;\n }\n \n if (lng < -180 || lng > 180) {\n return undefined;\n }\n \n const res: google.maps.LatLngLiteral = {\n lat,\n lng\n };\n \n return res;\n }\n\n public static move(latLng: google.maps.LatLngLiteral, distanceKm: number, heading: number): google.maps.LatLngLiteral {\n const earthRadiusMeters = 6371000;\n const startLatRads = CoordinateHelper.degToRad(latLng.lat);\n const distanceMeters = distanceKm * 1000;\n const angularDistance = distanceMeters / earthRadiusMeters;\n const headingRads = CoordinateHelper.degToRad(heading);\n\n const lat = Math.asin(\n (Math.sin(startLatRads) * Math.cos(angularDistance)) +\n (Math.cos(startLatRads) * Math.sin(angularDistance) * Math.cos(headingRads)));\n\n const lng = latLng.lng + CoordinateHelper.radToDeg(\n Math.atan2(\n Math.sin(headingRads) * Math.sin(angularDistance) * Math.cos(startLatRads),\n Math.cos(angularDistance) - (Math.sin(startLatRads) * Math.sin(lat))));\n\n return {\n lat: CoordinateHelper.radToDeg(lat),\n lng\n };\n }\n\n \n private static degToRad(degrees: number): number {\n return degrees * (Math.PI / 180.0);\n }\n\n private static radToDeg(radians: number): number {\n return radians * (180.0 / Math.PI);\n }\n\n private static tryParseCoordinate(str: string): number | undefined {\n let cleanStr = str.trim().toLocaleLowerCase();\n if (cleanStr.length === 0) {\n return undefined;\n }\n \n const parts = cleanStr.split(\" \");\n if (parts.length !== 2) {\n return undefined;\n }\n \n let degrees = parseInt(parts[0]);\n if (isNaN(degrees)) {\n return undefined;\n }\n\n const sign = Math.sign(degrees);\n\n degrees = Math.abs(degrees);\n \n const minutesDecimal = parseFloat(parts[1]);\n if (isNaN(minutesDecimal) || minutesDecimal < 0) {\n return undefined;\n }\n \n const minutes = Math.floor(minutesDecimal) / 60;\n const seconds = ((minutesDecimal - Math.floor(minutesDecimal)) * 60) / 3600;\n \n return sign * (degrees + minutes + seconds);\n }\n}","import React from \"react\";\nimport { nanoid } from \"nanoid\";\n\nimport { Button, FormControl, InputLabel, MenuItem, Select, SelectChangeEvent, Stack, TextField } from \"@mui/material\";\n\nimport { ClassType } from \"../Model/ClassType\";\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\nimport { CheckpointRating } from \"../Model/CheckpointRating\";\n\nimport { CoordinateHelper } from \"../Utility/CoordinateHelper\";\n\nexport interface IProps {\n readonly onAdd: (checkpoint: ICheckpoint) => void;\n}\n\nconst StateKey = \"checkpointDrawerState\";\n\ntype Direction = \"to\" | \"from\";\n\ninterface IState {\n readonly class: ClassType;\n readonly year: string;\n readonly competitionDay: string;\n readonly name: string;\n readonly rating: CheckpointRating;\n\n readonly lat: string;\n readonly lng: string;\n\n readonly distance: string;\n readonly heading: string;\n readonly direction: Direction;\n}\n\nconst EmptyState: IState = {\n year: \"\",\n class: ClassType.FourByFour,\n competitionDay: \"\",\n name: \"\",\n rating: CheckpointRating.Basecamp,\n\n lat: \"\",\n lng: \"\",\n\n distance: \"\",\n heading: \"\",\n direction: \"from\"\n};\n\nfunction nameof(key: keyof T): keyof T {\n return key;\n}\n\nfunction tryCreateCheckpoint(state: IState): ICheckpoint {\n const errors = new Set();\n\n const year = parseInt(state.year);\n if (isNaN(year) || year <= 0) {\n errors.add(nameof(\"year\"));\n }\n\n const competitionDay = parseInt(state.competitionDay);\n if (isNaN(competitionDay) || competitionDay <= 0) {\n errors.add(nameof(\"competitionDay\"));\n }\n\n if (state.name === undefined || state.name.length === 0) {\n errors.add(nameof(\"name\"));\n }\n\n if (state.rating === undefined) {\n errors.add(nameof(\"rating\"));\n }\n\n let coord = CoordinateHelper.tryConvert(state.lat, state.lng);\n if (coord === undefined) {\n errors.add(nameof(\"lat\"));\n errors.add(nameof(\"lng\"));\n }\n\n let distance = NaN;\n let heading = NaN;\n let validDistance = false;\n let validHeading = false;\n if (state.distance.length !== 0 && state.heading.length !== 0 && state.direction.length !== 0) {\n distance = parseFloat(state.distance);\n heading = parseFloat(state.heading);\n\n validDistance = !isNaN(distance);\n validHeading = !isNaN(heading);\n\n if (!validDistance) {\n errors.add(nameof(\"distance\"));\n }\n\n if (!validHeading) {\n errors.add(nameof(\"heading\"));\n }\n\n if (!validDistance || !validHeading) {\n distance = heading = NaN;\n validDistance = validHeading = false;\n }\n }\n\n if (validDistance && validHeading && coord) {\n if (state.direction === \"from\") {\n coord = CoordinateHelper.move(coord, distance, heading);\n } else if (state.direction === \"to\") {\n coord = CoordinateHelper.move(coord, distance, heading - 180);\n } else {\n errors.add(nameof(\"direction\"));\n }\n }\n\n if (errors.size !== 0) {\n throw errors;\n }\n\n return {\n id: nanoid(),\n class: state.class,\n year,\n competitionDay,\n name: state.name!,\n rating: state.rating!,\n lat: coord!.lat,\n lng: coord!.lng\n }\n}\n\nexport function AddCheckpoint(props: IProps): React.ReactElement {\n const [state, setState] = React.useState(() => {\n const json = localStorage.getItem(StateKey);\n if (json) {\n return JSON.parse(json) as IState;\n } else {\n return EmptyState;\n }\n });\n\n React.useEffect(() => {\n return function() {\n localStorage.setItem(StateKey, JSON.stringify(state));\n }\n },\n [state]);\n\n\n const [errors, setErrors] = React.useState>(new Set());\n\n const onChange = (name: string, event: React.ChangeEvent) => {\n setState({ ...state, [name]: event.target.value });\n };\n\n const onClassChange = (event: SelectChangeEvent) => {\n setState({ ...state, class: event.target.value as ClassType });\n };\n\n const onRatingChange = (event: SelectChangeEvent) => {\n setState({ ...state, rating: event.target.value as CheckpointRating });\n };\n\n const onDirectionChange = (event: SelectChangeEvent) => {\n setState({ ...state, direction: event.target.value as Direction });\n };\n\n const onAdd = () => {\n try {\n const checkpoint = tryCreateCheckpoint(state);\n\n props.onAdd(checkpoint);\n setErrors(new Set());\n } catch (e) {\n setErrors(e as Set);\n }\n };\n\n return (\n \n \n Class\n \n {ClassType.FourByFour}\n {ClassType.XCross}\n \n \n\n (\"year\"))}\n onChange={e => onChange(nameof(\"year\"), e)}\n value={state.year} />\n\n (\"competitionDay\"))}\n onChange={e => onChange(nameof(\"competitionDay\"), e)}\n value={state.competitionDay} />\n\n (\"name\"))}\n onChange={e => onChange(nameof(\"name\"), e)}\n value={state.name} />\n\n \n Rating\n \n Basecamp\n Green\n Blue\n Black\n \n \n\n (\"lat\"))}\n onChange={e => onChange(nameof(\"lat\"), e)}\n value={state.lat} />\n\n (\"lng\"))}\n onChange={e => onChange(nameof(\"lng\"), e)}\n value={state.lng} />\n\n (\"distance\"))}\n onChange={e => onChange(nameof(\"distance\"), e)}\n value={state.distance} />\n\n (\"heading\"))}\n onChange={e => onChange(nameof(\"heading\"), e)}\n value={state.heading} />\n\n \n Direction\n \n From\n To\n \n \n\n \n \n );\n}\n","import { IAppState } from \"../../Model/IAppState\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nfunction reducer(state: IAppState, busy: boolean): IAppState {\n return { ...state, busy };\n}\n\nexport const setBusy = ActionRegistry.addReducer(\"setBusy\", reducer);","import { IAppState } from \"../../Model/IAppState\";\nimport { ICheckpoint } from \"../../Model/ICheckpoint\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { FilterParamsHelper } from \"../../Utility/FilterParamsHelper\";\n\nfunction reducer(state: IAppState, checkpoints: ReadonlyArray): IAppState {\n const newFilterParams = FilterParamsHelper.update(state.filterParams, checkpoints);\n const filteredCheckpoints = FilterParamsHelper.filter(newFilterParams, checkpoints);\n\n return {\n ...state,\n filteredCheckpoints,\n allCheckpoints: checkpoints,\n filterParams: newFilterParams,\n };\n}\n\nexport const setCheckpoints = ActionRegistry.addReducer(\"setCheckpoints\", reducer);","import { IAppState } from \"../../Model/IAppState\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nfunction reducer(state: IAppState, message: string): IAppState {\n return { ...state, errorMessage: message };\n}\n\nexport const setErrorMessage = ActionRegistry.addReducer(\"setErrorMessage\", reducer);","import { ActionRegistry } from \"../ActionRegistry\";\n\nimport { IAppState } from \"../../Model/IAppState\";\nimport { ILatLngLocation } from \"../../Model/ILatLngLocation\";\n\nfunction reducer(state: IAppState, location: ILatLngLocation): IAppState {\n return { ...state, cameraLocation: location };\n}\n\nexport const setCameraLocation = ActionRegistry.addReducer(\"setCameraLocation\", reducer);","import axios from \"axios\";\n\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\n\nconst CheckpointsEndpoint = \"api/checkpoints\";\n\nexport class CheckpointStore {\n public static async load(): Promise {\n const result = await axios.get(CheckpointsEndpoint);\n\n return result.data;\n }\n \n public static async save(token: string, checkpoints: ReadonlyArray): Promise {\n const config = {\n headers: {\n Authorization: `Bearer ${token}`\n }\n }\n \n await axios.post(CheckpointsEndpoint, JSON.stringify(checkpoints), config);\n }\n}","import { ICheckpoint } from \"../Model/ICheckpoint\";\n\nexport class CheckpointHelper {\n public static isDuplicate(checkpoint: ICheckpoint, checkpoints: ReadonlyArray): boolean {\n for (const point of checkpoints) {\n const dlat = checkpoint.lat - point.lat;\n const dlng = checkpoint.lng - point.lng;\n const distance = Math.sqrt((dlat * dlat) + (dlng * dlng));\n\n if (distance <= Number.EPSILON) {\n return true;\n }\n }\n\n return false;\n }\n}","import { setBusy } from \"./setBusy\";\nimport { setDrawerState } from \"./setDrawerState\";\nimport { setCheckpoints } from \"./setCheckpoints\";\nimport { setErrorMessage } from \"./setErrorMessage\";\nimport { setCameraLocation } from \"./setCameraLocation\";\n\nimport { Action } from \"../Action\";\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { DrawerType } from \"../../Model/DrawerType\";\nimport { ICheckpoint } from \"../../Model/ICheckpoint\";\n\nimport { CheckpointStore } from \"../../Utility/CheckpointStore\";\nimport { CheckpointHelper } from \"../../Utility/CheckpointHelper\";\n\nasync function add(\n dispatch: React.Dispatch,\n token: string,\n checkpoint: ICheckpoint,\n checkpoints: ReadonlyArray): Promise {\n\n if (token.trim().length === 0) {\n setErrorMessage(dispatch, \"You must log in before adding checkpoints!\");\n return;\n }\n\n if (CheckpointHelper.isDuplicate(checkpoint, checkpoints)) {\n setErrorMessage(dispatch, \"Duplicate checkpoint detected!\");\n return;\n }\n\n setBusy(dispatch, true);\n\n setDrawerState(dispatch, DrawerType.AddItem, false);\n\n try {\n const newCheckpoints = [...checkpoints, checkpoint];\n\n await CheckpointStore.save(token, newCheckpoints);\n\n setCameraLocation(dispatch, checkpoint);\n setCheckpoints(dispatch, newCheckpoints);\n } catch {\n setErrorMessage(dispatch, \"Failed to save checkpoints!\");\n }\n\n setBusy(dispatch, false);\n}\n\nexport const addCheckpoint = ActionRegistry.addDispatcher(\"addCheckpoint\", add);","import React from \"react\";\n\nimport { AppContext } from \"../AppContext\";\n\nimport { SideDrawer } from \"./SideDrawer\";\nimport { AddCheckpoint } from \"./AddCheckpoint\";\n\nimport { DrawerType } from \"../Model/DrawerType\";\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\n\nimport { addCheckpoint } from \"../State/Actions/addCheckpoint\";\n\nexport function AddCheckpointDrawer(): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n const onAddCheckpoint = (checkpoint: ICheckpoint) => {\n if (state.busy) {\n return;\n }\n\n addCheckpoint(dispatch, state.loginToken, checkpoint, state.allCheckpoints);\n };\n\n return (\n \n \n \n );\n}","import React from \"react\";\n\nimport { Button, Stack, TextField } from \"@mui/material\";\n\nimport { ClassType } from \"../Model/ClassType\";\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\n\nexport interface IProps {\n readonly checkpoint: ICheckpoint;\n\n readonly onRemove: (checkpoint: ICheckpoint) => void;\n}\n\nconst InputProps = {\n readOnly: true\n};\n\nexport function CheckpointProperties(props: IProps): React.ReactElement {\n const checkpoint = props.checkpoint;\n\n return (\n \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n \n );\n}\n","import { setBusy } from \"./setBusy\";\nimport { setDrawerState } from \"./setDrawerState\";\nimport { setCheckpoints } from \"./setCheckpoints\";\nimport { setErrorMessage } from \"./setErrorMessage\";\n\nimport { Action } from \"../Action\";\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { DrawerType } from \"../../Model/DrawerType\";\nimport { ICheckpoint } from \"../../Model/ICheckpoint\";\n\nimport { CheckpointStore } from \"../../Utility/CheckpointStore\";\n\nasync function remove(\n dispatch: React.Dispatch,\n token: string,\n checkpoint: ICheckpoint,\n checkpoints: ReadonlyArray): Promise {\n\n if (token.trim().length === 0) {\n setErrorMessage(dispatch, \"You must log in before removing checkpoints!\");\n return;\n }\n\n setBusy(dispatch, true);\n\n setDrawerState(dispatch, DrawerType.Properties, false);\n\n try {\n const newCheckpoints = checkpoints.filter(c => c !== checkpoint);\n\n await CheckpointStore.save(token, newCheckpoints);\n\n setCheckpoints(dispatch, newCheckpoints);\n } catch {\n setErrorMessage(dispatch, \"Failed to save checkpoints!\");\n }\n\n setBusy(dispatch, false);\n}\n\nexport const removeCheckpoint = ActionRegistry.addDispatcher(\"removeCheckpoint\", remove);","import React from \"react\";\n\nimport { SideDrawer } from \"./SideDrawer\";\n\nimport { AppContext } from \"../AppContext\";\n\nimport { DrawerType } from \"../Model/DrawerType\";\nimport { ICheckpoint } from \"../Model/ICheckpoint\";\n\nimport { CheckpointProperties } from \"./CheckpointProperties\";\n\nimport { removeCheckpoint } from \"../State/Actions/removeCheckpoint\";\n\nexport function CheckpointPropertiesDrawer(): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n const onCheckpointRemove = async (checkpoint: ICheckpoint) => {\n if (state.busy) {\n return;\n }\n\n removeCheckpoint(dispatch, state.loginToken, checkpoint, state.allCheckpoints);\n }\n\n return (\n \n {state.selectedCheckpoint &&\n \n }\n \n );\n}","import React from \"react\";\n\nimport { LoginDrawer } from \"./LoginDrawer\";\nimport { FilterDrawer } from \"./FilterDrawer\";\nimport { AddCheckpointDrawer } from \"./AddCheckpointDrawer\";\nimport { CheckpointPropertiesDrawer } from \"./CheckpointPropertiesDrawer\";\n\nexport function Drawers(): React.ReactElement {\n return (\n <>\n \n \n \n \n \n );\n}","import { ICheckpoint } from \"../../Model/ICheckpoint\";\nimport { CheckpointRating } from \"../../Model/CheckpointRating\";\n\nfunction createMarker(checkpoint: ICheckpoint, map: google.maps.Map): google.maps.Marker {\n const coord: google.maps.LatLngLiteral = {\n lat: checkpoint.lat,\n lng: checkpoint.lng,\n };\n\n let url: string | undefined = undefined;\n switch (checkpoint.rating) {\n case CheckpointRating.Basecamp:\n url = \"rating-basecamp.png\";\n break;\n case CheckpointRating.Green:\n url = \"rating-green.png\";\n break;\n case CheckpointRating.Blue:\n url = \"rating-blue.png\";\n break;\n case CheckpointRating.Black:\n url = \"rating-black.png\";\n break;\n }\n \n return new google.maps.Marker({\n map,\n position: coord,\n icon: {\n url,\n labelOrigin: new google.maps.Point(11 / 2.0, -7)\n },\n title: checkpoint.name,\n label: checkpoint.name,\n });\n}\n\nexport class GoogleMapWrapper {\n private readonly map: google.maps.Map;\n private readonly markers = new Map();\n private readonly onCheckpointClicked: (checkpoint: ICheckpoint) => void;\n\n constructor(target: HTMLDivElement, zoom: number, center: google.maps.LatLngLiteral, onCheckpointClicked: (checkpoint: ICheckpoint) => void) {\n this.map = new google.maps.Map(target, {\n center,\n zoom\n });\n\n this.onCheckpointClicked = onCheckpointClicked;\n }\n\n public setZoom(zoom: number) {\n this.map.setZoom(zoom);\n }\n\n public setCenter(center: google.maps.LatLngLiteral) {\n this.map.setCenter(center);\n }\n\n public updateMarkers(checkpoints: ReadonlyArray) {\n const markerIdsToRemove = new Set(this.markers.keys());\n\n for (const checkpoint of checkpoints) {\n const id = checkpoint.id;\n\n markerIdsToRemove.delete(id);\n\n if (this.markers.has(id)) {\n continue;\n }\n\n const marker = createMarker(checkpoint, this.map);\n\n marker.addListener(\"click\", () => this.onCheckpointClicked(checkpoint));\n\n this.markers.set(id, marker);\n }\n\n markerIdsToRemove.forEach(id => {\n const marker = this.markers.get(id);\n\n marker!.setMap(null);\n this.markers.delete(id);\n });\n }\n}","import React from \"react\";\n\nimport { ICheckpoint } from \"../../Model/ICheckpoint\";\nimport { ILatLngLocation } from \"../../Model/ILatLngLocation\";\n\nimport { GoogleMapWrapper } from \"./GoogleMapWrapper\";\n\nexport interface IProps {\n readonly zoom: number;\n readonly center: ILatLngLocation;\n\n readonly checkpoints: ReadonlyArray;\n\n readonly onCheckpointClicked: (checkpoint: ICheckpoint) => void;\n}\n\nexport function CheckpointMap(props: IProps): React.ReactElement {\n const ref = React.useRef(null);\n const [map, setMap] = React.useState(null);\n\n const center = props.center;\n const checkpoints = props.checkpoints;\n\n React.useEffect(() => {\n if (ref.current === null) {\n return;\n }\n\n if (map !== null) {\n return;\n }\n\n setMap(new GoogleMapWrapper(ref.current, props.zoom, center, props.onCheckpointClicked));\n },\n [ref, map, center, props.onCheckpointClicked, props.zoom]);\n\n React.useEffect(() => map?.updateMarkers(checkpoints), [map, checkpoints]);\n React.useEffect(() => map?.setCenter(center), [map, center]);\n\n return (\n
\n )\n}","import { IAppState } from \"../../Model/IAppState\";\nimport { ICheckpoint } from \"../../Model/ICheckpoint\";\n\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nfunction reducer(state: IAppState, selectedCheckpoint: ICheckpoint | null): IAppState {\n return { ...state, selectedCheckpoint }\n}\n\nexport const setSelectedCheckpoint = ActionRegistry.addReducer(\"setSelectedCheckpoint\", reducer);","import React from \"react\";\n\nimport { Alert, AlertTitle, Box, LinearProgress, Snackbar, SxProps } from \"@mui/material\";\n\nimport { AppContext } from \"./AppContext\";\n\nimport { TopNav } from \"./Component/TopNav\";\nimport { Drawers } from \"./Component/Drawers\";\nimport { CheckpointMap } from \"./Component/CheckpointMap\";\n\nimport { DrawerType } from \"./Model/DrawerType\";\nimport { ICheckpoint } from \"./Model/ICheckpoint\";\nimport { setErrorMessage } from \"./State/Actions/setErrorMessage\";\nimport { setDrawerState } from \"./State/Actions/setDrawerState\";\nimport { setSelectedCheckpoint } from \"./State/Actions/setSelectedCheckpoint\";\n\nconst TopNavItems = [\n {\n name: \"Add\",\n value: DrawerType.AddItem\n },\n {\n name: \"Filter\",\n value: DrawerType.Filter\n },\n {\n name: \"Login\",\n value: DrawerType.Login\n }\n];\n\nexport function App(): React.ReactElement {\n const { state, dispatch } = React.useContext(AppContext);\n\n const boxStyle: SxProps = {\n display: \"flex\",\n flexDirection: \"column\",\n\n width: \"100%\",\n height: \"100%\"\n };\n\n const onNavItemClicked = (value: DrawerType) => setDrawerState(dispatch, value, true);\n\n const onClearError = () => setErrorMessage(dispatch, \"\");\n\n const onCheckpointClicked = (checkpoint: ICheckpoint) => {\n setSelectedCheckpoint(dispatch, checkpoint);\n\n setDrawerState(dispatch, DrawerType.Properties, true);\n }\n\n return (\n \n {state.busy && }\n \n\n \n \n \n\n \n \n Error\n {state.errorMessage}\n \n \n \n );\n}","import { setBusy } from \"./setBusy\";\nimport { setCheckpoints } from \"./setCheckpoints\";\nimport { setErrorMessage } from \"./setErrorMessage\";\nimport { setFilterParams } from \"./setFilterParams\";\nimport { setCameraLocation } from \"./setCameraLocation\";\n\nimport { Action } from \"../Action\";\nimport { ActionRegistry } from \"../ActionRegistry\";\n\nimport { CheckpointStore } from \"../../Utility/CheckpointStore\";\nimport { FilterParamsHelper } from \"../../Utility/FilterParamsHelper\";\n\nasync function initialize(dispatch: React.Dispatch): Promise {\n setBusy(dispatch, true);\n\n try {\n const checkpoints = await CheckpointStore.load();\n\n if (checkpoints.length !== 0) {\n setCameraLocation(dispatch, checkpoints[0]);\n setFilterParams(dispatch, FilterParamsHelper.create(checkpoints));\n }\n\n setCheckpoints(dispatch, checkpoints);\n } catch {\n setErrorMessage(dispatch, \"Failed to load checkpoints!\");\n }\n\n setBusy(dispatch, false);\n}\n\nexport const initializeApp = ActionRegistry.addDispatcher(\"initializeApp\", initialize);","import React from \"react\";\n\nimport { Action } from \"./Action\";\nimport { ActionRegistry } from \"./ActionRegistry\";\n\nimport { initializeApp } from \"./Actions/initializeApp\";\n\nimport { IAppState } from \"../Model/IAppState\";\nimport { DrawerType } from \"../Model/DrawerType\";\n\nimport { LoginTokenStore } from \"../Utility/LoginTokenStore\";\nimport { FilterParamsHelper } from \"../Utility/FilterParamsHelper\";\n\nconst DefaultState: IAppState = {\n busy: false,\n\n errorMessage: \"\",\n loginToken: LoginTokenStore.load(),\n\n allCheckpoints: [],\n filteredCheckpoints: [],\n\n selectedCheckpoint: null,\n\n cameraLocation: { lat: 39.0968, lng: -120.0324 },\n\n drawerState: new Map(),\n\n filterParams: FilterParamsHelper.createDefault()\n};\n\nfunction reducer(state: IAppState, action: Action): IAppState {\n const reducerForType = ActionRegistry.getReducer(action.type);\n if (reducerForType === undefined) {\n return state;\n }\n\n return reducerForType(state, ...action.args);\n}\n\nfunction dispatchMiddleware(dispatch: React.Dispatch) {\n return (action: Action) => {\n const dispatcherForType = ActionRegistry.getDispatcher(action.type);\n if (dispatcherForType === undefined) {\n dispatch(action);\n } else {\n dispatcherForType(dispatch, ...action.args)\n }\n }\n}\n\nexport function useAppState(): [IAppState, React.Dispatch] {\n const [state, baseDispatch] = React.useReducer(reducer, DefaultState);\n const dispatch = React.useMemo(() => dispatchMiddleware(baseDispatch), [baseDispatch]);\n\n React.useEffect(() => initializeApp(dispatch), [dispatch]);\n\n return [state, dispatch];\n}","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport { App } from \"./App\";\nimport { AppContext } from \"./AppContext\";\n\nimport { useAppState } from \"./State/useAppState\";\n\nfunction AppContainer(): React.ReactElement {\n const [state, dispatch] = useAppState();\n\n return (\n \n \n \n \n \n );\n}\n\nReactDOM.render(, document.getElementById('root'));"],"sourceRoot":""}