Loading frontend/src/components/Questionnaire/index.tsx +12 −4 Original line number Diff line number Diff line import { questionNumber } from '@/components/Questionnaire/classes' import { Classes, Divider } from '@blueprintjs/core' import { css } from '@emotion/css' import { css, cx } from '@emotion/css' import type { Content, Question } from '@inject/graphql/fragment-types' import type { FC, ReactNode } from 'react' import { Fragment, useCallback } from 'react' Loading @@ -27,12 +27,15 @@ const contentWrapper = css` ` const body = css` flex: 1; margin: 0.5rem; ` const bodyGrid = css` display: grid; grid-template-columns: auto auto 1fr; row-gap: 1rem; column-gap: 0.5rem; flex: 1; margin: 0.5rem; ` const questionActionsWrapper = css` Loading Loading @@ -128,7 +131,12 @@ const Questionnaire: FC<QuestionnaireProps> = ({ /> </div> <div className={body}> <div className={cx({ [body]: true, [bodyGrid]: questionsAndAnswers.length > 1, })} > {questionsAndAnswers.map((questionAndAnswer, questionIndex) => ( <Fragment key={questionAndAnswer.question.id}> {questionsAndAnswers.length > 1 && ( Loading frontend/src/instructor/InstructorQuestionnaire/InstructorQuestionnaireCard.tsx +5 −1 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import ErrorMessage from '@inject/shared/components/ErrorMessage' import { useMemo, type FC } from 'react' import InstructorQuestionnaire from '.' import Status from './Status' import { canBeReviewed } from './utils' const objectiveClass = css` flex-shrink: 0; Loading Loading @@ -61,7 +62,10 @@ const InstructorQuestionnaireCard: FC<InstructorQuestionnaireCardProps> = ({ title={details.title} className={objectiveClass} rightElement={ <Status teamStateStatus={data.questionnaireState.status || 'UNSENT'} /> <Status teamStateStatus={data.questionnaireState.status || 'UNSENT'} canBeReviewed={canBeReviewed(details.questions)} /> } collapsible > Loading frontend/src/instructor/InstructorQuestionnaire/Status.tsx +6 −5 Original line number Diff line number Diff line Loading @@ -11,9 +11,10 @@ export const tag = css` interface StatusProps { teamStateStatus: TeamQuestionnaireState['status'] canBeReviewed: boolean } const Status: FC<StatusProps> = ({ teamStateStatus }) => { const Status: FC<StatusProps> = ({ teamStateStatus, canBeReviewed }) => { const label = useMemo(() => { switch (teamStateStatus) { case 'UNSENT': Loading @@ -23,13 +24,13 @@ const Status: FC<StatusProps> = ({ teamStateStatus }) => { return 'not answered' case 'ANSWERED': // TODO: add timestamp return 'answered' return canBeReviewed ? 'not reviewed' : 'answered' case 'REVIEWED': return 'reviewed' default: throw new Error(`Unsupported status: ${teamStateStatus}`) } }, [teamStateStatus]) }, [canBeReviewed, teamStateStatus]) const intent: Intent = useMemo(() => { switch (teamStateStatus) { case 'UNSENT': Loading @@ -37,13 +38,13 @@ const Status: FC<StatusProps> = ({ teamStateStatus }) => { case 'SENT': return 'danger' case 'ANSWERED': return 'warning' return canBeReviewed ? 'warning' : 'success' case 'REVIEWED': return 'success' default: throw new Error(`Unsupported status: ${teamStateStatus}`) } }, [teamStateStatus]) }, [canBeReviewed, teamStateStatus]) return ( <Tag minimal round className={tag} intent={intent}> Loading frontend/src/instructor/InstructorQuestionnaire/index.tsx +2 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import { notify } from '@inject/shared/notification/engine' import type { FC, ReactNode } from 'react' import { useCallback, useMemo, useState } from 'react' import ReviewButton from './ReviewButton' import { canBeReviewed } from './utils' interface InstructorQuestionnaireProps { questionnaireId: string Loading Loading @@ -112,10 +113,7 @@ const InstructorQuestionnaire: FC<InstructorQuestionnaireProps> = ({ ) const actions = useMemo<ReactNode>(() => { if ( hideReview || !questions.some(question => question.type === 'FREE_FORM') ) { if (hideReview || !canBeReviewed(questions)) { return undefined } Loading frontend/src/instructor/InstructorQuestionnaire/utils.ts 0 → 100644 +11 −0 Original line number Diff line number Diff line import type { FreeFormQuestionDetails, Question, } from '@inject/graphql/fragment-types' export const canBeReviewed = (questions: Question[]) => questions.some( question => question.type === 'FREE_FORM' && (question.details as FreeFormQuestionDetails).relatedMilestones.length > 0 ) Loading
frontend/src/components/Questionnaire/index.tsx +12 −4 Original line number Diff line number Diff line import { questionNumber } from '@/components/Questionnaire/classes' import { Classes, Divider } from '@blueprintjs/core' import { css } from '@emotion/css' import { css, cx } from '@emotion/css' import type { Content, Question } from '@inject/graphql/fragment-types' import type { FC, ReactNode } from 'react' import { Fragment, useCallback } from 'react' Loading @@ -27,12 +27,15 @@ const contentWrapper = css` ` const body = css` flex: 1; margin: 0.5rem; ` const bodyGrid = css` display: grid; grid-template-columns: auto auto 1fr; row-gap: 1rem; column-gap: 0.5rem; flex: 1; margin: 0.5rem; ` const questionActionsWrapper = css` Loading Loading @@ -128,7 +131,12 @@ const Questionnaire: FC<QuestionnaireProps> = ({ /> </div> <div className={body}> <div className={cx({ [body]: true, [bodyGrid]: questionsAndAnswers.length > 1, })} > {questionsAndAnswers.map((questionAndAnswer, questionIndex) => ( <Fragment key={questionAndAnswer.question.id}> {questionsAndAnswers.length > 1 && ( Loading
frontend/src/instructor/InstructorQuestionnaire/InstructorQuestionnaireCard.tsx +5 −1 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import ErrorMessage from '@inject/shared/components/ErrorMessage' import { useMemo, type FC } from 'react' import InstructorQuestionnaire from '.' import Status from './Status' import { canBeReviewed } from './utils' const objectiveClass = css` flex-shrink: 0; Loading Loading @@ -61,7 +62,10 @@ const InstructorQuestionnaireCard: FC<InstructorQuestionnaireCardProps> = ({ title={details.title} className={objectiveClass} rightElement={ <Status teamStateStatus={data.questionnaireState.status || 'UNSENT'} /> <Status teamStateStatus={data.questionnaireState.status || 'UNSENT'} canBeReviewed={canBeReviewed(details.questions)} /> } collapsible > Loading
frontend/src/instructor/InstructorQuestionnaire/Status.tsx +6 −5 Original line number Diff line number Diff line Loading @@ -11,9 +11,10 @@ export const tag = css` interface StatusProps { teamStateStatus: TeamQuestionnaireState['status'] canBeReviewed: boolean } const Status: FC<StatusProps> = ({ teamStateStatus }) => { const Status: FC<StatusProps> = ({ teamStateStatus, canBeReviewed }) => { const label = useMemo(() => { switch (teamStateStatus) { case 'UNSENT': Loading @@ -23,13 +24,13 @@ const Status: FC<StatusProps> = ({ teamStateStatus }) => { return 'not answered' case 'ANSWERED': // TODO: add timestamp return 'answered' return canBeReviewed ? 'not reviewed' : 'answered' case 'REVIEWED': return 'reviewed' default: throw new Error(`Unsupported status: ${teamStateStatus}`) } }, [teamStateStatus]) }, [canBeReviewed, teamStateStatus]) const intent: Intent = useMemo(() => { switch (teamStateStatus) { case 'UNSENT': Loading @@ -37,13 +38,13 @@ const Status: FC<StatusProps> = ({ teamStateStatus }) => { case 'SENT': return 'danger' case 'ANSWERED': return 'warning' return canBeReviewed ? 'warning' : 'success' case 'REVIEWED': return 'success' default: throw new Error(`Unsupported status: ${teamStateStatus}`) } }, [teamStateStatus]) }, [canBeReviewed, teamStateStatus]) return ( <Tag minimal round className={tag} intent={intent}> Loading
frontend/src/instructor/InstructorQuestionnaire/index.tsx +2 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import { notify } from '@inject/shared/notification/engine' import type { FC, ReactNode } from 'react' import { useCallback, useMemo, useState } from 'react' import ReviewButton from './ReviewButton' import { canBeReviewed } from './utils' interface InstructorQuestionnaireProps { questionnaireId: string Loading Loading @@ -112,10 +113,7 @@ const InstructorQuestionnaire: FC<InstructorQuestionnaireProps> = ({ ) const actions = useMemo<ReactNode>(() => { if ( hideReview || !questions.some(question => question.type === 'FREE_FORM') ) { if (hideReview || !canBeReviewed(questions)) { return undefined } Loading
frontend/src/instructor/InstructorQuestionnaire/utils.ts 0 → 100644 +11 −0 Original line number Diff line number Diff line import type { FreeFormQuestionDetails, Question, } from '@inject/graphql/fragment-types' export const canBeReviewed = (questions: Question[]) => questions.some( question => question.type === 'FREE_FORM' && (question.details as FreeFormQuestionDetails).relatedMilestones.length > 0 )