Skip to content

Commit

Permalink
Merge pull request #50 from the-deep/feature/questions-order
Browse files Browse the repository at this point in the history
Implement questions order and visibility mutation
  • Loading branch information
AdityaKhatri authored Sep 12, 2023
2 parents 2e0b726 + 9b56ccd commit 722941e
Show file tree
Hide file tree
Showing 8 changed files with 403 additions and 19 deletions.
5 changes: 5 additions & 0 deletions src/components/EditQuestionnaireModal/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.modal-body {
display: flex;
flex-direction: column;
gap: var(--dui-spacing-medium);
}
112 changes: 109 additions & 3 deletions src/components/EditQuestionnaireModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
Modal,
Button,
TextInput,
SelectInput,
NumberInput,
useAlert,
} from '@the-deep/deep-ui';
import {
Expand All @@ -24,8 +26,21 @@ import {
QuestionnaireDetailQuery,
QuestionnaireDetailQueryVariables,
QuestionnaireCreateInput,
QuestionnaireMetadataQuery,
QuestionnaireMetadataQueryVariables,
QuestionnarePriorityLevelTypeEnum,
QuestionnareEnumeratorSkillTypeEnum,
QuestionnareDataCollectionMethodTypeEnum,
} from '#generated/types';

import {
EnumOptions,
enumKeySelector,
enumLabelSelector,
} from '#utils/common';

import styles from './index.module.css';

const CREATE_QUESTIONNAIRE = gql`
mutation CreateQuestionnaire(
$projectId: ID!,
Expand Down Expand Up @@ -71,16 +86,46 @@ const QUESTIONNAIRE_DETAIL = gql`
private {
projectScope(pk: $projectId) {
questionnaire(pk: $questionnaireId) {
createdAt
id
title
projectId
createdAt
dataCollectionMethod
dataCollectionMethodDisplay
enumeratorSkill
enumeratorSkillDisplay
priorityLevelDisplay
priorityLevel
requiredDuration
}
}
}
}
`;

const QUESTIONNAIRE_METADATA = gql`
query QuestionnaireMetadata {
questionnarePriorityLevelTypeOptions: __type(name: "QuestionnarePriorityLevelTypeEnum") {
enumValues {
name
description
}
}
questionnareEnumeratorSkillTypeOptions: __type(name: "QuestionnareEnumeratorSkillTypeEnum") {
enumValues {
name
description
}
}
questionnareDataCollectionMethodTypeOptions: __type(name: "QuestionnareDataCollectionMethodTypeEnum") {
enumValues {
name
description
}
}
}
`;

type FormType = PartialForm<QuestionnaireCreateInput>;
type FormSchema = ObjectSchema<FormType>;
type FormSchemaFields = ReturnType<FormSchema['fields']>;
Expand All @@ -91,6 +136,10 @@ const schema: FormSchema = {
required: true,
requiredValidation: requiredStringCondition,
},
dataCollectionMethod: {},
enumeratorSkill: {},
priorityLevel: {},
requiredDuration: {},
}),
};

Expand Down Expand Up @@ -149,19 +198,35 @@ function EditQuestionnaireModal(props: Props) {
const questionnaireDetails = response?.private?.projectScope?.questionnaire;
setValue({
title: questionnaireDetails?.title,
priorityLevel: questionnaireDetails?.priorityLevel,
enumeratorSkill: questionnaireDetails?.enumeratorSkill,
dataCollectionMethod: questionnaireDetails?.dataCollectionMethod,
requiredDuration: questionnaireDetails?.requiredDuration,
});
},
},
);

const {
data: metadataResponse,
} = useQuery<QuestionnaireMetadataQuery, QuestionnaireMetadataQueryVariables>(
QUESTIONNAIRE_METADATA,
);

const priorityLevelOptions = metadataResponse?.questionnarePriorityLevelTypeOptions?.enumValues;
const enumeratorSkillOptions = metadataResponse
?.questionnareEnumeratorSkillTypeOptions?.enumValues;
const dataCollectionMethods = metadataResponse
?.questionnareDataCollectionMethodTypeOptions?.enumValues;

const [
triggerQuestionnaireCreate,
{ loading: questionnaireCreatePending },
] = useMutation<CreateQuestionnaireMutation, CreateQuestionnaireMutationVariables>(
CREATE_QUESTIONNAIRE,
{
onCompleted: (questionnaireResponse) => {
const response = questionnaireResponse?.private?.projectScope?.createQuestionnaire;
onCompleted: (res) => {
const response = res?.private?.projectScope?.createQuestionnaire;
if (!response) {
return;
}
Expand Down Expand Up @@ -264,6 +329,7 @@ function EditQuestionnaireModal(props: Props) {
<Modal
onCloseButtonClick={onClose}
heading="Create Questionnaire"
bodyClassName={styles.modalBody}
freeHeight
size="small"
footerActions={(
Expand All @@ -281,12 +347,52 @@ function EditQuestionnaireModal(props: Props) {
>
<TextInput
name="title"
label="Title"
placeholder="Questionnaire Title"
value={formValue?.title}
error={fieldError?.title}
onChange={setFieldValue}
autoFocus
/>
<SelectInput
name="priorityLevel"
label="Priority Level"
onChange={setFieldValue}
value={formValue?.priorityLevel}
error={fieldError?.priorityLevel}
options={priorityLevelOptions as EnumOptions<QuestionnarePriorityLevelTypeEnum>}
keySelector={enumKeySelector}
labelSelector={enumLabelSelector}
/>
<SelectInput
name="enumeratorSkill"
label="Enumerator Skill"
onChange={setFieldValue}
value={formValue?.enumeratorSkill}
error={fieldError?.enumeratorSkill}
options={enumeratorSkillOptions as EnumOptions<QuestionnareEnumeratorSkillTypeEnum>}
keySelector={enumKeySelector}
labelSelector={enumLabelSelector}
/>
<SelectInput
name="dataCollectionMethod"
label="Data Collection Method"
onChange={setFieldValue}
value={formValue?.dataCollectionMethod}
error={fieldError?.dataCollectionMethod}
options={
dataCollectionMethods as EnumOptions<QuestionnareDataCollectionMethodTypeEnum>
}
keySelector={enumKeySelector}
labelSelector={enumLabelSelector}
/>
<NumberInput
name="requiredDuration"
label="Maximum Duration (in minutes)"
onChange={setFieldValue}
value={formValue?.requiredDuration}
error={fieldError?.requiredDuration}
/>
</Modal>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import {
SingleOptionListQuery,
SingleOptionListQueryVariables,
} from '#generated/types';
import {
type ProjectScope,
} from '#utils/common';

import styles from './index.module.css';

Expand All @@ -43,7 +46,7 @@ const SINGLE_OPTION_LIST = gql`
}
`;

type ChoiceType = NonNullable<NonNullable<NonNullable<NonNullable<SingleOptionListQuery['private']>['projectScope']>['choiceCollection']>['choices']>[number];
type ChoiceType = NonNullable<NonNullable<ProjectScope<SingleOptionListQuery>['choiceCollection']>['choices']>[number];

const choiceCollectionKeySelector = (d: ChoiceType) => d.id;
const choiceCollectionLabelSelector = (d: ChoiceType) => d.label;
Expand Down
20 changes: 20 additions & 0 deletions src/utils/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { capitalize } from '@togglecorp/fujs';

// eslint-disable-next-line import/prefer-default-export
export function flatten<A, K>(
list: A[],
Expand Down Expand Up @@ -61,3 +63,21 @@ export type DeepReplace<T, A, B> = (
)
)
);

export interface EnumEntity<T> {
name: T;
description?: string | null;
}

export type EnumOptions<T> = EnumEntity<T>[] | null | undefined;

export const enumKeySelector = <T>(d: EnumEntity<T>) => (
d.name
);
export const enumLabelSelector = <T extends string | number>(d: EnumEntity<T>) => (
d.description ?? capitalize(String(d.name))
);

export type ProjectScope<T> = T extends {
private ?: { projectScope?: infer X }
} ? NonNullable<X> : never;
Loading

0 comments on commit 722941e

Please sign in to comment.