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

akvo / nmis-mobile / 5709599933

31 Jul 2023 01:33AM UTC coverage: 78.664% (-0.03%) from 78.69%
5709599933

push

github

wayangalihpratama
[#90] Merge branch 'main' into feature/90-implement-survey-timer

607 of 811 branches covered (74.85%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 1 file covered. (100.0%)

1207 of 1495 relevant lines covered (80.74%)

15.45 hits per line

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

93.51
/app/src/form/fields/TypeCascade.js
1
import React, { useState, useEffect } from 'react';
2
import { View, Text } from 'react-native';
3
import { Dropdown } from 'react-native-element-dropdown';
4
import { FieldLabel } from '../support';
5
import { styles } from '../styles';
6
import { FormState } from '../../store';
7

8
const TypeCascade = ({
4✔
9
  onChange,
10
  values,
11
  keyform,
12
  id,
13
  name,
14
  tooltip,
15
  required,
16
  requiredSign,
17
  source,
18
  dataSource = [],
1✔
19
}) => {
20
  const [dropdownItems, setDropdownItems] = useState([]);
34✔
21

22
  const groupBy = (array, property) => {
34✔
23
    const gd = array
12✔
24
      .sort((a, b) => a?.name?.localeCompare(b?.name))
45✔
25
      .reduce((groups, item) => {
26
        const key = item[property];
36✔
27
        if (!groups[key]) {
36✔
28
          groups[key] = [];
18✔
29
        }
30
        groups[key].push(item);
36✔
31
        return groups;
36✔
32
      }, {});
33
    const groupedData = {};
12✔
34
    Object.entries(gd).forEach(([key, value]) => {
12✔
35
      groupedData[key] = value;
18✔
36
    });
37
    return groupedData;
12✔
38
  };
39

40
  const handleOnChange = (index, value) => {
34✔
41
    const nextIndex = index + 1;
7✔
42
    const updatedItems = dropdownItems
7✔
43
      .slice(0, nextIndex)
44
      .map((d, dx) => (dx === index ? { ...d, value } : d));
13✔
45

46
    const options = dataSource?.filter((d) => d?.parent === value);
56✔
47

48
    if (options.length) {
7✔
49
      updatedItems.push({
3✔
50
        options,
51
        value: null,
52
      });
53
    }
54
    const dropdownValues = updatedItems.filter((dd) => dd.value);
16✔
55
    const finalValues =
56
      updatedItems.length !== dropdownValues.length ? null : dropdownValues.map((dd) => dd.value);
7✔
57
    onChange(id, finalValues);
7✔
58

59
    if (finalValues) {
7✔
60
      const { options: selectedOptions, value: selectedValue } = dropdownValues.pop();
1✔
61
      const findSelected = selectedOptions?.find((o) => o.id === selectedValue) || [];
1!
62
      const cascadeName = findSelected?.name || null;
1!
63
      FormState.update((s) => {
1✔
64
        s.dataPointName = s.dataPointName.map((dn) =>
1✔
65
          dn.type === 'cascade' ? { ...dn, value: cascadeName } : dn,
×
66
        );
67
      });
68
    }
69
    setDropdownItems(updatedItems);
7✔
70
  };
71

72
  useEffect(() => {
34✔
73
    const parentID = source?.parent_id || 0;
33✔
74
    const filterDs = dataSource.filter(
33✔
75
      (ds) =>
76
        ds?.id === parentID ||
199✔
77
        ds?.parent === parentID ||
78
        (values[id] && (values[id].includes(ds?.id) || values[id].includes(ds?.parent))),
79
    );
80
    if (dropdownItems.length === 0 && dataSource.length && filterDs.length) {
33✔
81
      const groupedDs = groupBy(filterDs, 'parent');
12✔
82
      const initialDropdowns = Object.values(groupedDs).map((options, ox) => {
12✔
83
        return {
18✔
84
          options,
85
          value: values[id] ? values[id][ox] : null,
18✔
86
        };
87
      });
88
      setDropdownItems(initialDropdowns);
12✔
89
    }
90
  }, [dataSource, dropdownItems, source, values, id]);
91

92
  return (
34✔
93
    <View testID="view-type-cascade">
94
      <FieldLabel
95
        keyform={keyform}
96
        name={name}
97
        tooltip={tooltip}
98
        requiredSign={required ? requiredSign : null}
34✔
99
      />
100
      <Text testID="text-values" style={styles.cascadeValues}>
101
        {values[id]}
102
      </Text>
103
      <View style={styles.cascadeContainer}>
104
        {dropdownItems.map((item, index) => {
105
          return (
36✔
106
            <Dropdown
107
              key={index}
108
              labelField="name"
109
              valueField="id"
110
              testID={`dropdown-cascade-${index}`}
111
              data={item?.options}
112
              onChange={({ id: selectedID }) => handleOnChange(index, selectedID)}
7✔
113
              value={item.value}
114
              style={[styles.dropdownField]}
115
            />
116
          );
117
        })}
118
      </View>
119
    </View>
120
  );
121
};
122

123
export default TypeCascade;
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