@dhiraj0720/report1chart 1.0.5 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.jsx +481 -461
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "src/index.jsx",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/index.jsx CHANGED
@@ -19,26 +19,41 @@ const ReportChart = ({
19
19
  const [reportData, setReportData] = useState(null);
20
20
  const [loading, setLoading] = useState(false);
21
21
  const [error, setError] = useState(null);
22
+ const [viewType, setViewType] = useState('default');
22
23
 
23
24
  // Default reports if none provided
24
25
  const defaultReports = [
25
26
  {
26
27
  id: 1,
27
- name: 'Report 1',
28
- title: 'Revenue Trend',
29
- type: 'line',
30
- description: 'Monthly revenue analysis'
28
+ name: 'Performance Report',
29
+ title: 'PERFORMANS RAPORU (USD)',
30
+ type: 'table',
31
+ description: 'Fallyet Kar/Zarar tablosu - Varsayılan Görünüm'
32
+ },
33
+ {
34
+ id: 1.1,
35
+ name: 'Performance Report A',
36
+ title: 'PERFORMANS RAPORU (USD)',
37
+ type: 'table',
38
+ description: 'Fallyet Kar/Zarar tablosu - Kompakt Görünüm'
39
+ },
40
+ {
41
+ id: 1.2,
42
+ name: 'Performance Report B',
43
+ title: 'PERFORMANS RAPORU (USD)',
44
+ type: 'table',
45
+ description: 'Fallyet Kar/Zarar tablosu - Sabit Kolonlu Görünüm'
31
46
  },
32
47
  {
33
48
  id: 2,
34
- name: 'Report 2',
49
+ name: 'Revenue by Mode',
35
50
  title: 'Revenue by Mode',
36
51
  type: 'bar',
37
52
  description: 'Revenue distribution across modes'
38
53
  },
39
54
  {
40
55
  id: 3,
41
- name: 'Report 3',
56
+ name: 'Shipment by Direction',
42
57
  title: 'Shipment by Direction',
43
58
  type: 'pie',
44
59
  description: 'Shipment direction analysis'
@@ -52,9 +67,9 @@ const ReportChart = ({
52
67
  setError(null);
53
68
  setReportData(null);
54
69
  setSelectedReport(report);
70
+ setViewType('default'); // Reset view type when selecting new report
55
71
 
56
72
  try {
57
- // Call the parent function to fetch data
58
73
  if (onFetchReportData) {
59
74
  const data = await onFetchReportData(report);
60
75
  if (data) {
@@ -66,7 +81,6 @@ const ReportChart = ({
66
81
  }
67
82
  }
68
83
 
69
- // Callback to parent
70
84
  if (onReportSelect) {
71
85
  onReportSelect(report.name);
72
86
  }
@@ -77,57 +91,357 @@ const ReportChart = ({
77
91
  }
78
92
  };
79
93
 
80
- // Add currency formatter
81
- const formatCurrency = (value) => {
82
- const num = Number(value);
83
- if (isNaN(num)) return '0';
84
-
85
- if (num >= 1000000) {
86
- return `${(num / 1000000).toFixed(1)}M`;
87
- } else if (num >= 1000) {
88
- return `${(num / 1000).toFixed(1)}K`;
89
- }
90
- return num.toString();
91
- };
94
+ const formatCurrency = (value) => {
95
+ const num = Number(value);
96
+ if (isNaN(num)) return '0';
97
+
98
+ if (num >= 1000000) {
99
+ return `${(num / 1000000).toFixed(1)}M`;
100
+ } else if (num >= 1000) {
101
+ return `${(num / 1000).toFixed(1)}K`;
102
+ }
103
+ return num.toLocaleString();
104
+ };
105
+
106
+ const formatNumber = (num) => {
107
+ return num.toLocaleString();
108
+ };
109
+
110
+ const getColor = (index) => {
111
+ const colors = ['#4CAF50', '#2196F3', '#FF9800', '#E91E63', '#9C27B0', '#00BCD4'];
112
+ return colors[index % colors.length];
113
+ };
114
+
115
+ const handleClose = () => {
116
+ setSelectedReport(null);
117
+ setReportData(null);
118
+ if (onClose) onClose();
119
+ };
120
+
121
+ // ========== TABLE RENDERERS ==========
122
+ const renderTable = (data) => {
123
+ if (!Array.isArray(data) || data.length === 0) {
124
+ return (
125
+ <View style={styles.noDataContainer}>
126
+ <Text style={styles.noDataText}>No data available for this report</Text>
127
+ </View>
128
+ );
129
+ }
92
130
 
93
- const renderChart = () => {
94
- if (!reportData || !reportData.data) {
95
131
  return (
96
- <View style={styles.noDataContainer}>
97
- <Text style={styles.noDataText}>No data available for this report</Text>
98
- </View>
132
+ <ScrollView horizontal showsHorizontalScrollIndicator={true}>
133
+ <View style={styles.table}>
134
+ {/* Table Header */}
135
+ <View style={styles.tableHeader}>
136
+ <View style={[styles.headerCell, styles.firstColumn]}>
137
+ <Text style={styles.headerText}>FALİYET KAR/ZARAR</Text>
138
+ </View>
139
+ <View style={styles.headerCell}>
140
+ <Text style={styles.headerText}>2024 Fiili</Text>
141
+ </View>
142
+ <View style={styles.headerCell}>
143
+ <Text style={styles.headerText}>2025 Fiili</Text>
144
+ </View>
145
+ <View style={styles.headerCell}>
146
+ <Text style={styles.headerText}>Fiili Artış %</Text>
147
+ </View>
148
+ <View style={styles.headerCell}>
149
+ <Text style={styles.headerText}>2025 Bütçe</Text>
150
+ </View>
151
+ <View style={styles.headerCell}>
152
+ <Text style={styles.headerText}>Sapma %</Text>
153
+ </View>
154
+ <View style={styles.headerCell}>
155
+ <Text style={styles.headerText}>BRÜT KAR %</Text>
156
+ </View>
157
+ </View>
158
+
159
+ {/* Table Rows */}
160
+ {data.map((item, index) => (
161
+ <View
162
+ key={index}
163
+ style={[
164
+ styles.tableRow,
165
+ item.isTotal ? styles.totalRow : (index % 2 === 0 ? styles.evenRow : styles.oddRow)
166
+ ]}
167
+ >
168
+ <View style={[styles.cell, styles.firstColumn]}>
169
+ <Text style={item.isTotal ? styles.totalText : styles.cellText}>
170
+ {item.name}
171
+ </Text>
172
+ </View>
173
+
174
+ <View style={styles.cell}>
175
+ <Text style={styles.numberText}>
176
+ {formatCurrency(item.actual2024)}
177
+ </Text>
178
+ </View>
179
+
180
+ <View style={styles.cell}>
181
+ <Text style={styles.numberText}>
182
+ {formatCurrency(item.actual2025)}
183
+ </Text>
184
+ </View>
185
+
186
+ <View style={styles.cell}>
187
+ <Text style={[
188
+ styles.percentText,
189
+ item.yoYChangePercent >= 0 ? styles.positive : styles.negative
190
+ ]}>
191
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
192
+ </Text>
193
+ </View>
194
+
195
+ <View style={styles.cell}>
196
+ <Text style={styles.numberText}>
197
+ {formatCurrency(item.budget2025)}
198
+ </Text>
199
+ </View>
200
+
201
+ <View style={styles.cell}>
202
+ <Text style={[
203
+ styles.percentText,
204
+ item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
205
+ ]}>
206
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
207
+ </Text>
208
+ </View>
209
+
210
+ <View style={styles.cell}>
211
+ <Text style={[
212
+ styles.percentText,
213
+ styles.grossMargin
214
+ ]}>
215
+ {item.grossMarginPercent}%
216
+ </Text>
217
+ </View>
218
+ </View>
219
+ ))}
220
+ </View>
221
+ </ScrollView>
99
222
  );
100
- }
223
+ };
101
224
 
102
- const { type, subType, data } = reportData;
103
-
104
- if (type === 'table') {
105
- switch (subType) {
106
- case 'compact': // Report 1A
107
- return renderCompactTable(data);
108
- case 'freeze': // Report 1B
109
- return renderFreezeTable(data);
110
- case 'default': // Report 1
111
- default:
112
- return renderTable(data); // Original table
225
+ const renderCompactTable = (data) => {
226
+ if (!Array.isArray(data) || data.length === 0) {
227
+ return (
228
+ <View style={styles.noDataContainer}>
229
+ <Text style={styles.noDataText}>No data available for this report</Text>
230
+ </View>
231
+ );
113
232
  }
114
- }
115
-
116
- switch (type) {
117
- case 'line':
118
- return renderLineChart(data);
119
- case 'bar':
120
- return renderBarChart(data);
121
- case 'pie':
122
- return renderPieChart(data);
123
- default:
124
- return renderBarChart(data);
125
- }
126
- };
127
233
 
234
+ return (
235
+ <ScrollView style={styles.compactContainer}>
236
+ {data.map((item, index) => (
237
+ <View
238
+ key={index}
239
+ style={[
240
+ styles.compactCard,
241
+ item.isTotal && styles.compactTotalCard,
242
+ index % 2 === 0 ? styles.evenCard : styles.oddCard
243
+ ]}
244
+ >
245
+ {/* Card Header */}
246
+ <View style={styles.compactHeader}>
247
+ <Text style={[
248
+ styles.compactTitle,
249
+ item.isTotal && styles.totalTitle
250
+ ]}>
251
+ {item.name}
252
+ </Text>
253
+ <Text style={[
254
+ styles.compactGrossMargin,
255
+ styles.grossMargin
256
+ ]}>
257
+ Brüt Kar: {item.grossMarginPercent}%
258
+ </Text>
259
+ </View>
260
+
261
+ {/* Card Body - Grid Layout */}
262
+ <View style={styles.compactGrid}>
263
+ {/* Column 1 */}
264
+ <View style={styles.compactColumn}>
265
+ <Text style={styles.compactLabel}>2024 Fiili</Text>
266
+ <Text style={styles.compactValue}>
267
+ {formatCurrency(item.actual2024)}
268
+ </Text>
269
+ </View>
270
+
271
+ {/* Column 2 */}
272
+ <View style={styles.compactColumn}>
273
+ <Text style={styles.compactLabel}>2025 Fiili</Text>
274
+ <Text style={styles.compactValue}>
275
+ {formatCurrency(item.actual2025)}
276
+ </Text>
277
+ </View>
278
+
279
+ {/* Column 3 */}
280
+ <View style={styles.compactColumn}>
281
+ <Text style={styles.compactLabel}>Fiili Artış</Text>
282
+ <View style={styles.percentBadge}>
283
+ <Text style={[
284
+ styles.percentText,
285
+ item.yoYChangePercent >= 0 ? styles.positive : styles.negative
286
+ ]}>
287
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
288
+ </Text>
289
+ </View>
290
+ </View>
291
+
292
+ {/* Column 4 */}
293
+ <View style={styles.compactColumn}>
294
+ <Text style={styles.compactLabel}>2025 Bütçe</Text>
295
+ <Text style={styles.compactValue}>
296
+ {formatCurrency(item.budget2025)}
297
+ </Text>
298
+ </View>
299
+
300
+ {/* Column 5 */}
301
+ <View style={styles.compactColumn}>
302
+ <Text style={styles.compactLabel}>Sapma</Text>
303
+ <View style={styles.percentBadge}>
304
+ <Text style={[
305
+ styles.percentText,
306
+ item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
307
+ ]}>
308
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
309
+ </Text>
310
+ </View>
311
+ </View>
312
+ </View>
313
+
314
+ {/* Status Indicator */}
315
+ <View style={styles.statusIndicator}>
316
+ <View style={[
317
+ styles.statusDot,
318
+ (item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0)
319
+ ? styles.statusGood
320
+ : styles.statusWarning
321
+ ]} />
322
+ <Text style={styles.statusText}>
323
+ {item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0
324
+ ? 'Performans İyi'
325
+ : 'İnceleme Gerekli'}
326
+ </Text>
327
+ </View>
328
+ </View>
329
+ ))}
330
+ </ScrollView>
331
+ );
332
+ };
333
+
334
+ const renderFreezeTable = (data) => {
335
+ if (!Array.isArray(data) || data.length === 0) {
336
+ return (
337
+ <View style={styles.noDataContainer}>
338
+ <Text style={styles.noDataText}>No data available for this report</Text>
339
+ </View>
340
+ );
341
+ }
128
342
 
343
+ return (
344
+ <View style={styles.freezeContainer}>
345
+ {/* Fixed First Column */}
346
+ <View style={styles.freezeColumn}>
347
+ <View style={[styles.freezeHeader, styles.freezeFirstCell]}>
348
+ <Text style={styles.freezeHeaderText}>FALİYET KAR/ZARAR</Text>
349
+ </View>
350
+ {data.map((item, index) => (
351
+ <View
352
+ key={index}
353
+ style={[
354
+ styles.freezeRow,
355
+ item.isTotal && styles.freezeTotalRow,
356
+ index % 2 === 0 ? styles.evenRow : styles.oddRow
357
+ ]}
358
+ >
359
+ <Text style={[
360
+ styles.freezeCellText,
361
+ item.isTotal && styles.freezeTotalText
362
+ ]}>
363
+ {item.name}
364
+ </Text>
365
+ </View>
366
+ ))}
367
+ </View>
368
+
369
+ {/* Scrollable Data Columns */}
370
+ <ScrollView horizontal showsHorizontalScrollIndicator={true}>
371
+ <View style={styles.scrollableColumns}>
372
+ {/* Headers for scrollable columns */}
373
+ <View style={styles.freezeHeaderRow}>
374
+ {['2024 Fiili', '2025 Fiili', 'Fiili Artış %', '2025 Bütçe', 'Sapma %', 'BRÜT KAR %'].map((header, idx) => (
375
+ <View key={idx} style={styles.freezeHeader}>
376
+ <Text style={styles.freezeHeaderText}>{header}</Text>
377
+ </View>
378
+ ))}
379
+ </View>
380
+
381
+ {/* Data rows for scrollable columns */}
382
+ {data.map((item, rowIndex) => (
383
+ <View
384
+ key={rowIndex}
385
+ style={[
386
+ styles.freezeDataRow,
387
+ item.isTotal && styles.freezeTotalDataRow,
388
+ rowIndex % 2 === 0 ? styles.evenRow : styles.oddRow
389
+ ]}
390
+ >
391
+ <View style={styles.freezeDataCell}>
392
+ <Text style={styles.freezeDataText}>
393
+ {formatCurrency(item.actual2024)}
394
+ </Text>
395
+ </View>
396
+
397
+ <View style={styles.freezeDataCell}>
398
+ <Text style={styles.freezeDataText}>
399
+ {formatCurrency(item.actual2025)}
400
+ </Text>
401
+ </View>
402
+
403
+ <View style={styles.freezeDataCell}>
404
+ <Text style={[
405
+ styles.freezePercent,
406
+ item.yoYChangePercent >= 0 ? styles.positive : styles.negative
407
+ ]}>
408
+ {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
409
+ </Text>
410
+ </View>
411
+
412
+ <View style={styles.freezeDataCell}>
413
+ <Text style={styles.freezeDataText}>
414
+ {formatCurrency(item.budget2025)}
415
+ </Text>
416
+ </View>
417
+
418
+ <View style={styles.freezeDataCell}>
419
+ <Text style={[
420
+ styles.freezePercent,
421
+ item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
422
+ ]}>
423
+ {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
424
+ </Text>
425
+ </View>
426
+
427
+ <View style={styles.freezeDataCell}>
428
+ <Text style={[
429
+ styles.freezePercent,
430
+ styles.grossMargin
431
+ ]}>
432
+ {item.grossMarginPercent}%
433
+ </Text>
434
+ </View>
435
+ </View>
436
+ ))}
437
+ </View>
438
+ </ScrollView>
439
+ </View>
440
+ );
441
+ };
442
+
443
+ // ========== CHART RENDERERS ==========
129
444
  const renderLineChart = (data) => {
130
- // Handle both formats: { labels, values } or array format
131
445
  const values = data.values || data.map(d => d.value || d.revenue || d.shipments || 0);
132
446
  const labels = data.labels || data.map(d => d.label || d.month || d.mode || d.direction || '');
133
447
 
@@ -138,7 +452,7 @@ const formatCurrency = (value) => {
138
452
 
139
453
  return (
140
454
  <View style={styles.chartContainer}>
141
- <Text style={styles.chartTitle}>{reportData.title}</Text>
455
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
142
456
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
143
457
  <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
144
458
  {values.map((value, index) => {
@@ -164,7 +478,6 @@ const formatCurrency = (value) => {
164
478
  };
165
479
 
166
480
  const renderBarChart = (data) => {
167
- // Handle array format or object format
168
481
  const isArray = Array.isArray(data);
169
482
  const values = isArray ? data.map(d => d.revenue || d.value || d.shipments || 0) : data.values;
170
483
  const labels = isArray ? data.map(d => d.mode || d.label || '') : data.labels;
@@ -176,7 +489,7 @@ const formatCurrency = (value) => {
176
489
 
177
490
  return (
178
491
  <View style={styles.chartContainer}>
179
- <Text style={styles.chartTitle}>{reportData.title}</Text>
492
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
180
493
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
181
494
  <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
182
495
  {values.map((value, index) => {
@@ -201,337 +514,12 @@ const formatCurrency = (value) => {
201
514
  );
202
515
  };
203
516
 
204
- const renderTable = (data) => {
205
- if (!Array.isArray(data) || data.length === 0) {
206
- return (
207
- <View style={styles.noDataContainer}>
208
- <Text style={styles.noDataText}>No data available for this report</Text>
209
- </View>
210
- );
211
- }
212
-
213
- return (
214
- <ScrollView horizontal showsHorizontalScrollIndicator={true}>
215
- <View style={styles.table}>
216
- {/* Table Header */}
217
- <View style={styles.tableHeader}>
218
- <View style={[styles.headerCell, styles.firstColumn]}>
219
- <Text style={styles.headerText}>FALİYET KAR/ZARAR</Text>
220
- </View>
221
- <View style={styles.headerCell}>
222
- <Text style={styles.headerText}>2024 Fiili</Text>
223
- </View>
224
- <View style={styles.headerCell}>
225
- <Text style={styles.headerText}>2025 Fiili</Text>
226
- </View>
227
- <View style={styles.headerCell}>
228
- <Text style={styles.headerText}>Fiili Artış %</Text>
229
- </View>
230
- <View style={styles.headerCell}>
231
- <Text style={styles.headerText}>2025 Bütçe</Text>
232
- </View>
233
- <View style={styles.headerCell}>
234
- <Text style={styles.headerText}>Sapma %</Text>
235
- </View>
236
- <View style={styles.headerCell}>
237
- <Text style={styles.headerText}>FALİYET GİD.</Text>
238
- <Text style={styles.headerText}>/ BRÜT KAR %</Text>
239
- </View>
240
- </View>
241
-
242
- {/* Table Rows */}
243
- {data.map((item, index) => (
244
- <View
245
- key={index}
246
- style={[
247
- styles.tableRow,
248
- item.isTotal ? styles.totalRow : (index % 2 === 0 ? styles.evenRow : styles.oddRow)
249
- ]}
250
- >
251
- <View style={[styles.cell, styles.firstColumn]}>
252
- <Text style={item.isTotal ? styles.totalText : styles.cellText}>
253
- {item.name}
254
- </Text>
255
- </View>
256
-
257
- <View style={styles.cell}>
258
- <Text style={styles.numberText}>
259
- {formatCurrency(item.actual2024)}
260
- </Text>
261
- </View>
262
-
263
- <View style={styles.cell}>
264
- <Text style={styles.numberText}>
265
- {formatCurrency(item.actual2025)}
266
- </Text>
267
- </View>
268
-
269
- <View style={styles.cell}>
270
- <Text style={[
271
- styles.percentText,
272
- item.yoYChangePercent >= 0 ? styles.positive : styles.negative
273
- ]}>
274
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
275
- </Text>
276
- </View>
277
-
278
- <View style={styles.cell}>
279
- <Text style={styles.numberText}>
280
- {formatCurrency(item.budget2025)}
281
- </Text>
282
- </View>
283
-
284
- <View style={styles.cell}>
285
- <Text style={[
286
- styles.percentText,
287
- item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
288
- ]}>
289
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
290
- </Text>
291
- </View>
292
-
293
- <View style={styles.cell}>
294
- <Text style={[
295
- styles.percentText,
296
- styles.grossMargin
297
- ]}>
298
- {item.grossMarginPercent}%
299
- </Text>
300
- </View>
301
- </View>
302
- ))}
303
- </View>
304
- </ScrollView>
305
- );
306
- };
307
-
308
- const renderCompactTable = (data) => {
309
- if (!Array.isArray(data) || data.length === 0) {
310
- return (
311
- <View style={styles.noDataContainer}>
312
- <Text style={styles.noDataText}>No data available for this report</Text>
313
- </View>
314
- );
315
- }
316
-
317
- return (
318
- <ScrollView style={styles.compactContainer}>
319
- {data.map((item, index) => (
320
- <View
321
- key={index}
322
- style={[
323
- styles.compactCard,
324
- item.isTotal && styles.compactTotalCard,
325
- index % 2 === 0 ? styles.evenCard : styles.oddCard
326
- ]}
327
- >
328
- {/* Card Header */}
329
- <View style={styles.compactHeader}>
330
- <Text style={[
331
- styles.compactTitle,
332
- item.isTotal && styles.totalTitle
333
- ]}>
334
- {item.name}
335
- </Text>
336
- <Text style={[
337
- styles.compactGrossMargin,
338
- item.grossMarginPercent >= 0 ? styles.positive : styles.negative
339
- ]}>
340
- Brüt Kar: {item.grossMarginPercent}%
341
- </Text>
342
- </View>
343
-
344
- {/* Card Body - Grid Layout */}
345
- <View style={styles.compactGrid}>
346
- {/* Column 1 */}
347
- <View style={styles.compactColumn}>
348
- <Text style={styles.compactLabel}>2024 Fiili</Text>
349
- <Text style={styles.compactValue}>
350
- {formatCurrency(item.actual2024)}
351
- </Text>
352
- </View>
353
-
354
- {/* Column 2 */}
355
- <View style={styles.compactColumn}>
356
- <Text style={styles.compactLabel}>2025 Fiili</Text>
357
- <Text style={styles.compactValue}>
358
- {formatCurrency(item.actual2025)}
359
- </Text>
360
- </View>
361
-
362
- {/* Column 3 */}
363
- <View style={styles.compactColumn}>
364
- <Text style={styles.compactLabel}>Fiili Artış</Text>
365
- <View style={styles.percentBadge}>
366
- <Text style={[
367
- styles.percentText,
368
- item.yoYChangePercent >= 0 ? styles.positive : styles.negative
369
- ]}>
370
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
371
- </Text>
372
- </View>
373
- </View>
374
-
375
- {/* Column 4 */}
376
- <View style={styles.compactColumn}>
377
- <Text style={styles.compactLabel}>2025 Bütçe</Text>
378
- <Text style={styles.compactValue}>
379
- {formatCurrency(item.budget2025)}
380
- </Text>
381
- </View>
382
-
383
- {/* Column 5 */}
384
- <View style={styles.compactColumn}>
385
- <Text style={styles.compactLabel}>Sapma</Text>
386
- <View style={styles.percentBadge}>
387
- <Text style={[
388
- styles.percentText,
389
- item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
390
- ]}>
391
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
392
- </Text>
393
- </View>
394
- </View>
395
- </View>
396
-
397
- {/* Status Indicator */}
398
- <View style={styles.statusIndicator}>
399
- <View style={[
400
- styles.statusDot,
401
- (item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0)
402
- ? styles.statusGood
403
- : styles.statusWarning
404
- ]} />
405
- <Text style={styles.statusText}>
406
- {item.yoYChangePercent >= 0 && item.budgetVariancePercent >= 0
407
- ? 'Performans İyi'
408
- : 'İnceleme Gerekli'}
409
- </Text>
410
- </View>
411
- </View>
412
- ))}
413
- </ScrollView>
414
- );
415
- };
416
-
417
- // Report 1B: Freeze First Column Table
418
- const renderFreezeTable = (data) => {
419
- if (!Array.isArray(data) || data.length === 0) {
420
- return (
421
- <View style={styles.noDataContainer}>
422
- <Text style={styles.noDataText}>No data available for this report</Text>
423
- </View>
424
- );
425
- }
426
-
427
- return (
428
- <View style={styles.freezeContainer}>
429
- {/* Fixed First Column */}
430
- <View style={styles.freezeColumn}>
431
- <View style={[styles.freezeHeader, styles.freezeFirstCell]}>
432
- <Text style={styles.freezeHeaderText}>FALİYET KAR/ZARAR</Text>
433
- </View>
434
- {data.map((item, index) => (
435
- <View
436
- key={index}
437
- style={[
438
- styles.freezeRow,
439
- item.isTotal && styles.freezeTotalRow,
440
- index % 2 === 0 ? styles.evenRow : styles.oddRow
441
- ]}
442
- >
443
- <Text style={[
444
- styles.freezeCellText,
445
- item.isTotal && styles.freezeTotalText
446
- ]}>
447
- {item.name}
448
- </Text>
449
- </View>
450
- ))}
451
- </View>
452
-
453
- {/* Scrollable Data Columns */}
454
- <ScrollView horizontal showsHorizontalScrollIndicator={true}>
455
- <View style={styles.scrollableColumns}>
456
- {/* Headers for scrollable columns */}
457
- <View style={styles.freezeHeaderRow}>
458
- {['2024 Fiili', '2025 Fiili', 'Fiili Artış %', '2025 Bütçe', 'Sapma %', 'BRÜT KAR %'].map((header, idx) => (
459
- <View key={idx} style={styles.freezeHeader}>
460
- <Text style={styles.freezeHeaderText}>{header}</Text>
461
- </View>
462
- ))}
463
- </View>
464
-
465
- {/* Data rows for scrollable columns */}
466
- {data.map((item, rowIndex) => (
467
- <View
468
- key={rowIndex}
469
- style={[
470
- styles.freezeDataRow,
471
- item.isTotal && styles.freezeTotalDataRow,
472
- rowIndex % 2 === 0 ? styles.evenRow : styles.oddRow
473
- ]}
474
- >
475
- <View style={styles.freezeDataCell}>
476
- <Text style={styles.freezeDataText}>
477
- {formatCurrency(item.actual2024)}
478
- </Text>
479
- </View>
480
-
481
- <View style={styles.freezeDataCell}>
482
- <Text style={styles.freezeDataText}>
483
- {formatCurrency(item.actual2025)}
484
- </Text>
485
- </View>
486
-
487
- <View style={styles.freezeDataCell}>
488
- <Text style={[
489
- styles.freezePercent,
490
- item.yoYChangePercent >= 0 ? styles.positive : styles.negative
491
- ]}>
492
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
493
- </Text>
494
- </View>
495
-
496
- <View style={styles.freezeDataCell}>
497
- <Text style={styles.freezeDataText}>
498
- {formatCurrency(item.budget2025)}
499
- </Text>
500
- </View>
501
-
502
- <View style={styles.freezeDataCell}>
503
- <Text style={[
504
- styles.freezePercent,
505
- item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
506
- ]}>
507
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
508
- </Text>
509
- </View>
510
-
511
- <View style={styles.freezeDataCell}>
512
- <Text style={[
513
- styles.freezePercent,
514
- styles.grossMargin
515
- ]}>
516
- {item.grossMarginPercent}%
517
- </Text>
518
- </View>
519
- </View>
520
- ))}
521
- </View>
522
- </ScrollView>
523
- </View>
524
- );
525
- };
526
-
527
-
528
517
  const renderPieChart = (data) => {
529
- // Data should be array of objects with label and value
530
518
  const total = data.reduce((sum, item) => sum + (item.shipments || item.revenue || item.value || 0), 0);
531
519
 
532
520
  return (
533
521
  <View style={styles.chartContainer}>
534
- <Text style={styles.chartTitle}>{reportData.title}</Text>
522
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
535
523
  <View style={styles.pieContainer}>
536
524
  {data.map((item, index) => {
537
525
  const value = item.shipments || item.revenue || item.value || 0;
@@ -556,21 +544,51 @@ const renderFreezeTable = (data) => {
556
544
  );
557
545
  };
558
546
 
559
- const formatNumber = (num) => {
560
- return num.toLocaleString();
561
- };
562
-
563
- const getColor = (index) => {
564
- const colors = ['#4CAF50', '#2196F3', '#FF9800', '#E91E63', '#9C27B0', '#00BCD4'];
565
- return colors[index % colors.length];
566
- };
547
+ // ========== MAIN RENDER LOGIC ==========
548
+ const renderChart = () => {
549
+ if (!reportData || !reportData.data) {
550
+ return (
551
+ <View style={styles.noDataContainer}>
552
+ <Text style={styles.noDataText}>No data available for this report</Text>
553
+ </View>
554
+ );
555
+ }
567
556
 
568
- const handleClose = () => {
569
- setSelectedReport(null);
570
- setReportData(null);
571
- if (onClose) onClose();
557
+ const { type, data } = reportData;
558
+
559
+ // For performance reports
560
+ if (type === 'table' && selectedReport &&
561
+ (selectedReport.id === 1 || selectedReport.id === 1.1 || selectedReport.id === 1.2)) {
562
+ switch (viewType) {
563
+ case 'compact':
564
+ return renderCompactTable(data);
565
+ case 'freeze':
566
+ return renderFreezeTable(data);
567
+ case 'default':
568
+ default:
569
+ return renderTable(data);
570
+ }
571
+ }
572
+
573
+ // For other table reports
574
+ if (type === 'table') {
575
+ return renderTable(data);
576
+ }
577
+
578
+ // For chart reports
579
+ switch (type) {
580
+ case 'line':
581
+ return renderLineChart(data);
582
+ case 'bar':
583
+ return renderBarChart(data);
584
+ case 'pie':
585
+ return renderPieChart(data);
586
+ default:
587
+ return renderBarChart(data);
588
+ }
572
589
  };
573
590
 
591
+ // ========== RENDER SELECTED REPORT VIEW ==========
574
592
  if (selectedReport) {
575
593
  return (
576
594
  <View style={styles.container}>
@@ -580,6 +598,7 @@ const renderFreezeTable = (data) => {
580
598
  onPress={() => {
581
599
  setSelectedReport(null);
582
600
  setReportData(null);
601
+ setViewType('default');
583
602
  }}
584
603
  >
585
604
  <Text style={styles.backText}>‹</Text>
@@ -610,7 +629,63 @@ const renderFreezeTable = (data) => {
610
629
  </View>
611
630
  ) : (
612
631
  <ScrollView style={styles.chartView}>
613
- {renderChart()}
632
+ {/* View Type Selector for Performance Reports */}
633
+ {selectedReport &&
634
+ (selectedReport.id === 1 || selectedReport.id === 1.1 || selectedReport.id === 1.2) &&
635
+ reportData && (
636
+ <View style={styles.viewTypeSelector}>
637
+ <TouchableOpacity
638
+ style={[
639
+ styles.viewTypeButton,
640
+ viewType === 'default' && styles.activeViewType
641
+ ]}
642
+ onPress={() => setViewType('default')}
643
+ >
644
+ <Text style={[
645
+ styles.viewTypeText,
646
+ viewType === 'default' && styles.activeViewTypeText
647
+ ]}>Varsayılan</Text>
648
+ </TouchableOpacity>
649
+
650
+ <TouchableOpacity
651
+ style={[
652
+ styles.viewTypeButton,
653
+ viewType === 'compact' && styles.activeViewType
654
+ ]}
655
+ onPress={() => setViewType('compact')}
656
+ >
657
+ <Text style={[
658
+ styles.viewTypeText,
659
+ viewType === 'compact' && styles.activeViewTypeText
660
+ ]}>Kompakt</Text>
661
+ </TouchableOpacity>
662
+
663
+ <TouchableOpacity
664
+ style={[
665
+ styles.viewTypeButton,
666
+ viewType === 'freeze' && styles.activeViewType
667
+ ]}
668
+ onPress={() => setViewType('freeze')}
669
+ >
670
+ <Text style={[
671
+ styles.viewTypeText,
672
+ viewType === 'freeze' && styles.activeViewTypeText
673
+ ]}>Sabit Kolon</Text>
674
+ </TouchableOpacity>
675
+ </View>
676
+ )}
677
+
678
+ <View style={styles.chartContainer}>
679
+ <Text style={styles.chartTitle}>{reportData?.title || selectedReport.title}</Text>
680
+ {selectedReport.id === 1 || selectedReport.id === 1.1 || selectedReport.id === 1.2 ? (
681
+ <Text style={styles.reportSubtitle}>
682
+ {viewType === 'default' ? 'Varsayılan Görünüm' :
683
+ viewType === 'compact' ? 'Kompakt Görünüm' :
684
+ 'Sabit Kolonlu Görünüm'}
685
+ </Text>
686
+ ) : null}
687
+ {renderChart()}
688
+ </View>
614
689
 
615
690
  {reportData && reportData.data && (
616
691
  <View style={styles.dataInfo}>
@@ -630,6 +705,7 @@ const renderFreezeTable = (data) => {
630
705
  );
631
706
  }
632
707
 
708
+ // ========== RENDER REPORT LIST VIEW ==========
633
709
  return (
634
710
  <View style={styles.container}>
635
711
  <View style={styles.header}>
@@ -946,7 +1022,7 @@ const styles = StyleSheet.create({
946
1022
  textAlign: 'center',
947
1023
  },
948
1024
 
949
- // Table Styles
1025
+ // Table Styles
950
1026
  table: {
951
1027
  minWidth: 700,
952
1028
  marginBottom: 20,
@@ -1009,12 +1085,6 @@ const styles = StyleSheet.create({
1009
1085
  color: '#333',
1010
1086
  textAlign: 'center',
1011
1087
  },
1012
- totalText: {
1013
- fontSize: 12,
1014
- fontWeight: '700',
1015
- color: '#2c3e50',
1016
- textAlign: 'center',
1017
- },
1018
1088
  numberText: {
1019
1089
  fontSize: 11,
1020
1090
  fontWeight: '500',
@@ -1037,6 +1107,7 @@ const styles = StyleSheet.create({
1037
1107
  fontWeight: '700',
1038
1108
  },
1039
1109
 
1110
+ // Compact Table Styles
1040
1111
  compactContainer: {
1041
1112
  flex: 1,
1042
1113
  paddingHorizontal: 8,
@@ -1151,7 +1222,7 @@ const styles = StyleSheet.create({
1151
1222
  color: '#666',
1152
1223
  },
1153
1224
 
1154
- // Report 1B: Freeze First Column Styles
1225
+ // Freeze Table Styles
1155
1226
  freezeContainer: {
1156
1227
  flex: 1,
1157
1228
  flexDirection: 'row',
@@ -1242,7 +1313,7 @@ const styles = StyleSheet.create({
1242
1313
  fontFamily: 'monospace',
1243
1314
  },
1244
1315
 
1245
- // Add view type selector for performance reports
1316
+ // View Type Selector
1246
1317
  viewTypeSelector: {
1247
1318
  flexDirection: 'row',
1248
1319
  backgroundColor: '#f0f0f0',
@@ -1274,65 +1345,14 @@ const styles = StyleSheet.create({
1274
1345
  color: '#4CAF50',
1275
1346
  fontWeight: '600',
1276
1347
  },
1348
+ reportSubtitle: {
1349
+ fontSize: 14,
1350
+ fontWeight: '600',
1351
+ color: '#4CAF50',
1352
+ textAlign: 'center',
1353
+ marginBottom: 16,
1354
+ fontStyle: 'italic',
1355
+ },
1277
1356
  });
1278
1357
 
1279
- // Add view type selector component in the chart view
1280
- {selectedReport && (selectedReport.id === 1 || selectedReport.id === 1.1 || selectedReport.id === 1.2) && (
1281
- <View style={styles.viewTypeSelector}>
1282
- <TouchableOpacity
1283
- style={[
1284
- styles.viewTypeButton,
1285
- reportData?.subType === 'default' && styles.activeViewType
1286
- ]}
1287
- onPress={() => {
1288
- setReportData({
1289
- ...reportData,
1290
- subType: 'default'
1291
- });
1292
- }}
1293
- >
1294
- <Text style={[
1295
- styles.viewTypeText,
1296
- reportData?.subType === 'default' && styles.activeViewTypeText
1297
- ]}>Varsayılan</Text>
1298
- </TouchableOpacity>
1299
-
1300
- <TouchableOpacity
1301
- style={[
1302
- styles.viewTypeButton,
1303
- reportData?.subType === 'compact' && styles.activeViewType
1304
- ]}
1305
- onPress={() => {
1306
- setReportData({
1307
- ...reportData,
1308
- subType: 'compact'
1309
- });
1310
- }}
1311
- >
1312
- <Text style={[
1313
- styles.viewTypeText,
1314
- reportData?.subType === 'compact' && styles.activeViewTypeText
1315
- ]}>Kompakt</Text>
1316
- </TouchableOpacity>
1317
-
1318
- <TouchableOpacity
1319
- style={[
1320
- styles.viewTypeButton,
1321
- reportData?.subType === 'freeze' && styles.activeViewType
1322
- ]}
1323
- onPress={() => {
1324
- setReportData({
1325
- ...reportData,
1326
- subType: 'freeze'
1327
- });
1328
- }}
1329
- >
1330
- <Text style={[
1331
- styles.viewTypeText,
1332
- reportData?.subType === 'freeze' && styles.activeViewTypeText
1333
- ]}>Sabit Kolon</Text>
1334
- </TouchableOpacity>
1335
- </View>
1336
- )}
1337
-
1338
1358
  export default ReportChart;