@dhiraj0720/report1chart 2.2.7 → 2.2.8

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,12 +1,13 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "2.2.7",
3
+ "version": "2.2.8",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
7
7
  },
8
8
  "dependencies": {
9
- "axios": "^1.13.2"
9
+ "axios": "^1.13.2",
10
+ "react-native-svg": "^15.15.1"
10
11
  },
11
12
  "peerDependencies": {
12
13
  "react": ">=16.8.0",
@@ -21,6 +22,5 @@
21
22
  ],
22
23
  "author": "Dhiraj",
23
24
  "license": "MIT",
24
- "description": "A simple report chart and table package for React Native",
25
- "devDependencies": {}
25
+ "description": "A simple report chart and table package for React Native"
26
26
  }
@@ -0,0 +1,96 @@
1
+ import React from 'react';
2
+ import { View, Text, StyleSheet } from 'react-native';
3
+
4
+ const BarLineChart = ({ data }) => {
5
+ if (!data?.series?.length) return null;
6
+
7
+ const max = Math.max(...data.series.flatMap(s => s.data));
8
+
9
+ return (
10
+ <View style={styles.container}>
11
+ <Text style={styles.title}>{data.title}</Text>
12
+
13
+ <View style={styles.chart}>
14
+ {data.labels.map((label, i) => (
15
+ <View key={label} style={styles.group}>
16
+ {data.series.map((s, idx) => {
17
+ const height = (s.data[i] / max) * 120;
18
+ return (
19
+ <View
20
+ key={idx}
21
+ style={[
22
+ styles.bar,
23
+ {
24
+ height,
25
+ backgroundColor:
26
+ idx === 0
27
+ ? '#FB8C00'
28
+ : idx === 1
29
+ ? '#1E88E5'
30
+ : '#90CAF9',
31
+ },
32
+ ]}
33
+ />
34
+ );
35
+ })}
36
+ <Text style={styles.label}>{label}</Text>
37
+ </View>
38
+ ))}
39
+ </View>
40
+
41
+ <View style={styles.legend}>
42
+ {data.series.map(s => (
43
+ <Text key={s.name} style={styles.legendText}>
44
+ ■ {s.name}
45
+ </Text>
46
+ ))}
47
+ </View>
48
+ </View>
49
+ );
50
+ };
51
+
52
+ export default BarLineChart;
53
+
54
+ const styles = StyleSheet.create({
55
+ container: {
56
+ backgroundColor: '#fff',
57
+ padding: 12,
58
+ borderRadius: 12,
59
+ marginVertical: 12,
60
+ },
61
+ title: {
62
+ fontWeight: '700',
63
+ marginBottom: 8,
64
+ textAlign: 'center',
65
+ },
66
+ chart: {
67
+ flexDirection: 'row',
68
+ alignItems: 'flex-end',
69
+ justifyContent: 'space-around',
70
+ height: 160,
71
+ },
72
+ group: {
73
+ alignItems: 'center',
74
+ flexDirection: 'row',
75
+ },
76
+ bar: {
77
+ width: 10,
78
+ marginHorizontal: 2,
79
+ borderRadius: 2,
80
+ },
81
+ label: {
82
+ fontSize: 10,
83
+ marginTop: 4,
84
+ position: 'absolute',
85
+ bottom: -16,
86
+ },
87
+ legend: {
88
+ flexDirection: 'row',
89
+ justifyContent: 'center',
90
+ marginTop: 16,
91
+ },
92
+ legendText: {
93
+ fontSize: 12,
94
+ marginHorizontal: 8,
95
+ },
96
+ });
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { ScrollView, Text, TouchableOpacity, StyleSheet } from 'react-native';
2
+ import { ScrollView, TouchableOpacity, Text, StyleSheet } from 'react-native';
3
3
 
