@dhiraj0720/report1chart 2.6.7 → 2.6.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 +1 -1
- package/src/components/DivisionFilterModal.jsx +102 -23
- package/src/components/FrozenTableReport2A.jsx +32 -68
- package/src/components/MonthFilterModal.jsx +143 -27
- package/src/components/SvgBarLineChartCompact.jsx +3 -3
- package/src/screens/Report2AScreen.jsx +63 -64
- package/src/screens/Report3AScreen.jsx +166 -59
package/package.json
CHANGED
|
@@ -1,27 +1,106 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Modal,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ScrollView,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
TouchableWithoutFeedback,
|
|
10
|
+
} from 'react-native';
|
|
3
11
|
|
|
4
|
-
const DivisionFilterModal = ({ visible, divisions, selected, onSelect, onClose }) =>
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
<
|
|
12
|
+
const DivisionFilterModal = ({ visible, divisions, selected, onSelect, onClose }) => {
|
|
13
|
+
return (
|
|
14
|
+
<Modal visible={visible} transparent animationType="fade">
|
|
15
|
+
<TouchableWithoutFeedback onPress={onClose}>
|
|
16
|
+
<View style={styles.overlay}>
|
|
17
|
+
<TouchableWithoutFeedback>
|
|
18
|
+
<View style={styles.modalContent}>
|
|
19
|
+
{/* Header with Close Icon */}
|
|
20
|
+
<View style={styles.header}>
|
|
21
|
+
<Text style={styles.title}>Select Division</Text>
|
|
22
|
+
<TouchableOpacity onPress={onClose}>
|
|
23
|
+
<Text style={styles.closeIcon}>✕</Text>
|
|
24
|
+
</TouchableOpacity>
|
|
25
|
+
</View>
|
|
9
26
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
<ScrollView style={styles.list}>
|
|
28
|
+
{divisions.map(d => (
|
|
29
|
+
<TouchableOpacity
|
|
30
|
+
key={d.code}
|
|
31
|
+
onPress={() => {
|
|
32
|
+
onSelect(d.code);
|
|
33
|
+
onClose();
|
|
34
|
+
}}
|
|
35
|
+
style={styles.item}
|
|
36
|
+
>
|
|
37
|
+
<Text style={[
|
|
38
|
+
styles.itemText,
|
|
39
|
+
selected === d.code && styles.selectedText
|
|
40
|
+
]}>
|
|
41
|
+
{selected === d.code ? '✓ ' : ' '}{d.displayName}
|
|
42
|
+
</Text>
|
|
43
|
+
</TouchableOpacity>
|
|
44
|
+
))}
|
|
45
|
+
</ScrollView>
|
|
46
|
+
</View>
|
|
47
|
+
</TouchableWithoutFeedback>
|
|
48
|
+
</View>
|
|
49
|
+
</TouchableWithoutFeedback>
|
|
50
|
+
</Modal>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
26
53
|
|
|
27
|
-
|
|
54
|
+
const styles = StyleSheet.create({
|
|
55
|
+
overlay: {
|
|
56
|
+
flex: 1,
|
|
57
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
58
|
+
justifyContent: 'center',
|
|
59
|
+
alignItems: 'center',
|
|
60
|
+
},
|
|
61
|
+
modalContent: {
|
|
62
|
+
width: '85%',
|
|
63
|
+
maxHeight: '80%',
|
|
64
|
+
backgroundColor: '#fff',
|
|
65
|
+
borderRadius: 12,
|
|
66
|
+
padding: 16,
|
|
67
|
+
shadowColor: '#000',
|
|
68
|
+
shadowOffset: { width: 0, height: 4 },
|
|
69
|
+
shadowOpacity: 0.3,
|
|
70
|
+
shadowRadius: 8,
|
|
71
|
+
elevation: 10,
|
|
72
|
+
},
|
|
73
|
+
header: {
|
|
74
|
+
flexDirection: 'row',
|
|
75
|
+
justifyContent: 'space-between',
|
|
76
|
+
alignItems: 'center',
|
|
77
|
+
marginBottom: 16,
|
|
78
|
+
},
|
|
79
|
+
title: {
|
|
80
|
+
fontSize: 18,
|
|
81
|
+
fontWeight: '700',
|
|
82
|
+
color: '#000',
|
|
83
|
+
},
|
|
84
|
+
closeIcon: {
|
|
85
|
+
fontSize: 24,
|
|
86
|
+
color: '#000',
|
|
87
|
+
fontWeight: '300',
|
|
88
|
+
},
|
|
89
|
+
list: {
|
|
90
|
+
maxHeight: 300,
|
|
91
|
+
},
|
|
92
|
+
item: {
|
|
93
|
+
paddingVertical: 12,
|
|
94
|
+
paddingHorizontal: 4,
|
|
95
|
+
},
|
|
96
|
+
itemText: {
|
|
97
|
+
fontSize: 16,
|
|
98
|
+
color: '#333',
|
|
99
|
+
},
|
|
100
|
+
selectedText: {
|
|
101
|
+
fontWeight: '700',
|
|
102
|
+
color: '#000',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export default DivisionFilterModal;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View, Text, ScrollView, StyleSheet } from 'react-native';
|
|
3
3
|
|
|
4
|
-
// Helper: Format numbers with commas (e.g., 1083203 → 1,083,203)
|
|
5
4
|
const formatNumber = (value) => {
|
|
6
5
|
if (value === null || value === undefined || value === '') return '-';
|
|
7
6
|
return Number(value).toLocaleString('en-US');
|
|
8
7
|
};
|
|
9
8
|
|
|
10
|
-
// Percentage cell with up/down arrow and color
|
|
11
9
|
const PercentCell = ({ value }) => {
|
|
12
10
|
if (value === null || value === undefined) return <Text>-</Text>;
|
|
13
11
|
const positive = value >= 0;
|
|
@@ -21,10 +19,10 @@ const PercentCell = ({ value }) => {
|
|
|
21
19
|
);
|
|
22
20
|
};
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
const Cell = ({ children, bold = false, highlight = false }) => (
|
|
22
|
+
const Cell = ({ children, bold = false, highlight = false, width }) => (
|
|
26
23
|
<View style={[
|
|
27
24
|
styles.cell,
|
|
25
|
+
{ width }, // dynamic width
|
|
28
26
|
bold && styles.bold,
|
|
29
27
|
highlight && styles.highlightCell
|
|
30
28
|
]}>
|
|
@@ -34,24 +32,24 @@ const Cell = ({ children, bold = false, highlight = false }) => (
|
|
|
34
32
|
</View>
|
|
35
33
|
);
|
|
36
34
|
|
|
37
|
-
const FrozenTableReport2A = ({ rows = [] }) => {
|
|
38
|
-
if (!rows
|
|
39
|
-
return <Text>No data available</Text>;
|
|
35
|
+
const FrozenTableReport2A = ({ rows = [], isFullscreen = false }) => {
|
|
36
|
+
if (!rows.length) {
|
|
37
|
+
return <Text style={{ textAlign: 'center', padding: 20 }}>No data available</Text>;
|
|
40
38
|
}
|
|
41
39
|
|
|
40
|
+
// Dynamic widths based on fullscreen mode
|
|
41
|
+
const frozenColumnWidth = isFullscreen ? 180 : 120;
|
|
42
|
+
const cellWidth = isFullscreen ? 140 : 130;
|
|
43
|
+
|
|
42
44
|
return (
|
|
43
45
|
<View style={styles.container}>
|
|
44
|
-
{/* Frozen
|
|
45
|
-
<View style={styles.frozenColumn}>
|
|
46
|
-
<Cell bold>AY</Cell>
|
|
47
|
-
{rows.map((row,
|
|
46
|
+
{/* Frozen Column */}
|
|
47
|
+
<View style={[styles.frozenColumn, { width: frozenColumnWidth }]}>
|
|
48
|
+
<Cell bold width={frozenColumnWidth}>AY</Cell>
|
|
49
|
+
{rows.map((row, i) => {
|
|
48
50
|
const isTotal = row.monthLabel === 'Total';
|
|
49
51
|
return (
|
|
50
|
-
<Cell
|
|
51
|
-
key={index}
|
|
52
|
-
bold={isTotal}
|
|
53
|
-
highlight={isTotal}
|
|
54
|
-
>
|
|
52
|
+
<Cell key={i} bold={isTotal} highlight={isTotal} width={frozenColumnWidth}>
|
|
55
53
|
{row.monthLabel}
|
|
56
54
|
</Cell>
|
|
57
55
|
);
|
|
@@ -61,41 +59,24 @@ const FrozenTableReport2A = ({ rows = [] }) => {
|
|
|
61
59
|
{/* Scrollable Columns */}
|
|
62
60
|
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
63
61
|
<View>
|
|
64
|
-
{/* Header Row */}
|
|
65
62
|
<View style={styles.headerRow}>
|
|
66
|
-
{[
|
|
67
|
-
|
|
68
|
-
'2024 Kar', '2025 Kar', 'Kar %',
|
|
69
|
-
'2025 Bütçe', 'Bütçe %'
|
|
70
|
-
].map((header) => (
|
|
71
|
-
<Cell key={header} bold>
|
|
72
|
-
{header}
|
|
73
|
-
</Cell>
|
|
63
|
+
{['2024 TEU', '2025 TEU', 'TEU %', '2024 Kar', '2025 Kar', 'Kar %', '2025 Bütçe', 'Bütçe %'].map((h) => (
|
|
64
|
+
<Cell key={h} bold width={cellWidth}>{h}</Cell>
|
|
74
65
|
))}
|
|
75
66
|
</View>
|
|
76
67
|
|
|
77
|
-
{
|
|
78
|
-
{rows.map((row, index) => {
|
|
68
|
+
{rows.map((row, i) => {
|
|
79
69
|
const isTotal = row.monthLabel === 'Total';
|
|
80
|
-
|
|
81
70
|
return (
|
|
82
|
-
<View key={
|
|
83
|
-
<Cell highlight={isTotal}>{formatNumber(row.teu2024)}</Cell>
|
|
84
|
-
<Cell highlight={isTotal}>{formatNumber(row.teu2025)}</Cell>
|
|
85
|
-
<Cell highlight={isTotal}>
|
|
86
|
-
|
|
87
|
-
</Cell>
|
|
88
|
-
|
|
89
|
-
<Cell highlight={isTotal}>{formatNumber(row.
|
|
90
|
-
<Cell highlight={isTotal}
|
|
91
|
-
<Cell highlight={isTotal}>
|
|
92
|
-
<PercentCell value={row.profitChangePercent} />
|
|
93
|
-
</Cell>
|
|
94
|
-
|
|
95
|
-
<Cell highlight={isTotal}>{formatNumber(row.budgetProfitUsd2025)}</Cell>
|
|
96
|
-
<Cell highlight={isTotal}>
|
|
97
|
-
<PercentCell value={row.budgetChangePercent} />
|
|
98
|
-
</Cell>
|
|
71
|
+
<View key={i} style={styles.dataRow}>
|
|
72
|
+
<Cell highlight={isTotal} width={cellWidth}>{formatNumber(row.teu2024)}</Cell>
|
|
73
|
+
<Cell highlight={isTotal} width={cellWidth}>{formatNumber(row.teu2025)}</Cell>
|
|
74
|
+
<Cell highlight={isTotal} width={cellWidth}><PercentCell value={row.teuChangePercent} /></Cell>
|
|
75
|
+
<Cell highlight={isTotal} width={cellWidth}>{formatNumber(row.profitUsd2024)}</Cell>
|
|
76
|
+
<Cell highlight={isTotal} width={cellWidth}>{formatNumber(row.profitUsd2025)}</Cell>
|
|
77
|
+
<Cell highlight={isTotal} width={cellWidth}><PercentCell value={row.profitChangePercent} /></Cell>
|
|
78
|
+
<Cell highlight={isTotal} width={cellWidth}>{formatNumber(row.budgetProfitUsd2025)}</Cell>
|
|
79
|
+
<Cell highlight={isTotal} width={cellWidth}><PercentCell value={row.budgetChangePercent} /></Cell>
|
|
99
80
|
</View>
|
|
100
81
|
);
|
|
101
82
|
})}
|
|
@@ -118,20 +99,13 @@ const styles = StyleSheet.create({
|
|
|
118
99
|
backgroundColor: '#fff',
|
|
119
100
|
},
|
|
120
101
|
frozenColumn: {
|
|
121
|
-
width: 120,
|
|
122
102
|
backgroundColor: '#f4f6f8',
|
|
123
103
|
borderRightWidth: 1,
|
|
124
104
|
borderColor: '#ddd',
|
|
125
105
|
},
|
|
126
|
-
headerRow: {
|
|
127
|
-
|
|
128
|
-
backgroundColor: '#f4f6f8',
|
|
129
|
-
},
|
|
130
|
-
dataRow: {
|
|
131
|
-
flexDirection: 'row',
|
|
132
|
-
},
|
|
106
|
+
headerRow: { flexDirection: 'row', backgroundColor: '#f4f6f8' },
|
|
107
|
+
dataRow: { flexDirection: 'row' },
|
|
133
108
|
cell: {
|
|
134
|
-
width: 130,
|
|
135
109
|
paddingVertical: 10,
|
|
136
110
|
paddingHorizontal: 6,
|
|
137
111
|
justifyContent: 'center',
|
|
@@ -143,18 +117,8 @@ const styles = StyleSheet.create({
|
|
|
143
117
|
textAlign: 'center',
|
|
144
118
|
color: '#333',
|
|
145
119
|
},
|
|
146
|
-
bold: {
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
fontWeight: '700',
|
|
151
|
-
},
|
|
152
|
-
highlightCell: {
|
|
153
|
-
backgroundColor: '#e9f0f8',
|
|
154
|
-
},
|
|
155
|
-
percentText: {
|
|
156
|
-
fontWeight: '700',
|
|
157
|
-
fontSize: 12,
|
|
158
|
-
textAlign: 'center',
|
|
159
|
-
},
|
|
120
|
+
bold: { backgroundColor: '#e9f0f8' },
|
|
121
|
+
boldText: { fontWeight: '700' },
|
|
122
|
+
highlightCell: { backgroundColor: '#e9f0f8' },
|
|
123
|
+
percentText: { fontWeight: '700', fontSize: 12, textAlign: 'center' },
|
|
160
124
|
});
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Modal,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ScrollView,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
TouchableWithoutFeedback,
|
|
10
|
+
} from 'react-native';
|
|
3
11
|
|
|
4
12
|
const MonthFilterModal = ({ visible, months, selected, onApply, onClose }) => {
|
|
5
|
-
const [local, setLocal] = useState(selected);
|
|
13
|
+
const [local, setLocal] = useState(selected || []);
|
|
6
14
|
|
|
7
15
|
const toggle = (m) => {
|
|
8
16
|
if (local.includes(m)) {
|
|
@@ -12,36 +20,144 @@ const MonthFilterModal = ({ visible, months, selected, onApply, onClose }) => {
|
|
|
12
20
|
}
|
|
13
21
|
};
|
|
14
22
|
|
|
23
|
+
const selectAll = () => setLocal(months);
|
|
24
|
+
const clearAll = () => setLocal([]);
|
|
25
|
+
|
|
15
26
|
return (
|
|
16
27
|
<Modal visible={visible} transparent animationType="fade">
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
{/* Tap outside to close */}
|
|
29
|
+
<TouchableWithoutFeedback onPress={onClose}>
|
|
30
|
+
<View style={styles.overlay}>
|
|
31
|
+
<TouchableWithoutFeedback>
|
|
32
|
+
<View style={styles.modalContent}>
|
|
33
|
+
{/* Header with Close Icon */}
|
|
34
|
+
<View style={styles.header}>
|
|
35
|
+
<Text style={styles.title}>Select Months</Text>
|
|
36
|
+
<TouchableOpacity onPress={onClose}>
|
|
37
|
+
<Text style={styles.closeIcon}>✕</Text>
|
|
38
|
+
</TouchableOpacity>
|
|
39
|
+
</View>
|
|
40
|
+
|
|
41
|
+
{/* Select All / Clear All */}
|
|
42
|
+
<View style={styles.actionsRow}>
|
|
43
|
+
<TouchableOpacity onPress={selectAll}>
|
|
44
|
+
<Text style={styles.actionTextSelect}>Select All</Text>
|
|
45
|
+
</TouchableOpacity>
|
|
46
|
+
<TouchableOpacity onPress={clearAll}>
|
|
47
|
+
<Text style={styles.actionTextClear}>Clear All</Text>
|
|
48
|
+
</TouchableOpacity>
|
|
49
|
+
</View>
|
|
50
|
+
|
|
51
|
+
{/* Month List */}
|
|
52
|
+
<ScrollView style={styles.list}>
|
|
53
|
+
{months.map(m => (
|
|
54
|
+
<TouchableOpacity key={m} onPress={() => toggle(m)} style={styles.item}>
|
|
55
|
+
<Text style={[
|
|
56
|
+
styles.itemText,
|
|
57
|
+
local.includes(m) && styles.selectedText
|
|
58
|
+
]}>
|
|
59
|
+
{local.includes(m) ? '✓ ' : ' '}{m}
|
|
60
|
+
</Text>
|
|
61
|
+
</TouchableOpacity>
|
|
62
|
+
))}
|
|
63
|
+
</ScrollView>
|
|
64
|
+
|
|
65
|
+
{/* Apply Button */}
|
|
66
|
+
<TouchableOpacity
|
|
67
|
+
style={styles.applyBtn}
|
|
68
|
+
onPress={() => {
|
|
69
|
+
onApply(local);
|
|
70
|
+
onClose();
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<Text style={styles.applyText}>Apply</Text>
|
|
31
74
|
</TouchableOpacity>
|
|
32
|
-
|
|
33
|
-
</
|
|
34
|
-
|
|
35
|
-
<TouchableOpacity
|
|
36
|
-
style={{ marginTop: 12, alignSelf: 'flex-end' }}
|
|
37
|
-
onPress={() => { onApply(local); onClose(); }}
|
|
38
|
-
>
|
|
39
|
-
<Text style={{ fontWeight: '700' }}>Apply</Text>
|
|
40
|
-
</TouchableOpacity>
|
|
75
|
+
</View>
|
|
76
|
+
</TouchableWithoutFeedback>
|
|
41
77
|
</View>
|
|
42
|
-
</
|
|
78
|
+
</TouchableWithoutFeedback>
|
|
43
79
|
</Modal>
|
|
44
80
|
);
|
|
45
81
|
};
|
|
46
82
|
|
|
47
|
-
|
|
83
|
+
const styles = StyleSheet.create({
|
|
84
|
+
overlay: {
|
|
85
|
+
flex: 1,
|
|
86
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
alignItems: 'center',
|
|
89
|
+
},
|
|
90
|
+
modalContent: {
|
|
91
|
+
width: '85%',
|
|
92
|
+
maxHeight: '80%',
|
|
93
|
+
backgroundColor: '#fff',
|
|
94
|
+
borderRadius: 12,
|
|
95
|
+
padding: 16,
|
|
96
|
+
shadowColor: '#000',
|
|
97
|
+
shadowOffset: { width: 0, height: 4 },
|
|
98
|
+
shadowOpacity: 0.3,
|
|
99
|
+
shadowRadius: 8,
|
|
100
|
+
elevation: 10,
|
|
101
|
+
},
|
|
102
|
+
header: {
|
|
103
|
+
flexDirection: 'row',
|
|
104
|
+
justifyContent: 'space-between',
|
|
105
|
+
alignItems: 'center',
|
|
106
|
+
marginBottom: 12,
|
|
107
|
+
},
|
|
108
|
+
title: {
|
|
109
|
+
fontSize: 18,
|
|
110
|
+
fontWeight: '700',
|
|
111
|
+
color: '#000',
|
|
112
|
+
},
|
|
113
|
+
closeIcon: {
|
|
114
|
+
fontSize: 24,
|
|
115
|
+
color: '#000',
|
|
116
|
+
fontWeight: '300',
|
|
117
|
+
},
|
|
118
|
+
actionsRow: {
|
|
119
|
+
flexDirection: 'row',
|
|
120
|
+
justifyContent: 'space-between',
|
|
121
|
+
marginBottom: 12,
|
|
122
|
+
},
|
|
123
|
+
actionTextSelect: {
|
|
124
|
+
color: '#1e88e5',
|
|
125
|
+
fontWeight: '600',
|
|
126
|
+
fontSize: 15,
|
|
127
|
+
},
|
|
128
|
+
actionTextClear: {
|
|
129
|
+
color: '#d32f2f',
|
|
130
|
+
fontWeight: '600',
|
|
131
|
+
fontSize: 15,
|
|
132
|
+
},
|
|
133
|
+
list: {
|
|
134
|
+
maxHeight: 300,
|
|
135
|
+
},
|
|
136
|
+
item: {
|
|
137
|
+
paddingVertical: 10,
|
|
138
|
+
paddingHorizontal: 4,
|
|
139
|
+
},
|
|
140
|
+
itemText: {
|
|
141
|
+
fontSize: 16,
|
|
142
|
+
color: '#333',
|
|
143
|
+
},
|
|
144
|
+
selectedText: {
|
|
145
|
+
fontWeight: '700',
|
|
146
|
+
color: '#000',
|
|
147
|
+
},
|
|
148
|
+
applyBtn: {
|
|
149
|
+
marginTop: 16,
|
|
150
|
+
alignSelf: 'flex-end',
|
|
151
|
+
paddingHorizontal: 20,
|
|
152
|
+
paddingVertical: 10,
|
|
153
|
+
backgroundColor: '#1e88e5',
|
|
154
|
+
borderRadius: 8,
|
|
155
|
+
},
|
|
156
|
+
applyText: {
|
|
157
|
+
color: '#fff',
|
|
158
|
+
fontWeight: '700',
|
|
159
|
+
fontSize: 16,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export default MonthFilterModal;
|
|
@@ -93,7 +93,7 @@ const SvgBarLineChartCompact = ({ data }) => {
|
|
|
93
93
|
fill="white"
|
|
94
94
|
fontWeight="700"
|
|
95
95
|
>
|
|
96
|
-
|
|
96
|
+
{formatNumber(val2024)}
|
|
97
97
|
</SvgText>
|
|
98
98
|
)}
|
|
99
99
|
|
|
@@ -114,7 +114,7 @@ const SvgBarLineChartCompact = ({ data }) => {
|
|
|
114
114
|
fill="white"
|
|
115
115
|
fontWeight="700"
|
|
116
116
|
>
|
|
117
|
-
|
|
117
|
+
{formatNumber(val2025)}
|
|
118
118
|
</SvgText>
|
|
119
119
|
)}
|
|
120
120
|
|
|
@@ -150,7 +150,7 @@ const SvgBarLineChartCompact = ({ data }) => {
|
|
|
150
150
|
fill="#333"
|
|
151
151
|
fontWeight="700"
|
|
152
152
|
>
|
|
153
|
-
|
|
153
|
+
{formatNumber(budget)}
|
|
154
154
|
</SvgText>
|
|
155
155
|
|
|
156
156
|
{/* X Axis Label - Rotated */}
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
Modal,
|
|
9
9
|
Dimensions,
|
|
10
10
|
ActivityIndicator,
|
|
11
|
-
Alert,
|
|
12
11
|
} from 'react-native';
|
|
13
12
|
import Svg, { Path } from 'react-native-svg';
|
|
14
13
|
import { filterChartByMonths } from '../utils/filterChartByMonths';
|
|
@@ -23,7 +22,6 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
23
22
|
const [monthsModal, setMonthsModal] = useState(false);
|
|
24
23
|
const [divisionModal, setDivisionModal] = useState(false);
|
|
25
24
|
const [fullscreen, setFullscreen] = useState(false);
|
|
26
|
-
const [zoomScale, setZoomScale] = useState(1);
|
|
27
25
|
|
|
28
26
|
const [months, setMonths] = useState([]);
|
|
29
27
|
const [selectedMonths, setSelectedMonths] = useState([]);
|
|
@@ -40,8 +38,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
40
38
|
.then((d) => {
|
|
41
39
|
setDivisions(d);
|
|
42
40
|
if (d.length > 0) setDivision(d[0].code);
|
|
43
|
-
})
|
|
44
|
-
.catch(() => Alert.alert('Error', 'Failed to load divisions'));
|
|
41
|
+
});
|
|
45
42
|
}, [api.divisions, token]);
|
|
46
43
|
|
|
47
44
|
useEffect(() => {
|
|
@@ -76,7 +73,6 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
76
73
|
const filteredLine = filterChartByMonths(line, selectedMonths);
|
|
77
74
|
const filteredBar = filterChartByMonths(bar, selectedMonths);
|
|
78
75
|
|
|
79
|
-
// Detect landscape
|
|
80
76
|
const { width, height } = Dimensions.get('window');
|
|
81
77
|
const isLandscape = width > height;
|
|
82
78
|
|
|
@@ -93,67 +89,28 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
93
89
|
{/* FILTERS */}
|
|
94
90
|
<View style={styles.filterBar}>
|
|
95
91
|
<TouchableOpacity onPress={() => setMonthsModal(true)} style={styles.filterItem}>
|
|
96
|
-
{/* FILTER FUNNEL ICON */}
|
|
97
92
|
<Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
|
|
98
|
-
<Path
|
|
99
|
-
|
|
100
|
-
stroke="#000"
|
|
101
|
-
strokeWidth={2}
|
|
102
|
-
strokeLinecap="round"
|
|
103
|
-
strokeLinejoin="round"
|
|
104
|
-
/>
|
|
105
|
-
<Path
|
|
106
|
-
d="M8 11V19L16 19V11"
|
|
107
|
-
stroke="#000"
|
|
108
|
-
strokeWidth={2}
|
|
109
|
-
strokeLinecap="round"
|
|
110
|
-
strokeLinejoin="round"
|
|
111
|
-
/>
|
|
93
|
+
<Path d="M20 4H4V6.5L12 14.5L20 6.5V4Z" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
94
|
+
<Path d="M8 11V19L16 19V11" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
112
95
|
</Svg>
|
|
113
96
|
<Text style={styles.filterText}>Months ({selectedMonths.length}/{months.length})</Text>
|
|
114
97
|
</TouchableOpacity>
|
|
115
98
|
|
|
116
99
|
<TouchableOpacity onPress={() => setDivisionModal(true)} style={styles.filterItem}>
|
|
117
|
-
{/* SAME FILTER ICON */}
|
|
118
100
|
<Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
|
|
119
|
-
<Path
|
|
120
|
-
|
|
121
|
-
stroke="#000"
|
|
122
|
-
strokeWidth={2}
|
|
123
|
-
strokeLinecap="round"
|
|
124
|
-
strokeLinejoin="round"
|
|
125
|
-
/>
|
|
126
|
-
<Path
|
|
127
|
-
d="M8 11V19L16 19V11"
|
|
128
|
-
stroke="#000"
|
|
129
|
-
strokeWidth={2}
|
|
130
|
-
strokeLinecap="round"
|
|
131
|
-
strokeLinejoin="round"
|
|
132
|
-
/>
|
|
101
|
+
<Path d="M20 4H4V6.5L12 14.5L20 6.5V4Z" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
102
|
+
<Path d="M8 11V19L16 19V11" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
133
103
|
</Svg>
|
|
134
104
|
<Text style={styles.filterText}>{currentDivisionName}</Text>
|
|
135
105
|
</TouchableOpacity>
|
|
136
106
|
</View>
|
|
137
107
|
|
|
138
108
|
<ScrollView style={styles.content}>
|
|
139
|
-
{/* FULL SCREEN
|
|
140
|
-
<TouchableOpacity
|
|
141
|
-
onPress={() => {
|
|
142
|
-
setFullscreen(true);
|
|
143
|
-
setZoomScale(1);
|
|
144
|
-
Alert.alert('Tip', 'Rotate your device to landscape for full view');
|
|
145
|
-
}}
|
|
146
|
-
style={styles.fullScreenBtn}
|
|
147
|
-
>
|
|
148
|
-
{/* FULL SCREEN EXPAND ICON */}
|
|
109
|
+
{/* FULL SCREEN BUTTON */}
|
|
110
|
+
<TouchableOpacity onPress={() => setFullscreen(true)} style={styles.fullScreenBtn}>
|
|
149
111
|
<Svg width={28} height={28} viewBox="0 0 24 24" fill="none">
|
|
150
|
-
<Path
|
|
151
|
-
|
|
152
|
-
stroke="#000"
|
|
153
|
-
strokeWidth={2}
|
|
154
|
-
strokeLinecap="round"
|
|
155
|
-
strokeLinejoin="round"
|
|
156
|
-
/>
|
|
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" />
|
|
157
114
|
</Svg>
|
|
158
115
|
<Text style={styles.fullScreenText}>Full Screen Table</Text>
|
|
159
116
|
</TouchableOpacity>
|
|
@@ -169,30 +126,39 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
169
126
|
</View>
|
|
170
127
|
</ScrollView>
|
|
171
128
|
|
|
172
|
-
{/* FULL SCREEN MODAL -
|
|
173
|
-
<Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']}>
|
|
129
|
+
{/* FULL SCREEN MODAL - PERFECT LANDSCAPE FIT + ZOOM */}
|
|
130
|
+
<Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']} animationType="fade">
|
|
174
131
|
<View style={styles.fullModal}>
|
|
132
|
+
{/* TOP BAR - ONE LINE */}
|
|
175
133
|
<View style={styles.fullHeader}>
|
|
134
|
+
<Text style={styles.fullHintText}>
|
|
135
|
+
Rotate device • Pinch to zoom
|
|
136
|
+
</Text>
|
|
176
137
|
<TouchableOpacity onPress={() => setFullscreen(false)}>
|
|
177
|
-
<Text style={styles.
|
|
138
|
+
<Text style={styles.closeBtn}>✕</Text>
|
|
178
139
|
</TouchableOpacity>
|
|
179
|
-
<Text style={styles.fullHint}>Rotate to landscape • Pinch to zoom</Text>
|
|
180
140
|
</View>
|
|
181
141
|
|
|
142
|
+
{/* ZOOMABLE & FIT TABLE */}
|
|
182
143
|
<ScrollView
|
|
183
144
|
maximumZoomScale={3}
|
|
184
|
-
minimumZoomScale={0.
|
|
185
|
-
|
|
186
|
-
|
|
145
|
+
minimumZoomScale={0.7}
|
|
146
|
+
showsHorizontalScrollIndicator={false}
|
|
147
|
+
showsVerticalScrollIndicator={false}
|
|
148
|
+
contentContainerStyle={styles.zoomContent}
|
|
149
|
+
pinchGestureEnabled={true}
|
|
150
|
+
bouncesZoom={true}
|
|
187
151
|
>
|
|
188
|
-
<View style={
|
|
152
|
+
<View style={[
|
|
153
|
+
styles.tableWrapper,
|
|
154
|
+
isLandscape && styles.landscapeFit
|
|
155
|
+
]}>
|
|
189
156
|
<FrozenTableReport2A rows={table.rows} isFullscreen />
|
|
190
157
|
</View>
|
|
191
158
|
</ScrollView>
|
|
192
159
|
</View>
|
|
193
160
|
</Modal>
|
|
194
161
|
|
|
195
|
-
{/* Existing modals */}
|
|
196
162
|
<MonthFilterModal visible={monthsModal} months={months} selected={selectedMonths} onApply={setSelectedMonths} onClose={() => setMonthsModal(false)} />
|
|
197
163
|
<DivisionFilterModal visible={divisionModal} divisions={divisions} selected={division} onSelect={setDivision} onClose={() => setDivisionModal(false)} />
|
|
198
164
|
</View>
|
|
@@ -241,9 +207,42 @@ const styles = StyleSheet.create({
|
|
|
241
207
|
chartContainer: { borderWidth: 1, borderColor: '#ddd', borderRadius: 10, overflow: 'hidden', marginVertical: 12, backgroundColor: '#fff' },
|
|
242
208
|
|
|
243
209
|
fullModal: { flex: 1, backgroundColor: '#fff' },
|
|
244
|
-
fullHeader: {
|
|
245
|
-
|
|
246
|
-
|
|
210
|
+
fullHeader: {
|
|
211
|
+
flexDirection: 'row',
|
|
212
|
+
justifyContent: 'center',
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
paddingVertical: 16,
|
|
215
|
+
paddingHorizontal: 20,
|
|
216
|
+
backgroundColor: '#f8f8f8',
|
|
217
|
+
borderBottomWidth: 1,
|
|
218
|
+
borderColor: '#ddd',
|
|
219
|
+
},
|
|
220
|
+
fullHintText: {
|
|
221
|
+
fontSize: 16,
|
|
222
|
+
color: '#000',
|
|
223
|
+
fontWeight: '600',
|
|
224
|
+
textAlign: 'center',
|
|
225
|
+
flex: 1,
|
|
226
|
+
},
|
|
227
|
+
closeBtn: { fontSize: 28, color: '#000', paddingLeft: 20 },
|
|
228
|
+
|
|
229
|
+
zoomContent: {
|
|
230
|
+
flexGrow: 1,
|
|
231
|
+
justifyContent: 'center',
|
|
232
|
+
alignItems: 'center',
|
|
233
|
+
padding: 20,
|
|
234
|
+
},
|
|
235
|
+
tableWrapper: {
|
|
236
|
+
shadowColor: '#000',
|
|
237
|
+
shadowOffset: { width: 0, height: 2 },
|
|
238
|
+
shadowOpacity: 0.1,
|
|
239
|
+
shadowRadius: 8,
|
|
240
|
+
elevation: 5,
|
|
241
|
+
},
|
|
242
|
+
landscapeFit: {
|
|
243
|
+
transform: [{ scale: 1.4 }], // Perfect fit in landscape
|
|
244
|
+
maxWidth: '100%',
|
|
245
|
+
},
|
|
247
246
|
});
|
|
248
247
|
|
|
249
248
|
export default Report2AScreen;
|
|
@@ -4,9 +4,12 @@ import {
|
|
|
4
4
|
Text,
|
|
5
5
|
TouchableOpacity,
|
|
6
6
|
View,
|
|
7
|
-
ActivityIndicator,
|
|
8
7
|
StyleSheet,
|
|
8
|
+
Modal,
|
|
9
|
+
Dimensions,
|
|
10
|
+
ActivityIndicator,
|
|
9
11
|
} from 'react-native';
|
|
12
|
+
import Svg, { Path } from 'react-native-svg';
|
|
10
13
|
import {
|
|
11
14
|
fetchReport3Table,
|
|
12
15
|
fetchReport3Line,
|
|
@@ -19,28 +22,26 @@ import SvgBarLineChartCompact3A from '../components/SvgBarLineChartCompact3A';
|
|
|
19
22
|
|
|
20
23
|
const Report3AScreen = ({ api, token, onBack }) => {
|
|
21
24
|
const [monthsModal, setMonthsModal] = useState(false);
|
|
25
|
+
const [fullscreen, setFullscreen] = useState(false);
|
|
26
|
+
|
|
22
27
|
const [months, setMonths] = useState([]);
|
|
23
28
|
const [selectedMonths, setSelectedMonths] = useState([]);
|
|
24
29
|
const [table, setTable] = useState(null);
|
|
25
30
|
const [line, setLine] = useState(null);
|
|
26
31
|
const [bar, setBar] = useState(null);
|
|
27
32
|
const [loading, setLoading] = useState(true);
|
|
28
|
-
const [error, setError] = useState(null);
|
|
29
33
|
|
|
30
34
|
useEffect(() => {
|
|
31
35
|
if (!api || !token) return;
|
|
32
36
|
|
|
33
37
|
setLoading(true);
|
|
34
|
-
setError(null);
|
|
35
38
|
|
|
36
39
|
Promise.all([
|
|
37
|
-
fetchReport3Table(api.table, token)
|
|
38
|
-
fetchReport3Line(api.line, token)
|
|
39
|
-
fetchReport3Bar(api.bar, token)
|
|
40
|
+
fetchReport3Table(api.table, token),
|
|
41
|
+
fetchReport3Line(api.line, token),
|
|
42
|
+
fetchReport3Bar(api.bar, token),
|
|
40
43
|
])
|
|
41
44
|
.then(([t, l, b]) => {
|
|
42
|
-
if (!t || !l || !b) throw new Error('Failed to load data');
|
|
43
|
-
|
|
44
45
|
setTable(t);
|
|
45
46
|
setLine(l);
|
|
46
47
|
setBar(b);
|
|
@@ -50,11 +51,10 @@ const Report3AScreen = ({ api, token, onBack }) => {
|
|
|
50
51
|
.map(r => r.monthLabel);
|
|
51
52
|
|
|
52
53
|
setMonths(monthLabels);
|
|
53
|
-
setSelectedMonths(monthLabels);
|
|
54
|
+
setSelectedMonths(monthLabels);
|
|
54
55
|
})
|
|
55
56
|
.catch((err) => {
|
|
56
57
|
console.error(err);
|
|
57
|
-
setError('Failed to load Report 3A data');
|
|
58
58
|
})
|
|
59
59
|
.finally(() => setLoading(false));
|
|
60
60
|
}, [api, token]);
|
|
@@ -62,19 +62,7 @@ const Report3AScreen = ({ api, token, onBack }) => {
|
|
|
62
62
|
if (loading) {
|
|
63
63
|
return (
|
|
64
64
|
<View style={styles.center}>
|
|
65
|
-
<ActivityIndicator size="large" color="#
|
|
66
|
-
<Text style={styles.loadingText}>Loading Report 3A...</Text>
|
|
67
|
-
</View>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (error) {
|
|
72
|
-
return (
|
|
73
|
-
<View style={styles.center}>
|
|
74
|
-
<Text style={styles.errorText}>{error}</Text>
|
|
75
|
-
<TouchableOpacity onPress={onBack}>
|
|
76
|
-
<Text style={styles.backLink}>← Go Back</Text>
|
|
77
|
-
</TouchableOpacity>
|
|
65
|
+
<ActivityIndicator size="large" color="#000" />
|
|
78
66
|
</View>
|
|
79
67
|
);
|
|
80
68
|
}
|
|
@@ -103,36 +91,87 @@ const Report3AScreen = ({ api, token, onBack }) => {
|
|
|
103
91
|
const filteredLine = filterChart(line);
|
|
104
92
|
const filteredBar = filterChart(bar);
|
|
105
93
|
|
|
94
|
+
const { width, height } = Dimensions.get('window');
|
|
95
|
+
const isLandscape = width > height;
|
|
96
|
+
|
|
106
97
|
return (
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
onPress={() => setMonthsModal(true)}
|
|
115
|
-
style={styles.filterButton}
|
|
116
|
-
>
|
|
117
|
-
<Text style={styles.filterText}>
|
|
118
|
-
Months ({selectedMonths.length}/{months.length}) ⛃
|
|
119
|
-
</Text>
|
|
120
|
-
</TouchableOpacity>
|
|
121
|
-
|
|
122
|
-
{/* Table */}
|
|
123
|
-
<FrozenTableReport3A rows={filteredRows} />
|
|
124
|
-
|
|
125
|
-
{/* Line Chart - Yük Adet */}
|
|
126
|
-
<View style={styles.chartWrapper}>
|
|
127
|
-
<SvgLineChartCompact3A data={filteredLine} />
|
|
98
|
+
<View style={styles.container}>
|
|
99
|
+
{/* HEADER WITH BACK ICON */}
|
|
100
|
+
<View style={styles.header}>
|
|
101
|
+
<TouchableOpacity onPress={onBack}>
|
|
102
|
+
<Text style={styles.backIcon}>←</Text>
|
|
103
|
+
</TouchableOpacity>
|
|
104
|
+
<Text style={styles.headerTitle}>Ulaştırma Hizmetleri Analizi (A)</Text>
|
|
128
105
|
</View>
|
|
129
106
|
|
|
130
|
-
{/*
|
|
131
|
-
<View style={styles.
|
|
132
|
-
<
|
|
107
|
+
{/* FILTER WITH FUNNEL ICON */}
|
|
108
|
+
<View style={styles.filterBar}>
|
|
109
|
+
<TouchableOpacity onPress={() => setMonthsModal(true)} style={styles.filterItem}>
|
|
110
|
+
<Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
|
|
111
|
+
<Path d="M20 4H4V6.5L12 14.5L20 6.5V4Z" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
112
|
+
<Path d="M8 11V19L16 19V11" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
113
|
+
</Svg>
|
|
114
|
+
<Text style={styles.filterText}>
|
|
115
|
+
Months ({selectedMonths.length}/{months.length})
|
|
116
|
+
</Text>
|
|
117
|
+
</TouchableOpacity>
|
|
133
118
|
</View>
|
|
134
119
|
|
|
135
|
-
{
|
|
120
|
+
<ScrollView style={styles.content}>
|
|
121
|
+
{/* FULL SCREEN BUTTON */}
|
|
122
|
+
<TouchableOpacity onPress={() => setFullscreen(true)} style={styles.fullScreenBtn}>
|
|
123
|
+
<Svg width={28} height={28} viewBox="0 0 24 24" fill="none">
|
|
124
|
+
<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"
|
|
125
|
+
stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
|
|
126
|
+
</Svg>
|
|
127
|
+
<Text style={styles.fullScreenText}>Full Screen Table</Text>
|
|
128
|
+
</TouchableOpacity>
|
|
129
|
+
|
|
130
|
+
{/* TABLE */}
|
|
131
|
+
<FrozenTableReport3A rows={filteredRows} />
|
|
132
|
+
|
|
133
|
+
{/* CHARTS */}
|
|
134
|
+
<View style={styles.chartContainer}>
|
|
135
|
+
<SvgLineChartCompact3A data={filteredLine} />
|
|
136
|
+
</View>
|
|
137
|
+
|
|
138
|
+
<View style={styles.chartContainer}>
|
|
139
|
+
<SvgBarLineChartCompact3A data={filteredBar} />
|
|
140
|
+
</View>
|
|
141
|
+
</ScrollView>
|
|
142
|
+
|
|
143
|
+
{/* FULL SCREEN MODAL */}
|
|
144
|
+
<Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']} animationType="fade">
|
|
145
|
+
<View style={styles.fullModal}>
|
|
146
|
+
<View style={styles.fullHeader}>
|
|
147
|
+
<Text style={styles.fullHintText}>
|
|
148
|
+
Rotate device • Pinch to zoom
|
|
149
|
+
</Text>
|
|
150
|
+
<TouchableOpacity onPress={() => setFullscreen(false)}>
|
|
151
|
+
<Text style={styles.closeBtn}>✕</Text>
|
|
152
|
+
</TouchableOpacity>
|
|
153
|
+
</View>
|
|
154
|
+
|
|
155
|
+
<ScrollView
|
|
156
|
+
maximumZoomScale={3}
|
|
157
|
+
minimumZoomScale={0.7}
|
|
158
|
+
showsHorizontalScrollIndicator={false}
|
|
159
|
+
showsVerticalScrollIndicator={false}
|
|
160
|
+
contentContainerStyle={styles.zoomContent}
|
|
161
|
+
pinchGestureEnabled={true}
|
|
162
|
+
bouncesZoom={true}
|
|
163
|
+
>
|
|
164
|
+
<View style={[
|
|
165
|
+
styles.tableWrapper,
|
|
166
|
+
isLandscape && styles.landscapeFit
|
|
167
|
+
]}>
|
|
168
|
+
<FrozenTableReport3A rows={table.rows} isFullscreen />
|
|
169
|
+
</View>
|
|
170
|
+
</ScrollView>
|
|
171
|
+
</View>
|
|
172
|
+
</Modal>
|
|
173
|
+
|
|
174
|
+
{/* MONTH FILTER MODAL */}
|
|
136
175
|
<MonthFilterModal
|
|
137
176
|
visible={monthsModal}
|
|
138
177
|
months={months}
|
|
@@ -140,21 +179,51 @@ const Report3AScreen = ({ api, token, onBack }) => {
|
|
|
140
179
|
onApply={setSelectedMonths}
|
|
141
180
|
onClose={() => setMonthsModal(false)}
|
|
142
181
|
/>
|
|
143
|
-
</
|
|
182
|
+
</View>
|
|
144
183
|
);
|
|
145
184
|
};
|
|
146
185
|
|
|
147
186
|
const styles = StyleSheet.create({
|
|
148
|
-
container: {
|
|
149
|
-
center: { flex: 1, justifyContent: 'center', alignItems: 'center'
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
187
|
+
container: { flex: 1, backgroundColor: '#f8f9fa' },
|
|
188
|
+
center: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
|
189
|
+
|
|
190
|
+
header: {
|
|
191
|
+
flexDirection: 'row',
|
|
192
|
+
alignItems: 'center',
|
|
193
|
+
paddingHorizontal: 16,
|
|
194
|
+
paddingVertical: 18,
|
|
195
|
+
backgroundColor: '#fff',
|
|
196
|
+
borderBottomWidth: 1,
|
|
197
|
+
borderColor: '#eee',
|
|
198
|
+
},
|
|
199
|
+
backIcon: { fontSize: 28, color: '#000' },
|
|
200
|
+
headerTitle: { fontSize: 19, fontWeight: '700', color: '#000', flex: 1, textAlign: 'center' },
|
|
201
|
+
|
|
202
|
+
filterBar: {
|
|
203
|
+
flexDirection: 'row',
|
|
204
|
+
justifyContent: 'flex-start',
|
|
205
|
+
paddingHorizontal: 16,
|
|
206
|
+
paddingVertical: 14,
|
|
207
|
+
backgroundColor: '#fff',
|
|
208
|
+
borderBottomWidth: 1,
|
|
209
|
+
borderColor: '#eee',
|
|
210
|
+
},
|
|
211
|
+
filterItem: { flexDirection: 'row', alignItems: 'center' },
|
|
212
|
+
filterText: { fontSize: 16, color: '#000', fontWeight: '600', marginLeft: 8 },
|
|
213
|
+
|
|
214
|
+
fullScreenBtn: {
|
|
215
|
+
flexDirection: 'row',
|
|
216
|
+
alignItems: 'center',
|
|
217
|
+
justifyContent: 'center',
|
|
218
|
+
padding: 14,
|
|
219
|
+
backgroundColor: '#f0f0f0',
|
|
220
|
+
borderRadius: 8,
|
|
221
|
+
marginVertical: 12,
|
|
222
|
+
},
|
|
223
|
+
fullScreenText: { marginLeft: 10, fontSize: 16, color: '#000', fontWeight: '600' },
|
|
224
|
+
|
|
225
|
+
content: { flex: 1, padding: 12 },
|
|
226
|
+
chartContainer: {
|
|
158
227
|
borderWidth: 1,
|
|
159
228
|
borderColor: '#ddd',
|
|
160
229
|
borderRadius: 10,
|
|
@@ -162,6 +231,44 @@ const styles = StyleSheet.create({
|
|
|
162
231
|
marginVertical: 12,
|
|
163
232
|
backgroundColor: '#fff',
|
|
164
233
|
},
|
|
234
|
+
|
|
235
|
+
fullModal: { flex: 1, backgroundColor: '#fff' },
|
|
236
|
+
fullHeader: {
|
|
237
|
+
flexDirection: 'row',
|
|
238
|
+
justifyContent: 'center',
|
|
239
|
+
alignItems: 'center',
|
|
240
|
+
paddingVertical: 16,
|
|
241
|
+
paddingHorizontal: 20,
|
|
242
|
+
backgroundColor: '#f8f8f8',
|
|
243
|
+
borderBottomWidth: 1,
|
|
244
|
+
borderColor: '#ddd',
|
|
245
|
+
},
|
|
246
|
+
fullHintText: {
|
|
247
|
+
fontSize: 16,
|
|
248
|
+
color: '#000',
|
|
249
|
+
fontWeight: '600',
|
|
250
|
+
textAlign: 'center',
|
|
251
|
+
flex: 1,
|
|
252
|
+
},
|
|
253
|
+
closeBtn: { fontSize: 28, color: '#000', paddingLeft: 20 },
|
|
254
|
+
|
|
255
|
+
zoomContent: {
|
|
256
|
+
flexGrow: 1,
|
|
257
|
+
justifyContent: 'center',
|
|
258
|
+
alignItems: 'center',
|
|
259
|
+
padding: 20,
|
|
260
|
+
},
|
|
261
|
+
tableWrapper: {
|
|
262
|
+
shadowColor: '#000',
|
|
263
|
+
shadowOffset: { width: 0, height: 2 },
|
|
264
|
+
shadowOpacity: 0.1,
|
|
265
|
+
shadowRadius: 8,
|
|
266
|
+
elevation: 5,
|
|
267
|
+
},
|
|
268
|
+
landscapeFit: {
|
|
269
|
+
transform: [{ scale: 1.4 }],
|
|
270
|
+
maxWidth: '100%',
|
|
271
|
+
},
|
|
165
272
|
});
|
|
166
273
|
|
|
167
274
|
export default Report3AScreen;
|