{"version":3,"sources":["utils/isElectron.ts","utils/localStorageHelpers.ts","utils/flatMap.ts","interview-engine/useInterview.ts","interview-engine/useInterviewActions.ts","interview-engine/helpers.ts","utils/fileUtils.ts","interview-engine/loadSaveInterview.ts","InterviewContext.tsx","interview-engine/useActivities.ts","i18n/i18n.ts","components/Navigation.tsx","App.tsx","index.tsx","components/Loading.tsx"],"names":["isElectron","window","process","type","versions","electron","navigator","userAgent","indexOf","getFromLocalStorage","key","item","localStorage","getItem","JSON","parse","error","console","storeToLocalStorage","value","setItem","stringify","deleteFromLocalStorage","removeItem","flatMap","array","transformer","reduce","x","y","initialState","interviewStarted","abandonInterviewRequested","engine","state","action","interview","Error","reducers","newState","interviewName","INTERVIEW_LOCAL_STORAGE_KEY","aqi","actionParams","answeredTopic","topics","find","t","topicID","toLowerCase","topicId","answeredQuestion","questions","q","questionID","questionId","chosenChoice","choices","c","choiceID","choiceId","forEach","selected","isBelow","isAnswered","isCurrentQuestion","comment","resultPanels","rp","results","result","toRemoveIndex","resultPanelName","findIndex","r","resultID","splice","NOTCOMP","push","resultText","shortName","embeddedLinks","resultOrder","skipEvaluation","selectedChoices","filter","selectedChoiceResultPanels","minPanelPrecedent","Math","min","map","panelPrecedence","query","length","current","endTopic","notCompResults","nextQuestion","findQuestion","alreadyExists","DEC","NOT","sort","a","b","localeCompare","element","index","undefined","reallyAbandon","File","FileReader","FileList","Blob","fileAsText","input","reader","Promise","resolve","reject","onerror","abort","onload","files","readAsText","loadInterview","text","validateSavedInterview","savedInterview","savedInterviewString","activities","validateInterview","validateActivities","object","isMultiInterview","Array","isArray","resultValues","activity","id","article","name","comments","InterviewContext","React","createContext","interviewState","startInterview","_","changeInterviewName","answerQuestion","abandonInterview","confirmAbandonInterview","addActivity","updateActivity","removeActivity","clearAllActivities","restoreActivities","saveInterview","InterviewContextProvider","children","useReducer","dispatch","useEffect","storedState","answer","useInterview","activityState","useState","setActivities","random","toString","useActivities","loadInterviewWrapper","Provider","asString","blob","saveAs","availableLanguages","abbreviation","Set","i18n","use","Backend","LanguageDetector","initReactI18next","init","load","fallbackLng","keySeparator","interpolation","escapeValue","whitelist","l","nonExplicitWhitelist","saveMissing","missingKeyHandler","detection","order","Navigation","useTranslation","isOpen","setIsOpen","Navbar","expand","className","light","tag","NavbarBrand","to","RRNavLink","src","alt","NavbarToggler","onClick","Collapse","navbar","Nav","NavItem","NavLink","UncontrolledDropdown","nav","inNavbar","DropdownToggle","caret","DropdownMenu","right","DropdownItem","ActivityArea","lazy","ActivityReport","Contact","Downloads","FAQ","Footer","HelpArea","Home","InterviewArea","InterviewInProgress","InterviewReport","Video","Router","App","fallback","Loading","Container","fluid","path","exact","component","render","Component","ReactDOM","document","getElementById"],"mappings":"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","file":"static/js/main.163c7ec2.chunk.js","sourcesContent":["export default function isElectron() {\r\n // Renderer process\r\n if (\r\n typeof window !== \"undefined\" &&\r\n // @ts-ignore\r\n typeof window.process === \"object\" &&\r\n // @ts-ignore\r\n window.process.type === \"renderer\"\r\n ) {\r\n return true;\r\n }\r\n\r\n // Main process\r\n if (\r\n typeof process !== \"undefined\" &&\r\n typeof process.versions === \"object\" &&\r\n // @ts-ignore\r\n !!process.versions.electron\r\n ) {\r\n return true;\r\n }\r\n\r\n // Detect the user agent when the `nodeIntegration` option is set to true\r\n if (\r\n typeof navigator === \"object\" &&\r\n typeof navigator.userAgent === \"string\" &&\r\n navigator.userAgent.indexOf(\"Electron\") >= 0\r\n ) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n","export function getFromLocalStorage(key: string): T | undefined {\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item) {\r\n return JSON.parse(item);\r\n } else {\r\n return undefined;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n return undefined;\r\n }\r\n}\r\n\r\nexport function storeToLocalStorage(key: string, value: T) {\r\n window.localStorage.setItem(key, JSON.stringify(value));\r\n}\r\n\r\nexport function deleteFromLocalStorage(key: string) {\r\n window.localStorage.removeItem(key);\r\n}\r\n","export function flatMap(array: T[], transformer: (x: T) => U[]): U[] {\r\n return array.reduce((x, y) => [...x, ...transformer(y)], [] as U[]);\r\n}\r\n","import { useReducer, useEffect } from \"react\";\r\nimport { Interview } from \"./Interview\";\r\nimport { getFromLocalStorage } from \"../utils/localStorageHelpers\";\r\nimport * as reducers from \"./useInterviewActions\";\r\n\r\nexport interface State {\r\n interviewStarted: boolean;\r\n abandonInterviewRequested: boolean;\r\n interview?: Interview;\r\n}\r\n\r\nexport type StartInterviewAction = {\r\n type: \"startInterview\";\r\n interview: Interview;\r\n};\r\nexport type ChangeInterviewNameAction = {\r\n type: \"changeInterviewName\";\r\n interviewName: string;\r\n};\r\nexport type AnswerQuestionAction = {\r\n type: \"answerQuestion\";\r\n actionParams: AnswerQuestionActionParams;\r\n};\r\nexport type AbandonInterviewAction = { type: \"abandonInterview\" };\r\nexport type ConfirmAbandonInterviewAction = {\r\n type: \"confirmAbandonInterview\";\r\n reallyAbandon: boolean;\r\n};\r\n\r\nexport type EngineAction =\r\n | StartInterviewAction\r\n | ChangeInterviewNameAction\r\n | AnswerQuestionAction\r\n | AbandonInterviewAction\r\n | ConfirmAbandonInterviewAction;\r\n\r\nexport interface AnswerQuestionActionParams {\r\n topicId: string;\r\n questionId: string;\r\n choiceId: string;\r\n}\r\n\r\nconst initialState: State = {\r\n interviewStarted: false,\r\n abandonInterviewRequested: false\r\n};\r\nexport { initialState };\r\n\r\nexport function engine(state: State, action: EngineAction): State {\r\n switch (action.type) {\r\n case \"startInterview\":\r\n return reducers.startInterview(state, action);\r\n\r\n case \"changeInterviewName\":\r\n return reducers.changeInterviewName(state, action);\r\n\r\n case \"answerQuestion\":\r\n return reducers.answerQuestion(state, action);\r\n\r\n case \"abandonInterview\":\r\n return reducers.abandonInterview(state, action);\r\n\r\n case \"confirmAbandonInterview\":\r\n return reducers.confirmAbandonInterview(state, action);\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport const INTERVIEW_LOCAL_STORAGE_KEY = \"INTERVIEW\";\r\n\r\nexport default function useInterview() {\r\n const [interviewState, dispatch] = useReducer(engine, initialState);\r\n\r\n const startInterview = (interview: Interview) =>\r\n dispatch({ type: \"startInterview\", interview });\r\n\r\n const changeInterviewName = (interviewName: string) =>\r\n dispatch({ type: \"changeInterviewName\", interviewName });\r\n\r\n const answerQuestion = (answer: AnswerQuestionActionParams) =>\r\n dispatch({ type: \"answerQuestion\", actionParams: answer });\r\n\r\n const abandonInterview = () => dispatch({ type: \"abandonInterview\" });\r\n\r\n const confirmAbandonInterview = (reallyAbandon: boolean) =>\r\n dispatch({ type: \"confirmAbandonInterview\", reallyAbandon });\r\n\r\n useEffect(() => {\r\n const storedState = getFromLocalStorage(INTERVIEW_LOCAL_STORAGE_KEY);\r\n if (storedState && storedState.interview) {\r\n startInterview(storedState.interview);\r\n }\r\n }, []);\r\n\r\n return {\r\n interviewState,\r\n answerQuestion,\r\n changeInterviewName,\r\n startInterview,\r\n abandonInterview,\r\n confirmAbandonInterview\r\n };\r\n}\r\n","import {\r\n State,\r\n StartInterviewAction,\r\n ChangeInterviewNameAction,\r\n AnswerQuestionAction,\r\n AbandonInterviewAction,\r\n ConfirmAbandonInterviewAction,\r\n INTERVIEW_LOCAL_STORAGE_KEY\r\n} from \"./useInterview\";\r\nimport {\r\n storeToLocalStorage,\r\n deleteFromLocalStorage\r\n} from \"../utils/localStorageHelpers\";\r\nimport { findQuestion } from \"./helpers\";\r\nimport { ResultPanel } from \"./ResultPanel\";\r\nimport { Choice } from \"./Choice\";\r\nimport { flatMap } from \"../utils/flatMap\";\r\n\r\nexport function startInterview(state: State, action: StartInterviewAction) {\r\n const interview = action.interview;\r\n if (!interview) {\r\n throw new Error(\"An interview must be specified to start.\");\r\n }\r\n return { ...state, interviewStarted: true, interview };\r\n}\r\n\r\nexport function changeInterviewName(\r\n state: State,\r\n action: ChangeInterviewNameAction\r\n) {\r\n const newState = JSON.parse(JSON.stringify(state)) as State;\r\n if (!newState.interviewStarted || !newState.interview) {\r\n throw new Error(\r\n \"Interview must be started before questions can be answered!\"\r\n );\r\n }\r\n\r\n newState.interview.interviewName = action.interviewName;\r\n\r\n // Now persist the new interview state to localStorage\r\n storeToLocalStorage(INTERVIEW_LOCAL_STORAGE_KEY, newState);\r\n\r\n return newState;\r\n}\r\n\r\nexport function answerQuestion(state: State, action: AnswerQuestionAction) {\r\n const aqi = action.actionParams;\r\n if (!aqi) {\r\n throw new Error(\"No answered question information provided!\");\r\n }\r\n\r\n const newState = JSON.parse(JSON.stringify(state)) as State;\r\n\r\n if (!newState.interviewStarted || !newState.interview) {\r\n throw new Error(\r\n \"Interview must be started before questions can be answered!\"\r\n );\r\n }\r\n\r\n const answeredTopic = newState.interview.topics.find(\r\n t => t.topicID.toLowerCase() === aqi.topicId.toLowerCase()\r\n )!;\r\n const answeredQuestion = answeredTopic.questions.find(\r\n q => q.questionID.toLowerCase() === aqi.questionId.toLowerCase()\r\n )!;\r\n const chosenChoice = answeredQuestion.choices.find(\r\n c => c.choiceID.toLowerCase() === aqi.choiceId.toLowerCase()\r\n )!;\r\n\r\n answeredQuestion.choices.forEach(c => (c.selected = false));\r\n\r\n // When a question is answered, reset all questions below it in this topic\r\n let isBelow: boolean = false;\r\n answeredTopic.questions.forEach(q => {\r\n if (q.questionID === answeredQuestion.questionID) {\r\n isBelow = true;\r\n }\r\n if (isBelow) {\r\n // Reset\r\n q.isAnswered = false;\r\n q.isCurrentQuestion = false;\r\n q.comment = \"\";\r\n q.choices.forEach(c => {\r\n c.selected = false;\r\n\r\n // Remove any results that came from the downstream choices\r\n c.resultPanels.forEach(rp => {\r\n rp.results.forEach(result => {\r\n if (!newState.interview) return;\r\n\r\n const toRemoveIndex = newState.interview.resultPanels[\r\n rp.resultPanelName\r\n ].results.findIndex(\r\n r => r.resultID.toLowerCase() === result.resultID.toLowerCase()\r\n );\r\n if (toRemoveIndex !== -1) {\r\n newState.interview.resultPanels[\r\n rp.resultPanelName\r\n ].results.splice(toRemoveIndex, 1);\r\n }\r\n });\r\n });\r\n });\r\n }\r\n });\r\n\r\n // set the question as answered\r\n answeredQuestion.isAnswered = true;\r\n answeredQuestion.isCurrentQuestion = false;\r\n\r\n // set the correct choice to answered\r\n answeredQuestion.choices.forEach(c => (c.selected = false));\r\n chosenChoice.selected = true;\r\n\r\n // Set this topic to be in-progress if not already there\r\n newState.interview.resultPanels.NOTCOMP.results.push({\r\n resultID: answeredTopic.topicID,\r\n resultText: answeredTopic.shortName,\r\n embeddedLinks: [],\r\n resultOrder: 0\r\n });\r\n\r\n if (!chosenChoice.skipEvaluation) {\r\n const { questions } = answeredTopic;\r\n\r\n // Grab all answered questions\r\n const answeredQuestions = questions.filter(q => q.isAnswered);\r\n\r\n // grab all the selected choices from all the answered questions\r\n\r\n const selectedChoices: Choice[] = flatMap(\r\n answeredQuestions,\r\n q => q.choices\r\n ).filter(c => c.selected);\r\n\r\n const selectedChoiceResultPanels: ResultPanel[] = flatMap(\r\n selectedChoices,\r\n c => c.resultPanels\r\n );\r\n\r\n // get the top priority result panels from the selected choices\r\n const minPanelPrecedent: number = Math.min(\r\n ...selectedChoiceResultPanels.map(rp => rp.panelPrecedence)\r\n );\r\n const query = selectedChoiceResultPanels.filter(\r\n rp => rp.panelPrecedence === minPanelPrecedent\r\n );\r\n\r\n //exit out if results are not known yet.\r\n if (query.length > 0) {\r\n // grab the top 1 which is the highest precedence panel from all answered\r\n // questions and selected choices.\r\n const min: number = query[0].panelPrecedence;\r\n\r\n for (const q of questions) {\r\n for (const c of q.choices) {\r\n for (const r of c.resultPanels) {\r\n if (q.isAnswered && c.selected && r.panelPrecedence === min) {\r\n const current: ResultPanel =\r\n newState.interview.resultPanels[r.resultPanelName];\r\n\r\n if (current) {\r\n if (!current.results) {\r\n current.results = [];\r\n }\r\n\r\n for (const result of r.results) {\r\n if (\r\n !current.results.find(\r\n x =>\r\n x.resultID.toLowerCase() ===\r\n result.resultID.toLowerCase()\r\n )\r\n ) {\r\n current.results.push(result);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n //Did the current choice end the topic?\r\n if (chosenChoice.endTopic) {\r\n //assuming a NOT COMPLETE panel exists, remove this topic from it now that\r\n //it is done.\r\n if (\r\n newState.interview.resultPanels.NOTCOMP.results.find(\r\n r => r.resultID.toLowerCase() === answeredTopic.topicID.toLowerCase()\r\n )\r\n ) {\r\n const notCompResults = newState.interview.resultPanels.NOTCOMP.results;\r\n newState.interview.resultPanels.NOTCOMP.results = notCompResults.filter(\r\n r => r.resultID.toLowerCase() !== answeredTopic.topicID.toLowerCase()\r\n );\r\n }\r\n } else if (chosenChoice.nextQuestion) {\r\n // Set the next question to be answered\r\n findQuestion(\r\n answeredTopic.questions,\r\n chosenChoice.nextQuestion\r\n )!.isCurrentQuestion = true;\r\n }\r\n\r\n // TODO: Remove any results from \"not declarable\" if it's also in the \"declarable\"\r\n\r\n // Sort the result panels and remove duplicates\r\n const alreadyExists: { [key: string]: boolean } = {};\r\n\r\n [\r\n newState.interview.resultPanels.DEC,\r\n newState.interview.resultPanels.NOT,\r\n newState.interview.resultPanels.NOTCOMP\r\n ].forEach(rp => {\r\n rp.results = rp.results\r\n .sort((a, b) => a.resultID.localeCompare(b.resultID))\r\n .filter((element, index, array) => {\r\n if (element.resultID in alreadyExists) {\r\n return false;\r\n } else {\r\n alreadyExists[element.resultID] = true;\r\n return true;\r\n }\r\n });\r\n });\r\n\r\n // Now persist the new interview state to localStorage\r\n storeToLocalStorage(INTERVIEW_LOCAL_STORAGE_KEY, newState);\r\n\r\n return newState;\r\n}\r\n\r\nexport function abandonInterview(state: State, action: AbandonInterviewAction) {\r\n return {\r\n ...state,\r\n abandonInterviewRequested: true\r\n };\r\n}\r\n\r\nexport function confirmAbandonInterview(\r\n state: State,\r\n action: ConfirmAbandonInterviewAction\r\n) {\r\n if (action.reallyAbandon !== undefined && action.reallyAbandon) {\r\n deleteFromLocalStorage(INTERVIEW_LOCAL_STORAGE_KEY);\r\n return {\r\n ...state,\r\n interview: undefined,\r\n abandonInterviewRequested: false,\r\n interviewStarted: false\r\n };\r\n } else {\r\n return {\r\n ...state,\r\n abandonInterviewRequested: false\r\n };\r\n }\r\n}\r\n","import { Topic } from \"./Topic\";\r\nimport { Question } from \"./Question\";\r\nimport { Choice } from \"./Choice\";\r\nimport { Result } from \"./Result\";\r\n\r\nexport function findTopic(topics: Topic[], topicId: string): Topic | undefined {\r\n return topics.find(t => t.topicID.toLowerCase() === topicId.toLowerCase());\r\n}\r\n\r\nexport function findQuestion(\r\n questions: Question[],\r\n questionId: string\r\n): Question | undefined {\r\n return questions.find(\r\n q => q.questionID.toLowerCase() === questionId.toLowerCase()\r\n );\r\n}\r\n\r\nexport function findChoice(\r\n choices: Choice[],\r\n choiceId: string\r\n): Choice | undefined {\r\n return choices.find(c => c.choiceID.toLowerCase() === choiceId.toLowerCase());\r\n}\r\n\r\nexport function findResult(\r\n results: Result[],\r\n resultId: string\r\n): Result | undefined {\r\n return results.find(c => c.resultID.toLowerCase() === resultId.toLowerCase());\r\n}\r\n","const fileApisSupported =\r\n // @ts-ignore\r\n window.File && window.FileReader && window.FileList && window.Blob;\r\n\r\nexport { fileApisSupported };\r\n\r\nexport async function fileAsText(input: HTMLInputElement): Promise {\r\n const reader = new FileReader();\r\n return new Promise((resolve, reject) => {\r\n reader.onerror = () => {\r\n reader.abort();\r\n reject(\"Problem reading file from input element.\");\r\n };\r\n\r\n reader.onload = () => {\r\n resolve(reader.result as string);\r\n };\r\n\r\n if (!input.files || input.files.length !== 1) {\r\n reject(\"Input files were not valid.\");\r\n } else {\r\n reader.readAsText(input.files[0]);\r\n }\r\n });\r\n}\r\n","import { Interview } from \"./Interview\";\r\nimport { Activity } from \"./Activity\";\r\nimport { fileAsText } from \"../utils/fileUtils\";\r\nimport { saveAs } from \"file-saver\";\r\n\r\ninterface SavedInterview {\r\n interview: Interview;\r\n activities: Activity[];\r\n}\r\n\r\nexport function saveInterview(savedInterview: SavedInterview) {\r\n const asString = JSON.stringify(savedInterview, null, 2);\r\n const blob = new Blob([asString], { type: \"application/json\" });\r\n saveAs(blob, \"interview.json\");\r\n}\r\n\r\nexport async function loadInterview(\r\n input: HTMLInputElement\r\n): Promise {\r\n try {\r\n const text = await fileAsText(input);\r\n const savedInterview = await validateSavedInterview(text);\r\n return savedInterview;\r\n } catch (error) {\r\n console.error(error);\r\n throw new Error(\"Could not load saved interview.\");\r\n }\r\n}\r\n\r\nasync function validateSavedInterview(\r\n savedInterviewString: string\r\n): Promise {\r\n try {\r\n const savedInterview = JSON.parse(savedInterviewString) as SavedInterview;\r\n if (!savedInterview.interview || !savedInterview.activities) {\r\n throw new Error(\r\n \"Could not find interview information in the loaded file.\"\r\n );\r\n }\r\n\r\n validateInterview(savedInterview.interview);\r\n validateActivities(savedInterview.activities);\r\n return savedInterview;\r\n } catch (error) {\r\n console.error(error);\r\n throw new Error(`Could not validate saved interview.`);\r\n }\r\n}\r\n\r\nfunction validateInterview(object: any): Promise {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const interview = object as Interview;\r\n\r\n if (typeof interview.isMultiInterview !== \"boolean\") {\r\n reject(\"isMultiInterview is not present\");\r\n return;\r\n }\r\n\r\n if (!Array.isArray(interview.topics)) {\r\n reject(\"topics are not present\");\r\n return;\r\n }\r\n\r\n if (!Array.isArray(interview.resultValues)) {\r\n reject(\"resultValues are not present\");\r\n return;\r\n }\r\n\r\n if (typeof interview.resultPanels !== \"object\") {\r\n reject(\"resultPanels are not present\");\r\n return;\r\n }\r\n\r\n resolve(interview);\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nfunction validateActivities(object: any): Promise {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (!Array.isArray(object)) {\r\n reject(\"Activities are not an array\");\r\n return;\r\n }\r\n\r\n const activities = object as Activity[];\r\n\r\n for (const activity of activities) {\r\n if (\r\n typeof activity.id !== \"string\" ||\r\n typeof activity.article !== \"string\" ||\r\n typeof activity.name !== \"string\" ||\r\n typeof activity.comments !== \"string\"\r\n ) {\r\n reject(\"Could not parse activity\");\r\n return;\r\n }\r\n }\r\n\r\n resolve(activities);\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n}\r\n","import React from \"react\";\r\nimport useInterview, { initialState } from \"./interview-engine/useInterview\";\r\nimport useActivities from \"./interview-engine/useActivities\";\r\nimport {\r\n loadInterview,\r\n saveInterview\r\n} from \"./interview-engine/loadSaveInterview\";\r\n\r\n// prettier-ignore\r\nexport type InterviewContextType = \r\n ReturnType &\r\n ReturnType & {\r\n loadInterview: (input: HTMLInputElement) => void;\r\n saveInterview: () => void;\r\n };\r\n\r\nconst InterviewContext = React.createContext({\r\n // interview stuff\r\n interviewState: initialState,\r\n startInterview: _ => ({}),\r\n changeInterviewName: _ => ({}),\r\n answerQuestion: _ => ({}),\r\n abandonInterview: () => ({}),\r\n confirmAbandonInterview: () => ({}),\r\n // activity stuff\r\n activities: [],\r\n addActivity: _ => ({}),\r\n updateActivity: _ => ({}),\r\n removeActivity: _ => ({}),\r\n clearAllActivities: () => ({}),\r\n restoreActivities: _ => ({}),\r\n //persistence stuff\r\n saveInterview: () => ({}),\r\n loadInterview: _ => ({})\r\n});\r\n\r\nfunction InterviewContextProvider({ children }: React.Props) {\r\n const interviewState = useInterview();\r\n const activityState = useActivities();\r\n\r\n const loadInterviewWrapper = async (input: HTMLInputElement) => {\r\n try {\r\n const interview = await loadInterview(input);\r\n interviewState.startInterview(interview.interview);\r\n activityState.clearAllActivities();\r\n activityState.restoreActivities(interview.activities);\r\n } catch (error) {\r\n throw error;\r\n }\r\n };\r\n\r\n const saveInterviewWrapper = () => {\r\n saveInterview({\r\n interview: interviewState.interviewState.interview!,\r\n activities: activityState.activities\r\n });\r\n };\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n}\r\n\r\nexport { InterviewContext, InterviewContextProvider };\r\n","import { useState, useEffect } from \"react\";\r\nimport {\r\n getFromLocalStorage,\r\n storeToLocalStorage,\r\n deleteFromLocalStorage\r\n} from \"../utils/localStorageHelpers\";\r\nimport { Activity } from \"./Activity\";\r\n\r\nconst ACTIVITIES_LOCAL_STORAGE_KEY = \"ACTIVITIES\";\r\n\r\nexport default function useActivities() {\r\n const [activities, setActivities] = useState([]);\r\n\r\n useEffect(() => {\r\n const storedState = getFromLocalStorage(\r\n ACTIVITIES_LOCAL_STORAGE_KEY\r\n );\r\n if (storedState && Array.isArray(storedState)) {\r\n setActivities(storedState);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n storeToLocalStorage(ACTIVITIES_LOCAL_STORAGE_KEY, activities);\r\n }, [activities]);\r\n\r\n const addActivity = (activity: Activity) => {\r\n activity.id = Math.random().toString(36);\r\n setActivities([...activities, activity]);\r\n };\r\n\r\n const updateActivity = (activity: Activity) => {\r\n setActivities(activities.map(a => (a.id === activity.id ? activity : a)));\r\n };\r\n\r\n const removeActivity = (id: string) => {\r\n setActivities(activities.filter(a => a.id !== id));\r\n };\r\n\r\n const clearAllActivities = () => {\r\n deleteFromLocalStorage(ACTIVITIES_LOCAL_STORAGE_KEY);\r\n setActivities([]);\r\n };\r\n\r\n const restoreActivities = (activities: Activity[]) => {\r\n setActivities(\r\n activities.map(a => ({ ...a, id: Math.random().toString(36) }))\r\n );\r\n };\r\n\r\n return {\r\n activities,\r\n addActivity,\r\n updateActivity,\r\n removeActivity,\r\n clearAllActivities,\r\n restoreActivities\r\n };\r\n}\r\n","import i18n from \"i18next\";\r\nimport Backend from \"i18next-xhr-backend\";\r\nimport LanguageDetector from \"i18next-browser-languagedetector\";\r\nimport { initReactI18next } from \"react-i18next\";\r\n\r\ninterface Language {\r\n name: string;\r\n abbreviation: string;\r\n}\r\n\r\nconst availableLanguages: Language[] = [\r\n { name: \"English\", abbreviation: \"en\" },\r\n { name: \"Español\", abbreviation: \"es\" },\r\n { name: \"Français\", abbreviation: \"fr\" }\r\n];\r\nexport { availableLanguages };\r\n\r\nconst missingKeys = new Set();\r\nfunction missingKeyHandler(\r\n langs: string[],\r\n ns: string,\r\n key: string,\r\n res: string\r\n) {\r\n missingKeys.add(key);\r\n\r\n console.warn(\r\n `Found missing translation with key ${key}. \r\n Logging all currently missing translation keys.`\r\n );\r\n\r\n console.warn(missingKeys);\r\n}\r\n\r\ni18n\r\n .use(Backend)\r\n .use(LanguageDetector)\r\n .use(initReactI18next)\r\n .init({\r\n load: \"languageOnly\",\r\n // lng: \"en\",\r\n fallbackLng: \"en\",\r\n keySeparator: false,\r\n interpolation: {\r\n escapeValue: false\r\n },\r\n whitelist: availableLanguages.map(l => l.abbreviation),\r\n nonExplicitWhitelist: true,\r\n saveMissing: true,\r\n missingKeyHandler:\r\n process.env.NODE_ENV === \"development\" ? missingKeyHandler : undefined,\r\n detection: {\r\n order: [\"localStorage\"]\r\n }\r\n // debug: true,\r\n });\r\n\r\nexport default i18n;\r\n","import React, { useState } from \"react\";\r\nimport {\r\n Nav,\r\n Navbar,\r\n NavbarToggler,\r\n Collapse,\r\n NavItem,\r\n NavLink,\r\n NavbarBrand,\r\n UncontrolledDropdown,\r\n DropdownToggle,\r\n DropdownMenu,\r\n DropdownItem,\r\n} from \"reactstrap\";\r\nimport { NavLink as RRNavLink } from \"react-router-dom\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport isElectron from \"../utils/isElectron\";\r\n\r\nimport \"./Navigation.scss\";\r\n\r\nfunction Navigation() {\r\n const { t } = useTranslation();\r\n const [isOpen, setIsOpen] = useState(false);\r\n\r\n return (\r\n \r\n \r\n \"NNSA{\" \"}\r\n {t(\"AP Declaration Helper\")}\r\n \r\n setIsOpen(!isOpen)} />\r\n \r\n \r\n \r\n \r\n );\r\n}\r\n\r\nexport default Navigation;\r\n","import React, { Component, lazy, Suspense } from \"react\";\r\nimport { Container } from \"reactstrap\";\r\nimport {\r\n Route,\r\n Switch,\r\n BrowserRouter,\r\n HashRouter,\r\n Redirect\r\n} from \"react-router-dom\";\r\nimport isElectron from \"./utils/isElectron\";\r\n\r\nimport { InterviewContextProvider } from \"./InterviewContext\";\r\n\r\nimport Loading from \"./components/Loading\";\r\nimport Navigation from \"./components/Navigation\";\r\n\r\nconst ActivityArea = lazy(() => import(\"./components/activities/ActivityArea\"));\r\nconst ActivityReport = lazy(() =>\r\n import(\"./components/activities/ActivityReport\")\r\n);\r\nconst Contact = lazy(() => import(\"./components/contact/Contact\"));\r\nconst Downloads = lazy(() => import(\"./components/downloads/Downloads\"));\r\nconst FAQ = lazy(() => import(\"./components/faq/FAQ\"));\r\nconst Footer = lazy(() => import(\"./components/Footer\"));\r\nconst HelpArea = lazy(() => import(\"./components/help/HelpArea\"));\r\nconst Home = lazy(() => import(\"./components/home/Home\"));\r\nconst InterviewArea = lazy(() =>\r\n import(\"./components/interview/InterviewArea\")\r\n);\r\nconst InterviewInProgress = lazy(() =>\r\n import(\"./components/interview/InterviewInProgress\")\r\n);\r\nconst InterviewReport = lazy(() =>\r\n import(\"./components/interview/InterviewReport\")\r\n);\r\nconst Video = lazy(() => import(\"./components/video/Video\"));\r\n\r\nimport \"./App.css\"; // eslint-disable-line import/first\r\n\r\nfunction Router({ children }: React.Props) {\r\n return isElectron() ? (\r\n {children}\r\n ) : (\r\n {children}\r\n );\r\n}\r\n\r\nclass App extends Component {\r\n render() {\r\n return (\r\n \r\n \r\n
\r\n \r\n }>\r\n \r\n \r\n
\r\n \r\n }>\r\n \r\n \r\n {/* Redirect from the default Electron path*/}\r\n }\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n }>\r\n
\r\n \r\n
\r\n
\r\n
\r\n );\r\n }\r\n}\r\n\r\nexport default App;\r\n","// Polyfill for older browsers\r\n// import \"core-js\";\r\nimport \"react-app-polyfill/ie11\";\r\nimport \"react-app-polyfill/stable\";\r\n\r\n// Bootstrap styling\r\nimport \"./bootstrap-custom.scss\";\r\n\r\n// Root level styles\r\nimport \"./index.css\";\r\n\r\n// React libraries\r\nimport React, { Suspense } from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\n\r\nimport \"./i18n/i18n\";\r\n\r\nimport App from \"./App\";\r\nimport Loading from \"./components/Loading\";\r\n\r\nReactDOM.render(\r\n }>\r\n \r\n ,\r\n document.getElementById(\"root\")\r\n);\r\n","import React from \"react\";\r\n\r\nexport default () =>
Loading
;\r\n"],"sourceRoot":""}