@dhiraj0720/report1chart 3.0.8 → 3.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "3.0.8",
3
+ "version": "3.0.9",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
@@ -17,7 +17,46 @@ const normalizeCell = (value) => {
17
17
  return { text: String(value), color: '#2b3850', weight: '600' };
18
18
  };
19
19
 
20
- const ModernDataTable = ({ title, columns = [], rows = [], compact = false }) => {
20
+ const renderCell = (col, row, rowIndex, compact) => {
21
+ const raw = col.render ? col.render(row) : row[col.key];
22
+ const cell = normalizeCell(raw);
23
+
24
+ return (
25
+ <View
26
+ key={`cell-${rowIndex}-${col.key}`}
27
+ style={[
28
+ styles.cell,
29
+ { width: col.width || (compact ? 110 : 126) },
30
+ col.align === 'right' && styles.alignRight,
31
+ ]}
32
+ >
33
+ <Text
34
+ numberOfLines={1}
35
+ ellipsizeMode="tail"
36
+ style={[
37
+ styles.cellText,
38
+ { color: cell.color, fontWeight: cell.weight },
39
+ col.align === 'right' && styles.textRight,
40
+ col.align === 'center' && styles.textCenter,
41
+ ]}
42
+ >
43
+ {cell.text}
44
+ </Text>
45
+ </View>
46
+ );
47
+ };
48
+
49
+ const ModernDataTable = ({
50
+ title,
51
+ columns = [],
52
+ rows = [],
53
+ compact = false,
54
+ freezeFirstColumn = false,
55
+ }) => {
56
+ const firstColumn = columns[0];
57
+ const scrollColumns = columns.slice(1);
58
+ const shouldFreeze = freezeFirstColumn && columns.length > 1;
59
+
21
60
  return (
22
61
  <View style={styles.card}>
23
62
  <Text style={styles.title}>{title}</Text>
@@ -26,6 +65,84 @@ const ModernDataTable = ({ title, columns = [], rows = [], compact = false }) =>
26
65
  <View style={styles.emptyWrap}>
27
66
  <Text style={styles.emptyText}>No table data for selected filters.</Text>
28
67
  </View>
68
+ ) : shouldFreeze ? (
69
+ <View style={styles.freezeWrap}>
70
+ <View style={styles.frozenSide}>
71
+ <View style={styles.headerRow}>
72
+ <View
73
+ style={[
74
+ styles.cell,
75
+ styles.headerCell,
76
+ styles.frozenCell,
77
+ { width: firstColumn.width || (compact ? 110 : 126) },
78
+ firstColumn.align === 'right' && styles.alignRight,
79
+ ]}
80
+ >
81
+ <Text
82
+ style={[
83
+ styles.headerText,
84
+ firstColumn.align === 'right' && styles.textRight,
85
+ firstColumn.align === 'center' && styles.textCenter,
86
+ ]}
87
+ >
88
+ {firstColumn.label}
89
+ </Text>
90
+ </View>
91
+ </View>
92
+
93
+ {rows.map((row, rowIndex) => (
94
+ <View
95
+ key={`frozen-row-${rowIndex}`}
96
+ style={[
97
+ styles.dataRow,
98
+ rowIndex % 2 === 0 ? styles.rowEven : styles.rowOdd,
99
+ ]}
100
+ >
101
+ {renderCell(firstColumn, row, rowIndex, compact)}
102
+ </View>
103
+ ))}
104
+ </View>
105
+
106
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
107
+ <View>
108
+ <View style={styles.headerRow}>
109
+ {scrollColumns.map((col) => (
110
+ <View
111
+ key={`header-${col.key}`}
112
+ style={[
113
+ styles.cell,
114
+ styles.headerCell,
115
+ { width: col.width || (compact ? 110 : 126) },
116
+ col.align === 'right' && styles.alignRight,
117
+ ]}
118
+ >
119
+ <Text
120
+ style={[
121
+ styles.headerText,
122
+ col.align === 'right' && styles.textRight,
123
+ col.align === 'center' && styles.textCenter,
124
+ ]}
125
+ >
126
+ {col.label}
127
+ </Text>
128
+ </View>
129
+ ))}
130
+ </View>
131
+
132
+ {rows.map((row, rowIndex) => (
133
+ <View
134
+ key={`row-${rowIndex}`}
135
+ style={[
136
+ styles.dataRow,
137
+ rowIndex % 2 === 0 ? styles.rowEven : styles.rowOdd,
138
+ ]}
139
+ >
140
+ {scrollColumns.map((col) => renderCell(col, row, rowIndex, compact))}
141
+ </View>
142
+ ))}
143
+ </View>
144
+ </ScrollView>
145
+ </View>
29
146
  ) : (
30
147
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
31
148
  <View>
@@ -61,34 +178,7 @@ const ModernDataTable = ({ title, columns = [], rows = [], compact = false }) =>
61
178
  rowIndex % 2 === 0 ? styles.rowEven : styles.rowOdd,
62
179
  ]}
63
180
  >
64
- {columns.map((col) => {
65
- const raw = col.render ? col.render(row) : row[col.key];
66
- const cell = normalizeCell(raw);
67
-
68
- return (
69
- <View
70
- key={`cell-${rowIndex}-${col.key}`}
71
- style={[
72
- styles.cell,
73
- { width: col.width || (compact ? 110 : 126) },
74
- col.align === 'right' && styles.alignRight,
75
- ]}
76
- >
77
- <Text
78
- numberOfLines={1}
79
- ellipsizeMode="tail"
80
- style={[
81
- styles.cellText,
82
- { color: cell.color, fontWeight: cell.weight },
83
- col.align === 'right' && styles.textRight,
84
- col.align === 'center' && styles.textCenter,
85
- ]}
86
- >
87
- {cell.text}
88
- </Text>
89
- </View>
90
- );
91
- })}
181
+ {columns.map((col) => renderCell(col, row, rowIndex, compact))}
92
182
  </View>
93
183
  ))}
