@dhiraj0720/report1chart 1.0.1 → 1.0.4

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@dhiraj0720/report1chart",
3
- "version": "1.0.1",
4
- "main": "src/index.js",
3
+ "version": "1.0.4",
4
+ "main": "src/index.jsx",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
package/src/index.jsx ADDED
@@ -0,0 +1,813 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ ScrollView,
8
+ ActivityIndicator,
9
+ Dimensions,
10
+ } from 'react-native';
11
+
12
+ const ReportChart = ({
13
+ onReportSelect,
14
+ onClose,
15
+ reports = [],
16
+ onFetchReportData
17
+ }) => {
18
+ const [selectedReport, setSelectedReport] = useState(null);
19
+ const [reportData, setReportData] = useState(null);
20
+ const [loading, setLoading] = useState(false);
21
+ const [error, setError] = useState(null);
22
+
23
+ // Default reports if none provided
24
+ const defaultReports = [
25
+ {
26
+ id: 1,
27
+ name: 'Report 1',
28
+ title: 'Revenue Trend',
29
+ type: 'line',
30
+ description: 'Monthly revenue analysis'
31
+ },
32
+ {
33
+ id: 2,
34
+ name: 'Report 2',
35
+ title: 'Revenue by Mode',
36
+ type: 'bar',
37
+ description: 'Revenue distribution across modes'
38
+ },
39
+ {
40
+ id: 3,
41
+ name: 'Report 3',
42
+ title: 'Shipment by Direction',
43
+ type: 'pie',
44
+ description: 'Shipment direction analysis'
45
+ },
46
+ ];
47
+
48
+ const reportList = reports.length > 0 ? reports : defaultReports;
49
+
50
+ const handleReportClick = async (report) => {
51
+ setLoading(true);
52
+ setError(null);
53
+ setReportData(null);
54
+ setSelectedReport(report);
55
+
56
+ try {
57
+ // Call the parent function to fetch data
58
+ if (onFetchReportData) {
59
+ const data = await onFetchReportData(report);
60
+ if (data) {
61
+ setReportData({
62
+ ...data,
63
+ title: report.title || report.name,
64
+ type: report.type || 'bar',
65
+ });
66
+ }
67
+ }
68
+
69
+ // Callback to parent
70
+ if (onReportSelect) {
71
+ onReportSelect(report.name);
72
+ }
73
+ } catch (err) {
74
+ setError(err.message || 'Failed to fetch report data');
75
+ } finally {
76
+ setLoading(false);
77
+ }
78
+ };
79
+
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
+ };
92
+
93
+ const renderChart = () => {
94
+ if (!reportData || !reportData.data) {
95
+ return (
96
+ <View style={styles.noDataContainer}>
97
+ <Text style={styles.noDataText}>No data available for this report</Text>
98
+ </View>
99
+ );
100
+ }
101
+
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
+ };
117
+
118
+
119
+ const renderLineChart = (data) => {
120
+ // Handle both formats: { labels, values } or array format
121
+ const values = data.values || data.map(d => d.value || d.revenue || d.shipments || 0);
122
+ const labels = data.labels || data.map(d => d.label || d.month || d.mode || d.direction || '');
123
+
124
+ const maxValue = Math.max(...values, 1);
125
+ const chartHeight = 200;
126
+ const chartWidth = Dimensions.get('window').width - 64;
127
+ const barWidth = (chartWidth / values.length) - 10;
128
+
129
+ return (
130
+ <View style={styles.chartContainer}>
131
+ <Text style={styles.chartTitle}>{reportData.title}</Text>
132
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
133
+ <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
134
+ {values.map((value, index) => {
135
+ const height = (value / maxValue) * chartHeight;
136
+ const label = labels[index] || `M${index + 1}`;
137
+
138
+ return (
139
+ <View key={index} style={styles.linePointWrapper}>
140
+ <View style={[styles.linePoint, {
141
+ height: Math.max(height, 2),
142
+ width: barWidth
143
+ }]} />
144
+ <View style={styles.lineConnector} />
145
+ <Text style={styles.lineLabel} numberOfLines={1}>{label}</Text>
146
+ <Text style={styles.valueText}>{formatNumber(value)}</Text>
147
+ </View>
148
+ );
149
+ })}
150
+ </View>
151
+ </ScrollView>
152
+ </View>
153
+ );
154
+ };
155
+
156
+ const renderBarChart = (data) => {
157
+ // Handle array format or object format
158
+ const isArray = Array.isArray(data);
159
+ const values = isArray ? data.map(d => d.revenue || d.value || d.shipments || 0) : data.values;
160
+ const labels = isArray ? data.map(d => d.mode || d.label || '') : data.labels;
161
+
162
+ const maxValue = Math.max(...values, 1);
163
+ const chartHeight = 200;
164
+ const chartWidth = Dimensions.get('window').width - 64;
165
+ const barWidth = Math.min(40, (chartWidth / values.length) - 10);
166
+
167
+ return (
168
+ <View style={styles.chartContainer}>
169
+ <Text style={styles.chartTitle}>{reportData.title}</Text>
170
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
171
+ <View style={[styles.chart, { height: chartHeight, width: chartWidth }]}>
172
+ {values.map((value, index) => {
173
+ const height = (value / maxValue) * chartHeight;
174
+ const label = labels?.[index] || `Item ${index + 1}`;
175
+
176
+ return (
177
+ <View key={index} style={styles.barWrapper}>
178
+ <View style={[styles.bar, {
179
+ height,
180
+ width: barWidth,
181
+ backgroundColor: getColor(index)
182
+ }]} />
183
+ <Text style={styles.barLabel} numberOfLines={1}>{label}</Text>
184
+ <Text style={styles.valueText}>{formatNumber(value)}</Text>
185
+ </View>
186
+ );
187
+ })}
188
+ </View>
189
+ </ScrollView>
190
+ </View>
191
+ );
192
+ };
193
+
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
+ const renderPieChart = (data) => {
301
+ // Data should be array of objects with label and value
302
+ const total = data.reduce((sum, item) => sum + (item.shipments || item.revenue || item.value || 0), 0);
303
+
304
+ return (
305
+ <View style={styles.chartContainer}>
306
+ <Text style={styles.chartTitle}>{reportData.title}</Text>
307
+ <View style={styles.pieContainer}>
308
+ {data.map((item, index) => {
309
+ const value = item.shipments || item.revenue || item.value || 0;
310
+ const label = item.direction || item.mode || item.label || `Item ${index + 1}`;
311
+ const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : '0';
312
+
313
+ return (
314
+ <View key={index} style={styles.pieItem}>
315
+ <View style={[styles.pieColor, { backgroundColor: getColor(index) }]} />
316
+ <Text style={styles.pieLabel}>{label}:</Text>
317
+ <Text style={styles.pieValue}>
318
+ {formatNumber(value)} ({percentage}%)
319
+ </Text>
320
+ </View>
321
+ );
322
+ })}
323
+ </View>
324
+ {total > 0 && (
325
+ <Text style={styles.totalText}>Total: {formatNumber(total)}</Text>
326
+ )}
327
+ </View>
328
+ );
329
+ };
330
+
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
+ };
339
+
340
+ const handleClose = () => {
341
+ setSelectedReport(null);
342
+ setReportData(null);
343
+ if (onClose) onClose();
344
+ };
345
+
346
+ if (selectedReport) {
347
+ return (
348
+ <View style={styles.container}>
349
+ <View style={styles.header}>
350
+ <TouchableOpacity
351
+ style={styles.backButton}
352
+ onPress={() => {
353
+ setSelectedReport(null);
354
+ setReportData(null);
355
+ }}
356
+ >
357
+ <Text style={styles.backText}>‹</Text>
358
+ <Text style={styles.backButtonText}>Back</Text>
359
+ </TouchableOpacity>
360
+ <Text style={styles.headerTitle} numberOfLines={1}>
361
+ {selectedReport.title || selectedReport.name}
362
+ </Text>
363
+ <TouchableOpacity onPress={handleClose} style={styles.closeButton}>
364
+ <Text style={styles.closeText}>×</Text>
365
+ </TouchableOpacity>
366
+ </View>
367
+
368
+ {loading ? (
369
+ <View style={styles.loadingContainer}>
370
+ <ActivityIndicator size="large" color="#4CAF50" />
371
+ <Text style={styles.loadingText}>Loading report data...</Text>
372
+ </View>
373
+ ) : error ? (
374
+ <View style={styles.errorContainer}>
375
+ <Text style={styles.errorText}>Error: {error}</Text>
376
+ <TouchableOpacity
377
+ style={styles.retryButton}
378
+ onPress={() => handleReportClick(selectedReport)}
379
+ >
380
+ <Text style={styles.retryText}>Retry</Text>
381
+ </TouchableOpacity>
382
+ </View>
383
+ ) : (
384
+ <ScrollView style={styles.chartView}>
385
+ {renderChart()}
386
+
387
+ {reportData && reportData.data && (
388
+ <View style={styles.dataInfo}>
389
+ <Text style={styles.infoTitle}>Report Information</Text>
390
+ <Text style={styles.infoText}>
391
+ {selectedReport.description || 'Detailed analysis report'}
392
+ </Text>
393
+ <Text style={styles.dataSource}>
394
+ Data points: {Array.isArray(reportData.data) ? reportData.data.length :
395
+ reportData.data.values?.length || reportData.data.labels?.length || 'N/A'}
396
+ </Text>
397
+ </View>
398
+ )}
399
+ </ScrollView>
400
+ )}
401
+ </View>
402
+ );
403
+ }
404
+
405
+ return (
406
+ <View style={styles.container}>
407
+ <View style={styles.header}>
408
+ <Text style={styles.headerTitle}>Reports Dashboard</Text>
409
+ <TouchableOpacity onPress={handleClose} style={styles.closeButton}>
410
+ <Text style={styles.closeText}>×</Text>
411
+ </TouchableOpacity>
412
+ </View>
413
+
414
+ <ScrollView style={styles.reportsList}>
415
+ {reportList.map((report) => (
416
+ <TouchableOpacity
417
+ key={report.id}
418
+ style={styles.reportCard}
419
+ onPress={() => handleReportClick(report)}
420
+ >
421
+ <View style={[styles.reportIcon, { backgroundColor: getColor(report.id) }]}>
422
+ <Text style={styles.reportIconText}>{report.id}</Text>
423
+ </View>
424
+ <View style={styles.reportInfo}>
425
+ <Text style={styles.reportName}>{report.name}</Text>
426
+ <Text style={styles.reportTitle}>{report.title}</Text>
427
+ <Text style={styles.reportDesc}>{report.description}</Text>
428
+ </View>
429
+ <Text style={styles.arrow}>›</Text>
430
+ </TouchableOpacity>
431
+ ))}
432
+ </ScrollView>
433
+ </View>
434
+ );
435
+ };
436
+
437
+ const styles = StyleSheet.create({
438
+ container: {
439
+ flex: 1,
440
+ backgroundColor: '#f8f9fa',
441
+ },
442
+ header: {
443
+ flexDirection: 'row',
444
+ alignItems: 'center',
445
+ justifyContent: 'space-between',
446
+ backgroundColor: '#fff',
447
+ paddingHorizontal: 16,
448
+ paddingVertical: 12,
449
+ borderBottomWidth: 1,
450
+ borderBottomColor: '#e0e0e0',
451
+ },
452
+ headerTitle: {
453
+ fontSize: 18,
454
+ fontWeight: '700',
455
+ color: '#000',
456
+ flex: 1,
457
+ textAlign: 'center',
458
+ },
459
+ backButton: {
460
+ flexDirection: 'row',
461
+ alignItems: 'center',
462
+ padding: 8,
463
+ },
464
+ backText: {
465
+ fontSize: 24,
466
+ color: '#4CAF50',
467
+ marginRight: 4,
468
+ },
469
+ backButtonText: {
470
+ fontSize: 16,
471
+ color: '#4CAF50',
472
+ fontWeight: '600',
473
+ },
474
+ closeButton: {
475
+ width: 32,
476
+ height: 32,
477
+ borderRadius: 16,
478
+ backgroundColor: '#f0f0f0',
479
+ justifyContent: 'center',
480
+ alignItems: 'center',
481
+ },
482
+ closeText: {
483
+ fontSize: 20,
484
+ color: '#666',
485
+ fontWeight: '300',
486
+ },
487
+ reportsList: {
488
+ flex: 1,
489
+ padding: 16,
490
+ },
491
+ reportCard: {
492
+ flexDirection: 'row',
493
+ alignItems: 'center',
494
+ backgroundColor: '#fff',
495
+ borderRadius: 12,
496
+ padding: 16,
497
+ marginBottom: 12,
498
+ borderWidth: 1,
499
+ borderColor: '#e8e8e8',
500
+ shadowColor: '#000',
501
+ shadowOffset: { width: 0, height: 1 },
502
+ shadowOpacity: 0.05,
503
+ shadowRadius: 2,
504
+ elevation: 2,
505
+ },
506
+ reportIcon: {
507
+ width: 44,
508
+ height: 44,
509
+ borderRadius: 22,
510
+ justifyContent: 'center',
511
+ alignItems: 'center',
512
+ marginRight: 12,
513
+ },
514
+ reportIconText: {
515
+ fontSize: 18,
516
+ fontWeight: '700',
517
+ color: '#fff',
518
+ },
519
+ reportInfo: {
520
+ flex: 1,
521
+ },
522
+ reportName: {
523
+ fontSize: 16,
524
+ fontWeight: '600',
525
+ color: '#000',
526
+ marginBottom: 2,
527
+ },
528
+ reportTitle: {
529
+ fontSize: 14,
530
+ fontWeight: '500',
531
+ color: '#4CAF50',
532
+ marginBottom: 4,
533
+ },
534
+ reportDesc: {
535
+ fontSize: 13,
536
+ color: '#666',
537
+ lineHeight: 18,
538
+ },
539
+ arrow: {
540
+ fontSize: 24,
541
+ color: '#ccc',
542
+ fontWeight: '300',
543
+ },
544
+ chartView: {
545
+ flex: 1,
546
+ padding: 16,
547
+ },
548
+ chartContainer: {
549
+ backgroundColor: '#fff',
550
+ borderRadius: 12,
551
+ padding: 16,
552
+ marginBottom: 16,
553
+ borderWidth: 1,
554
+ borderColor: '#e8e8e8',
555
+ shadowColor: '#000',
556
+ shadowOffset: { width: 0, height: 1 },
557
+ shadowOpacity: 0.05,
558
+ shadowRadius: 2,
559
+ elevation: 2,
560
+ },
561
+ chartTitle: {
562
+ fontSize: 18,
563
+ fontWeight: '700',
564
+ color: '#000',
565
+ marginBottom: 20,
566
+ textAlign: 'center',
567
+ },
568
+ chart: {
569
+ flexDirection: 'row',
570
+ alignItems: 'flex-end',
571
+ justifyContent: 'space-between',
572
+ paddingHorizontal: 8,
573
+ },
574
+ barWrapper: {
575
+ alignItems: 'center',
576
+ marginHorizontal: 4,
577
+ },
578
+ bar: {
579
+ borderRadius: 4,
580
+ },
581
+ barLabel: {
582
+ marginTop: 8,
583
+ fontSize: 11,
584
+ color: '#666',
585
+ textAlign: 'center',
586
+ width: 60,
587
+ },
588
+ linePointWrapper: {
589
+ alignItems: 'center',
590
+ marginHorizontal: 4,
591
+ },
592
+ linePoint: {
593
+ backgroundColor: '#2196F3',
594
+ borderRadius: 2,
595
+ },
596
+ lineConnector: {
597
+ width: 2,
598
+ backgroundColor: '#2196F3',
599
+ opacity: 0.3,
600
+ marginVertical: 2,
601
+ flex: 1,
602
+ },
603
+ lineLabel: {
604
+ marginTop: 8,
605
+ fontSize: 11,
606
+ color: '#666',
607
+ textAlign: 'center',
608
+ width: 60,
609
+ },
610
+ valueText: {
611
+ fontSize: 10,
612
+ color: '#999',
613
+ marginTop: 4,
614
+ fontWeight: '500',
615
+ },
616
+ pieContainer: {
617
+ padding: 10,
618
+ },
619
+ pieItem: {
620
+ flexDirection: 'row',
621
+ alignItems: 'center',
622
+ marginBottom: 12,
623
+ padding: 8,
624
+ backgroundColor: '#f9f9f9',
625
+ borderRadius: 8,
626
+ },
627
+ pieColor: {
628
+ width: 16,
629
+ height: 16,
630
+ borderRadius: 8,
631
+ marginRight: 12,
632
+ },
633
+ pieLabel: {
634
+ fontSize: 15,
635
+ fontWeight: '600',
636
+ color: '#000',
637
+ flex: 1,
638
+ },
639
+ pieValue: {
640
+ fontSize: 14,
641
+ color: '#666',
642
+ fontWeight: '500',
643
+ },
644
+ totalText: {
645
+ fontSize: 16,
646
+ fontWeight: '700',
647
+ color: '#4CAF50',
648
+ textAlign: 'center',
649
+ marginTop: 16,
650
+ paddingTop: 16,
651
+ borderTopWidth: 1,
652
+ borderTopColor: '#eee',
653
+ },
654
+ dataInfo: {
655
+ backgroundColor: '#e8f5e9',
656
+ borderRadius: 12,
657
+ padding: 16,
658
+ marginTop: 8,
659
+ },
660
+ infoTitle: {
661
+ fontSize: 16,
662
+ fontWeight: '700',
663
+ color: '#2e7d32',
664
+ marginBottom: 8,
665
+ },
666
+ infoText: {
667
+ fontSize: 14,
668
+ color: '#555',
669
+ lineHeight: 20,
670
+ marginBottom: 8,
671
+ },
672
+ dataSource: {
673
+ fontSize: 13,
674
+ color: '#777',
675
+ fontStyle: 'italic',
676
+ },
677
+ loadingContainer: {
678
+ flex: 1,
679
+ justifyContent: 'center',
680
+ alignItems: 'center',
681
+ padding: 40,
682
+ },
683
+ loadingText: {
684
+ marginTop: 16,
685
+ fontSize: 16,
686
+ color: '#666',
687
+ },
688
+ errorContainer: {
689
+ flex: 1,
690
+ justifyContent: 'center',
691
+ alignItems: 'center',
692
+ padding: 40,
693
+ },
694
+ errorText: {
695
+ fontSize: 16,
696
+ color: '#d32f2f',
697
+ textAlign: 'center',
698
+ marginBottom: 20,
699
+ },
700
+ retryButton: {
701
+ backgroundColor: '#4CAF50',
702
+ paddingHorizontal: 24,
703
+ paddingVertical: 12,
704
+ borderRadius: 8,
705
+ },
706
+ retryText: {
707
+ color: '#fff',
708
+ fontSize: 16,
709
+ fontWeight: '600',
710
+ },
711
+ noDataContainer: {
712
+ padding: 40,
713
+ alignItems: 'center',
714
+ },
715
+ noDataText: {
716
+ fontSize: 16,
717
+ color: '#999',
718
+ textAlign: 'center',
719
+ },
720
+
721
+ // Table Styles
722
+ table: {
723
+ minWidth: 700,
724
+ marginBottom: 20,
725
+ },
726
+ tableHeader: {
727
+ flexDirection: 'row',
728
+ backgroundColor: '#2c3e50',
729
+ borderBottomWidth: 1,
730
+ borderBottomColor: '#ddd',
731
+ },
732
+ headerCell: {
733
+ flex: 1,
734
+ padding: 10,
735
+ minWidth: 100,
736
+ justifyContent: 'center',
737
+ alignItems: 'center',
738
+ borderRightWidth: 1,
739
+ borderRightColor: '#444',
740
+ },
741
+ firstColumn: {
742
+ flex: 1.5,
743
+ minWidth: 180,
744
+ },
745
+ headerText: {
746
+ color: '#fff',
747
+ fontWeight: '600',
748
+ fontSize: 11,
749
+ textAlign: 'center',
750
+ },
751
+ tableRow: {
752
+ flexDirection: 'row',
753
+ borderBottomWidth: 1,
754
+ borderBottomColor: '#eee',
755
+ minHeight: 40,
756
+ },
757
+ evenRow: {
758
+ backgroundColor: '#fff',
759
+ },
760
+ oddRow: {
761
+ backgroundColor: '#f9f9f9',
762
+ },
763
+ totalRow: {
764
+ backgroundColor: '#e8f5e9',
765
+ borderTopWidth: 2,
766
+ borderTopColor: '#4CAF50',
767
+ borderBottomWidth: 2,
768
+ borderBottomColor: '#4CAF50',
769
+ },
770
+ cell: {
771
+ flex: 1,
772
+ padding: 8,
773
+ minWidth: 100,
774
+ justifyContent: 'center',
775
+ alignItems: 'center',
776
+ borderRightWidth: 1,
777
+ borderRightColor: '#eee',
778
+ },
779
+ cellText: {
780
+ fontSize: 12,
781
+ color: '#333',
782
+ textAlign: 'center',
783
+ },
784
+ totalText: {
785
+ fontSize: 12,
786
+ fontWeight: '700',
787
+ color: '#2c3e50',
788
+ textAlign: 'center',
789
+ },
790
+ numberText: {
791
+ fontSize: 11,
792
+ fontWeight: '500',
793
+ fontFamily: 'monospace',
794
+ color: '#333',
795
+ },
796
+ percentText: {
797
+ fontSize: 12,
798
+ fontWeight: '600',
799
+ fontFamily: 'monospace',
800
+ },
801
+ positive: {
802
+ color: '#27ae60',
803
+ },
804
+ negative: {
805
+ color: '#e74c3c',
806
+ },
807
+ grossMargin: {
808
+ color: '#2c3e50',
809
+ fontWeight: '700',
810
+ },
811
+ });
812
+
813
+ export default ReportChart;
package/src/index.js DELETED
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { View, Text, StyleSheet } from 'react-native';
3
-
4
- const BarChart = ({ data = [], height = 200 }) => {
5
- const maxValue = Math.max(...data.map(d => d.value), 1);
6
-
7
- return (
8
- <View style={[styles.container, { height }]}>
9
- {data.map((item, index) => {
10
- const barHeight = (item.value / maxValue) * height;
11
-
12
- return (
13
- <View key={index} style={styles.barWrapper}>
14
- <View style={[styles.bar, { height: barHeight }]} />
15
- <Text style={styles.label}>{item.name}</Text>
16
- </View>
17
- );
18
- })}
19
- </View>
20
- );
21
- };
22
-
23
- export default BarChart; // ✅ DEFAULT EXPORT
24
-
25
- const styles = StyleSheet.create({
26
- container: {
27
- flexDirection: 'row',
28
- alignItems: 'flex-end',
29
- },
30
- barWrapper: {
31
- flex: 1,
32
- alignItems: 'center',
33
- },
34
- bar: {
35
- width: 22,
36
- backgroundColor: '#4CAF50',
37
- borderRadius: 6,
38
- },
39
- label: {
40
- marginTop: 6,
41
- fontSize: 12,
42
- },
43
- });