@dhiraj0720/report1chart 2.6.5 → 2.6.6
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/screens/Report2AScreen.jsx +68 -20
- package/src/screens/icons.js +34 -0
package/package.json
CHANGED
|
@@ -5,8 +5,12 @@ import {
|
|
|
5
5
|
TouchableOpacity,
|
|
6
6
|
View,
|
|
7
7
|
StyleSheet,
|
|
8
|
+
Modal,
|
|
9
|
+
Dimensions,
|
|
8
10
|
ActivityIndicator,
|
|
9
11
|
} from 'react-native';
|
|
12
|
+
import { PinchGestureHandler, State } from 'react-native-gesture-handler';
|
|
13
|
+
import Svg from 'react-native-svg'; // if not imported globally
|
|
10
14
|
import { filterChartByMonths } from '../utils/filterChartByMonths';
|
|
11
15
|
import { getDivisions, getTable, getLine, getBar } from '../api/report2Fetcher';
|
|
12
16
|
import MonthFilterModal from '../components/MonthFilterModal';
|
|
@@ -14,6 +18,7 @@ import DivisionFilterModal from '../components/DivisionFilterModal';
|
|
|
14
18
|
import FrozenTableReport2A from '../components/FrozenTableReport2A';
|
|
15
19
|
import SvgLineChartCompact from '../components/SvgLineChartCompact';
|
|
16
20
|
import SvgBarLineChartCompact from '../components/SvgBarLineChartCompact';
|
|
21
|
+
import { FilterIcon, FullScreenIcon } from './icons'; // or inline
|
|
17
22
|
|
|
18
23
|
// Proper SVG Funnel Icon Component (clean black filter icon)
|
|
19
24
|
const FunnelIcon = () => (
|
|
@@ -36,6 +41,8 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
36
41
|
const [selectedMonths, setSelectedMonths] = useState([]);
|
|
37
42
|
const [divisions, setDivisions] = useState([]);
|
|
38
43
|
const [division, setDivision] = useState(null);
|
|
44
|
+
const [fullscreen, setFullscreen] = useState(false);
|
|
45
|
+
const [zoomScale, setZoomScale] = useState(1);
|
|
39
46
|
|
|
40
47
|
const [table, setTable] = useState(null);
|
|
41
48
|
const [line, setLine] = useState(null);
|
|
@@ -43,6 +50,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
43
50
|
const [loading, setLoading] = useState(true);
|
|
44
51
|
const [error, setError] = useState(null);
|
|
45
52
|
|
|
53
|
+
|
|
46
54
|
useEffect(() => {
|
|
47
55
|
if (!api?.divisions || !token) return;
|
|
48
56
|
|
|
@@ -91,7 +99,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
91
99
|
<View style={styles.center}>
|
|
92
100
|
<Text style={styles.errorText}>{error}</Text>
|
|
93
101
|
<TouchableOpacity onPress={onBack}>
|
|
94
|
-
<Text style={styles.backLink}
|
|
102
|
+
<Text style={styles.backLink}>‹ Back to Reports</Text>
|
|
95
103
|
</TouchableOpacity>
|
|
96
104
|
</View>
|
|
97
105
|
);
|
|
@@ -101,8 +109,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
101
109
|
return <View style={styles.center}><Text>No data available</Text></View>;
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
const currentDivisionName = divisions.find(d => d.code === division)?.displayName || 'Division';
|
|
106
113
|
const filteredRows = table.rows.filter(r => selectedMonths.includes(r.monthLabel));
|
|
107
114
|
const filteredLine = filterChartByMonths(line, selectedMonths);
|
|
108
115
|
const filteredBar = filterChartByMonths(bar, selectedMonths);
|
|
@@ -112,7 +119,7 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
112
119
|
{/* HEADER WITH BACK ICON + HEADING */}
|
|
113
120
|
<View style={styles.header}>
|
|
114
121
|
<TouchableOpacity onPress={onBack} style={styles.backButton}>
|
|
115
|
-
<Text style={styles.backIcon}
|
|
122
|
+
<Text style={styles.backIcon}>‹</Text>
|
|
116
123
|
</TouchableOpacity>
|
|
117
124
|
|
|
118
125
|
<Text style={styles.headerTitle}>
|
|
@@ -122,28 +129,27 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
122
129
|
|
|
123
130
|
{/* FILTERS - BLACK TEXT + PROPER FUNNEL ICON */}
|
|
124
131
|
<View style={styles.filterBar}>
|
|
125
|
-
<TouchableOpacity
|
|
126
|
-
|
|
127
|
-
style={styles.
|
|
128
|
-
>
|
|
129
|
-
<FunnelIcon />
|
|
130
|
-
<Text style={styles.filterText}>
|
|
131
|
-
Months ({selectedMonths.length}/{months.length})
|
|
132
|
-
</Text>
|
|
132
|
+
<TouchableOpacity onPress={() => setMonthsModal(true)} style={styles.filterItem}>
|
|
133
|
+
<FilterIcon />
|
|
134
|
+
<Text style={styles.filterText}>Months ({selectedMonths.length}/{months.length})</Text>
|
|
133
135
|
</TouchableOpacity>
|
|
134
136
|
|
|
135
|
-
<TouchableOpacity
|
|
136
|
-
|
|
137
|
-
style={styles.
|
|
138
|
-
>
|
|
139
|
-
<FunnelIcon />
|
|
140
|
-
<Text style={styles.filterText}>
|
|
141
|
-
{currentDivisionName}
|
|
142
|
-
</Text>
|
|
137
|
+
<TouchableOpacity onPress={() => setDivisionModal(true)} style={styles.filterItem}>
|
|
138
|
+
<FilterIcon />
|
|
139
|
+
<Text style={styles.filterText}>{currentDivisionName}</Text>
|
|
143
140
|
</TouchableOpacity>
|
|
144
141
|
</View>
|
|
145
142
|
|
|
146
143
|
<ScrollView style={styles.content}>
|
|
144
|
+
{/* FULL SCREEN ICON ABOVE TABLE */}
|
|
145
|
+
<TouchableOpacity
|
|
146
|
+
onPress={() => setFullscreen(true)}
|
|
147
|
+
style={styles.fullScreenBtn}
|
|
148
|
+
>
|
|
149
|
+
<FullScreenIcon size={28} />
|
|
150
|
+
<Text style={styles.fullScreenText}>Full Screen View</Text>
|
|
151
|
+
</TouchableOpacity>
|
|
152
|
+
|
|
147
153
|
<FrozenTableReport2A rows={filteredRows} />
|
|
148
154
|
|
|
149
155
|
<View style={styles.chartContainer}>
|
|
@@ -156,6 +162,34 @@ const Report2AScreen = ({ api, token, onBack }) => {
|
|
|
156
162
|
</ScrollView>
|
|
157
163
|
|
|
158
164
|
{/* MODALS */}
|
|
165
|
+
|
|
166
|
+
{/* FULL SCREEN MODAL */}
|
|
167
|
+
<Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']}>
|
|
168
|
+
<View style={styles.fullModal}>
|
|
169
|
+
<View style={styles.fullHeader}>
|
|
170
|
+
<TouchableOpacity onPress={() => setFullscreen(false)}>
|
|
171
|
+
<Text style={styles.closeFull}>✕</Text>
|
|
172
|
+
</TouchableOpacity>
|
|
173
|
+
<Text style={styles.fullTitle}>Rotate device to landscape for best view</Text>
|
|
174
|
+
</View>
|
|
175
|
+
|
|
176
|
+
<PinchGestureHandler
|
|
177
|
+
onGestureEvent={(e) => setZoomScale(e.nativeEvent.scale)}
|
|
178
|
+
onHandlerStateChange={(e) => {
|
|
179
|
+
if (e.nativeEvent.state === State.END) {
|
|
180
|
+
setZoomScale(Math.max(0.8, Math.min(e.nativeEvent.scale, 3)));
|
|
181
|
+
}
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
<View style={styles.zoomView}>
|
|
185
|
+
<View style={{ transform: [{ scale: zoomScale }] }}>
|
|
186
|
+
<FrozenTableReport2A rows={table.rows} isFullscreen /> {/* all rows */}
|
|
187
|
+
</View>
|
|
188
|
+
</View>
|
|
189
|
+
</PinchGestureHandler>
|
|
190
|
+
</View>
|
|
191
|
+
</Modal>
|
|
192
|
+
|
|
159
193
|
<MonthFilterModal
|
|
160
194
|
visible={monthsModal}
|
|
161
195
|
months={months}
|
|
@@ -264,6 +298,20 @@ const styles = StyleSheet.create({
|
|
|
264
298
|
marginVertical: 12,
|
|
265
299
|
backgroundColor: '#fff',
|
|
266
300
|
},
|
|
301
|
+
fullScreenBtn: {
|
|
302
|
+
flexDirection: 'row',
|
|
303
|
+
alignItems: 'center',
|
|
304
|
+
justifyContent: 'center',
|
|
305
|
+
padding: 12,
|
|
306
|
+
marginBottom: 12,
|
|
307
|
+
},
|
|
308
|
+
fullScreenText: { marginLeft: 8, fontSize: 16, color: '#000', fontWeight: '600' },
|
|
309
|
+
|
|
310
|
+
fullModal: { flex: 1, backgroundColor: '#fff' },
|
|
311
|
+
fullHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', padding: 16, backgroundColor: '#f8f9fa', position: 'relative' },
|
|
312
|
+
closeFull: { position: 'absolute', left: 16, fontSize: 28, color: '#000' },
|
|
313
|
+
fullTitle: { fontSize: 16, color: '#000' },
|
|
314
|
+
zoomView: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
|
267
315
|
});
|
|
268
316
|
|
|
269
317
|
export default Report2AScreen;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Svg, { Path } from 'react-native-svg';
|
|
2
|
+
|
|
3
|
+
// Filter Funnel Icon (exact match to your image)
|
|
4
|
+
const FilterIcon = ({ size = 20, color = '#000' }) => (
|
|
5
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
6
|
+
<Path
|
|
7
|
+
d="M20 4H4V6.5L12 14.5L20 6.5V4Z"
|
|
8
|
+
stroke={color}
|
|
9
|
+
strokeWidth={2}
|
|
10
|
+
strokeLinecap="round"
|
|
11
|
+
strokeLinejoin="round"
|
|
12
|
+
/>
|
|
13
|
+
<Path
|
|
14
|
+
d="M8 11V19L16 19V11"
|
|
15
|
+
stroke={color}
|
|
16
|
+
strokeWidth={2}
|
|
17
|
+
strokeLinecap="round"
|
|
18
|
+
strokeLinejoin="round"
|
|
19
|
+
/>
|
|
20
|
+
</Svg>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// Full Screen Expand Icon
|
|
24
|
+
const FullScreenIcon = ({ size = 24, color = '#000' }) => (
|
|
25
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
26
|
+
<Path
|
|
27
|
+
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"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth={2}
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
</Svg>
|
|
34
|
+
);
|