4
4
  const DivisionSelector = ({ divisions, selected, onSelect }) => (
5
5
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
+
4
+ const Cell = ({ children, bold }) => (
5
+ <Text style={[styles.cell, bold && styles.bold]}>{children}</Text>
6
+ );
7
+
8
+ const FrozenTableReport2 = ({ rows }) => (
9
+ <View style={styles.container}>
10
+ <View style={styles.frozen}>
11
+ <Cell bold>AY</Cell>
12
+ {rows.map((r, i) => (
13
+ <Cell key={i} bold={r.monthLabel === 'Total'}>{r.monthLabel}</Cell>
14
+ ))}
15
+ </View>
16
+
17
+ <ScrollView horizontal>
18
+ <View>
19
+ <View style={styles.headerRow}>
20
+ {[
21
+ '2024 TEU','2025 TEU','TEU %',
22
+ '2024 Kar','2025 Kar','Kar %',
23
+ '2025 Bütçe','Bütçe %'
24
+ ].map(h => <Cell key={h} bold>{h}</Cell>)}
25
+ </View>
26
+
27
+ {rows.map((r, i) => (
28
+ <View key={i} style={styles.row}>
29
+ <Cell>{r.teu2024}</Cell>
30
+ <Cell>{r.teu2025}</Cell>
31
+ <Cell>{r.teuChangePercent}%</Cell>
32
+ <Cell>{r.profitUsd2024}</Cell>
33
+ <Cell>{r.profitUsd2025}</Cell>
34
+ <Cell>{r.profitChangePercent}%</Cell>
35
+ <Cell>{r.budgetProfitUsd2025}</Cell>
36
+ <Cell>{r.budgetChangePercent}%</Cell>
37
+ </View>
38
+ ))}
39
+ </View>
40
+ </ScrollView>
41
+ </View>
42
+ );
43
+
44
+ export default FrozenTableReport2;
45
+
46
+ const styles = StyleSheet.create({
47
+ container: { flexDirection: 'row' },
48
+ frozen: { width: 90, backgroundColor: '#f4f4f4' },
49
+ headerRow: { flexDirection: 'row', backgroundColor: '#f4f4f4' },
50
+ row: { flexDirection: 'row' },
51
+ cell: {
52
+ width: 90,
53
+ padding: 8,
54
+ textAlign: 'center',
55
+ borderBottomWidth: 1,
56
+ borderColor: '#ddd',
57
+ },
58
+ bold: { fontWeight: '700' },
59
+ });
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
+
4
+ const Cell = ({ children, bold }) => (
5
+ <Text style={[styles.cell, bold && styles.bold]}>{children}</Text>
6
+ );
7
+
8
+ const FrozenTableReport3 = ({ rows }) => (
9
+ <View style={styles.container}>
10
+ <View style={styles.frozen}>
11
+ <Cell bold>AY</Cell>
12
+ {rows.map((r, i) => (
13
+ <Cell key={i} bold={r.monthLabel === 'Total'}>{r.monthLabel}</Cell>
14
+ ))}
15
+ </View>
16
+
17
+ <ScrollView horizontal>
18
+ <View>
19
+ <View style={styles.headerRow}>
20
+ {[
21
+ '2024 Yük','2025 Yük','Yük %',
22
+ '2024 Gelir','2025 Gelir','Gelir %',
23
+ '2025 Bütçe','Bütçe %'
24
+ ].map(h => <Cell key={h} bold>{h}</Cell>)}
25
+ </View>
26
+
27
+ {rows.map((r, i) => (
28
+ <View key={i} style={styles.row}>
29
+ <Cell>{r.loadCount2024}</Cell>
30
+ <Cell>{r.loadCount2025}</Cell>
31
+ <Cell>{r.loadCountChangePercent}%</Cell>
32
+ <Cell>{r.revenueTl2024}</Cell>
33
+ <Cell>{r.revenueTl2025}</Cell>
34
+ <Cell>{r.revenueChangePercent}%</Cell>
35
+ <Cell>{r.budgetRevenueTl2025}</Cell>
36
+ <Cell>{r.budgetChangePercent}%</Cell>
37
+ </View>
38
+ ))}
39
+ </View>
40
+ </ScrollView>
41
+ </View>
42
+ );
43
+
44
+ export default FrozenTableReport3;
45
+
46
+ const styles = StyleSheet.create({
47
+ container: { flexDirection: 'row' },
48
+ frozen: { width: 90, backgroundColor: '#f4f4f4' },
49
+ headerRow: { flexDirection: 'row', backgroundColor: '#f4f4f4' },
50
+ row: { flexDirection: 'row' },
51
+ cell: {
52
+ width: 100,
53
+ padding: 8,
54
+ textAlign: 'center',
55
+ borderBottomWidth: 1,
56
+ borderColor: '#ddd',
57
+ },
58
+ bold: { fontWeight: '700' },
59
+ });
@@ -1,35 +1,47 @@
1
1
  import React from 'react';
2
- import { View, Text, ScrollView, StyleSheet } from 'react-native';
2
+ import { View, Text, StyleSheet } from 'react-native';
3
3
 
4
4
  const LineChart = ({ data }) => {
5
- if (!data?.series) return null;
5
+ if (!data?.series?.length) return null;
6
6
 
7
7
  const max = Math.max(...data.series.flatMap(s => s.data));
8
8
 
9
9
  return (
10
10
  <View style={styles.container}>
11
11
  <Text style={styles.title}>{data.title}</Text>
12
- <ScrollView horizontal>
13
- <View style={styles.chart}>
14
- {data.labels.map((label, i) => (
15
- <View key={i} style={styles.column}>
16
- {data.series.map((s, idx) => (
17
- <View
18
- key={idx}
19
- style={[
20
- styles.bar,
21
- {
22
- height: (s.data[i] / max) * 120,
23
- backgroundColor: idx === 0 ? '#2962FF' : '#9E9E9E'
24
- }
25
- ]}
26
- />
27
- ))}
28
- <Text style={styles.label}>{label}</Text>
12
+
13
+ <View style={styles.chart}>
14
+ {data.labels.map((label, i) => (
15
+ <View key={label} style={styles.column}>
16
+ <View style={styles.lines}>
17
+ {data.series.map((s, idx) => {
18
+ const height = (s.data[i] / max) * 120;
19
+ return (
20
+ <View
21
+ key={idx}
22
+ style={[
23
+ styles.point,
24
+ {
25
+ bottom: height,
26
+ backgroundColor: idx === 0 ? '#FB8C00' : '#1E88E5',
27
+ },
28
+ ]}
29
+ />
30
+ );
31
+ })}
29
32
  </View>
30
- ))}
31
- </View>
32
- </ScrollView>
33
+ <Text style={styles.label}>{label}</Text>
34
+ </View>
35
+ ))}
36
+ </View>
37
+
38
+ <View style={styles.legend}>
39
+ {data.series.map((s, i) => (
40
+ <Text key={s.name} style={styles.legendText}>
41
+ ● {s.name}
42
+ </Text>
43
+ ))}
44
+ </View>
33
45
  </View>
34
46
  );
35
47
  };
@@ -37,10 +49,47 @@ const LineChart = ({ data }) => {
37
49
  export default LineChart;
38
50
 
39
51
  const styles = StyleSheet.create({
40
- container: { marginVertical: 12 },
41
- title: { fontWeight: '700', marginBottom: 8 },
42
- chart: { flexDirection: 'row', alignItems: 'flex-end' },
43
- column: { alignItems: 'center', marginHorizontal: 6 },
44
- bar: { width: 8, marginHorizontal: 1, borderRadius: 2 },
45
- label: { fontSize: 10, marginTop: 4 }
52
+ container: {
53
+ backgroundColor: '#fff',
54
+ padding: 12,
55
+ borderRadius: 12,
56
+ marginVertical: 12,
57
+ },
58
+ title: {
59
+ fontWeight: '700',
60
+ marginBottom: 8,
61
+ textAlign: 'center',
62
+ },
63
+ chart: {
64
+ flexDirection: 'row',
65
+ justifyContent: 'space-around',
66
+ height: 160,
67
+ },
68
+ column: {
69
+ alignItems: 'center',
70
+ width: 40,
71
+ },
72
+ lines: {
73
+ flex: 1,
74
+ justifyContent: 'flex-end',
75
+ },
76
+ point: {
77
+ width: 8,
78
+ height: 8,
79
+ borderRadius: 4,
80
+ position: 'absolute',
81
+ },
82
+ label: {
83
+ fontSize: 10,
84
+ marginTop: 4,
85
+ },
86
+ legend: {
87
+ flexDirection: 'row',
88
+ justifyContent: 'center',
89
+ marginTop: 8,
90
+ },
91
+ legendText: {
92
+ fontSize: 12,
93
+ marginHorizontal: 8,
94
+ },
46
95
  });
@@ -1,28 +1,28 @@
1
1
  import React from 'react';
2
2
  import { ScrollView, TouchableOpacity, Text, StyleSheet } from 'react-native';
3
3
 
4
- const MonthSelector = ({ months, selected, onSelect }) => {
5
- return (
6
- <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.row}>
4
+ const MonthSelector = ({ months, selected, onSelect }) => (
5
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.row}>
6
+ <TouchableOpacity
7
+ style={[styles.btn, selected === 'ALL' && styles.active]}
8
+ onPress={() => onSelect('ALL')}
9
+ >
10
+ <Text style={styles.text}>Select all</Text>
11
+ </TouchableOpacity>
12
+
13
+ {months.map(m => (
7
14
  <TouchableOpacity
8
- style={[styles.btn, selected === 'ALL' && styles.active]}
9
- onPress={() => onSelect('ALL')}
15
+ key={m}
16
+ style={[styles.btn, selected === m && styles.active]}
17
+ onPress={() => onSelect(m)}
10
18
  >
11
- <Text style={styles.text}>Select all</Text>
19
+ <Text style={styles.text}>{m}</Text>
12
20
  </TouchableOpacity>
21
+ ))}
22
+ </ScrollView>
23
+ );
13
24
 
14
- {months.map(m => (
15
- <TouchableOpacity
16
- key={m}
17
- style={[styles.btn, selected === m && styles.active]}
18
- onPress={() => onSelect(m)}
19
- >
20
- <Text style={styles.text}>{m}</Text>
21
- </TouchableOpacity>
22
- ))}
23
- </ScrollView>
24
- );
25
- };
25
+ export default MonthSelector;
26
26
 