94
184
  </View>
@@ -113,6 +203,15 @@ const styles = StyleSheet.create({
113
203
  color: '#1c2f47',
114
204
  marginBottom: 8,
115
205
  },
206
+ freezeWrap: {
207
+ flexDirection: 'row',
208
+ },
209
+ frozenSide: {
210
+ borderRightWidth: 1,
211
+ borderRightColor: '#c7d7ef',
212
+ backgroundColor: '#fff',
213
+ zIndex: 2,
214
+ },
116
215
  headerRow: {
117
216
  flexDirection: 'row',
118
217
  backgroundColor: '#1f385a',
@@ -145,6 +244,9 @@ const styles = StyleSheet.create({
145
244
  borderRightColor: '#e2ebf7',
146
245
  justifyContent: 'center',
147
246
  },
247
+ frozenCell: {
248
+ borderRightColor: '#c7d7ef',
249
+ },
148
250
  cellText: {
149
251
  fontSize: 11.5,
150
252
  color: '#2b3850',
@@ -103,10 +103,6 @@ const Report1ModernScreen = ({ api, token, onBack }) => {
103
103
  return;
104
104
  }
105
105
 
106
- if (!force && loadedByTab[tabKey]) {
107
- return;
108
- }
109
-
110
106
  setLoading(true);
111
107
  setErrorByTab((prev) => ({ ...prev, [tabKey]: null }));
112
108
 
@@ -126,7 +122,7 @@ const Report1ModernScreen = ({ api, token, onBack }) => {
126
122
  } finally {
127
123
  setLoading(false);
128
124
  }
129
- }, [endpointByTab, loadedByTab, token]);
125
+ }, [endpointByTab, token]);
130
126
 
