• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

akvo / nmis-mobile / 5750775598

03 Aug 2023 11:53AM UTC coverage: 80.025% (-0.04%) from 80.065%
5750775598

push

github

web-flow
Merge pull request #110 from akvo/feature/108-performance-issue-related-to-datapoint-name

Feature/108 performance issue related to datapoint name

598 of 802 branches covered (74.56%)

Branch coverage included in aggregate %.

78 of 78 new or added lines in 10 files covered. (100.0%)

1317 of 1591 relevant lines covered (82.78%)

17.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.42
/app/src/form/FormContainer.js
1
import React, { useState, useRef, useMemo, useEffect } from 'react';
2
import { BaseLayout } from '../components';
3
import { ScrollView, View } from 'react-native';
4
import { Formik } from 'formik';
5
import { styles } from './styles';
6
import { FormNavigation, QuestionGroupList } from './support';
7
import QuestionGroup from './components/QuestionGroup';
8
import { transformForm, generateDataPointName } from './lib';
9
import { FormState, UIState } from '../store';
10

11
// TODO:: Allow other not supported yet
12
// TODO:: Repeat group not supported yet
13

14
const checkValuesBeforeCallback = (values) =>
3✔
15
  Object.keys(values)
6✔
16
    .map((key) => {
17
      let value = values[key];
27✔
18
      if (typeof value === 'string') {
27✔
19
        value = value.trim();
10✔
20
      }
21
      // check array
22
      if (value && Array.isArray(value)) {
27✔
23
        const check = value.filter((y) => typeof y !== 'undefined' && (y || isNaN(y)));
13!
24
        value = check.length ? check : null;
12✔
25
      }
26
      // check empty
27
      if (!value && value !== 0) {
27✔
28
        return false;
5✔
29
      }
30
      return { [key]: value };
22✔
31
    })
32
    .filter((v) => v)
27✔
33
    .reduce((res, current) => ({ ...res, ...current }), {});
22✔
34

35
const FormContainer = ({ forms, initialValues = {}, onSubmit, onSave }) => {
3✔
36
  const formRef = useRef();
12✔
37
  const [activeGroup, setActiveGroup] = useState(0);
12✔
38
  const [showQuestionGroupList, setShowQuestionGroupList] = useState(false);
12✔
39
  const currentValues = FormState.useState((s) => s.currentValues);
13✔
40
  const questionGroupListCurrentValues = FormState.useState(
12✔
41
    (s) => s.questionGroupListCurrentValues,
13✔
42
  );
43
  const cascades = FormState.useState((s) => s.cascades);
13✔
44
  const activeLang = UIState.useState((s) => s.lang);
12✔
45

46
  useEffect(() => {
12✔
47
    if (onSave) {
11✔
48
      const results = checkValuesBeforeCallback(currentValues);
3✔
49
      if (!Object.keys(results).length) {
3✔
50
        return onSave(null, refreshForm);
2✔
51
      }
52
      const { dpName, dpGeo } = generateDataPointName(forms, currentValues, cascades);
1✔
53
      const values = { name: dpName, geo: dpGeo, answers: results };
1✔
54
      return onSave(values, refreshForm);
1✔
55
    }
56
  }, [currentValues, onSave]);
57

58
  const formDefinition = useMemo(() => {
12✔
59
    const transformedForm = transformForm(forms, activeLang);
6✔
60
    FormState.update((s) => {
6✔
61
      s.visitedQuestionGroup = [transformedForm.question_group[0].id];
6✔
62
    });
63
    return transformedForm;
6✔
64
  }, [forms, activeLang]);
65

66
  const currentGroup = useMemo(() => {
12✔
67
    return formDefinition.question_group.find((qg) => qg.id === activeGroup);
6✔
68
  }, [formDefinition, activeGroup]);
69

70
  const initialFormValues = useMemo(() => {
12✔
71
    if (Object.keys(initialValues).length) {
6✔
72
      FormState.update((s) => {
5✔
73
        s.currentValues = initialValues;
5✔
74
        s.questionGroupListCurrentValues = initialValues;
5✔
75
      });
76
      return initialValues;
5✔
77
    }
78
    return {};
1✔
79
  }, [initialValues]);
80

81
  const refreshForm = () => {
12✔
82
    FormState.update((s) => {
×
83
      s.currentValues = {};
×
84
      s.questionGroupListCurrentValues = {};
×
85
      s.visitedQuestionGroup = [];
×
86
      s.cascades = {};
×
87
      s.surveyDuration = 0;
×
88
    });
89
    formRef.current?.resetForm();
×
90
  };
91

92
  const handleOnSubmitForm = (values) => {
12✔
93
    const results = checkValuesBeforeCallback(values);
3✔
94
    if (onSubmit) {
3!
95
      const { dpName, dpGeo } = generateDataPointName(forms, currentValues, cascades);
3✔
96
      onSubmit({ name: dpName, geo: dpGeo, answers: results }, refreshForm);
3✔
97
    }
98
  };
99

100
  return (
12✔
101
    <>
102
      <ScrollView>
103
        <BaseLayout.Content>
104
          {!showQuestionGroupList ? (
12!
105
            <Formik
106
              innerRef={formRef}
107
              initialValues={initialFormValues}
108
              onSubmit={handleOnSubmitForm}
109
              validateOnBlur={true}
110
              validateOnChange={true}
111
            >
112
              {({ setFieldValue, values }) => (
113
                <View style={styles.formContainer}>
33✔
114
                  {formDefinition?.question_group?.map((group) => {
115
                    if (activeGroup !== group.id) {
33!
116
                      return '';
×
117
                    }
118
                    return (
33✔
119
                      <QuestionGroup
120
                        key={`group-${group.id}`}
121
                        index={group.id}
122
                        group={group}
123
                        setFieldValue={setFieldValue}
124
                        values={values}
125
                      />
126
                    );
127
                  })}
128
                </View>
129
              )}
130
            </Formik>
131
          ) : (
132
            <QuestionGroupList
133
              form={formDefinition}
134
              values={questionGroupListCurrentValues}
135
              activeQuestionGroup={activeGroup}
136
              setActiveQuestionGroup={setActiveGroup}
137
              setShowQuestionGroupList={setShowQuestionGroupList}
138
            />
139
          )}
140
        </BaseLayout.Content>
141
      </ScrollView>
142
      <View>
143
        <FormNavigation
144
          currentGroup={currentGroup}
145
          formRef={formRef}
146
          onSubmit={() => {
147
            if (formRef.current) {
3!
148
              formRef.current.handleSubmit();
3✔
149
            }
150
          }}
151
          activeGroup={activeGroup}
152
          setActiveGroup={setActiveGroup}
153
          totalGroup={formDefinition?.question_group?.length || 0}
12!
154
          showQuestionGroupList={showQuestionGroupList}
155
          setShowQuestionGroupList={setShowQuestionGroupList}
156
        />
157
      </View>
158
    </>
159
  );
160
};
161

162
export default FormContainer;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc