@dhiraj0720/report1chart 2.2.0 → 2.2.1

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.2.0",
3
+ "version": "2.2.1",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
@@ -13,34 +13,30 @@ class ApiService {
13
13
 
14
14
  async fetchReportData(apiConfig) {
15
15
  try {
16
- console.log('Fetching from npm package:', apiConfig.url);
17
-
18
16
  const config = {
19
17
  url: apiConfig.url,
20
18
  method: apiConfig.method || 'GET',
21
19
  timeout: apiConfig.timeout || 15000,
22
20
  headers: {
23
21
  'Content-Type': 'application/json',
24
- 'Accept': 'application/json',
25
- ...(apiConfig.token && {
26
- 'Authorization': `Bearer ${apiConfig.token}`
27
- })
22
+ 'Accept': 'application/json'
28
23
  }
29
24
  };
30
25
 
26
+ if (apiConfig.token) {
27
+ config.headers.Authorization = `Bearer ${apiConfig.token}`;
28
+ }
29
+
31
30
  const response = await this.api(config);
32
-
33
- // Transform data based on endpoint
34
31
  return this.transformData(response.data, apiConfig.url);
35
32
 
36
33
  } catch (error) {
37
- console.error('NPM Package API Error:', error);
38
- throw this.handleError(error, apiConfig.url);
34
+ console.error('API Error:', error.message);
35
+ return this.getFallbackData(apiConfig.url);
39
36
  }
40
37
  }
41
38
 
42
39
  transformData(data, url) {
43
- // Transform data based on endpoint patterns
44
40
  if (url.includes('cumulative-operating-profit')) {
45
41
  return this.transformPerformanceData(data);
46
42
  } else if (url.includes('revenue-by-mode')) {
@@ -51,55 +47,44 @@ class ApiService {
51
47
  return this.transformRevenueTrend(data);
52
48
  }
53
49
 
54
- // Return as-is for unknown formats
55
50
  return data;
56
51
  }
57
52
 
58
53
  transformPerformanceData(data) {
59
- // Transform performance report data to match table structure
60
- if (!data || !data.data) return [];
54
+ if (!data || !data.data) return this.getPerformanceFallbackData();
61
55
 
62
56
  return data.data.map(item => ({
63
- name: item.name || item.activity || 'Unknown',
64
- actual2024: item.actual2024 || item.lastYear || 0,
65
- actual2025: item.actual2025 || item.currentYear || 0,
66
- budget2025: item.budget2025 || item.budget || 0,
67
- yoYChangePercent: this.calculatePercentageChange(
68
- item.actual2024 || item.lastYear || 0,
69
- item.actual2025 || item.currentYear || 0
70
- ),
71
- budgetVariancePercent: this.calculatePercentageChange(
72
- item.budget2025 || item.budget || 0,
73
- item.actual2025 || item.currentYear || 0
74
- ),
75
- grossMarginPercent: item.grossMargin || item.margin || 0,
76
- isTotal: item.isTotal || item.name?.toLowerCase().includes('total')
57
+ name: item.name || 'Unknown',
58
+ actual2024: item.actual2024 || 0,
59
+ actual2025: item.actual2025 || 0,
60
+ budget2025: item.budget2025 || 0,
61
+ yoYChangePercent: this.calculatePercentageChange(item.actual2024 || 0, item.actual2025 || 0),
62
+ budgetVariancePercent: this.calculatePercentageChange(item.budget2025 || 0, item.actual2025 || 0),
63
+ grossMarginPercent: item.grossMarginPercent || 0,
64
+ isTotal: item.isTotal || false
77
65
  }));
78
66
  }
79
67
 
80
68
  transformRevenueByMode(data) {
81
- // Transform revenue by mode data
82
69
  if (Array.isArray(data)) {
83
70
  return data.map(item => ({
84
- mode: item.mode || item.transportMode || 'Unknown',
85
- revenue: item.revenue || item.value || 0
71
+ mode: item.mode || 'Unknown',
72
+ revenue: item.revenue || 0
86
73
  }));
87
74
  }
88
75
 
89
- // Handle different response formats
90
76
  if (data.data && Array.isArray(data.data)) {
91
77
  return data.data;
92
78
  }
93
79
 
94
- return [];
80
+ return this.getRevenueByModeFallbackData();
95
81
  }
96
82
 
97
83
  transformShipmentByDirection(data) {
98
- // Transform shipment by direction data
99
84
  if (Array.isArray(data)) {
100
85
  return data.map(item => ({
101
- direction: item.direction || item.type || 'Unknown',
102
- shipments: item.shipments || item.count || item.value || 0
86
+ direction: item.direction || 'Unknown',
87
+ shipments: item.shipments || 0
103
88
  }));
104
89
  }
105
90
 
@@ -107,11 +92,10 @@ class ApiService {
107
92
  return data.data;
108
93
  }
109
94
 
110
- return [];
95
+ return this.getShipmentFallbackData();
111
96
  }
112
97
 
113
98
  transformRevenueTrend(data) {
114
- // Transform revenue trend data
115
99
  if (data.labels && data.values) {
116
100
  return {
117
101
  labels: data.labels,
@@ -119,62 +103,60 @@ class ApiService {
119
103
  };
120
104
  }
121
105
 
122
- return data;
106
+ return this.getRevenueTrendFallbackData();
123
107
  }
124
108
 
125
109
  calculatePercentageChange(oldValue, newValue) {
126
110
  if (!oldValue || oldValue === 0) return 0;
127
- return ((newValue - oldValue) / Math.abs(oldValue)) * 100;
128
- }
129
-
130
- handleError(error, url) {
131
- let errorMessage = 'Failed to fetch report data';
132
-
133
- if (error.response) {
134
- // Server responded with error
135
- errorMessage = `Server Error: ${error.response.status} - ${error.response.data?.message || 'Unknown error'}`;
136
- } else if (error.request) {
137
- // Request made but no response
138
- errorMessage = 'Network Error: No response from server';
139
- } else {
140
- // Something else happened
141
- errorMessage = error.message || 'Unknown error occurred';
142
- }
143
-
144
- // Fallback mock data for development
145
- console.warn('Using fallback data for:', url);
146
- return {
147
- error: errorMessage,
148
- fallbackData: this.getFallbackData(url)
149
- };
111
+ return Number(((newValue - oldValue) / Math.abs(oldValue)) * 100).toFixed(1);
150
112
  }
151
113
 
152
114
  getFallbackData(url) {
153
- // Return mock data for development
154
115
  if (url.includes('cumulative-operating-profit')) {
155
- return [
156
- { name: "Ocean Transportation", actual2024: 45000000, actual2025: 52000000, budget2025: 50000000, grossMarginPercent: 25, isTotal: false },
157
- { name: "Air Freight", actual2024: 18000000, actual2025: 21000000, budget2025: 20000000, grossMarginPercent: 22, isTotal: false },
158
- { name: "Road Logistics", actual2024: 32000000, actual2025: 38000000, budget2025: 35000000, grossMarginPercent: 28, isTotal: false },
159
- { name: "Warehousing", actual2024: 12000000, actual2025: 15000000, budget2025: 14000000, grossMarginPercent: 35, isTotal: false },
160
- { name: "Customs Clearance", actual2024: 8000000, actual2025: 9500000, budget2025: 9000000, grossMarginPercent: 40, isTotal: false },
161
- { name: "TOTAL", actual2024: 115000000, actual2025: 135500000, budget2025: 128000000, grossMarginPercent: 28, isTotal: true }
162
- ];
116
+ return this.getPerformanceFallbackData();
163
117
  } else if (url.includes('revenue-by-mode')) {
164
- return [
165
- { mode: "Ocean", revenue: 101951456 },
166
- { mode: "Road", revenue: 89158437 },
167
- { mode: "Air", revenue: 40171032 }
168
- ];
118
+ return this.getRevenueByModeFallbackData();
169
119
  } else if (url.includes('shipment-by-direction')) {
170
- return [
171
- { direction: "Export", shipments: 568 },
172
- { direction: "Import", shipments: 546 }
173
- ];
120
+ return this.getShipmentFallbackData();
121
+ } else if (url.includes('revenue-trend')) {
122
+ return this.getRevenueTrendFallbackData();
174
123
  }
175
124
 
176
125
  return [];
177
126
  }
127
+
128
+ getPerformanceFallbackData() {
129
+ return [
130
+ { name: "Ocean Transportation", actual2024: 45000000, actual2025: 52000000, budget2025: 50000000, grossMarginPercent: 25, isTotal: false },
131
+ { name: "Air Freight", actual2024: 18000000, actual2025: 21000000, budget2025: 20000000, grossMarginPercent: 22, isTotal: false },
132
+ { name: "Road Logistics", actual2024: 32000000, actual2025: 38000000, budget2025: 35000000, grossMarginPercent: 28, isTotal: false },
133
+ { name: "Warehousing", actual2024: 12000000, actual2025: 15000000, budget2025: 14000000, grossMarginPercent: 35, isTotal: false },
134
+ { name: "Customs Clearance", actual2024: 8000000, actual2025: 9500000, budget2025: 9000000, grossMarginPercent: 40, isTotal: false },
135
+ { name: "TOTAL", actual2024: 115000000, actual2025: 135500000, budget2025: 128000000, grossMarginPercent: 28, isTotal: true }
136
+ ];
137
+ }
138
+
139
+ getRevenueByModeFallbackData() {
140
+ return [
141
+ { mode: "Ocean", revenue: 101951456 },
142
+ { mode: "Road", revenue: 89158437 },
143
+ { mode: "Air", revenue: 40171032 }
144
+ ];
145
+ }
146
+
147
+ getShipmentFallbackData() {
148
+ return [
149
+ { direction: "Export", shipments: 568 },
150
+ { direction: "Import", shipments: 546 }
151
+ ];
152
+ }
153
+
154
+ getRevenueTrendFallbackData() {
155
+ return {
156
+ labels: ["01-2025", "02-2025", "03-2025", "04-2025", "05-2025", "06-2025"],
157
+ values: [16011213, 13368072, 17004674, 19065790, 19978378, 20766951]
158
+ };
159
+ }
178
160
  }
179
161
 
180
- export default new ApiService();
162
+ export default new ApiService();
@@ -24,12 +24,11 @@ const BarChart = ({ data, title }) => {
24
24
  );
25
25
  }
26
26
 
27
- const values = data.map(d => d.revenue || d.value || d.shipments || 0);
28
- const labels = data.map(d => d.mode || d.label || d.direction || '');
27
+ const values = data.map(d => d.revenue || d.value || 0);
28
+ const labels = data.map(d => d.mode || d.label || '');
29
29
 
30
30
  const maxValue = Math.max(...values, 1);
31
31
  const chartHeight = 200;
32
- const barWidth = 40; // Fixed width, no Dimensions needed
33
32
 
34
33
  return (
35
34
  <View style={styles.container}>
@@ -37,7 +36,6 @@ const BarChart = ({ data, title }) => {
37
36
  <ScrollView
38
37
  horizontal
39
38
  showsHorizontalScrollIndicator={true}
40
- contentContainerStyle={styles.scrollContent}
41
39
  >
42
40
  <View style={[styles.chart, { height: chartHeight }]}>
43
41
  {values.map((value, index) => {
@@ -48,7 +46,6 @@ const BarChart = ({ data, title }) => {
48
46
  <View key={index} style={styles.barWrapper}>
49
47
  <View style={[styles.bar, {
50
48
  height,
51
- width: barWidth,
52
49
  backgroundColor: getColor(index)
53
50
  }]} />
54
51
  <Text style={styles.barLabel} numberOfLines={1}>{label}</Text>
@@ -78,31 +75,29 @@ const styles = StyleSheet.create({
78
75
  marginBottom: 20,
79
76
  textAlign: 'center',
80
77
  },
81
- scrollContent: {
82
- paddingHorizontal: 8,
83
- },
84
78
  chart: {
85
79
  flexDirection: 'row',
86
80
  alignItems: 'flex-end',
87
- justifyContent: 'flex-start',
81
+ paddingHorizontal: 8,
88
82
  minWidth: 400,
89
83
  },
90
84
  barWrapper: {
91
85
  alignItems: 'center',
92
- marginHorizontal: 8,
86
+ marginHorizontal: 12,
93
87
  },
94
88
  bar: {
89
+ width: 40,
95
90
  borderRadius: 4,
96
91
  },
97
92
  barLabel: {
98
93
  marginTop: 8,
99
- fontSize: 11,
94
+ fontSize: 12,
100
95
  color: '#666',
101
96
  textAlign: 'center',
102
97
  width: 60,
103
98
  },
104
99
  valueText: {
105
- fontSize: 10,
100
+ fontSize: 11,
106
101
  color: '#999',
107
102
  marginTop: 4,
108
103
  fontWeight: '500',
@@ -19,15 +19,12 @@ const LineChart = ({ data, title }) => {
19
19
  );
20
20
  }
21
21
 
22
- // Handle different data formats
23
22
  let values, labels;
24
23
 
25
24
  if (Array.isArray(data)) {
26
- // If data is array of objects
27
- values = data.map(d => d.value || d.revenue || d.shipments || 0);
28
- labels = data.map(d => d.label || d.month || d.mode || d.direction || '');
25
+ values = data.map(d => d.value || 0);
26
+ labels = data.map(d => d.label || '');
29
27
  } else {
30
- // If data has separate values and labels
31
28
  values = data.values || [];
32
29
  labels = data.labels || [];
33
30
  }
@@ -42,7 +39,6 @@ const LineChart = ({ data, title }) => {
42
39
 
43
40
  const maxValue = Math.max(...values, 1);
44
41
  const chartHeight = 200;
45
- const barWidth = 30; // Fixed width
46
42
 
47
43
  return (
48
44
  <View style={styles.container}>
@@ -50,7 +46,6 @@ const LineChart = ({ data, title }) => {
50
46
  <ScrollView
51
47
  horizontal
52
48
  showsHorizontalScrollIndicator={true}
53
- contentContainerStyle={styles.scrollContent}
54
49
  >
55
50
  <View style={[styles.chart, { height: chartHeight }]}>
56
51
  {values.map((value, index) => {
@@ -61,7 +56,6 @@ const LineChart = ({ data, title }) => {
61
56
  <View key={index} style={styles.pointWrapper}>
62
57
  <View style={[styles.point, {
63
58
  height: Math.max(height, 2),
64
- width: barWidth
65
59
  }]} />
66
60
  <View style={styles.connector} />
67
61
  <Text style={styles.pointLabel} numberOfLines={1}>{label}</Text>
@@ -91,20 +85,18 @@ const styles = StyleSheet.create({
91
85
  marginBottom: 20,
92
86
  textAlign: 'center',
93
87
  },
94
- scrollContent: {
95
- paddingHorizontal: 8,
96
- },
97
88
  chart: {
98
89
  flexDirection: 'row',
99
90
  alignItems: 'flex-end',
100
- justifyContent: 'flex-start',
91
+ paddingHorizontal: 8,
101
92
  minWidth: 400,
102
93
  },
103
94
  pointWrapper: {
104
95
  alignItems: 'center',
105
- marginHorizontal: 8,
96
+ marginHorizontal: 12,
106
97
  },
107
98
  point: {
99
+ width: 30,
108
100
  backgroundColor: '#2196F3',
109
101
  borderRadius: 2,
110
102
  },
@@ -117,13 +109,13 @@ const styles = StyleSheet.create({
117
109
  },
118
110
  pointLabel: {
119
111
  marginTop: 8,
120
- fontSize: 11,
112
+ fontSize: 12,
121
113
  color: '#666',
122
114
  textAlign: 'center',
123
115
  width: 60,
124
116
  },
125
117
  valueText: {
126
- fontSize: 10,
118
+ fontSize: 11,
127
119
  color: '#999',
128
120
  marginTop: 4,
129
121
  fontWeight: '500',
@@ -23,15 +23,15 @@ const PieChart = ({ data, title }) => {
23
23
  );
24
24
  }
25
25
 
26
- const total = data.reduce((sum, item) => sum + (item.shipments || item.revenue || item.value || 0), 0);
26
+ const total = data.reduce((sum, item) => sum + (item.shipments || item.value || 0), 0);
27
27
 
28
28
  return (
29
29
  <View style={styles.container}>
30
30
  {title && <Text style={styles.title}>{title}</Text>}
31
31
  <View style={styles.pieContainer}>
32
32
  {data.map((item, index) => {
33
- const value = item.shipments || item.revenue || item.value || 0;
34
- const label = item.direction || item.mode || item.label || `Item ${index + 1}`;
33
+ const value = item.shipments || item.value || 0;
34
+ const label = item.direction || item.label || `Item ${index + 1}`;
35
35
  const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : '0';
36
36
 
37
37
  return (
@@ -60,11 +60,6 @@ const styles = StyleSheet.create({
60
60
  marginBottom: 16,
61
61
  borderWidth: 1,
62
62
  borderColor: '#e8e8e8',
63
- shadowColor: '#000',
64
- shadowOffset: { width: 0, height: 1 },
65
- shadowOpacity: 0.05,
66
- shadowRadius: 2,
67
- elevation: 2,
68
63
  },
69
64
  title: {
70
65
  fontSize: 18,
@@ -24,9 +24,6 @@ const ReportCard = ({ report, onPress }) => {
24
24
  <Text style={styles.name}>{report.name}</Text>
25
25
  <Text style={styles.title}>{report.title}</Text>
26
26
  <Text style={styles.desc}>{report.description}</Text>
27
- <Text style={styles.apiInfo}>
28
- API: {report.apiConfig?.url ? 'Configured' : 'No API'}
29
- </Text>
30
27
  </View>
31
28
  <Text style={styles.arrow}>›</Text>
32
29
  </TouchableOpacity>
@@ -43,11 +40,6 @@ const styles = StyleSheet.create({
43
40
  marginBottom: 12,
44
41
  borderWidth: 1,
45
42
  borderColor: '#e8e8e8',
46
- shadowColor: '#000',
47
- shadowOffset: { width: 0, height: 1 },
48
- shadowOpacity: 0.05,
49
- shadowRadius: 2,
50
- elevation: 2,
51
43
  },
52
44
  icon: {
53
45
  width: 44,
@@ -81,12 +73,6 @@ const styles = StyleSheet.create({
81
73
  fontSize: 13,
82
74
  color: '#666',
83
75
  lineHeight: 18,
84
- marginBottom: 4,
85
- },
86
- apiInfo: {
87
- fontSize: 12,
88
- color: '#888',
89
- fontStyle: 'italic',
90
76
  },
91
77
  arrow: {
92
78
  fontSize: 24,
@@ -35,10 +35,8 @@ const CompactTable = ({ data }) => {
35
35
  style={[
36
36
  styles.card,
37
37
  item.isTotal && styles.totalCard,
38
- index % 2 === 0 ? styles.evenCard : styles.oddCard
39
38
  ]}
40
39
  >
41
- {/* Card Header */}
42
40
  <View style={styles.header}>
43
41
  <Text style={[
44
42
  styles.title,
@@ -48,79 +46,53 @@ const CompactTable = ({ data }) => {
48
46
  </Text>
49
47
  <Text style={[
50
48
  styles.grossMargin,
51
- styles.grossMarginText
52
49
  ]}>
53
- Brüt Kar: {item.grossMarginPercent}%
50
+ Gross Margin: {item.grossMarginPercent}%
54
51
  </Text>
55
52
  </View>
56
53
 
57
- {/* Card Body - Grid Layout */}
58
54
  <View style={styles.grid}>
59
- {/* Column 1 */}
60
55
  <View style={styles.column}>
61
- <Text style={styles.label}>2024 Fiili</Text>
56
+ <Text style={styles.label}>2024 Actual</Text>
62
57
  <Text style={styles.value}>
63
58
  {formatCurrency(item.actual2024)}
64
59
  </Text>
65
60
  </View>
66
61
 
67
- {/* Column 2 */}
68
62
  <View style={styles.column}>
69
- <Text style={styles.label}>2025 Fiili</Text>
63
+ <Text style={styles.label}>2025 Actual</Text>
70
64
  <Text style={styles.value}>
71
65
  {formatCurrency(item.actual2025)}
72
66
  </Text>
73
67
  </View>
74
68
 
75
- {/* Column 3 */}
76
69
  <View style={styles.column}>
77
- <Text style={styles.label}>Fiili Artış</Text>
78
- <View style={styles.percentBadge}>
79
- <Text style={[
80
- styles.percentText,
81
- item.yoYChangePercent >= 0 ? styles.positive : styles.negative
82
- ]}>
83
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent).toFixed(1)}%
84
- </Text>
85
- </View>
70
+ <Text style={styles.label}>YoY Change</Text>
71
+ <Text style={[
72
+ styles.percentText,
73
+ item.yoYChangePercent >= 0 ? styles.positive : styles.negative
74
+ ]}>
75
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
76
+ </Text>
86
77
  </View>
87
78
 
88
- {/* Column 4 */}
89
79
  <View style={styles.column}>
90
- <Text style={styles.label}>2025 Bütçe</Text>
80
+ <Text style={styles.label}>2025 Budget</Text>
91
81
  <Text style={styles.value}>
92
82
  {formatCurrency(item.budget2025)}
93
83
  </Text>
94
84
  </View>
95
85
 
96
- {/* Column 5 */}
97
86
  <View style={styles.column}>
98
- <Text style={styles.label}>Sapma</Text>
99
- <View style={styles.percentBadge}>
100
- <Text style={[
101
- styles.percentText,
102
- item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
103
- ]}>
104
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent).toFixed(1)}%
105
- </Text>
106
- </View>
87
+ <Text style={styles.label}>Variance</Text>
88
+ <Text style={[
89
+ styles.percentText,
90
+ item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
91
+ ]}>
92
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
93
+ </Text>
107
94
  </View>
108
95
  </View>
109
-
110
- {/* Status Indicator */}
111
- <View style={styles.statusIndicator}>
112
- <View style={[
113
- styles.statusDot,
114
- (item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0)
115
- ? styles.statusGood
116
- : styles.statusWarning
117
- ]} />
118
- <Text style={styles.statusText}>
119
- {item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0
120
- ? 'Performans İyi'
121
- : 'İnceleme Gerekli'}
122
- </Text>
123
- </View>
124
96
  </View>
125
97
  ))}
126
98
  </ScrollView>
@@ -139,23 +111,12 @@ const styles = StyleSheet.create({
139
111
  padding: 16,
140
112
  borderWidth: 1,
141
113
  borderColor: '#e8e8e8',
142
- shadowColor: '#000',
143
- shadowOffset: { width: 0, height: 2 },
144
- shadowOpacity: 0.1,
145
- shadowRadius: 3,
146
- elevation: 2,
147
114
  },
148
115
  totalCard: {
149
116
  backgroundColor: '#e8f5e9',
150
117
  borderColor: '#4CAF50',
151
118
  borderWidth: 2,
152
119
  },
153
- evenCard: {
154
- backgroundColor: '#fff',
155
- },
156
- oddCard: {
157
- backgroundColor: '#f9f9f9',
158
- },
159
120
  header: {
160
121
  flexDirection: 'row',
161
122
  justifyContent: 'space-between',
@@ -183,8 +144,6 @@ const styles = StyleSheet.create({
183
144
  paddingVertical: 4,
184
145
  borderRadius: 6,
185
146
  backgroundColor: '#f0f0f0',
186
- },
187
- grossMarginText: {
188
147
  color: '#2c3e50',
189
148
  },
190
149
  grid: {
@@ -210,20 +169,10 @@ const styles = StyleSheet.create({
210
169
  fontSize: 13,
211
170
  fontWeight: '600',
212
171
  color: '#2c3e50',
213
- fontFamily: 'monospace',
214
- },
215
- percentBadge: {
216
- backgroundColor: '#fff',
217
- paddingHorizontal: 10,
218
- paddingVertical: 4,
219
- borderRadius: 12,
220
- borderWidth: 1,
221
- borderColor: '#e0e0e0',
222
172
  },
223
173
  percentText: {
224
174
  fontSize: 12,
225
175
  fontWeight: '600',
226
- fontFamily: 'monospace',
227
176
  },
228
177
  positive: {
229
178
  color: '#27ae60',
@@ -231,30 +180,6 @@ const styles = StyleSheet.create({
231
180
  negative: {
232
181
  color: '#e74c3c',
233
182
  },
234
- statusIndicator: {
235
- flexDirection: 'row',
236
- alignItems: 'center',
237
- marginTop: 12,
238
- paddingTop: 12,
239
- borderTopWidth: 1,
240
- borderTopColor: '#eee',
241
- },
242
- statusDot: {
243
- width: 8,
244
- height: 8,
245
- borderRadius: 4,
246
- marginRight: 8,
247
- },
248
- statusGood: {
249
- backgroundColor: '#4CAF50',
250
- },
251
- statusWarning: {
252
- backgroundColor: '#FF9800',
253
- },
254
- statusText: {
255
- fontSize: 12,
256
- color: '#666',
257
- },
258
183
  noDataContainer: {
259
184
  padding: 40,
260
185
  alignItems: 'center',
@@ -30,32 +30,30 @@ const DefaultTable = ({ data }) => {
30
30
  return (
31
31
  <ScrollView horizontal showsHorizontalScrollIndicator={true}>
32
32
  <View style={styles.table}>
33
- {/* Table Header */}
34
33
  <View style={styles.tableHeader}>
35
34
  <View style={[styles.headerCell, styles.firstColumn]}>
36
- <Text style={styles.headerText}>FALİYET KAR/ZARAR</Text>
35
+ <Text style={styles.headerText}>ACTIVITY PROFIT/LOSS</Text>
37
36
  </View>
38
37
  <View style={styles.headerCell}>
39
- <Text style={styles.headerText}>2024 Fiili</Text>
38
+ <Text style={styles.headerText}>2024 Actual</Text>
40
39
  </View>
41
40
  <View style={styles.headerCell}>
42
- <Text style={styles.headerText}>2025 Fiili</Text>
41
+ <Text style={styles.headerText}>2025 Actual</Text>
43
42
  </View>
44
43
  <View style={styles.headerCell}>
45
- <Text style={styles.headerText}>Fiili Artış %</Text>
44
+ <Text style={styles.headerText}>YoY Change %</Text>
46
45
  </View>
47
46
  <View style={styles.headerCell}>
48
- <Text style={styles.headerText}>2025 Bütçe</Text>
47
+ <Text style={styles.headerText}>2025 Budget</Text>
49
48
  </View>
50
49
  <View style={styles.headerCell}>
51
- <Text style={styles.headerText}>Sapma %</Text>
50
+ <Text style={styles.headerText}>Variance %</Text>
52
51
  </View>
53
52
  <View style={styles.headerCell}>
54
- <Text style={styles.headerText}>BRÜT KAR %</Text>
53
+ <Text style={styles.headerText}>GROSS MARGIN %</Text>
55
54
  </View>
56
55
  </View>
57
56
 
58
- {/* Table Rows */}
59
57
  {data.map((item, index) => (
60
58
  <View
61
59
  key={index}
@@ -87,7 +85,7 @@ const DefaultTable = ({ data }) => {
87
85
  styles.percentText,
88
86
  item.yoYChangePercent >= 0 ? styles.positive : styles.negative
89
87
  ]}>
90
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent).toFixed(1)}%
88
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
91
89
  </Text>
92
90
  </View>
93
91
 
@@ -102,7 +100,7 @@ const DefaultTable = ({ data }) => {
102
100
  styles.percentText,
103
101
  item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
104
102
  ]}>
105
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent).toFixed(1)}%
103
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
106
104
  </Text>
107
105
  </View>
108
106
 
@@ -193,13 +191,11 @@ const styles = StyleSheet.create({
193
191
  numberText: {
194
192
  fontSize: 11,
195
193
  fontWeight: '500',
196
- fontFamily: 'monospace',
197
194
  color: '#333',
198
195
  },
199
196
  percentText: {
200
197
  fontSize: 12,
201
198
  fontWeight: '600',
202
- fontFamily: 'monospace',
203
199
  },
204
200
  positive: {
205
201
  color: '#27ae60',
@@ -29,10 +29,9 @@ const FreezeTable = ({ data }) => {
29
29
 
30
30
  return (
31
31
  <View style={styles.container}>
32
- {/* Fixed First Column */}
33
32
  <View style={styles.fixedColumn}>
34
33
  <View style={[styles.fixedHeader, styles.fixedFirstCell]}>
35
- <Text style={styles.fixedHeaderText}>FALİYET KAR/ZARAR</Text>
34
+ <Text style={styles.fixedHeaderText}>ACTIVITY</Text>
36
35
  </View>
37
36
  {data.map((item, index) => (
38
37
  <View
@@ -40,7 +39,6 @@ const FreezeTable = ({ data }) => {
40
39
  style={[
41
40
  styles.fixedRow,
42
41
  item.isTotal && styles.fixedTotalRow,
43
- index % 2 === 0 ? styles.evenRow : styles.oddRow
44
42
  ]}
45
43
  >
46
44
  <Text style={[
@@ -53,26 +51,22 @@ const FreezeTable = ({ data }) => {
53
51
  ))}
54
52
  </View>
55
53
 
56
- {/* Scrollable Data Columns */}
57
54
  <ScrollView horizontal showsHorizontalScrollIndicator={true}>
58
55
  <View style={styles.scrollableColumns}>
59
- {/* Headers for scrollable columns */}
60
56
  <View style={styles.scrollableHeaderRow}>
61
- {['2024 Fiili', '2025 Fiili', 'Fiili Artış %', '2025 Bütçe', 'Sapma %', 'BRÜT KAR %'].map((header, idx) => (
57
+ {['2024 Actual', '2025 Actual', 'YoY Change %', '2025 Budget', 'Variance %', 'GROSS MARGIN %'].map((header, idx) => (
62
58
  <View key={idx} style={styles.scrollableHeader}>
63
59
  <Text style={styles.scrollableHeaderText}>{header}</Text>
64
60
  </View>
65
61
  ))}
66
62
  </View>
67
63
 
68
- {/* Data rows for scrollable columns */}
69
64
  {data.map((item, rowIndex) => (
70
65
  <View
71
66
  key={rowIndex}
72
67
  style={[
73
68
  styles.scrollableDataRow,
74
69
  item.isTotal && styles.scrollableTotalDataRow,
75
- rowIndex % 2 === 0 ? styles.evenRow : styles.oddRow
76
70
  ]}
77
71
  >
78
72
  <View style={styles.scrollableDataCell}>
@@ -92,7 +86,7 @@ const FreezeTable = ({ data }) => {
92
86
  styles.scrollablePercent,
93
87
  item.yoYChangePercent >= 0 ? styles.positive : styles.negative
94
88
  ]}>
95
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent).toFixed(1)}%
89
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
96
90
  </Text>
97
91
  </View>
98
92
 
@@ -107,7 +101,7 @@ const FreezeTable = ({ data }) => {
107
101
  styles.scrollablePercent,
108
102
  item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
109
103
  ]}>
110
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent).toFixed(1)}%
104
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
111
105
  </Text>
112
106
  </View>
113
107
 
@@ -226,13 +220,11 @@ const styles = StyleSheet.create({
226
220
  scrollableDataText: {
227
221
  fontSize: 12,
228
222
  fontWeight: '500',
229
- fontFamily: 'monospace',
230
223
  color: '#333',
231
224
  },
232
225
  scrollablePercent: {
233
226
  fontSize: 12,
234
227
  fontWeight: '600',
235
- fontFamily: 'monospace',
236
228
  },
237
229
  positive: {
238
230
  color: '#27ae60',
@@ -244,12 +236,6 @@ const styles = StyleSheet.create({
244
236
  color: '#2c3e50',
245
237
  fontWeight: '700',
246
238
  },
247
- evenRow: {
248
- backgroundColor: '#fff',
249
- },
250
- oddRow: {
251
- backgroundColor: '#f9f9f9',
252
- },
253
239
  noDataContainer: {
254
240
  padding: 40,
255
241
  alignItems: 'center',
@@ -20,30 +20,19 @@ const ReportDashboard = ({ reports, onReportSelect, onClose }) => {
20
20
  setError(null);
21
21
 
22
22
  try {
23
- // Fetch data from API using npm package service
24
23
  const data = await ApiService.fetchReportData(report.apiConfig);
25
24
 
26
- if (data.error) {
27
- setError(data.error);
28
- // Use fallback data if available
29
- if (data.fallbackData) {
30
- setSelectedReport({
31
- ...report,
32
- data: data.fallbackData
33
- });
34
- }
35
- } else {
36
- setSelectedReport({
37
- ...report,
38
- data: data
39
- });
40
- }
25
+ setSelectedReport({
26
+ ...report,
27
+ data: data
28
+ });
41
29
 
42
30
  if (onReportSelect) {
43
31
  onReportSelect(report.name);
44
32
  }
45
33
  } catch (err) {
46
- setError(err.message || 'Failed to fetch report data');
34
+ setError('Failed to fetch data');
35
+ console.error(err);
47
36
  } finally {
48
37
  setLoading(false);
49
38
  }
@@ -5,7 +5,6 @@ import {
5
5
  StyleSheet,
6
6
  TouchableOpacity,
7
7
  ScrollView,
8
- ActivityIndicator,
9
8
  } from 'react-native';
10
9
  import DefaultTable from '../components/tables/DefaultTable';
11
10
  import CompactTable from '../components/tables/CompactTable';
@@ -36,7 +35,6 @@ const ReportDetail = ({ report, loading, error, onBack, onClose }) => {
36
35
  );
37
36
  }
38
37
 
39
- // Render based on report type
40
38
  switch (report.type) {
41
39
  case 'table':
42
40
  return renderTable();
@@ -57,7 +55,6 @@ const ReportDetail = ({ report, loading, error, onBack, onClose }) => {
57
55
  return <CompactTable data={report.data} />;
58
56
  case 'freeze':
59
57
  return <FreezeTable data={report.data} />;
60
- case 'default':
61
58
  default:
62
59
  return <DefaultTable data={report.data} />;
63
60
  }
@@ -93,7 +90,7 @@ const ReportDetail = ({ report, loading, error, onBack, onClose }) => {
93
90
  <Text style={[
94
91
  styles.viewTypeText,
95
92
  viewType === 'default' && styles.activeViewTypeText
96
- ]}>Varsayılan</Text>
93
+ ]}>Default</Text>
97
94
  </TouchableOpacity>
98
95
 
99
96
  <TouchableOpacity
@@ -106,7 +103,7 @@ const ReportDetail = ({ report, loading, error, onBack, onClose }) => {
106
103
  <Text style={[
107
104
  styles.viewTypeText,
108
105
  viewType === 'compact' && styles.activeViewTypeText
109
- ]}>Kompakt</Text>
106
+ ]}>Compact</Text>
110
107
  </TouchableOpacity>
111
108
 
112
109
  <TouchableOpacity
@@ -119,25 +116,13 @@ const ReportDetail = ({ report, loading, error, onBack, onClose }) => {
119
116
  <Text style={[
120
117
  styles.viewTypeText,
121
118
  viewType === 'freeze' && styles.activeViewTypeText
122
- ]}>Sabit Kolon</Text>
119
+ ]}>Freeze</Text>
123
120
  </TouchableOpacity>
124
121
  </View>
125
122
  )}
126
123
 
127
124
  <ScrollView style={styles.content}>
128
125
  {renderContent()}
129
-
130
- {report.data && (
131
- <View style={styles.dataInfo}>
132
- <Text style={styles.infoTitle}>Report Information</Text>
133
- <Text style={styles.infoText}>
134
- {report.description || 'Detailed analysis report'}
135
- </Text>
136
- <Text style={styles.dataSource}>
137
- Data points: {Array.isArray(report.data) ? report.data.length : 'N/A'}
138
- </Text>
139
- </View>
140
- )}
141
126
  </ScrollView>
142
127
  </View>
143
128
  );
@@ -213,11 +198,6 @@ const styles = StyleSheet.create({
213
198
  },
214
199
  activeViewType: {
215
200
  backgroundColor: '#fff',
216
- shadowColor: '#000',
217
- shadowOffset: { width: 0, height: 1 },
218
- shadowOpacity: 0.1,
219
- shadowRadius: 2,
220
- elevation: 2,
221
201
  },
222
202
  viewTypeText: {
223
203
  fontSize: 13,
@@ -228,29 +208,6 @@ const styles = StyleSheet.create({
228
208
  color: '#4CAF50',
229
209
  fontWeight: '600',
230
210
  },
231
- dataInfo: {
232
- backgroundColor: '#e8f5e9',
233
- borderRadius: 12,
234
- padding: 16,
235
- marginTop: 16,
236
- },
237
- infoTitle: {
238
- fontSize: 16,
239
- fontWeight: '700',
240
- color: '#2e7d32',
241
- marginBottom: 8,
242
- },
243
- infoText: {
244
- fontSize: 14,
245
- color: '#555',
246
- lineHeight: 20,
247
- marginBottom: 8,
248
- },
249
- dataSource: {
250
- fontSize: 13,
251
- color: '#777',
252
- fontStyle: 'italic',
253
- },
254
211
  noDataContainer: {
255
212
  padding: 40,
256
213
  alignItems: 'center',
@@ -1,27 +0,0 @@
1
- import ApiService from './ApiService';
2
-
3
- describe('ApiService', () => {
4
- it('should transform performance data correctly', () => {
5
- const mockData = {
6
- data: [
7
- { name: 'Ocean', actual2024: 100, actual2025: 120, budget2025: 110, grossMargin: 25 }
8
- ]
9
- };
10
-
11
- const result = ApiService.transformPerformanceData(mockData);
12
-
13
- expect(result).toHaveLength(1);
14
- expect(result[0].name).toBe('Ocean');
15
- expect(result[0].yoYChangePercent).toBe(20);
16
- expect(result[0].budgetVariancePercent).toBeCloseTo(9.09);
17
- });
18
-
19
- it('should handle API errors gracefully', async () => {
20
- const apiConfig = {
21
- url: 'http://invalid-url',
22
- method: 'GET'
23
- };
24
-
25
- await expect(ApiService.fetchReportData(apiConfig)).rejects.toThrow();
26
- });
27
- });
@@ -1,25 +0,0 @@
1
- export const formatCurrency = (value) => {
2
- const num = Number(value);
3
- if (isNaN(num)) return '0';
4
-
5
- if (num >= 1000000) {
6
- return `${(num / 1000000).toFixed(1)}M`;
7
- } else if (num >= 1000) {
8
- return `${(num / 1000).toFixed(1)}K`;
9
- }
10
- return num.toLocaleString();
11
- };
12
-
13
- export const formatNumber = (num) => {
14
- return num.toLocaleString();
15
- };
16
-
17
- export const getColor = (index) => {
18
- const colors = ['#4CAF50', '#2196F3', '#FF9800', '#E91E63', '#9C27B0', '#00BCD4'];
19
- return colors[index % colors.length];
20
- };
21
-
22
- export const calculatePercentageChange = (oldValue, newValue) => {
23
- if (!oldValue || oldValue === 0) return 0;
24
- return ((newValue - oldValue) / Math.abs(oldValue)) * 100;
25
- };
@@ -1,47 +0,0 @@
1
- import { Dimensions } from 'react-native';
2
-
3
- export const formatCurrency = (value) => {
4
- const num = Number(value);
5
- if (isNaN(num)) return '0';
6
-
7
- if (num >= 1000000) {
8
- return `${(num / 1000000).toFixed(1)}M`;
9
- } else if (num >= 1000) {
10
- return `${(num / 1000).toFixed(1)}K`;
11
- }
12
- return num.toLocaleString();
13
- };
14
-
15
- export const formatNumber = (num) => {
16
- return num.toLocaleString();
17
- };
18
-
19
- export const calculatePercentageChange = (oldValue, newValue) => {
20
- if (!oldValue || oldValue === 0) return 0;
21
- return ((newValue - oldValue) / Math.abs(oldValue)) * 100;
22
- };
23
-
24
- export const getTableWidth = (columns) => {
25
- const { width: screenWidth } = Dimensions.get('window');
26
- return Math.max(screenWidth, columns * 120);
27
- };
28
-
29
- export const getStatusColor = (yoYChange, budgetVariance) => {
30
- if (yoYChange >= 0 && budgetVariance >= 0) {
31
- return '#4CAF50'; // Good
32
- } else if (yoYChange >= 0 || budgetVariance >= 0) {
33
- return '#FF9800'; // Warning
34
- } else {
35
- return '#F44336'; // Critical
36
- }
37
- };
38
-
39
- export const getStatusText = (yoYChange, budgetVariance) => {
40
- if (yoYChange >= 0 && budgetVariance >= 0) {
41
- return 'Performans İyi';
42
- } else if (yoYChange >= 0 || budgetVariance >= 0) {
43
- return 'Kısmen İyi';
44
- } else {
45
- return 'İnceleme Gerekli';
46
- }
47
- };