@dhiraj0720/report1chart 1.0.4 → 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 +718 -173
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "1.0.4",
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,47 +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, data } = reportData;
103
-
104
- switch (type) {
105
- case 'table':
106
- return renderTable(data);
107
- case 'line':
108
- return renderLineChart(data);
109
- case 'bar':
110
- return renderBarChart(data);
111
- case 'pie':
112
- return renderPieChart(data);
113
- default:
114
- return renderBarChart(data);
115
- }
116
- };
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
+ );
232
+ }
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
+ }
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>
117
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>
118
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 ==========
119
444
  const renderLineChart = (data) => {
120
- // Handle both formats: { labels, values } or array format
121
445
  const values = data.values || data.map(d => d.value || d.revenue || d.shipments || 0);
122
446
  const labels = data.labels || data.map(d => d.label || d.month || d.mode || d.direction || '');
123
447
 
@@ -128,7 +452,7 @@ const formatCurrency = (value) => {
128
452
 
129
453
  return (
130
454
  <View style={styles.chartContainer}>
131
- <Text style={styles.chartTitle}>{reportData.title}</Text>
455
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
132
456
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
133
457
  <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
134
458
  {values.map((value, index) => {
@@ -154,7 +478,6 @@ const formatCurrency = (value) => {
154
478
  };
155
479
 
156
480
  const renderBarChart = (data) => {
157
- // Handle array format or object format
158
481
  const isArray = Array.isArray(data);
159
482
  const values = isArray ? data.map(d => d.revenue || d.value || d.shipments || 0) : data.values;
160
483
  const labels = isArray ? data.map(d => d.mode || d.label || '') : data.labels;
@@ -166,7 +489,7 @@ const formatCurrency = (value) => {
166
489
 
167
490
  return (
168
491
  <View style={styles.chartContainer}>
169
- <Text style={styles.chartTitle}>{reportData.title}</Text>
492
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
170
493
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
171
494
  <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
172
495
  {values.map((value, index) => {
@@ -191,119 +514,12 @@ const formatCurrency = (value) => {
191
514
  );
192
515
  };
193
516
 
194
- const renderTable = (data) => {
195
- if (!Array.isArray(data) || data.length === 0) {
196
- return (
197
- <View style={styles.noDataContainer}>
198
- <Text style={styles.noDataText}>No data available for this report</Text>
199
- </View>
200
- );
201
- }
202
-
203
- return (
204
- <ScrollView horizontal showsHorizontalScrollIndicator={true}>
205
- <View style={styles.table}>
206
- {/* Table Header */}
207
- <View style={styles.tableHeader}>
208
- <View style={[styles.headerCell, styles.firstColumn]}>
209
- <Text style={styles.headerText}>FALİYET KAR/ZARAR</Text>
210
- </View>
211
- <View style={styles.headerCell}>
212
- <Text style={styles.headerText}>2024 Fiili</Text>
213
- </View>
214
- <View style={styles.headerCell}>
215
- <Text style={styles.headerText}>2025 Fiili</Text>
216
- </View>
217
- <View style={styles.headerCell}>
218
- <Text style={styles.headerText}>Fiili Artış %</Text>
219
- </View>
220
- <View style={styles.headerCell}>
221
- <Text style={styles.headerText}>2025 Bütçe</Text>
222
- </View>
223
- <View style={styles.headerCell}>
224
- <Text style={styles.headerText}>Sapma %</Text>
225
- </View>
226
- <View style={styles.headerCell}>
227
- <Text style={styles.headerText}>FALİYET GİD.</Text>
228
- <Text style={styles.headerText}>/ BRÜT KAR %</Text>
229
- </View>
230
- </View>
231
-
232
- {/* Table Rows */}
233
- {data.map((item, index) => (
234
- <View
235
- key={index}
236
- style={[
237
- styles.tableRow,
238
- item.isTotal ? styles.totalRow : (index % 2 === 0 ? styles.evenRow : styles.oddRow)
239
- ]}
240
- >
241
- <View style={[styles.cell, styles.firstColumn]}>
242
- <Text style={item.isTotal ? styles.totalText : styles.cellText}>
243
- {item.name}
244
- </Text>
245
- </View>
246
-
247
- <View style={styles.cell}>
248
- <Text style={styles.numberText}>
249
- {formatCurrency(item.actual2024)}
250
- </Text>
251
- </View>
252
-
253
- <View style={styles.cell}>
254
- <Text style={styles.numberText}>
255
- {formatCurrency(item.actual2025)}
256
- </Text>
257
- </View>
258
-
259
- <View style={styles.cell}>
260
- <Text style={[
261
- styles.percentText,
262
- item.yoYChangePercent >= 0 ? styles.positive : styles.negative
263
- ]}>
264
- {item.yoYChangePercent >= 0 ? '↑' : '↓'} {Math.abs(item.yoYChangePercent)}%
265
- </Text>
266
- </View>
267
-
268
- <View style={styles.cell}>
269
- <Text style={styles.numberText}>
270
- {formatCurrency(item.budget2025)}
271
- </Text>
272
- </View>
273
-
274
- <View style={styles.cell}>
275
- <Text style={[
276
- styles.percentText,
277
- item.budgetVariancePercent >= 0 ? styles.positive : styles.negative
278
- ]}>
279
- {item.budgetVariancePercent >= 0 ? '↑' : '↓'} {Math.abs(item.budgetVariancePercent)}%
280
- </Text>
281
- </View>
282
-
283
- <View style={styles.cell}>
284
- <Text style={[
285
- styles.percentText,
286
- styles.grossMargin
287
- ]}>
288
- {item.grossMarginPercent}%
289
- </Text>
290
- </View>
291
- </View>
292
- ))}
293
- </View>
294
- </ScrollView>
295
- );
296
- };
297
-
298
-
299
-
300
517
  const renderPieChart = (data) => {
301
- // Data should be array of objects with label and value
302
518
  const total = data.reduce((sum, item) => sum + (item.shipments || item.revenue || item.value || 0), 0);
303
519
 
304
520
  return (
305
521
  <View style={styles.chartContainer}>
306
- <Text style={styles.chartTitle}>{reportData.title}</Text>
522
+ <Text style={styles.chartTitle}>{reportData?.title || ''}</Text>
307
523
  <View style={styles.pieContainer}>
308
524
  {data.map((item, index) => {
309
525
  const value = item.shipments || item.revenue || item.value || 0;
@@ -328,21 +544,51 @@ const formatCurrency = (value) => {
328
544
  );
329
545
  };
330
546
 
331
- const formatNumber = (num) => {
332
- return num.toLocaleString();
333
- };
334
-
335
- const getColor = (index) => {
336
- const colors = ['#4CAF50', '#2196F3', '#FF9800', '#E91E63', '#9C27B0', '#00BCD4'];
337
- return colors[index % colors.length];
338
- };
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
+ }
339
556
 
340
- const handleClose = () => {
341
- setSelectedReport(null);
342
- setReportData(null);
343
- 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
+ }
344
589
  };
345
590
 
591
+ // ========== RENDER SELECTED REPORT VIEW ==========
346
592
  if (selectedReport) {
347
593
  return (
348
594
  <View style={styles.container}>
@@ -352,6 +598,7 @@ const formatCurrency = (value) => {
352
598
  onPress={() => {
353
599
  setSelectedReport(null);
354
600
  setReportData(null);
601
+ setViewType('default');
355
602
  }}
356
603
  >
357
604
  <Text style={styles.backText}>‹</Text>
@@ -382,7 +629,63 @@ const formatCurrency = (value) => {
382
629
  </View>
383
630
  ) : (
384
631
  <ScrollView style={styles.chartView}>
385
- {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>
386
689
 
387
690
  {reportData && reportData.data && (
388
691
  <View style={styles.dataInfo}>
@@ -402,6 +705,7 @@ const formatCurrency = (value) => {
402
705
  );
403
706
  }
404
707
 
708
+ // ========== RENDER REPORT LIST VIEW ==========
405
709
  return (
406
710
  <View style={styles.container}>
407
711
  <View style={styles.header}>
@@ -718,7 +1022,7 @@ const styles = StyleSheet.create({
718
1022
  textAlign: 'center',
719
1023
  },
720
1024
 
721
- // Table Styles
1025
+ // Table Styles
722
1026
  table: {
723
1027
  minWidth: 700,
724
1028
  marginBottom: 20,
@@ -781,12 +1085,6 @@ const styles = StyleSheet.create({
781
1085
  color: '#333',
782
1086
  textAlign: 'center',
783
1087
  },
784
- totalText: {
785
- fontSize: 12,
786
- fontWeight: '700',
787
- color: '#2c3e50',
788
- textAlign: 'center',
789
- },
790
1088
  numberText: {
791
1089
  fontSize: 11,
792
1090
  fontWeight: '500',
@@ -808,6 +1106,253 @@ const styles = StyleSheet.create({
808
1106
  color: '#2c3e50',
809
1107
  fontWeight: '700',
810
1108
  },
1109
+
1110
+ // Compact Table Styles
1111
+ compactContainer: {
1112
+ flex: 1,
1113
+ paddingHorizontal: 8,
1114
+ },
1115
+ compactCard: {
1116
+ backgroundColor: '#fff',
1117
+ borderRadius: 12,
1118
+ marginBottom: 12,
1119
+ padding: 16,
1120
+ borderWidth: 1,
1121
+ borderColor: '#e8e8e8',
1122
+ shadowColor: '#000',
1123
+ shadowOffset: { width: 0, height: 2 },
1124
+ shadowOpacity: 0.1,
1125
+ shadowRadius: 3,
1126
+ elevation: 2,
1127
+ },
1128
+ compactTotalCard: {
1129
+ backgroundColor: '#e8f5e9',
1130
+ borderColor: '#4CAF50',
1131
+ borderWidth: 2,
1132
+ },
1133
+ evenCard: {
1134
+ backgroundColor: '#fff',
1135
+ },
1136
+ oddCard: {
1137
+ backgroundColor: '#f9f9f9',
1138
+ },
1139
+ compactHeader: {
1140
+ flexDirection: 'row',
1141
+ justifyContent: 'space-between',
1142
+ alignItems: 'center',
1143
+ marginBottom: 12,
1144
+ paddingBottom: 12,
1145
+ borderBottomWidth: 1,
1146
+ borderBottomColor: '#eee',
1147
+ },
1148
+ compactTitle: {
1149
+ fontSize: 14,
1150
+ fontWeight: '600',
1151
+ color: '#2c3e50',
1152
+ flex: 1,
1153
+ },
1154
+ totalTitle: {
1155
+ fontWeight: '700',
1156
+ color: '#2c3e50',
1157
+ fontSize: 15,
1158
+ },
1159
+ compactGrossMargin: {
1160
+ fontSize: 13,
1161
+ fontWeight: '600',
1162
+ paddingHorizontal: 8,
1163
+ paddingVertical: 4,
1164
+ borderRadius: 6,
1165
+ backgroundColor: '#f0f0f0',
1166
+ },
1167
+ compactGrid: {
1168
+ flexDirection: 'row',
1169
+ flexWrap: 'wrap',
1170
+ justifyContent: 'space-between',
1171
+ },
1172
+ compactColumn: {
1173
+ width: '48%',
1174
+ marginBottom: 12,
1175
+ backgroundColor: '#f8f9fa',
1176
+ padding: 10,
1177
+ borderRadius: 8,
1178
+ alignItems: 'center',
1179
+ },
1180
+ compactLabel: {
1181
+ fontSize: 11,
1182
+ color: '#666',
1183
+ marginBottom: 4,
1184
+ textAlign: 'center',
1185
+ },
1186
+ compactValue: {
1187
+ fontSize: 13,
1188
+ fontWeight: '600',
1189
+ color: '#2c3e50',
1190
+ fontFamily: 'monospace',
1191
+ },
1192
+ percentBadge: {
1193
+ backgroundColor: '#fff',
1194
+ paddingHorizontal: 10,
1195
+ paddingVertical: 4,
1196
+ borderRadius: 12,
1197
+ borderWidth: 1,
1198
+ borderColor: '#e0e0e0',
1199
+ },
1200
+ statusIndicator: {
1201
+ flexDirection: 'row',
1202
+ alignItems: 'center',
1203
+ marginTop: 12,
1204
+ paddingTop: 12,
1205
+ borderTopWidth: 1,
1206
+ borderTopColor: '#eee',
1207
+ },
1208
+ statusDot: {
1209
+ width: 8,
1210
+ height: 8,
1211
+ borderRadius: 4,
1212
+ marginRight: 8,
1213
+ },
1214
+ statusGood: {
1215
+ backgroundColor: '#4CAF50',
1216
+ },
1217
+ statusWarning: {
1218
+ backgroundColor: '#FF9800',
1219
+ },
1220
+ statusText: {
1221
+ fontSize: 12,
1222
+ color: '#666',
1223
+ },
1224
+
1225
+ // Freeze Table Styles
1226
+ freezeContainer: {
1227
+ flex: 1,
1228
+ flexDirection: 'row',
1229
+ },
1230
+ freezeColumn: {
1231
+ width: 180,
1232
+ borderRightWidth: 2,
1233
+ borderRightColor: '#ddd',
1234
+ backgroundColor: '#fff',
1235
+ },
1236
+ freezeFirstCell: {
1237
+ backgroundColor: '#2c3e50',
1238
+ justifyContent: 'center',
1239
+ alignItems: 'center',
1240
+ },
1241
+ freezeHeader: {
1242
+ height: 50,
1243
+ justifyContent: 'center',
1244
+ alignItems: 'center',
1245
+ backgroundColor: '#2c3e50',
1246
+ borderBottomWidth: 1,
1247
+ borderBottomColor: '#444',
1248
+ borderRightWidth: 1,
1249
+ borderRightColor: '#444',
1250
+ minWidth: 120,
1251
+ },
1252
+ freezeHeaderRow: {
1253
+ flexDirection: 'row',
1254
+ },
1255
+ freezeHeaderText: {
1256
+ color: '#fff',
1257
+ fontWeight: '600',
1258
+ fontSize: 12,
1259
+ textAlign: 'center',
1260
+ },
1261
+ freezeRow: {
1262
+ height: 45,
1263
+ justifyContent: 'center',
1264
+ paddingHorizontal: 10,
1265
+ borderBottomWidth: 1,
1266
+ borderBottomColor: '#eee',
1267
+ },
1268
+ freezeTotalRow: {
1269
+ backgroundColor: '#e8f5e9',
1270
+ borderTopWidth: 2,
1271
+ borderTopColor: '#4CAF50',
1272
+ borderBottomWidth: 2,
1273
+ borderBottomColor: '#4CAF50',
1274
+ },
1275
+ freezeCellText: {
1276
+ fontSize: 12,
1277
+ color: '#333',
1278
+ fontWeight: '500',
1279
+ },
1280
+ freezeTotalText: {
1281
+ fontWeight: '700',
1282
+ color: '#2c3e50',
1283
+ },
1284
+ scrollableColumns: {
1285
+ flex: 1,
1286
+ },
1287
+ freezeDataRow: {
1288
+ flexDirection: 'row',
1289
+ height: 45,
1290
+ borderBottomWidth: 1,
1291
+ borderBottomColor: '#eee',
1292
+ },
1293
+ freezeTotalDataRow: {
1294
+ backgroundColor: '#e8f5e9',
1295
+ },
1296
+ freezeDataCell: {
1297
+ minWidth: 120,
1298
+ justifyContent: 'center',
1299
+ alignItems: 'center',
1300
+ borderRightWidth: 1,
1301
+ borderRightColor: '#eee',
1302
+ paddingHorizontal: 8,
1303
+ },
1304
+ freezeDataText: {
1305
+ fontSize: 12,
1306
+ fontWeight: '500',
1307
+ fontFamily: 'monospace',
1308
+ color: '#333',
1309
+ },
1310
+ freezePercent: {
1311
+ fontSize: 12,
1312
+ fontWeight: '600',
1313
+ fontFamily: 'monospace',
1314
+ },
1315
+
1316
+ // View Type Selector
1317
+ viewTypeSelector: {
1318
+ flexDirection: 'row',
1319
+ backgroundColor: '#f0f0f0',
1320
+ borderRadius: 8,
1321
+ padding: 4,
1322
+ marginBottom: 16,
1323
+ alignSelf: 'center',
1324
+ },
1325
+ viewTypeButton: {
1326
+ paddingHorizontal: 16,
1327
+ paddingVertical: 8,
1328
+ borderRadius: 6,
1329
+ marginHorizontal: 2,
1330
+ },
1331
+ activeViewType: {
1332
+ backgroundColor: '#fff',
1333
+ shadowColor: '#000',
1334
+ shadowOffset: { width: 0, height: 1 },
1335
+ shadowOpacity: 0.1,
1336
+ shadowRadius: 2,
1337
+ elevation: 2,
1338
+ },
1339
+ viewTypeText: {
1340
+ fontSize: 13,
1341
+ fontWeight: '500',
1342
+ color: '#666',
1343
+ },
1344
+ activeViewTypeText: {
1345
+ color: '#4CAF50',
1346
+ fontWeight: '600',
1347
+ },
1348
+ reportSubtitle: {
1349
+ fontSize: 14,
1350
+ fontWeight: '600',
1351
+ color: '#4CAF50',
1352
+ textAlign: 'center',
1353
+ marginBottom: 16,
1354
+ fontStyle: 'italic',
1355
+ },
811
1356
  });
812
1357
 
813
1358
  export default ReportChart;