27
27
  const styles = StyleSheet.create({
28
28
  row: { paddingVertical: 10 },
@@ -33,13 +33,6 @@ const styles = StyleSheet.create({
33
33
  backgroundColor: '#eef2f7',
34
34
  marginRight: 8,
35
35
  },
36
- active: {
37
- backgroundColor: '#0f172a',
38
- },
39
- text: {
40
- color: '#000',
41
- fontWeight: '600',
42
- },
36
+ active: { backgroundColor: '#0f172a' },
37
+ text: { color: '#000', fontWeight: '600' },
43
38
  });
44
-
45
- export default MonthSelector;
@@ -23,6 +23,6 @@ const styles = StyleSheet.create({
23
23
  },
24
24
  fill: {
25
25
  height: '100%',
26
- backgroundColor: '#f57c00', // orange like original
26
+ backgroundColor: '#f57c00',
27
27
  },
28
28
  });
@@ -2,13 +2,13 @@ import React from 'react';
2
2
  import { View, Text, StyleSheet } from 'react-native';
3
3
  import ProgressBar from './ProgressBar';
4
4
 
5
- const format = (num) => (num ?? 0).toLocaleString();
5
+ const format = n => (n ?? 0).toLocaleString();
6
6
 
7
7
  const Trend = ({ value }) => {
8
- const positive = value >= 0;
8
+ const up = value >= 0;
9
9
  return (
10
- <Text style={[styles.trend, positive ? styles.up : styles.down]}>
11
- {positive ? '↑' : '↓'} {Math.abs(value)}%
10
+ <Text style={[styles.trend, up ? styles.up : styles.down]}>
11
+ {up ? '↑' : '↓'} {Math.abs(value)}%
12
12
  </Text>
13
13
  );
14
14
  };
