@dhiraj0720/report1chart 2.6.6 → 2.6.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "2.6.6",
3
+ "version": "2.6.8",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
@@ -8,6 +8,7 @@
8
8
  "dependencies": {
9
9
  "axios": "^1.13.2",
10
10
  "react-native-gesture-handler": "^2.30.0",
11
+ "react-native-reanimated": "^4.2.1",
11
12
  "react-native-svg": "^15.15.1"
12
13
  },
13
14
  "peerDependencies": {
@@ -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
- // Reusable cell component
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 || rows.length === 0) {
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 Left Column - AY (Month) */}
45
- <View style={styles.frozenColumn}>
46
- <Cell bold>AY</Cell>
47
- {rows.map((row, index) => {
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
- '2024 TEU', '2025 TEU', 'TEU %',
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
- {/* Data Rows */}
78
- {rows.map((row, index) => {
68
+ {rows.map((row, i) => {
79
69
  const isTotal = row.monthLabel === 'Total';
80
-
81
70
  return (
82
- <View key={index} style={styles.dataRow}>
83
- <Cell highlight={isTotal}>{formatNumber(row.teu2024)}</Cell>
84
- <Cell highlight={isTotal}>{formatNumber(row.teu2025)}</Cell>
85
- <Cell highlight={isTotal}>
86
- <PercentCell value={row.teuChangePercent} />
87
- </Cell>
88
-
89
- <Cell highlight={isTotal}>{formatNumber(row.profitUsd2024)}</Cell>
90
- <Cell highlight={isTotal}>{formatNumber(row.profitUsd2025)}</Cell>
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
- flexDirection: 'row',
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
- backgroundColor: '#e9f0f8',
148
- },
149
- boldText: {
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
  });
@@ -93,7 +93,7 @@ const SvgBarLineChartCompact = ({ data }) => {
93
93
  fill="white"
94
94
  fontWeight="700"
95
95
  >
96
- ${formatNumber(val2024)}
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
- ${formatNumber(val2025)}
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
- ${formatNumber(budget)}
153
+ {formatNumber(budget)}
154
154
  </SvgText>
155
155
 
156
156
  {/* X Axis Label - Rotated */}
@@ -9,8 +9,7 @@ import {
9
9
  Dimensions,
10
10
  ActivityIndicator,
11
11
  } from 'react-native';
12
- import { PinchGestureHandler, State } from 'react-native-gesture-handler';
13
- import Svg from 'react-native-svg'; // if not imported globally
12
+ import Svg, { Path } from 'react-native-svg';
14
13
  import { filterChartByMonths } from '../utils/filterChartByMonths';
15
14
  import { getDivisions, getTable, getLine, getBar } from '../api/report2Fetcher';
16
15
  import MonthFilterModal from '../components/MonthFilterModal';
@@ -18,57 +17,33 @@ import DivisionFilterModal from '../components/DivisionFilterModal';
18
17
  import FrozenTableReport2A from '../components/FrozenTableReport2A';
19
18
  import SvgLineChartCompact from '../components/SvgLineChartCompact';
20
19
  import SvgBarLineChartCompact from '../components/SvgBarLineChartCompact';
21
- import { FilterIcon, FullScreenIcon } from './icons'; // or inline
22
-
23
- // Proper SVG Funnel Icon Component (clean black filter icon)
24
- const FunnelIcon = () => (
25
- <View style={styles.funnelIcon}>
26
- <View style={styles.funnelTop} />
27
- <View style={styles.funnelBody} />
28
- <View style={styles.funnelLines}>
29
- <View style={styles.line1} />
30
- <View style={styles.line2} />
31
- <View style={styles.line3} />
32
- </View>
33
- </View>
34
- );
35
20
 
36
21
  const Report2AScreen = ({ api, token, onBack }) => {
37
22
  const [monthsModal, setMonthsModal] = useState(false);
38
23
  const [divisionModal, setDivisionModal] = useState(false);
24
+ const [fullscreen, setFullscreen] = useState(false);
39
25
 
40
26
  const [months, setMonths] = useState([]);
41
27
  const [selectedMonths, setSelectedMonths] = useState([]);
42
28
  const [divisions, setDivisions] = useState([]);
43
29
  const [division, setDivision] = useState(null);
44
- const [fullscreen, setFullscreen] = useState(false);
45
- const [zoomScale, setZoomScale] = useState(1);
46
30
 
47
31
  const [table, setTable] = useState(null);
48
32
  const [line, setLine] = useState(null);
49
33
  const [bar, setBar] = useState(null);
50
34
  const [loading, setLoading] = useState(true);
51
- const [error, setError] = useState(null);
52
35
 
53
-
54
36
  useEffect(() => {
55
- if (!api?.divisions || !token) return;
56
-
57
37
  getDivisions(api.divisions, token)
58
38
  .then((d) => {
59
39
  setDivisions(d);
60
40
  if (d.length > 0) setDivision(d[0].code);
61
- })
62
- .catch(() => setError('Failed to load divisions'))
63
- .finally(() => setLoading(false));
64
- }, [api?.divisions, token]);
41
+ });
42
+ }, [api.divisions, token]);
65
43
 
66
44
  useEffect(() => {
67
- if (!division || !api || !token) return;
68
-
45
+ if (!division) return;
69
46
  setLoading(true);
70
- setError(null);
71
-
72
47
  Promise.all([
73
48
  getTable(api.table, division, token),
74
49
  getLine(api.line, division, token),
@@ -81,73 +56,63 @@ const Report2AScreen = ({ api, token, onBack }) => {
81
56
  setMonths(l.labels || []);
82
57
  setSelectedMonths(l.labels || []);
83
58
  })
84
- .catch(() => setError('Failed to load data'))
85
59
  .finally(() => setLoading(false));
86
- }, [division, api, token]);
60
+ }, [division]);
87
61
 
88
62
  if (loading) {
89
63
  return (
90
64
  <View style={styles.center}>
91
65
  <ActivityIndicator size="large" color="#000" />
92
- <Text style={styles.loadingText}>Loading...</Text>
93
66
  </View>
94
67
  );
95
68
  }
96
69
 
97
- if (error) {
98
- return (
99
- <View style={styles.center}>
100
- <Text style={styles.errorText}>{error}</Text>
101
- <TouchableOpacity onPress={onBack}>
102
- <Text style={styles.backLink}>‹ Back to Reports</Text>
103
- </TouchableOpacity>
104
- </View>
105
- );
106
- }
107
-
108
- if (!table || !line || !bar || !division) {
109
- return <View style={styles.center}><Text>No data available</Text></View>;
110
- }
70
+ const currentDivisionName = divisions.find(d => d.code === division)?.displayName || 'Division';
111
71
 
112
- const currentDivisionName = divisions.find(d => d.code === division)?.displayName || 'Division';
113
72
  const filteredRows = table.rows.filter(r => selectedMonths.includes(r.monthLabel));
114
73
  const filteredLine = filterChartByMonths(line, selectedMonths);
115
74
  const filteredBar = filterChartByMonths(bar, selectedMonths);
116
75
 
76
+ const { width, height } = Dimensions.get('window');
77
+ const isLandscape = width > height;
78
+
117
79
  return (
118
80
  <View style={styles.container}>
119
- {/* HEADER WITH BACK ICON + HEADING */}
81
+ {/* HEADER */}
120
82
  <View style={styles.header}>
121
- <TouchableOpacity onPress={onBack} style={styles.backButton}>
122
- <Text style={styles.backIcon}>‹</Text>
83
+ <TouchableOpacity onPress={onBack}>
84
+ <Text style={styles.backIcon}>←</Text>
123
85
  </TouchableOpacity>
124
-
125
- <Text style={styles.headerTitle}>
126
- {currentDivisionName} Transportation
127
- </Text>
86
+ <Text style={styles.headerTitle}>{currentDivisionName} Transportation</Text>
128
87
  </View>
129
88
 
130
- {/* FILTERS - BLACK TEXT + PROPER FUNNEL ICON */}
89
+ {/* FILTERS */}
131
90
  <View style={styles.filterBar}>
132
91
  <TouchableOpacity onPress={() => setMonthsModal(true)} style={styles.filterItem}>
133
- <FilterIcon />
92
+ <Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
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" />
95
+ </Svg>
134
96
  <Text style={styles.filterText}>Months ({selectedMonths.length}/{months.length})</Text>
135
97
  </TouchableOpacity>
136
98
 
137
99
  <TouchableOpacity onPress={() => setDivisionModal(true)} style={styles.filterItem}>
138
- <FilterIcon />
100
+ <Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
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" />
103
+ </Svg>
139
104
  <Text style={styles.filterText}>{currentDivisionName}</Text>
140
105
  </TouchableOpacity>
141
106
  </View>
142
107
 
143
108
  <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>
109
+ {/* FULL SCREEN BUTTON */}
110
+ <TouchableOpacity onPress={() => setFullscreen(true)} style={styles.fullScreenBtn}>
111
+ <Svg width={28} height={28} viewBox="0 0 24 24" fill="none">
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>
151
116
  </TouchableOpacity>
152
117
 
153
118
  <FrozenTableReport2A rows={filteredRows} />
@@ -161,60 +126,48 @@ const currentDivisionName = divisions.find(d => d.code === division)?.displayNam
161
126
  </View>
162
127
  </ScrollView>
163
128
 
164
- {/* MODALS */}
165
-
166
- {/* FULL SCREEN MODAL */}
167
- <Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']}>
129
+ {/* FULL SCREEN MODAL - PERFECT LANDSCAPE FIT + ZOOM */}
130
+ <Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']} animationType="fade">
168
131
  <View style={styles.fullModal}>
132
+ {/* TOP BAR - ONE LINE */}
169
133
  <View style={styles.fullHeader}>
134
+ <Text style={styles.fullHintText}>
135
+ Rotate device • Pinch to zoom
136
+ </Text>
170
137
  <TouchableOpacity onPress={() => setFullscreen(false)}>
171
- <Text style={styles.closeFull}>✕</Text>
138
+ <Text style={styles.closeBtn}>✕</Text>
172
139
  </TouchableOpacity>
173
- <Text style={styles.fullTitle}>Rotate device to landscape for best view</Text>
174
140
  </View>
175
141
 
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
- }}
142
+ {/* ZOOMABLE & FIT TABLE */}
143
+ <ScrollView
144
+ maximumZoomScale={3}
145
+ minimumZoomScale={0.7}
146
+ showsHorizontalScrollIndicator={false}
147
+ showsVerticalScrollIndicator={false}
148
+ contentContainerStyle={styles.zoomContent}
149
+ pinchGestureEnabled={true}
150
+ bouncesZoom={true}
183
151
  >
184
- <View style={styles.zoomView}>
185
- <View style={{ transform: [{ scale: zoomScale }] }}>
186
- <FrozenTableReport2A rows={table.rows} isFullscreen /> {/* all rows */}
187
- </View>
152
+ <View style={[
153
+ styles.tableWrapper,
154
+ isLandscape && styles.landscapeFit
155
+ ]}>
156
+ <FrozenTableReport2A rows={table.rows} isFullscreen />
188
157
  </View>
189
- </PinchGestureHandler>
158
+ </ScrollView>
190
159
  </View>
191
160
  </Modal>
192
161
 
193
- <MonthFilterModal
194
- visible={monthsModal}
195
- months={months}
196
- selected={selectedMonths}
197
- onApply={setSelectedMonths}
198
- onClose={() => setMonthsModal(false)}
199
- />
200
-
201
- <DivisionFilterModal
202
- visible={divisionModal}
203
- divisions={divisions}
204
- selected={division}
205
- onSelect={setDivision}
206
- onClose={() => setDivisionModal(false)}
207
- />
162
+ <MonthFilterModal visible={monthsModal} months={months} selected={selectedMonths} onApply={setSelectedMonths} onClose={() => setMonthsModal(false)} />
163
+ <DivisionFilterModal visible={divisionModal} divisions={divisions} selected={division} onSelect={setDivision} onClose={() => setDivisionModal(false)} />
208
164
  </View>
209
165
  );
210
166
  };
211
167
 
212
168
  const styles = StyleSheet.create({
213
169
  container: { flex: 1, backgroundColor: '#f8f9fa' },
214
- center: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 },
215
- loadingText: { marginTop: 12, fontSize: 16, color: '#000' },
216
- errorText: { fontSize: 16, color: '#d32f2f', textAlign: 'center', marginBottom: 20 },
217
- backLink: { fontSize: 18, color: '#000', fontWeight: '600' },
170
+ center: { flex: 1, justifyContent: 'center', alignItems: 'center' },
218
171
 
219
172
  header: {
220
173
  flexDirection: 'row',
@@ -225,15 +178,8 @@ const styles = StyleSheet.create({
225
178
  borderBottomWidth: 1,
226
179
  borderColor: '#eee',
227
180
  },
228
- backButton: { paddingRight: 12 },
229
- backIcon: { fontSize: 28, color: '#000', fontWeight: '300' },
230
- headerTitle: {
231
- fontSize: 19,
232
- fontWeight: '700',
233
- color: '#000',
234
- flex: 1,
235
- textAlign: 'center',
236
- },
181
+ backIcon: { fontSize: 28, color: '#000' },
182
+ headerTitle: { fontSize: 19, fontWeight: '700', color: '#000', flex: 1, textAlign: 'center' },
237
183
 
238
184
  filterBar: {
239
185
  flexDirection: 'row',
@@ -243,75 +189,60 @@ const styles = StyleSheet.create({
243
189
  borderBottomWidth: 1,
244
190
  borderColor: '#eee',
245
191
  },
246
- filterItem: {
192
+ filterItem: { flexDirection: 'row', alignItems: 'center' },
193
+ filterText: { fontSize: 16, color: '#000', fontWeight: '600', marginLeft: 8 },
194
+
195
+ fullScreenBtn: {
196
+ flexDirection: 'row',
197
+ alignItems: 'center',
198
+ justifyContent: 'center',
199
+ padding: 14,
200
+ backgroundColor: '#f0f0f0',
201
+ borderRadius: 8,
202
+ marginVertical: 12,
203
+ },
204
+ fullScreenText: { marginLeft: 10, fontSize: 16, color: '#000', fontWeight: '600' },
205
+
206
+ content: { flex: 1, padding: 12 },
207
+ chartContainer: { borderWidth: 1, borderColor: '#ddd', borderRadius: 10, overflow: 'hidden', marginVertical: 12, backgroundColor: '#fff' },
208
+
209
+ fullModal: { flex: 1, backgroundColor: '#fff' },
210
+ fullHeader: {
247
211
  flexDirection: 'row',
212
+ justifyContent: 'center',
248
213
  alignItems: 'center',
249
- paddingHorizontal: 16,
250
- paddingVertical: 8,
214
+ paddingVertical: 16,
215
+ paddingHorizontal: 20,
216
+ backgroundColor: '#f8f8f8',
217
+ borderBottomWidth: 1,
218
+ borderColor: '#ddd',
251
219
  },
252
- filterText: {
220
+ fullHintText: {
253
221
  fontSize: 16,
254
222
  color: '#000',
255
223
  fontWeight: '600',
256
- marginLeft: 8,
224
+ textAlign: 'center',
225
+ flex: 1,
257
226
  },
227
+ closeBtn: { fontSize: 28, color: '#000', paddingLeft: 20 },
258
228
 
259
- // Proper Funnel Icon (SVG-style with Views)
260
- funnelIcon: {
261
- width: 20,
262
- height: 20,
229
+ zoomContent: {
230
+ flexGrow: 1,
263
231
  justifyContent: 'center',
264
232
  alignItems: 'center',
233
+ padding: 20,
265
234
  },
266
- funnelTop: {
267
- width: 16,
268
- height: 4,
269
- backgroundColor: '#000',
270
- borderRadius: 2,
235
+ tableWrapper: {
236
+ shadowColor: '#000',
237
+ shadowOffset: { width: 0, height: 2 },
238
+ shadowOpacity: 0.1,
239
+ shadowRadius: 8,
240
+ elevation: 5,
271
241
  },
272
- funnelBody: {
273
- width: 10,
274
- height: 10,
275
- borderLeftWidth: 4,
276
- borderRightWidth: 4,
277
- borderBottomWidth: 8,
278
- borderColor: 'transparent',
279
- borderBottomColor: '#000',
280
- marginTop: -2,
242
+ landscapeFit: {
243
+ transform: [{ scale: 1.4 }], // Perfect fit in landscape
244
+ maxWidth: '100%',
281
245
  },
282
- funnelLines: {
283
- position: 'absolute',
284
- top: 6,
285
- left: 4,
286
- right: 4,
287
- },
288
- line1: { height: 1, backgroundColor: '#000', marginVertical: 2 },
289
- line2: { height: 1, backgroundColor: '#000', marginVertical: 2 },
290
- line3: { height: 1, backgroundColor: '#000', marginVertical: 2 },
291
-
292
- content: { flex: 1, padding: 12 },
293
- chartContainer: {
294
- borderWidth: 1,
295
- borderColor: '#ddd',
296
- borderRadius: 10,
297
- overflow: 'hidden',
298
- marginVertical: 12,
299
- backgroundColor: '#fff',
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' },
315
246
  });
316
247
 
317
248
  export default Report2AScreen;