131
127
  useEffect(() => {
132
128
  loadTabData(activeTab);
@@ -331,6 +327,7 @@ const Report1ModernScreen = ({ api, token, onBack }) => {
331
327
 
332
328
  <ModernDataTable
333
329
  title="Performance Table"
330
+ freezeFirstColumn
334
331
  columns={[
335
332
  { key: 'name', label: 'Activity', width: 150 },
336
333
  { key: 'value2024', label: '2024', width: 120, align: 'right', render: (row) => formatNumber(row.value2024) },
@@ -27,6 +27,14 @@ const toPercent = (current, previous) => {
27
27
  return ((current - previous) / Math.abs(previous)) * 100;
28
28
  };
29
29
 
30
+ const toMonthKey = (value) => {
31
+ return String(value ?? '')
32
+ .trim()
33
+ .toLocaleUpperCase('tr-TR')
34
+ .normalize('NFD')
35
+ .replace(/[\u0300-\u036f]/g, '');
36
+ };
37
+
30
38
  const TrendBadge = ({ value }) => {
31
39
  const positive = value >= 0;
32
40
  return (
@@ -101,7 +109,8 @@ const Report2ModernScreen = ({ api, token, onBack }) => {
101
109
  if (!preserveSelection) {
102
110
  return monthLabels;
103
111
  }
104
- const kept = prev.filter((month) => monthLabels.includes(month));
112
+ const monthKeys = new Set(monthLabels.map(toMonthKey));
113
+ const kept = prev.filter((month) => monthKeys.has(toMonthKey(month)));
105
114
  return kept.length ? kept : monthLabels;
106
115
  });
107
116
  },
@@ -147,7 +156,8 @@ const Report2ModernScreen = ({ api, token, onBack }) => {
147
156
 
148
157
  const rows = useMemo(() => {
149
158
  if (!selectedMonths.length) return [];
150
- return baseRows.filter((row) => selectedMonths.includes(row.monthLabel));
159
+ const selectedKeys = new Set(selectedMonths.map(toMonthKey));
160
+ return baseRows.filter((row) => selectedKeys.has(toMonthKey(row.monthLabel)));
151
161
  }, [baseRows, selectedMonths]);
152
162
 
153
163
  const filteredLine = useMemo(() => {
@@ -298,6 +308,7 @@ const Report2ModernScreen = ({ api, token, onBack }) => {
298
308
 
299
309
  <ModernDataTable
300
310
  title="Gross Profit Table"
311
+ freezeFirstColumn
301
312
  columns={[
302
313
  { key: 'monthLabel', label: 'Month', width: 110 },
303
314
  { key: 'teu2024', label: '2024 TEU', width: 108, align: 'right', render: (row) => formatNumber(row.teu2024) },
@@ -35,6 +35,14 @@ const percentOf = (part, total) => {
35
35
  return (part / total) * 100;
36
36
  };
37
37
 
38
+ const toMonthKey = (value) => {
39
+ return String(value ?? '')
40
+ .trim()
41
+ .toLocaleUpperCase('tr-TR')
42
+ .normalize('NFD')
43
+ .replace(/[\u0300-\u036f]/g, '');
44
+ };
45
+
38
46
  const compactNumber = (value) => {
39
47
  const num = toNumber(value);
40
48
  if (Math.abs(num) >= 1000000000) return `${(num / 1000000000).toFixed(2)}B`;
@@ -120,7 +128,8 @@ const Report3ModernScreen = ({ api, token, onBack }) => {
120
128
  const months = lineRes?.labels || [];
121
129
  setSelectedMonths((prev) => {
122
130
  if (!preserveSelection) return months;
123
- const kept = prev.filter((month) => months.includes(month));
131
+ const monthKeys = new Set(months.map(toMonthKey));
132
+ const kept = prev.filter((month) => monthKeys.has(toMonthKey(month)));
124
133
  return kept.length ? kept : months;
125
134
  });
126
135
  },
@@ -153,7 +162,8 @@ const Report3ModernScreen = ({ api, token, onBack }) => {
153
162
 
154
163
  const rows = useMemo(() => {
155
164
  if (!selectedMonths.length) return [];
156
- return baseRows.filter((row) => selectedMonths.includes(row.monthLabel));
165
+ const selectedKeys = new Set(selectedMonths.map(toMonthKey));
166
+ return baseRows.filter((row) => selectedKeys.has(toMonthKey(row.monthLabel)));
157
167
  }, [baseRows, selectedMonths]);
158
168
 
159
169
  const filteredLine = useMemo(() => {
@@ -368,6 +378,7 @@ const Report3ModernScreen = ({ api, token, onBack }) => {
368
378
 
369
379
  <ModernDataTable
370
380
  title="Transportation Table"
381
+ freezeFirstColumn
371
382
  columns={[
372
383
  { key: 'monthLabel', label: 'Month', width: 110 },
373
384
  { key: 'loadCount2024', label: '2024 Load', width: 110, align: 'right', render: (row) => compactNumber(row.loadCount2024) },
@@ -12,8 +12,17 @@ export const filterChartByMonths = (chart, selectedMonths) => {
12
12
  };
13
13
  }
14
14
 
15
+ const toMonthKey = (value) => {
16
+ return String(value ?? '')
17
+ .trim()
18
+ .toLocaleUpperCase('tr-TR')
19
+ .normalize('NFD')
20
+ .replace(/[\u0300-\u036f]/g, '');
21
+ };
22
+ const selectedKeys = new Set(selectedMonths.map(toMonthKey));
23
+
15
24
  const indices = chart.labels
16
- .map((label, i) => (selectedMonths.includes(label) ? i : -1))
25
+ .map((label, i) => (selectedKeys.has(toMonthKey(label)) ? i : -1))
17
26
  .filter(i => i !== -1);
18
27
 
19
28
  return {