@@ -23,10 +23,8 @@ const Row = ({ label, value }) => (
23
23
  const Report1Card = ({ item }) => {
24
24
  return (
25
25
  <View style={styles.card}>
26
- {/* TITLE */}
27
26
  <Text style={styles.title}>{item.name}</Text>
28
27
 
29
- {/* VALUES */}
30
28
  <Row label="2024 Actual" value={format(item.actual2024)} />
31
29
  <Row label="2025 Actual" value={format(item.actual2025)} />
32
30
 
@@ -42,16 +40,14 @@ const Report1Card = ({ item }) => {
42
40
  <Trend value={item.budgetVariancePercent} />
43
41
  </View>
44
42
 
45
- {/* OPEX / GROSS PROFIT */}
46
43
  {item.opexToGrossProfitPercent !== undefined && (
47
44
  <>
48
45
  <View style={styles.row}>
49
- <Text style={styles.label}>OPEX / Gross Profit</Text>
46
+ <Text style={styles.label}>Faaliyet Gid. / Brüt Kar</Text>
50
47
  <Text style={styles.value}>
51
48
  {item.opexToGrossProfitPercent}%
52
49
  </Text>
53
50
  </View>
54
-
55
51
  <ProgressBar value={item.opexToGrossProfitPercent} />
56
52
  </>
57
53
  )}
@@ -74,7 +70,6 @@ const styles = StyleSheet.create({
74
70
  fontSize: 16,
75
71
  fontWeight: '700',
76
72
  marginBottom: 12,
77
- color: '#000',
78
73
  },
79
74
  row: {
80
75
  flexDirection: 'row',
@@ -88,16 +83,11 @@ const styles = StyleSheet.create({
88
83
  value: {
89
84
  fontSize: 13,
90
85
  fontWeight: '600',
91
- color: '#000',
92
86
  },
93
87
  trend: {
94
88
  fontSize: 13,
95
89
  fontWeight: '700',
96
90
  },
97
- up: {
98
- color: '#2e7d32',
99
- },
100
- down: {
101
- color: '#d32f2f',
102
- },
91
+ up: { color: '#2e7d32' },
92
+ down: { color: '#d32f2f' },
103
93
  });
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import { View, Text } from 'react-native';
3
+ import Svg, { Rect, Polyline, Circle, Text as SvgText } from 'react-native-svg';
4
+
5
+ const SvgBarLineChart = ({ data }) => {
6
+ if (!data?.series?.length) return null;
7
+
8
+ const width = 360;
9
+ const height = 190;
10
+ const padding = 30;
11
+ const barWidth = 12;
12
+
13
+ const max = Math.max(...data.series.flatMap(s => s.data));
14
+
15
+ const scaleX = i =>
16
+ padding + i * ((width - padding * 2) / data.labels.length);
17
+
18
+ const scaleY = v =>
19
+ height - padding - (v / max) * (height - padding * 2);
20
+
21
+ return (
22
+ <View style={{ backgroundColor: '#fff', padding: 12, borderRadius: 12 }}>
23
+ <Text style={{ fontWeight: '700', textAlign: 'center', marginBottom: 8 }}>
24
+ {data.title}
25
+ </Text>
26
+
27
+ <Svg width={width} height={height}>
28
+ {/* Bars */}
29
+ {data.labels.map((_, i) =>
30
+ data.series.slice(0, 2).map((s, idx) => (
31
+ <Rect
32
+ key={`${i}-${idx}`}
33
+ x={scaleX(i) + idx * (barWidth + 4)}
34
+ y={scaleY(s.data[i])}
35
+ width={barWidth}
36
+ height={height - padding - scaleY(s.data[i])}
37
+ fill={idx === 0 ? '#FB8C00' : '#1E88E5'}
38
+ rx="2"
39
+ />
40
+ ))
41
+ )}
42
+
43
+ {/* Budget dotted line */}
44
+ {data.series[2] && (
45
+ <>
46
+ <Polyline
47
+ points={data.series[2].data
48
+ .map((v, i) => `${scaleX(i) + barWidth},${scaleY(v)}`)
49
+ .join(' ')}
50
+ fill="none"
51
+ stroke="#90CAF9"
52
+ strokeWidth="2"
53
+ strokeDasharray="4,4"
54
+ />
55
+
56
+ {data.series[2].data.map((v, i) => (
57
+ <Circle
58
+ key={i}
59
+ cx={scaleX(i) + barWidth}
60
+ cy={scaleY(v)}
61
+ r="4"
62
+ fill="#90CAF9"
63
+ />
64
+ ))}
65
+ </>
66
+ )}
67
+
68
+ {/* Value labels */}
69
+ {data.series[2]?.data.map((v, i) => (
70
+ <SvgText
71
+ key={i}
72
+ x={scaleX(i) + barWidth}
73
+ y={scaleY(v) - 8}
74
+ fontSize="9"
75
+ fill="#333"
76
+ textAnchor="middle"
77
+ >
78
+ {(v / 1_000_000).toFixed(0)}M
79
+ </SvgText>
80
+ ))}
81
+ </Svg>
82
+ </View>
83
+ );
84
+ };
85
+
86
+ export default SvgBarLineChart;
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import { View, Text } from 'react-native';
3
+ import Svg, { Polyline, Circle, Line, Text as SvgText } from 'react-native-svg';
4
+
5
+ const SvgLineChart = ({ data }) => {
6
+ if (!data?.series?.length) return null;
7
+
8
+ const width = 340;
9
+ const height = 180;
10
+ const padding = 30;
11
+
12
+ const allValues = data.series.flatMap(s => s.data);
13
+ const max = Math.max(...allValues);
14
+ const min = Math.min(...allValues);
15
+
16
+ const scaleX = i =>
17
+ padding + (i * (width - padding * 2)) / (data.labels.length - 1);
18
+
19
+ const scaleY = v =>
20
+ height - padding - ((v - min) / (max - min)) * (height - padding * 2);
21
+
22
+ return (
23
+ <View style={{ backgroundColor: '#fff', padding: 12, borderRadius: 12 }}>
24
+ <Text style={{ fontWeight: '700', textAlign: 'center', marginBottom: 8 }}>
25
+ {data.title}
26
+ </Text>
27
+
28
+ <Svg width={width} height={height}>
29
+ {/* Grid */}
30
+ {[0.25, 0.5, 0.75].map(p => (
31
+ <Line
32
+ key={p}
33
+ x1={padding}
34
+ x2={width - padding}
35
+ y1={padding + p * (height - padding * 2)}
36
+ y2={padding + p * (height - padding * 2)}
37
+ stroke="#e0e0e0"
38
+ strokeDasharray="4,4"
39
+ />
40
+ ))}
41
+
42
+ {/* Lines */}
43
+ {data.series.map((s, idx) => {
44
+ const points = s.data
45
+ .map((v, i) => `${scaleX(i)},${scaleY(v)}`)
46
+ .join(' ');
47
+
48
+ return (
49
+ <Polyline
50
+ key={s.name}
51
+ points={points}
52
+ fill="none"
53
+ stroke={idx === 0 ? '#FB8C00' : '#1E88E5'}
54
+ strokeWidth="2"
55
+ />
56
+ );
57
+ })}
58
+
59
+ {/* Points + Labels */}
60
+ {data.series.map((s, idx) =>
61
+ s.data.map((v, i) => (
62
+ <React.Fragment key={`${idx}-${i}`}>
63
+ <Circle
64
+ cx={scaleX(i)}
65
+ cy={scaleY(v)}
66
+ r="4"
67
+ fill={idx === 0 ? '#FB8C00' : '#1E88E5'}
68
+ />
69
+ <SvgText
70
+ x={scaleX(i)}
71
+ y={scaleY(v) - 8}
72
+ fontSize="9"
73
+ fill="#333"
74
+ textAnchor="middle"
75
+ >
76
+ {v}
77
+ </SvgText>
78
+ </React.Fragment>
79
+ ))
80
+ )}
81
+ </Svg>
82
+ </View>
83
+ );
84
+ };
85
+
86
+ export default SvgLineChart;
package/src/index.jsx CHANGED
@@ -6,38 +6,38 @@ import Report2Screen from './screens/Report2Screen';
6
6
  import Report3Screen from './screens/Report3Screen';
7
7
 
8
8
  const AnalyticsReports = ({ config }) => {
9
- const [activeReport, setActiveReport] = useState(null);
9
+ const [active, setActive] = useState(null);
10
10
 
11
- if (!activeReport) {
12
- return <ReportListScreen onSelect={setActiveReport} />;
11
+ if (!active) {
12
+ return <ReportListScreen onSelect={setActive} />;
13
13
  }
14
14
 
15
- if (activeReport === 1) {
15
+ if (active === 1) {
16
16
  return (
17
17
  <Report1Screen
18
- api={config.report1}
18
+ endpoint={config.report1.url}
19
19
  token={config.token}
20
- onBack={() => setActiveReport(null)}
20
+ onBack={() => setActive(null)}
21
21
  />
22
22
  );
23
23
  }
24
24
 
25
- if (activeReport === 2) {
25
+ if (active === 2) {
26
26
  return (
27
27
  <Report2Screen
28
28
  api={config.report2}
29
29
  token={config.token}
30
- onBack={() => setActiveReport(null)}
30
+ onBack={() => setActive(null)}
31
31
  />
32
32
  );
33
33
  }
34
34
 
35
- if (activeReport === 3) {
35
+ if (active === 3) {
36
36
  return (
37
37
  <Report3Screen
38
38
  api={config.report3}
39
39
  token={config.token}
40
- onBack={() => setActiveReport(null)}
40
+ onBack={() => setActive(null)}
41
41
  />
42
42
  );
43
43
  }
@@ -3,18 +3,22 @@ import { ScrollView, Text, ActivityIndicator } from 'react-native';
3
3
  import fetchReport1 from '../api/report1Fetcher';
4
4
  import Report1Card from '../components/Report1Card';
5
5
 
6
- const Report1Screen = ({ report1Endpoint, token, onBack }) => {
6
+ const Report1Screen = ({ endpoint, token, onBack }) => {
7
7
  const [rows, setRows] = useState(null);
8
8
 
9
9
  useEffect(() => {
10
- fetchReport1(report1Endpoint, token).then(setRows);
10
+ fetchReport1(endpoint, token).then(setRows);
11
11
  }, []);
12
12
 
13
13
  if (!rows) return <ActivityIndicator />;
14
14
 
15
15
  return (
16
- <ScrollView>
17
- <Text onPress={onBack}>‹ Back</Text>
16
+ <ScrollView style={{ padding: 16 }}>
17
+ <Text onPress={onBack} style={{ marginBottom: 12 }}>‹ Back</Text>
18
+ <Text style={{ fontSize: 18, fontWeight: '700', marginBottom: 12 }}>
19
+ PERFORMANS RAPORU (USD)
20
+ </Text>
21
+
18
22
  {rows.map((r, i) => (
19
23
  <Report1Card key={i} item={r} />
20
24
  ))}
@@ -1,22 +1,23 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { ScrollView, Text, ActivityIndicator } from 'react-native';
3
+
3
4
  import { getDivisions, getTable, getLine, getBar } from '../api/report2Fetcher';
4
5
  import MonthSelector from '../components/MonthSelector';
5
6
  import DivisionSelector from '../components/DivisionSelector';
6
- import FrozenTable from '../components/FrozenTable';
7
- import LineChart from '../components/LineChart';
8
- import BarChart from '../components/BarChart';
7
+ import FrozenTableReport2 from '../components/FrozenTableReport2';
8
+ import SvgLineChart from '../components/SvgLineChart';
9
+ import SvgBarLineChart from '../components/SvgBarLineChart';
9
10
 
10
- const Report2Screen = ({ report2, token, onBack }) => {
11
+ const Report2Screen = ({ api, token, onBack }) => {
11
12
  const [divisions, setDivisions] = useState([]);
12
13
  const [division, setDivision] = useState(null);
14
+ const [month, setMonth] = useState('ALL');
13
15
  const [table, setTable] = useState(null);
14
16
  const [line, setLine] = useState(null);
15
17
  const [bar, setBar] = useState(null);
16
- const [month, setMonth] = useState(null);
17
18
 
18
19
  useEffect(() => {
19
- getDivisions(report2.divisions, token).then(d => {
20
+ getDivisions(api.divisions, token).then(d => {
20
21
  setDivisions(d);
21
22
  setDivision(d[0]?.code);
22
23
  });
@@ -25,37 +26,42 @@ const Report2Screen = ({ report2, token, onBack }) => {
25
26
  useEffect(() => {
26
27
  if (!division) return;
27
28
  Promise.all([
28
- getTable(report2.table, division, token),
29
- getLine(report2.lineChart, division, token),
30
- getBar(report2.barChart, division, token)
29
+ getTable(api.table, division, token),
30
+ getLine(api.line, division, token),
31
+ getBar(api.bar, division, token),
31
32
  ]).then(([t, l, b]) => {
32
33
  setTable(t);
33
34
  setLine(l);
34
35
  setBar(b);
35
- setMonth(null);
36
+ setMonth('ALL');
36
37
  });
37
38
  }, [division]);
38
39
 
39
40
  if (!table || !line || !bar) return <ActivityIndicator />;
40
41
 
41
- const rows = month
42
- ? table.rows.filter(r => r.monthLabel === month)
43
- : table.rows;
42
+ const rows =
43
+ month === 'ALL'
44
+ ? table.rows
45
+ : table.rows.filter(r => r.monthLabel === month);
44
46
 
45
47
  return (
46
- <ScrollView>
48
+ <ScrollView style={{ padding: 16 }}>
47
49
  <Text onPress={onBack}>‹ Back</Text>
48
50
 
51
+ <Text style={{ fontSize: 18, fontWeight: '700', marginVertical: 12 }}>
52
+ {table.title}
53
+ </Text>
54
+
49
55
  <MonthSelector
50
56
  months={line.labels}
51
57
  selected={month}
52
58
  onSelect={setMonth}
53
59
  />
54
60
 
55
- <FrozenTable rows={rows} />
61
+ <FrozenTableReport2 rows={rows} />
56
62
 
57
- <LineChart data={line} />
58
- <BarChart data={bar} />
63
+ <SvgLineChart data={line} />
64
+ <SvgBarLineChart data={bar} />
59
65
 
60
66
  <DivisionSelector
61
67
  divisions={divisions}
@@ -1,17 +1,18 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { ScrollView, ActivityIndicator } from 'react-native';
2
+ import { ScrollView, Text, ActivityIndicator } from 'react-native';
3
+
3
4
  import {
4
5
  fetchReport3Table,
5
6
  fetchReport3Line,
6
- fetchReport3Bar
7
+ fetchReport3Bar,
7
8
  } from '../api/report3Fetcher';
8
9
 
9
10
  import MonthSelector from '../components/MonthSelector';
10
- import FreezeTableReport3 from '../components/FreezeTableReport3';
11
- import LineChartReport3 from '../components/LineChartReport3';
12
- import BarChartReport3 from '../components/BarChartReport3';
11
+ import FrozenTableReport3 from '../components/FrozenTableReport3';
12
+ import SvgLineChart from '../components/SvgLineChart';
13
+ import SvgBarLineChart from '../components/SvgBarLineChart';
13
14
 
14
- const Report3Screen = ({ api, token }) => {
15
+ const Report3Screen = ({ api, token, onBack }) => {
15
16
  const [table, setTable] = useState(null);
16
17
  const [line, setLine] = useState(null);
17
18
  const [bar, setBar] = useState(null);
@@ -26,17 +27,30 @@ const Report3Screen = ({ api, token }) => {
26
27
  if (!table || !line || !bar) return <ActivityIndicator />;
27
28
 
28
29
  const months = table.rows.filter(r => r.month !== 99).map(r => r.monthLabel);
30
+
29
31
  const rows =
30
32
  month === 'ALL'
31
33
  ? table.rows
32
34
  : table.rows.filter(r => r.monthLabel === month);
33
35
 
34
36
  return (
35
- <ScrollView>
36
- <MonthSelector months={months} selected={month} onSelect={setMonth} />
37
- <FreezeTableReport3 rows={rows} />
38
- <LineChartReport3 data={line} />
39
- <BarChartReport3 data={bar} />
37
+ <ScrollView style={{ padding: 16 }}>
38
+ <Text onPress={onBack}>‹ Back</Text>
39
+
40
+ <Text style={{ fontSize: 18, fontWeight: '700', marginVertical: 12 }}>
41
+ {table.title}
42
+ </Text>
43
+
44
+ <MonthSelector
45
+ months={months}
46
+ selected={month}
47
+ onSelect={setMonth}
48
+ />
49
+
50
+ <FrozenTableReport3 rows={rows} />
51
+
52
+ <SvgLineChart data={line} />
53
+ <SvgBarLineChart data={bar} />
40
54
  </ScrollView>
41
55
  );
42
56
  };
@@ -1,38 +1,15 @@
1
1
  import React from 'react';
2
- import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
2
+ import { View } from 'react-native';
3
+ import ReportCard from '../components/ReportCard';
3
4
 
4
5
  const ReportListScreen = ({ onSelect }) => {
5
- const reports = [
6
- { id: 1, title: 'Report 1' },
7
- { id: 2, title: 'Report 2' },
8
- { id: 3, title: 'Report 3' },
9
- ];
10
-
11
6
  return (
12
- <View style={styles.container}>
13
- {reports.map(r => (
14
- <TouchableOpacity
15
- key={r.id}
16
- style={styles.card}
17
- onPress={() => onSelect(r.id)}
18
- >
19
- <Text style={styles.text}>{r.title}</Text>
20
- </TouchableOpacity>
21
- ))}
7
+ <View style={{ padding: 16 }}>
8
+ <ReportCard title="Report 1" onPress={() => onSelect(1)} />
9
+ <ReportCard title="Report 2" onPress={() => onSelect(2)} />
10
+ <ReportCard title="Report 3" onPress={() => onSelect(3)} />
22
11
  </View>
23
12
  );
24
13
  };
25
14
 
26
- const styles = StyleSheet.create({
27
- container: { padding: 16 },
28
- card: {
29
- backgroundColor: '#fff',
30
- padding: 20,
31
- borderRadius: 12,
32
- marginBottom: 12,
33
- elevation: 2,
34
- },
35
- text: { fontSize: 16, fontWeight: '700' },
36
- });
37
-
38
15
  export default ReportListScreen;
@@ -1,48 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
-
4
- const BarChart = ({ data }) => {
5
- if (!data?.series) return null;
6
-
7
- const max = Math.max(...data.series.flatMap(s => s.data));
8
-
9
- const colors = ['#FB8C00', '#1E88E5', '#9E9E9E'];
10
-
11
- return (
12
- <View style={styles.container}>
13
- <Text style={styles.title}>{data.title}</Text>
14
- <ScrollView horizontal>
15
- <View style={styles.chart}>
16
- {data.labels.map((label, i) => (
17
- <View key={i} style={styles.group}>
18
- {data.series.map((s, idx) => (
19
- <View
20
- key={idx}
21
- style={[
22
- styles.bar,
23
- {
24
- height: (s.data[i] / max) * 120,
25
- backgroundColor: colors[idx]
26
- }
27
- ]}
28
- />
29
- ))}
30
- <Text style={styles.label}>{label}</Text>
31
- </View>
32
- ))}
33
- </View>
34
- </ScrollView>
35
- </View>
36
- );
37
- };
38
-
39
- export default BarChart;
40
-
41
- const styles = StyleSheet.create({
42
- container: { marginVertical: 12 },
43
- title: { fontWeight: '700', marginBottom: 8 },
44
- chart: { flexDirection: 'row', alignItems: 'flex-end' },
45
- group: { flexDirection: 'row', alignItems: 'flex-end', marginHorizontal: 6 },
46
- bar: { width: 10, marginHorizontal: 2, borderRadius: 2 },
47
- label: { fontSize: 10, marginTop: 4, textAlign: 'center', width: 40 }
48
- });
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, StyleSheet } from 'react-native';
3
-
4
- const BarChartReport3 = ({ data }) => {
5
- return (
6
- <View style={styles.card}>
7
- <Text style={styles.title}>{data.title}</Text>
8
- {data.series.map(s => (
9
- <Text key={s.name} style={styles.legend}>{s.name}</Text>
10
- ))}
11
- </View>
12
- );
13
- };
14
-
15
- const styles = StyleSheet.create({
16
- card: { padding: 12, backgroundColor: '#fff', borderRadius: 12, marginTop: 12 },
17
- title: { fontWeight: '700', textAlign: 'center' },
18
- legend: { textAlign: 'center' },
19
- });
20
-
21
- export default BarChartReport3;
@@ -1,60 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
-
4
- const FreezeTableReport3 = ({ rows }) => {
5
- return (
6
- <View style={styles.container}>
7
- {/* Frozen column */}
8
- <View style={styles.left}>
9
- <Text style={styles.header}>AY</Text>
10
- {rows.map(r => (
11
- <Text key={r.sortOrder} style={styles.cell}>{r.monthLabel}</Text>
12
- ))}
13
- </View>
14
-
15
- {/* Scrollable */}
16
- <ScrollView horizontal>
17
- <View>
18
- <View style={styles.row}>
19
- {[
20
- '2024 Yük',
21
- '2025 Yük',
22
- 'Yük %',
23
- '2024 Gelir',
24
- '2025 Gelir',
25
- 'Gelir %',
26
- '2025 Bütçe',
27
- 'Bütçe %'
28
- ].map(h => (
29
- <Text key={h} style={styles.header}>{h}</Text>
30
- ))}
31
- </View>
32
-
33
- {rows.map(r => (
34
- <View key={r.sortOrder} style={styles.row}>
35
- <Text style={styles.cell}>{r.loadCount2024}</Text>
36
- <Text style={styles.cell}>{r.loadCount2025}</Text>
37
- <Text style={styles.percent}>{r.loadCountChangePercent}%</Text>
38
- <Text style={styles.cell}>{r.revenueTl2024}</Text>
39
- <Text style={styles.cell}>{r.revenueTl2025}</Text>
40
- <Text style={styles.percent}>{r.revenueChangePercent}%</Text>
41
- <Text style={styles.cell}>{r.budgetRevenueTl2025}</Text>
42
- <Text style={styles.percent}>{r.budgetChangePercent}%</Text>
43
- </View>
44
- ))}
45
- </View>
46
- </ScrollView>
47
- </View>
48
- );
49
- };
50
-
51
- const styles = StyleSheet.create({
52
- container: { flexDirection: 'row' },
53
- left: { width: 90, backgroundColor: '#fff' },
54
- header: { fontWeight: '700', padding: 8 },
55
- cell: { padding: 8 },
56
- percent: { padding: 8, fontWeight: '600' },
57
- row: { flexDirection: 'row' },
58
- });
59
-
60
- export default FreezeTableReport3;
@@ -1,71 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
-
4
- const Cell = ({ children, bold }) => (
5
- <View style={styles.cell}>
6
- <Text style={[styles.text, bold && styles.bold]}>{children}</Text>
7
- </View>
8
- );
9
-
10
- const FrozenTable = ({ rows = [] }) => {
11
- if (!rows.length) {
12
- return <Text style={styles.noData}>No data available</Text>;
13
- }
14
-
15
- return (
16
- <View style={styles.container}>
17
- {/* Frozen Column */}
18
- <View style={styles.frozen}>
19
- <Cell bold>AY</Cell>
20
- {rows.map((r, i) => (
21
- <Cell key={i} bold={r.monthLabel === 'Total'}>
22
- {r.monthLabel}
23
- </Cell>
24
- ))}
25
- </View>
26
-
27
- {/* Scrollable Columns */}
28
- <ScrollView horizontal>
29
- <View>
30
- <View style={styles.headerRow}>
31
- <Cell bold>2024 TEU</Cell>
32
- <Cell bold>2025 TEU</Cell>
33
- <Cell bold>TEU %</Cell>
34
- </View>
35
-
36
- {rows.map((r, i) => (
37
- <View key={i} style={styles.row}>
38
- <Cell>{r.teu2024}</Cell>
39
- <Cell>{r.teu2025}</Cell>
40
- <Cell style={r.teuChangePercent < 0 ? styles.down : styles.up}>
41
- {r.teuChangePercent}%
42
- </Cell>
43
- </View>
44
- ))}
45
- </View>
46
- </ScrollView>
47
- </View>
48
- );
49
- };
50
-
51
- export default FrozenTable;
52
-
53
- const styles = StyleSheet.create({
54
- container: { flexDirection: 'row', marginVertical: 12 },
55
- frozen: { width: 90, backgroundColor: '#f4f4f4' },
56
- headerRow: { flexDirection: 'row', backgroundColor: '#f4f4f4' },
57
- row: { flexDirection: 'row' },
58
- cell: {
59
- width: 90,
60
- padding: 8,
61
- borderBottomWidth: 1,
62
- borderColor: '#ddd',
63
- justifyContent: 'center',
64
- alignItems: 'center'
65
- },
66
- text: { fontSize: 12 },
67
- bold: { fontWeight: '700' },
68
- up: { color: 'green' },
69
- down: { color: 'red' },
70
- noData: { textAlign: 'center', padding: 16 }
71
- });
@@ -1,22 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, StyleSheet } from 'react-native';
3
-
4
- const LineChartReport3 = ({ data }) => {
5
- return (
6
- <View style={styles.card}>
7
- <Text style={styles.title}>{data.title}</Text>
8
- {/* Simple SVG-less visual representation */}
9
- {data.series.map(s => (
10
- <Text key={s.name} style={styles.legend}>{s.name}</Text>
11
- ))}
12
- </View>
13
- );
14
- };
15
-
16
- const styles = StyleSheet.create({
17
- card: { padding: 12, backgroundColor: '#fff', borderRadius: 12, marginTop: 12 },
18
- title: { fontWeight: '700', textAlign: 'center', marginBottom: 8 },
19
- legend: { textAlign: 'center' },
20
- });
21
-
22
- export default LineChartReport3;
File without changes