@dhiraj0720/report1chart 2.7.8 → 2.8.0
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
|
@@ -19,10 +19,10 @@ const PercentCell = ({ value }) => {
|
|
|
19
19
|
);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const Cell = ({ children, bold = false, highlight = false,
|
|
22
|
+
const Cell = ({ children, bold = false, highlight = false, isFrozen = false }) => (
|
|
23
23
|
<View style={[
|
|
24
24
|
styles.cell,
|
|
25
|
-
|
|
25
|
+
isFrozen && styles.frozenCell,
|
|
26
26
|
bold && styles.bold,
|
|
27
27
|
highlight && styles.highlightCell
|
|
28
28
|
]}>
|
|
@@ -34,49 +34,54 @@ const Cell = ({ children, bold = false, highlight = false, width }) => (
|
|
|
34
34
|
|
|
35
35
|
const FrozenTableReport2A = ({ rows = [], isFullscreen = false }) => {
|
|
36
36
|
if (!rows.length) {
|
|
37
|
-
return <Text style={{ textAlign: 'center', padding: 20 }}>No data available</Text>;
|
|
37
|
+
return <Text style={{ textAlign: 'center', padding: 20, color: '#666' }}>No data available</Text>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
const frozenColumnWidth = isFullscreen ?
|
|
42
|
-
const cellWidth = isFullscreen ? 140 : 130;
|
|
40
|
+
// Frozen column slightly wider for better readability
|
|
41
|
+
const frozenColumnWidth = isFullscreen ? 160 : 130;
|
|
43
42
|
|
|
44
43
|
return (
|
|
45
44
|
<View style={styles.container}>
|
|
46
|
-
{/* Frozen Column */}
|
|
45
|
+
{/* Frozen Left Column - AY */}
|
|
47
46
|
<View style={[styles.frozenColumn, { width: frozenColumnWidth }]}>
|
|
48
|
-
<Cell bold
|
|
47
|
+
<Cell bold isFrozen>AY</Cell>
|
|
49
48
|
{rows.map((row, i) => {
|
|
50
49
|
const isTotal = row.monthLabel === 'Total';
|
|
51
50
|
return (
|
|
52
|
-
<Cell key={i} bold={isTotal} highlight={isTotal}
|
|
51
|
+
<Cell key={i} bold={isTotal} highlight={isTotal} isFrozen>
|
|
53
52
|
{row.monthLabel}
|
|
54
53
|
</Cell>
|
|
55
54
|
);
|
|
56
55
|
})}
|
|
57
56
|
</View>
|
|
58
57
|
|
|
59
|
-
{/* Scrollable Columns */}
|
|
58
|
+
{/* Scrollable Columns - Auto-fit width */}
|
|
60
59
|
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
61
60
|
<View>
|
|
61
|
+
{/* Header Row */}
|
|
62
62
|
<View style={styles.headerRow}>
|
|
63
|
-
{[
|
|
64
|
-
|
|
63
|
+
{[
|
|
64
|
+
'2024 TEU', '2025 TEU', 'TEU %',
|
|
65
|
+
'2024 Kar', '2025 Kar', 'Kar %',
|
|
66
|
+
'2025 Bütçe', 'Bütçe %'
|
|
67
|
+
].map((header) => (
|
|
68
|
+
<Cell key={header} bold>{header}</Cell>
|
|
65
69
|
))}
|
|
66
70
|
</View>
|
|
67
71
|
|
|
72
|
+
{/* Data Rows */}
|
|
68
73
|
{rows.map((row, i) => {
|
|
69
74
|
const isTotal = row.monthLabel === 'Total';
|
|
70
75
|
return (
|
|
71
76
|
<View key={i} style={styles.dataRow}>
|
|
72
|
-
<Cell highlight={isTotal}
|
|
73
|
-
<Cell highlight={isTotal}
|
|
74
|
-
<Cell highlight={isTotal}
|
|
75
|
-
<Cell highlight={isTotal}
|
|
76
|
-
<Cell highlight={isTotal}
|
|
77
|
-
<Cell highlight={isTotal}
|
|
78
|
-
<Cell highlight={isTotal}
|
|
79
|
-
<Cell highlight={isTotal}
|
|
77
|
+
<Cell highlight={isTotal}>{formatNumber(row.teu2024)}</Cell>
|
|
78
|
+
<Cell highlight={isTotal}>{formatNumber(row.teu2025)}</Cell>
|
|
79
|
+
<Cell highlight={isTotal}><PercentCell value={row.teuChangePercent} /></Cell>
|
|
80
|
+
<Cell highlight={isTotal}>{formatNumber(row.profitUsd2024)}</Cell>
|
|
81
|
+
<Cell highlight={isTotal}>{formatNumber(row.profitUsd2025)}</Cell>
|
|
82
|
+
<Cell highlight={isTotal}><PercentCell value={row.profitChangePercent} /></Cell>
|
|
83
|
+
<Cell highlight={isTotal}>{formatNumber(row.budgetProfitUsd2025)}</Cell>
|
|
84
|
+
<Cell highlight={isTotal}><PercentCell value={row.budgetChangePercent} /></Cell>
|
|
80
85
|
</View>
|
|
81
86
|
);
|
|
82
87
|
})}
|
|
@@ -103,22 +108,44 @@ const styles = StyleSheet.create({
|
|
|
103
108
|
borderRightWidth: 1,
|
|
104
109
|
borderColor: '#ddd',
|
|
105
110
|
},
|
|
106
|
-
headerRow: {
|
|
107
|
-
|
|
111
|
+
headerRow: {
|
|
112
|
+
flexDirection: 'row',
|
|
113
|
+
backgroundColor: '#f4f6f8',
|
|
114
|
+
},
|
|
115
|
+
dataRow: {
|
|
116
|
+
flexDirection: 'row',
|
|
117
|
+
},
|
|
108
118
|
cell: {
|
|
109
|
-
|
|
110
|
-
paddingHorizontal:
|
|
119
|
+
minWidth: 110, // Minimum width for small content
|
|
120
|
+
paddingHorizontal: 11, // +5 left + +5 right = +10 total
|
|
121
|
+
paddingVertical: 12,
|
|
111
122
|
justifyContent: 'center',
|
|
123
|
+
alignItems: 'center',
|
|
112
124
|
borderBottomWidth: 1,
|
|
113
125
|
borderColor: '#e0e0e0',
|
|
114
126
|
},
|
|
127
|
+
frozenCell: {
|
|
128
|
+
paddingHorizontal: 14, // Slightly more padding for frozen column
|
|
129
|
+
justifyContent: 'flex-start',
|
|
130
|
+
paddingLeft: 16,
|
|
131
|
+
},
|
|
115
132
|
cellText: {
|
|
116
|
-
fontSize: 12,
|
|
133
|
+
fontSize: 12.5,
|
|
117
134
|
textAlign: 'center',
|
|
118
135
|
color: '#333',
|
|
119
136
|
},
|
|
120
|
-
bold: {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
137
|
+
bold: {
|
|
138
|
+
backgroundColor: '#e9f0f8',
|
|
139
|
+
},
|
|
140
|
+
boldText: {
|
|
141
|
+
fontWeight: '700',
|
|
142
|
+
},
|
|
143
|
+
highlightCell: {
|
|
144
|
+
backgroundColor: '#e9f0f8',
|
|
145
|
+
},
|
|
146
|
+
percentText: {
|
|
147
|
+
fontWeight: '700',
|
|
148
|
+
fontSize: 12.5,
|
|
149
|
+
textAlign: 'center',
|
|
150
|
+
},
|
|
124
151
|
});
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ScrollView,
|
|
4
|
+
Text,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
View,
|
|
7
|
+
ActivityIndicator,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
} from 'react-native';
|
|
3
10
|
import fetchReport1 from '../api/report1Fetcher';
|
|
4
11
|
import Report1Card from '../components/Report1Card';
|
|
5
12
|
|
|
@@ -8,23 +15,71 @@ const Report1Screen = ({ endpoint, token, onBack }) => {
|
|
|
8
15
|
|
|
9
16
|
useEffect(() => {
|
|
10
17
|
fetchReport1(endpoint, token).then(setRows);
|
|
11
|
-
}, []);
|
|
18
|
+
}, [endpoint, token]);
|
|
12
19
|
|
|
13
|
-
if (!rows)
|
|
20
|
+
if (!rows) {
|
|
21
|
+
return (
|
|
22
|
+
<View style={styles.loadingContainer}>
|
|
23
|
+
<ActivityIndicator size="large" color="#000" />
|
|
24
|
+
</View>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
14
27
|
|
|
15
28
|
return (
|
|
29
|
+
<View style={styles.container}>
|
|
30
|
+
{/* HEADER WITH BACK ICON */}
|
|
31
|
+
<View style={styles.header}>
|
|
32
|
+
<TouchableOpacity onPress={onBack}>
|
|
33
|
+
<Text style={styles.backIcon}>‹</Text>
|
|
34
|
+
</TouchableOpacity>
|
|
35
|
+
<Text style={styles.headerTitle}>PERFORMANS RAPORU (USD)</Text>
|
|
36
|
+
</View>
|
|
16
37
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</
|
|
22
|
-
|
|
23
|
-
{rows.map((r, i) => (
|
|
24
|
-
<Report1Card key={i} item={r} />
|
|
25
|
-
))}
|
|
26
|
-
</ScrollView>
|
|
38
|
+
<ScrollView style={styles.content}>
|
|
39
|
+
{rows.map((r, i) => (
|
|
40
|
+
<Report1Card key={i} item={r} />
|
|
41
|
+
))}
|
|
42
|
+
</ScrollView>
|
|
43
|
+
</View>
|
|
27
44
|
);
|
|
28
45
|
};
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
const styles = StyleSheet.create({
|
|
48
|
+
container: {
|
|
49
|
+
flex: 1,
|
|
50
|
+
backgroundColor: '#f8f9fa',
|
|
51
|
+
},
|
|
52
|
+
loadingContainer: {
|
|
53
|
+
flex: 1,
|
|
54
|
+
justifyContent: 'center',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
backgroundColor: '#f8f9fa',
|
|
57
|
+
},
|
|
58
|
+
header: {
|
|
59
|
+
flexDirection: 'row',
|
|
60
|
+
alignItems: 'center',
|
|
61
|
+
paddingHorizontal: 16,
|
|
62
|
+
paddingVertical: 18,
|
|
63
|
+
backgroundColor: '#fff',
|
|
64
|
+
borderBottomWidth: 1,
|
|
65
|
+
borderColor: '#eee',
|
|
66
|
+
},
|
|
67
|
+
backIcon: {
|
|
68
|
+
fontSize: 28,
|
|
69
|
+
color: '#000',
|
|
70
|
+
fontWeight: '300',
|
|
71
|
+
},
|
|
72
|
+
headerTitle: {
|
|
73
|
+
fontSize: 19,
|
|
74
|
+
fontWeight: '700',
|
|
75
|
+
color: '#000',
|
|
76
|
+
flex: 1,
|
|
77
|
+
textAlign: 'center',
|
|
78
|
+
},
|
|
79
|
+
content: {
|
|
80
|
+
flex: 1,
|
|
81
|
+
padding: 16,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export default Report1Screen;
|
|
@@ -106,46 +106,47 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
106
106
|
</View>
|
|
107
107
|
|
|
108
108
|
<ScrollView style={styles.content}>
|
|
109
|
-
{/* FULL SCREEN BUTTON
|
|
110
|
-
<TouchableOpacity onPress={() => setFullscreen(true)} style={styles.fullScreenBtn}>
|
|
111
|
-
<
|
|
112
|
-
<Path d="M8 3H5C4.44772 3 4 3.44772 4 4V8M20 8V4C20 3.44772 19.5523 3 19 3H16M16 21H19C19.5523 21 20 20.5523 20 20V16M4 16V20C4 20.5523 4.44772 21 5 21H8"
|
|
113
|
-
stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
114
|
-
</Svg>
|
|
115
|
-
<Text style={styles.fullScreenText}>Full Screen Table</Text>
|
|
109
|
+
{/* FULL SCREEN BUTTON */}
|
|
110
|
+
{/* <TouchableOpacity onPress={() => setFullscreen(true)} style={styles.fullScreenBtn}>
|
|
111
|
+
<Text style={styles.fullScreenText}>⤢ Full Screen</Text>
|
|
116
112
|
</TouchableOpacity> */}
|
|
117
|
-
|
|
118
113
|
<TouchableOpacity
|
|
119
|
-
onPress={() => setFullscreen(true)}
|
|
114
|
+
onPress={() => setFullscreen(true)}
|
|
115
|
+
style={{
|
|
116
|
+
alignSelf: 'flex-end',
|
|
117
|
+
marginBottom: 8,
|
|
118
|
+
padding: 6,
|
|
119
|
+
}}
|
|
120
120
|
>
|
|
121
121
|
<Text style={{ fontWeight: '700' }}>⤢ Full Screen</Text>
|
|
122
122
|
</TouchableOpacity>
|
|
123
123
|
|
|
124
|
+
{/* TABLE */}
|
|
124
125
|
<FrozenTableReport2A rows={filteredRows} />
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
{/* LINE CHART WITH TITLE */}
|
|
128
|
+
<View style={styles.chartWrapper}>
|
|
129
|
+
<Text style={styles.chartTitle}>AY BAZINDA KAR KARŞILAŞTIRMALARI</Text>
|
|
127
130
|
<SvgLineChartCompact data={filteredLine} />
|
|
128
131
|
</View>
|
|
129
132
|
|
|
130
|
-
|
|
133
|
+
{/* BAR CHART WITH TITLE - ONLY ONE CARD */}
|
|
134
|
+
<View style={styles.chartWrapper}>
|
|
135
|
+
<Text style={styles.chartTitle}>AY BAZINDA KAR KARŞILAŞTIRMALARI</Text>
|
|
131
136
|
<SvgBarLineChartCompact data={filteredBar} />
|
|
132
137
|
</View>
|
|
133
138
|
</ScrollView>
|
|
134
139
|
|
|
135
|
-
{/* FULL SCREEN MODAL
|
|
140
|
+
{/* FULL SCREEN MODAL */}
|
|
136
141
|
<Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']} animationType="fade">
|
|
137
142
|
<View style={styles.fullModal}>
|
|
138
|
-
{/* TOP BAR - ONE LINE */}
|
|
139
143
|
<View style={styles.fullHeader}>
|
|
140
|
-
<Text style={styles.fullHintText}>
|
|
141
|
-
Rotate device • Pinch to zoom
|
|
142
|
-
</Text>
|
|
144
|
+
<Text style={styles.fullHintText}>Rotate device • Pinch to zoom</Text>
|
|
143
145
|
<TouchableOpacity onPress={() => setFullscreen(false)}>
|
|
144
146
|
<Text style={styles.closeBtn}>✕</Text>
|
|
145
147
|
</TouchableOpacity>
|
|
146
148
|
</View>
|
|
147
149
|
|
|
148
|
-
{/* ZOOMABLE & FIT TABLE */}
|
|
149
150
|
<ScrollView
|
|
150
151
|
maximumZoomScale={3}
|
|
151
152
|
minimumZoomScale={0.7}
|
|
@@ -155,10 +156,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
155
156
|
pinchGestureEnabled={true}
|
|
156
157
|
bouncesZoom={true}
|
|
157
158
|
>
|
|
158
|
-
<View style={[
|
|
159
|
-
styles.tableWrapper,
|
|
160
|
-
isLandscape && styles.landscapeFit
|
|
161
|
-
]}>
|
|
159
|
+
<View style={[styles.tableWrapper, isLandscape && styles.landscapeFit]}>
|
|
162
160
|
<FrozenTableReport2A rows={table.rows} isFullscreen />
|
|
163
161
|
</View>
|
|
164
162
|
</ScrollView>
|
|
@@ -199,18 +197,38 @@ const styles = StyleSheet.create({
|
|
|
199
197
|
filterText: { fontSize: 16, color: '#000', fontWeight: '600', marginLeft: 8 },
|
|
200
198
|
|
|
201
199
|
fullScreenBtn: {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
padding: 14,
|
|
200
|
+
alignSelf: 'flex-end',
|
|
201
|
+
paddingHorizontal: 16,
|
|
202
|
+
paddingVertical: 10,
|
|
206
203
|
backgroundColor: '#f0f0f0',
|
|
207
204
|
borderRadius: 8,
|
|
208
205
|
marginVertical: 12,
|
|
206
|
+
marginRight: 12,
|
|
209
207
|
},
|
|
210
|
-
fullScreenText: {
|
|
208
|
+
fullScreenText: { fontSize: 16, color: '#000', fontWeight: '700' },
|
|
211
209
|
|
|
212
|
-
content: { flex: 1,
|
|
213
|
-
|
|
210
|
+
content: { flex: 1, paddingHorizontal: 12 },
|
|
211
|
+
|
|
212
|
+
chartWrapper: {
|
|
213
|
+
backgroundColor: '#fff',
|
|
214
|
+
borderRadius: 12,
|
|
215
|
+
padding: 16,
|
|
216
|
+
marginVertical: 12,
|
|
217
|
+
borderWidth: 1,
|
|
218
|
+
borderColor: '#ddd',
|
|
219
|
+
shadowColor: '#000',
|
|
220
|
+
shadowOffset: { width: 0, height: 2 },
|
|
221
|
+
shadowOpacity: 0.08,
|
|
222
|
+
shadowRadius: 6,
|
|
223
|
+
elevation: 4,
|
|
224
|
+
},
|
|
225
|
+
chartTitle: {
|
|
226
|
+
fontSize: 16,
|
|
227
|
+
fontWeight: '700',
|
|
228
|
+
color: '#000',
|
|
229
|
+
textAlign: 'center',
|
|
230
|
+
marginBottom: 16,
|
|
231
|
+
},
|
|
214
232
|
|
|
215
233
|
fullModal: { flex: 1, backgroundColor: '#fff' },
|
|
216
234
|
fullHeader: {
|
|
@@ -239,15 +257,17 @@ const styles = StyleSheet.create({
|
|
|
239
257
|
padding: 20,
|
|
240
258
|
},
|
|
241
259
|
tableWrapper: {
|
|
260
|
+
backgroundColor: '#fff',
|
|
261
|
+
borderRadius: 12,
|
|
262
|
+
overflow: 'hidden',
|
|
242
263
|
shadowColor: '#000',
|
|
243
|
-
shadowOffset: { width: 0, height:
|
|
244
|
-
shadowOpacity: 0.
|
|
245
|
-
shadowRadius:
|
|
246
|
-
elevation:
|
|
264
|
+
shadowOffset: { width: 0, height: 4 },
|
|
265
|
+
shadowOpacity: 0.15,
|
|
266
|
+
shadowRadius: 10,
|
|
267
|
+
elevation: 8,
|
|
247
268
|
},
|
|
248
269
|
landscapeFit: {
|
|
249
|
-
transform: [{ scale: 1.
|
|
250
|
-
maxWidth: '100%',
|
|
270
|
+
transform: [{ scale: 1.45 }],
|
|
251
271
|
},
|
|
252
272
|
});
|
|
253
273
|
|
|
@@ -8,35 +8,38 @@ import {
|
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
|
|
10
10
|
const REPORTS = [
|
|
11
|
-
|
|
12
|
-
id: 1,
|
|
13
|
-
title: 'Report 1',
|
|
14
|
-
desc: 'Performans Raporu (USD)',
|
|
15
|
-
},
|
|
11
|
+
|
|
16
12
|
{
|
|
17
13
|
id: '1A',
|
|
18
|
-
title: '
|
|
19
|
-
desc: '
|
|
14
|
+
title: 'Performans Raporu (USD)',
|
|
15
|
+
desc: 'Option 1',
|
|
20
16
|
},
|
|
21
17
|
{
|
|
22
|
-
id:
|
|
23
|
-
title: '
|
|
24
|
-
desc: '
|
|
18
|
+
id: 1,
|
|
19
|
+
title: 'Performans Raporu (USD)',
|
|
20
|
+
desc: 'Option 2',
|
|
25
21
|
},
|
|
22
|
+
|
|
26
23
|
{
|
|
27
24
|
id: '2A',
|
|
28
|
-
title: '
|
|
29
|
-
desc: '
|
|
25
|
+
title: 'Gross Profit by Company & Division',
|
|
26
|
+
desc: 'Option 1',
|
|
30
27
|
},
|
|
31
28
|
{
|
|
32
|
-
id:
|
|
33
|
-
title: '
|
|
34
|
-
desc: '
|
|
29
|
+
id: 2,
|
|
30
|
+
title: 'Gross Profit by Company & Division',
|
|
31
|
+
desc: 'Option 2',
|
|
35
32
|
},
|
|
33
|
+
|
|
36
34
|
{
|
|
37
35
|
id: '3A',
|
|
38
|
-
title: '
|
|
39
|
-
desc: '
|
|
36
|
+
title: 'Transportation Business Analysis',
|
|
37
|
+
desc: 'Option 1',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 3,
|
|
41
|
+
title: 'Transportation Business Analysis',
|
|
42
|
+
desc: 'Option 2',
|
|
40
43
|
},
|
|
41
44
|
];
|
|
42
45
|
|