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

DLR-SC / ESID / 16340431869

17 Jul 2025 08:42AM UTC coverage: 52.615% (+0.5%) from 52.16%
16340431869

push

github

JonasGilg
:sparkles: Formatting.

473 of 607 branches covered (77.92%)

Branch coverage included in aggregate %.

4527 of 8896 relevant lines covered (50.89%)

10.59 hits per line

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

98.46
/src/components/ScenarioComponents/CardsComponents/DataCard.tsx
1
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
2
// SPDX-License-Identifier: Apache-2.0
3

4
import Box from '@mui/material/Box';
1✔
5
import React, {Dispatch, useEffect, useMemo, useState} from 'react';
1✔
6
import MainCard from './MainCard/MainCard';
1✔
7
import FiltersContainer from './GroupFilter/FiltersContainer';
1✔
8
import {FilterValues} from 'types/card';
9
import {GroupFilter} from 'types/group';
10
import {Localization} from 'types/localization';
11
import {useSortable} from '@dnd-kit/sortable';
1✔
12
import {CSS} from '@dnd-kit/utilities';
1✔
13

14
interface DataCardProps {
15
  /** A unique identifier for the card.*/
16
  id: string;
17

18
  /** A dictionary of compartment values associated with the card.*/
19
  compartmentValues: Record<string, number | null> | null;
20

21
  /** A dictionary of start values used for calculating the rate. This determines whether the values have increased, decreased, or remained the same. */
22
  referenceValues: Record<string, number> | null;
23

24
  /** The title of the card.*/
25
  title: string;
26

27
  /** A description of the card's contents. */
28
  description?: JSX.Element;
29

30
  /** A boolean indicating whether the compartments are expanded.*/
31
  compartmentsExpanded: boolean;
32

33
  /** The compartment that is currently selected.*/
34
  selectedCompartmentId: string | null;
35

36
  /** A boolean indicating whether the scenario is selected.*/
37
  isSelected: boolean;
38

39
  /** The color of the card.*/
40
  color: string;
41

42
  /** if this scenario is active.*/
43
  isActive: boolean;
44

45
  /** A dictionary of filter values. This is an array of objects, each containing a title and a dictionary of numbers representing
46
   * the filtered information to be displayed, it's used a disctionary because each card has to have the same amount of filter. */
47
  filterValues?: Record<string, FilterValues[]> | null;
48

49
  /** A function to set the selected scenario.*/
50
  setSelected: Dispatch<{id: string; state: boolean}>;
51

52
  /** A function to set the active scenario.*/
53
  setActive: Dispatch<{id: string; state: boolean}>;
54

55
  /** A function to notify the parent that this scenario wants to be removed. */
56
  remove: Dispatch<string>;
57

58
  /** The minimum number of compartment rows.*/
59
  minCompartmentsRows: number;
60

61
  /** The maximum number of compartment rows.*/
62
  maxCompartmentsRows: number;
63

64
  /** An object containing localization information (translation & number formattation).*/
65
  localization?: Localization;
66

67
  /** A dictionary of group filters.*/
68
  groupFilters: Record<string, GroupFilter> | undefined;
69

70
  /** Boolean to determine if the card is draggable */
71
  draggable: boolean;
72

73
  /** Boolean to determine if the arrow is displayed */
74
  arrow?: boolean;
75
}
76

77
/**
78
 * This component renders a card for either the case data or the scenario cards. Each card contains a title, a list of
79
 * compartment values, and change rates relative to the simulation start. Additionally, the component includes a filter container.
80
 * The filter container renders a button and generates the necessary number of cards based on the presence of any filters.
81
 */
