@dhiraj0720/report1chart 2.9.2 → 2.9.3

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.9.2",
3
+ "version": "2.9.3",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
@@ -1,68 +1,78 @@
1
1
  import React from 'react';
2
2
  import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
3
 
4
- const Arrow = ({ value }) => (
5
- <Text
6
- style={[
7
- styles.arrow,
8
- value >= 0 ? styles.up : styles.down,
9
- ]}
10
- >
11
- {value >= 0 ? '↑' : '↓'} {Math.abs(value)}%
12
- </Text>
13
- );
4
+ // Format numbers with commas: 1234567 1,234,567
5
+ const formatNumber = (value) => {
6
+ if (value === null || value === undefined || value === '') return '-';
7
+ return Number(value).toLocaleString('en-US');
8
+ };
9
+
10
+ // Percentage cell with arrow and color
11
+ const PercentCell = ({ value }) => {
12
+ if (value === null || value === undefined) return <Text>-</Text>;
13
+ const positive = value >= 0;
14
+ return (
15
+ <Text style={[
16
+ styles.percentText,
17
+ { color: positive ? '#2e7d32' : '#d32f2f' }
18
+ ]}>
19
+ {positive ? '↑' : '↓'} {Math.abs(value)}%
20
+ </Text>
21
+ );
22
+ };
14
23
 