82
export default function DataCard({
22✔
83
  id,
22✔
84
  compartmentValues,
22✔
85
  referenceValues,
22✔
86
  title,
22✔
87
  description,
22✔
88
  compartmentsExpanded,
22✔
89
  selectedCompartmentId,
22✔
90
  filterValues,
22✔
91
  color,
22✔
92
  isActive,
22✔
93
  isSelected,
22✔
94
  minCompartmentsRows,
22✔
95
  maxCompartmentsRows,
22✔
96
  setSelected,
22✔
97
  setActive,
22✔
98
  remove,
22✔
99
  localization = {
22✔
100
    formatNumber: (value: number) => value.toString(),
22✔
101
    customLang: 'global',
22✔
102
    overrides: {},
22✔
103
  },
22✔
104
  groupFilters,
22✔
105
  draggable,
22✔
106
  arrow = true,
22✔
107
}: DataCardProps) {
22✔
108
  const [folded, setFolded] = useState<boolean>(false);
22✔
109
  const [visibility, setVisibility] = useState<boolean>(true);
22✔
110

111
  // drag and drop
112
  const {attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging, transition} = useSortable({
22✔
113
    id,
22✔
114
    disabled: {
22✔
115
      draggable: !draggable,
22✔
116
      droppable: !draggable,
22✔
117
    },
22✔
118
  });
22✔
119

120
  const filteredTitles: string[] = useMemo(() => {
22✔
121
    if (isActive && filterValues?.[id.toString()]) {
13✔
122
      return filterValues[id.toString()].map((filterValue: FilterValues) => filterValue.filteredTitle);
4✔
123
    }
4✔
124
    return [];
9✔
125
  }, [isActive, filterValues, id]);
22✔
126

127
  const filteredValues = useMemo(() => {
22✔
128
    if (isActive && filterValues?.[id.toString()]) {
13✔
129
      return filterValues[id.toString()].map((filterValue: FilterValues) => filterValue.filteredValues);
4✔
130
    }
4✔
131
    return [];
9✔
132
  }, [isActive, filterValues, id]);
22✔
133

134
  /*
135
   * This useEffect hook updates the visibility of the component based on groupFilters and filteredTitles.
136
   * It checks if the first title in filteredTitles matches any filter name in groupFilters and if that filter is visible.
137
   * If at least one matching filter is visible, the component becomes visible; otherwise, it remains hidden.
138
   */
139
  useEffect(() => {
22✔
140
    function checkVisibility(): boolean {
13✔
141
      if (groupFilters) {
13✔
142
        return Object.values(groupFilters)
13✔
143
          .map((filter) => (filter.name == filteredTitles[0] ? filter.isVisible : false))
13✔
144
          .includes(true);
13✔
145
      }
13!
146
      return false;
×
147
    }
13✔
148
    setVisibility(checkVisibility);
13✔
149
  }, [filteredTitles, groupFilters]);
22✔
150

151
  return (
22✔
152
    <Box
22✔
153
      id={`data-card-${id}`}
22✔
154
      sx={{
22✔
155
        display: 'flex',
22✔
156
        flexDirection: 'row',
22✔
157
        alignItems: 'flex-start',
22✔
158
        transform: CSS.Transform.toString(transform),
22✔
159
        transition,
22✔
160
      }}
22✔
161
      ref={setNodeRef}
22✔
162
    >
163
      <MainCard
22✔
164
        id={id}
22✔
165
        description={description}
22✔
166
        label={title}
22✔
167
        color={color}
22✔
168
        referenceValues={referenceValues}
22✔
169
        compartmentValues={compartmentValues}
22✔
170
        compartmentsExpanded={compartmentsExpanded}
22✔
171
        selectedCompartmentId={selectedCompartmentId}
22✔
172
        isSelected={isSelected}
22✔
173
        isActive={isActive}
22✔
174
        setSelected={setSelected}
22✔
175
        setActive={setActive}
22✔
176
        hide={remove}
22✔
177
        minCompartmentsRows={minCompartmentsRows}
22✔
178
        maxCompartmentsRows={maxCompartmentsRows}
22✔
179
        localization={localization}
22✔
180
        arrow={arrow}
22✔
181
        dragListeners={listeners}
22✔
182
        dragAttributes={attributes}
22✔
183
        draggable={draggable}
22✔
184
        setActivatorNodeRef={setActivatorNodeRef}
22✔
185
        isDragging={isDragging}
22✔
186
      />
22✔
187
      {isActive && filterValues?.[id.toString()] && Object.keys(groupFilters || {}).length !== 0 && visibility && (
22✔
188
        <FiltersContainer
4✔
189
          id={id}
4✔
190
          color={color}
4✔
191
          filteredTitles={filteredTitles}
4✔
192
          folded={folded}
4✔
193
          setFolded={setFolded}
4✔
194
          compartmentsExpanded={compartmentsExpanded}
4✔
195
          selectedCompartmentId={selectedCompartmentId}
4✔
196
          filteredValues={filteredValues}
4✔
197
          minCompartmentsRows={minCompartmentsRows}
4✔
198
          maxCompartmentsRows={maxCompartmentsRows}
4✔
199
          localization={localization}
4✔
200
        />
4✔
201
      )}
202
    </Box>
22✔
203
  );
204
}
22✔
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