15
- const Cell = ({ children, bold, frozen }) => (
16
- <View
17
- style={[
18
- styles.cell,
19
- frozen && styles.frozenCell,
20
- ]}
21
- >
22
- <Text
23
- numberOfLines={1}
24
- ellipsizeMode="tail"
25
- style={[
26
- styles.text,
27
- bold && styles.bold,
28
- ]}
29
- >
24
+ // Reusable Cell
25
+ const Cell = ({ children, bold = false, highlight = false, isFrozen = false }) => (
26
+ <View style={[
27
+ styles.cell,
28
+ isFrozen && styles.frozenCell,
29
+ bold && styles.bold,
30
+ highlight && styles.highlightCell
31
+ ]}>
32
+ <Text style={[styles.cellText, bold && styles.boldText]}>
30
33
  {children}
31
34
  </Text>
32
35
  </View>
33
36
  );
34
37
 
35
- const FrozenTableReport1A = ({ rows }) => {
38
+ const FrozenTableReport1A = ({ rows = [], isFullscreen = false }) => {
39
+ if (!rows.length) {
40
+ return <Text style={{ textAlign: 'center', padding: 20, color: '#666' }}>No data available</Text>;
41
+ }
42
+
43
+ // Wider frozen column in fullscreen
44
+ const frozenColumnWidth = isFullscreen ? 180 : 150;
45
+
36
46
  return (
37
47
  <View style={styles.container}>
38
- {/* LEFT FROZEN COLUMN */}
39
- <View style={styles.frozen}>
40
- <Cell bold frozen>FAALİYET</Cell>
41
- {rows.map((r, i) => (
42
- <Cell key={i} frozen bold>
43
- {r.name}
48
+ {/* Frozen Left Column - FAALİYET */}
49
+ <View style={[styles.frozenColumn, { width: frozenColumnWidth }]}>
50
+ <Cell bold isFrozen>FAALİYET</Cell>
51
+ {rows.map((row, i) => (
52
+ <Cell key={i} bold isFrozen>
53
+ {row.name}
44
54
  </Cell>
45
55
  ))}
46
56
  </View>
47
57
 
48
- {/* SCROLLABLE COLUMNS */}
58
+ {/* Scrollable Columns */}
49
59
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
50
60
  <View>
61
+ {/* Header Row */}
51
62
  <View style={styles.headerRow}>
52
- <Cell bold>2024</Cell>
53
- <Cell bold>2025</Cell>
54
- <Cell bold>Artış %</Cell>
55
- <Cell bold>2025 Bütçe</Cell>
56
- <Cell bold>Sapma %</Cell>
63
+ {['2024', '2025', 'Artış %', '2025 Bütçe', 'Sapma %'].map((header) => (
64
+ <Cell key={header} bold>{header}</Cell>
65
+ ))}
57
66
  </View>
58
67
 
59
- {rows.map((r, i) => (
60
- <View key={i} style={styles.row}>
61
- <Cell>{r.actual2024}</Cell>
62
- <Cell>{r.actual2025}</Cell>
63
- <Cell><Arrow value={r.actualChangePercent} /></Cell>
64
- <Cell>{r.budget2025}</Cell>
65
- <Cell><Arrow value={r.budgetVariancePercent} /></Cell>
68
+ {/* Data Rows */}
69
+ {rows.map((row, i) => (
70
+ <View key={i} style={styles.dataRow}>
71
+ <Cell>{formatNumber(row.actual2024)}</Cell>
72
+ <Cell>{formatNumber(row.actual2025)}</Cell>
73
+ <Cell><PercentCell value={row.actualChangePercent} /></Cell>
74
+ <Cell>{formatNumber(row.budget2025)}</Cell>
75
+ <Cell><PercentCell value={row.budgetVariancePercent} /></Cell>
66
76
  </View>
67
77
  ))}
68
78
  </View>
@@ -73,9 +83,6 @@ const FrozenTableReport1A = ({ rows }) => {
73
83
 
74
84
  export default FrozenTableReport1A;
75
85
 
76
- /* ======================
77
- STYLES (COMPACT)
78
- ====================== */
79
86
  const styles = StyleSheet.create({
80
87
  container: {
81
88
  flexDirection: 'row',
@@ -83,57 +90,51 @@ const styles = StyleSheet.create({
83
90
  borderColor: '#ddd',
84
91
  borderRadius: 8,
85
92
  overflow: 'hidden',
93
+ marginVertical: 12,
86
94
  backgroundColor: '#fff',
87
95
  },
88
-
89
- frozen: {
90
- width: 150, // 👈 fixed width
91
- backgroundColor: '#f5f7fa',
92
- },
93
-
94
- frozenCell: {
95
- alignItems: 'flex-start',
96
- paddingHorizontal: 8,
96
+ frozenColumn: {
97
+ backgroundColor: '#f4f6f8',
98
+ borderRightWidth: 1,
99
+ borderColor: '#ddd',
97
100
  },
98
-
99
101
  headerRow: {
100
102
  flexDirection: 'row',
101
- backgroundColor: '#f0f0f0',
103
+ backgroundColor: '#f4f6f8',
102
104
  },
103
-
104
- row: {
105
+ dataRow: {
105
106
  flexDirection: 'row',
106
107
  },
107
-
108
108
  cell: {
109
- width: 110, // 👈 compact width
110
- paddingVertical: 6, // 👈 reduced height
111
- paddingHorizontal: 6,
112
- borderBottomWidth: 1,
113
- borderColor: '#eee',
109
+ minWidth: 110,
110
+ paddingHorizontal: 14, // +7 left/right for spacious feel
111
+ paddingVertical: 12,
114
112
  justifyContent: 'center',
115
113
  alignItems: 'center',
114
+ borderBottomWidth: 1,
115
+ borderColor: '#e0e0e0',
116
116
  },
117
-
118
- text: {
119
- fontSize: 12, // 👈 smaller text
120
- color: '#222',
117
+ frozenCell: {
118
+ justifyContent: 'flex-start',
119
+ paddingLeft: 18,
120
+ },
121
+ cellText: {
122
+ fontSize: 12.5,
123
+ textAlign: 'center',
124
+ color: '#333',
121
125
  },
122
-
123
126
  bold: {
124
- fontWeight: '700',
127
+ backgroundColor: '#e9f0f8',
125
128
  },
126
-
127
- arrow: {
128
- fontSize: 12,
129
+ boldText: {
129
130
  fontWeight: '700',
130
131
  },
131
-
132
- up: {
133
- color: '#2e7d32',
132
+ highlightCell: {
133
+ backgroundColor: '#e9f0f8',
134
134
  },
135
-
136
- down: {
137
- color: '#d32f2f',
135
+ percentText: {
136
+ fontWeight: '700',
137
+ fontSize: 12.5,
138
+ textAlign: 'center',
138
139
  },
139
- });
140
+ });
@@ -1,9 +1,17 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { ScrollView, Text, TouchableOpacity, View, StyleSheet } from 'react-native';
2
+ import {
3
+ ScrollView,
4
+ Text,
5
+ TouchableOpacity,
6
+ View,
7
+ StyleSheet,
8
+ Modal,
9
+ Dimensions,
10
+ } from 'react-native';
11
+ import Svg, { Path } from 'react-native-svg';
3
12
  import fetchReport1 from '../api/report1Fetcher';
4
13
  import FrozenTableReport1A from '../components/FrozenTableReport1A';
5
14
  import Report1Card from '../components/Report1Card';
6
- import FullScreenTableModal from '../components/FullScreenTableModal';
7
15
 
8
16
  const Report1AScreen = ({ endpoint, token, onBack }) => {
9
17
  const [rows, setRows] = useState([]);
@@ -11,44 +19,42 @@ const Report1AScreen = ({ endpoint, token, onBack }) => {
11
19
 
12
20
  useEffect(() => {
13
21
  fetchReport1(endpoint, token).then(setRows);
14
- }, []);
22
+ }, [endpoint, token]);
23
+
24
+ const { width, height } = Dimensions.get('window');
25
+ const isLandscape = width > height;
15
26
 
16
27
  return (
17
- <>
18
- <ScrollView style={{ padding: 16 }}>
19
- {/* <Text onPress={onBack} style={{ marginBottom: 12 }}>‹ Back</Text>
20
-
21
- <Text style={{ fontSize: 18, fontWeight: '700', marginBottom: 12 }}>
22
- PERFORMANS RAPORU (USD)
23
- </Text> */}
24
-
25
- <View style={styles.header}>
26
- <TouchableOpacity onPress={onBack}>
27
- <Text style={styles.backIcon}>‹</Text>
28
- </TouchableOpacity>
29
- <Text style={styles.headerTitle}>PERFORMANS RAPORU (USD)</Text>
30
- </View>
31
-
32
-
33
-
34
- {/* FULLSCREEN BUTTON */}
35
- <TouchableOpacity
36
- onPress={() => setFullscreen(true)}
37
- style={{
38
- alignSelf: 'flex-end',
39
- marginBottom: 8,
40
- padding: 6,
41
- }}
42
- >
43
- <Text style={{ fontWeight: '700' }}>⤢ Full Screen</Text>
28
+ <View style={styles.container}>
29
+ {/* FULL-WIDTH BLUE HEADER */}
30
+ <View style={styles.header}>
31
+ <TouchableOpacity onPress={onBack} style={styles.backButton}>
32
+ <Text style={styles.backIcon}>←</Text>
33
+ </TouchableOpacity>
34
+ <Text style={styles.headerTitle}>PERFORMANS RAPORU (USD)</Text>
35
+ </View>
36
+
37
+ {/* FILTER BAR - DIVISION + FULL SCREEN */}
38
+ <View style={styles.filterBar}>
39
+ {/* DIVISION FILTER - LEFT */}
40
+ <TouchableOpacity style={styles.filterItemLeft}>
41
+ <Svg width={22} height={22} viewBox="0 0 24 24" fill="none">
42
+ <Path d="M20 4H4V6.5L12 14.5L20 6.5V4Z" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
43
+ <Path d="M8 11V19L16 19V11" stroke="#000" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
44
+ </Svg>
45
+ <Text style={styles.filterText}>Division Filter</Text>
44
46
  </TouchableOpacity>
45
47
 
48
+ {/* FULL SCREEN - RIGHT */}
49
+ <TouchableOpacity onPress={() => setFullscreen(true)} style={styles.filterItemRight}>
50
+ <Text style={styles.fullScreenFilterText}>⤢ Full Screen</Text>
51
+ </TouchableOpacity>
52
+ </View>
53
+
54
+ <ScrollView style={styles.content}>
46
55
  <FrozenTableReport1A rows={rows} />
47
56
 
48
- {/* BELOW TABLE → CARDS */}
49
- <Text style={{ marginVertical: 12, fontWeight: '700' }}>
50
- Individual Reports
51
- </Text>
57
+ <Text style={styles.sectionTitle}>Individual Reports</Text>
52
58
 
53
59
  {rows.map((r, i) => (
54
60
  <Report1Card key={i} item={r} />
@@ -56,41 +62,144 @@ const Report1AScreen = ({ endpoint, token, onBack }) => {
56
62
  </ScrollView>
57
63
 
58
64
  {/* FULL SCREEN MODAL */}
59
- <FullScreenTableModal
60
- visible={fullscreen}
61
- rows={rows}
62
- onClose={() => setFullscreen(false)}
63
- />
64
- </>
65
+ <Modal visible={fullscreen} supportedOrientations={['portrait', 'landscape']} animationType="fade">
66
+ <View style={styles.fullModal}>
67
+ <View style={styles.fullHeader}>
68
+ <Text style={styles.fullHintText}>Rotate device • Pinch to zoom</Text>
69
+ <TouchableOpacity onPress={() => setFullscreen(false)}>
70
+ <Text style={styles.closeBtn}>✕</Text>
71
+ </TouchableOpacity>
72
+ </View>
73
+
74
+ <ScrollView
75
+ maximumZoomScale={3}
76
+ minimumZoomScale={0.7}
77
+ showsHorizontalScrollIndicator={false}
78
+ showsVerticalScrollIndicator={false}
79
+ contentContainerStyle={styles.zoomContent}
80
+ pinchGestureEnabled={true}
81
+ bouncesZoom={true}
82
+ >
83
+ <View style={[styles.tableWrapper, isLandscape && styles.landscapeFit]}>
84
+ <FrozenTableReport1A rows={rows} isFullscreen />
85
+ </View>
86
+ </ScrollView>
87
+ </View>
88
+ </Modal>
89
+ </View>
65
90
  );
66
91
  };
67
92
 
68
- // ONLY ADDED THIS STYLES PART — NOTHING ELSE CHANGED
69
93
  const styles = StyleSheet.create({
94
+ container: { flex: 1, backgroundColor: '#f8f9fa' },
70
95
 
71
-
72
- header: {
96
+ // FULL-WIDTH BLUE HEADER
97
+ header: {
73
98
  flexDirection: 'row',
74
99
  alignItems: 'center',
75
- paddingHorizontal: 16,
76
100
  paddingVertical: 18,
77
- backgroundColor: '#4E79A7',
78
- borderBottomWidth: 1,
79
- borderColor: '#4E79A7',
101
+ paddingHorizontal: 16,
102
+ backgroundColor: '#1565c0', // Deep blue
103
+ },
104
+ backButton: {
105
+ padding: 8,
80
106
  },
81
107
  backIcon: {
82
108
  fontSize: 32,
83
- color: '#fff',
84
- marginRight: 16,
85
- fontWeight: '700',
109
+ color: '#ffffff',
110
+ fontWeight: '300',
86
111
  },
87
112
  headerTitle: {
88
113
  fontSize: 19,
89
114
  fontWeight: '700',
90
- color: '#fff',
115
+ color: '#ffffff',
116
+ flex: 1,
117
+ textAlign: 'center',
118
+ },
119
+
120
+ // FILTER BAR - LEFT & RIGHT ALIGNED
121
+ filterBar: {
122
+ flexDirection: 'row',
123
+ justifyContent: 'space-between',
124
+ alignItems: 'center',
125
+ paddingHorizontal: 16,
126
+ paddingVertical: 14,
127
+ backgroundColor: '#fff',
128
+ borderBottomWidth: 1,
129
+ borderColor: '#eee',
130
+ },
131
+ filterItemLeft: {
132
+ flexDirection: 'row',
133
+ alignItems: 'center',
134
+ },
135
+ filterItemRight: {
136
+ flexDirection: 'row',
137
+ alignItems: 'center',
138
+ },
139
+ filterText: {
140
+ fontSize: 16,
141
+ color: '#000',
142
+ fontWeight: '600',
143
+ marginLeft: 8,
144
+ },
145
+ fullScreenFilterText: {
146
+ fontSize: 16,
147
+ color: '#000',
148
+ fontWeight: '700',
149
+ },
150
+
151
+ content: {
91
152
  flex: 1,
153
+ paddingHorizontal: 12,
154
+ paddingTop: 12,
155
+ },
156
+
157
+ sectionTitle: {
158
+ fontSize: 16,
159
+ fontWeight: '700',
160
+ marginVertical: 16,
161
+ color: '#111',
162
+ },
163
+
164
+ fullModal: { flex: 1, backgroundColor: '#fff' },
165
+ fullHeader: {
166
+ flexDirection: 'row',
167
+ justifyContent: 'center',
168
+ alignItems: 'center',
169
+ paddingVertical: 16,
170
+ paddingHorizontal: 20,
171
+ backgroundColor: '#f8f8f8',
172
+ borderBottomWidth: 1,
173
+ borderColor: '#ddd',
174
+ },
175
+ fullHintText: {
176
+ fontSize: 16,
177
+ color: '#000',
178
+ fontWeight: '600',
92
179
  textAlign: 'center',
180
+ flex: 1,
181
+ },
182
+ closeBtn: { fontSize: 28, color: '#000', paddingLeft: 20 },
183
+
184
+ zoomContent: {
185
+ flexGrow: 1,
186
+ justifyContent: 'center',
187
+ alignItems: 'center',
188
+ padding: 20,
189
+ },
190
+ tableWrapper: {
191
+ backgroundColor: '#fff',
192
+ borderRadius: 12,
193
+ overflow: 'hidden',
194
+ shadowColor: '#000',
195
+ shadowOffset: { width: 0, height: 4 },
196
+ shadowOpacity: 0.15,
197
+ shadowRadius: 10,
198
+ elevation: 8,
199
+ },
200
+ landscapeFit: {
201
+ transform: [{ scale: 1.45 }],
93
202
  },
94
203
  });
95
204
 
96
- export default Report1AScreen;
205
+ export default Report1AScreen;