@dhiraj0720/report1chart 3.0.1 → 3.0.2

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": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "main": "src/index.jsx",
5
5
  "scripts": {
6
6
  "test": "echo 'No tests'"
@@ -1,8 +1,7 @@
1
- import React, { useMemo } from 'react';
2
- import { ScrollView, StyleSheet, Text, View, useWindowDimensions } from 'react-native';
3
- import { formatNumber } from '../utils/formatNumber';
1
+ import React from 'react';
2
+ import { View, Text, ScrollView, StyleSheet } from 'react-native';
4
3
 
5
- const TAB_TABLE_CONFIG = {
4
+ const TABLE_CONFIG = {
6
5
  kumule: {
7
6
  title: '2025 YILI ŞİRKET ve İŞTİPİ BAZINDA BRÜT KAR & FAALİYET KAR PERFORMANS TABLOSU',
8
7
  columns: [
@@ -71,222 +70,173 @@ const TAB_TABLE_CONFIG = {
71
70
  },
72
71
  };
73
72
 
74
- const trendUi = (trendValue) => {
75
- if (trendValue === 1) {
76
- return { icon: '', color: '#2e7d32' };
73
+ const formatNumber = (value) => {
74
+ if (value === null || value === undefined || value === '') {
75
+ return '-';
77
76
  }
78
77
 
79
- if (trendValue === 2) {
80
- return { icon: '↓', color: '#c62828' };
81
- }
78
+ return Number(value).toLocaleString('en-US');
79
+ };
82
80
 
83
- if (trendValue === 0) {
84
- return { icon: '●', color: '#c62828' };
81
+ const isTotalRow = (row) => row?.rowType === 1 || row?.rowType === 3;
82
+
83
+ const trendFromValue = (value) => {
84
+ if (value === null || value === undefined) {
85
+ return 0;
85
86
  }
86
87
 
87
- return { icon: '●', color: '#e65100' };
88
+ return value >= 0 ? 1 : 2;
88
89
  };
89
90
 
90
- const ratioTrend = (ratioValue) => {
91
- if (ratioValue === null || ratioValue === undefined) {
92
- return null;
91
+ const ratioTrend = (value) => {
92
+ if (value === null || value === undefined) {
93
+ return 0;
93
94
  }
94
95
 
95
- if (ratioValue < 0) {
96
+ if (value < 0) {
96
97
  return 0;
97
98
  }
98
99
 
99
- if (ratioValue <= 50) {
100
+ if (value <= 50) {
100
101
  return 1;
101
102
  }
102
103
 
103
104
  return 2;
104
105
  };
105
106
 
106
- const formatPercent = (value) => {
107
+ const PercentCell = ({ value, trend }) => {
107
108
  if (value === null || value === undefined) {
108
- return '-';
109
+ return <Text>-</Text>;
109
110
  }
110
111
 
111
- return Number(value).toLocaleString('en-US');
112
+ const resolvedTrend = trend || trendFromValue(value);
113
+ const isUp = resolvedTrend === 1;
114
+
115
+ return (
116
+ <Text
117
+ style={[
118
+ styles.percentText,
119
+ isUp ? styles.percentUp : styles.percentDown,
120
+ ]}
121
+ >
122
+ {isUp ? '↑' : '↓'} {Math.abs(value)}%
123
+ </Text>
124
+ );
112
125
  };
113
126
 
114
- const formatRatio = (value) => {
127
+ const RatioCell = ({ value }) => {
115
128
  if (value === null || value === undefined) {
116
- return '-';
129
+ return <Text>-</Text>;
117
130
  }
118
131
 
119
- if (value < 0) {
120
- return `-%${Math.abs(value)}`;
121
- }
132
+ const trend = ratioTrend(value);
133
+ const isUp = trend === 1;
122
134
 
123
- return `%${value}`;
135
+ return (
136
+ <Text
137
+ style={[
138
+ styles.percentText,
139
+ isUp ? styles.percentUp : styles.percentDown,
140
+ ]}
141
+ >
142
+ {isUp ? '↑' : '↓'} %{value}
143
+ </Text>
144
+ );
124
145
  };
125
146
 
126
- const DataCell = ({ children, rowStyle, cellStyle }) => (
127
- <View style={[styles.dataCell, rowStyle, cellStyle]}>
128
- {children}
147
+ const Cell = ({ children, bold = false, highlight = false, width = 100 }) => (
148
+ <View
149
+ style={[
150
+ styles.cell,
151
+ { width },
152
+ bold && styles.boldCell,
153
+ highlight && styles.highlightCell,
154
+ ]}
155
+ >
156
+ <Text
157
+ style={[
158
+ styles.cellText,
159
+ bold && styles.boldText,
160
+ ]}
161
+ numberOfLines={2}
162
+ >
163
+ {children}
164
+ </Text>
129
165
  </View>
130
166
  );
131
167
 
132
- const TrendValue = ({ value, trend }) => {
133
- const trendStyle = trendUi(trend);
134
-
135
- return (
136
- <View style={styles.trendWrapper}>
137
- <Text style={[styles.trendIcon, { color: trendStyle.color }]}>
138
- {trendStyle.icon}
139
- </Text>
140
- <Text numberOfLines={1} style={styles.dataCellText}>
141
- {value}
142
- </Text>
143
- </View>
144
- );
145
- };
146
-
147
- const renderCellValue = (row, column) => {
168
+ const renderDataCell = (row, column, isTotal) => {
148
169
  if (column.type === 'number') {
149
- return <Text style={styles.dataCellText}>{formatNumber(row[column.key])}</Text>;
170
+ return <Cell key={column.key} highlight={isTotal}>{formatNumber(row[column.key])}</Cell>;
150
171
  }
151
172
 
152
173
  if (column.type === 'trendPercent') {
153
174
  return (
154
- <TrendValue
155
- value={formatPercent(row[column.key])}
156
- trend={row[column.trendKey]}
157
- />
175
+ <Cell key={column.key} highlight={isTotal}>
176
+ <PercentCell value={row[column.key]} trend={row[column.trendKey]} />
177
+ </Cell>
158
178
  );
159
179
  }
160
180
 
161
181
  if (column.type === 'ratio') {
162
182
  return (
163
- <TrendValue
164
- value={formatRatio(row[column.key])}
165
- trend={ratioTrend(row[column.key])}
166
- />
183
+ <Cell key={column.key} highlight={isTotal}>
184
+ <RatioCell value={row[column.key]} />
185
+ </Cell>
167
186
  );
168
187
  }
169
188
 
170
- return <Text style={styles.dataCellText}>-</Text>;
171
- };
172
-
173
- const rowTypeStyle = (row, index) => {
174
- if (row.rowType === 1 || row.rowType === 3) {
175
- return styles.totalRow;
176
- }
177
-
178
- return index % 2 === 0 ? styles.evenRow : styles.oddRow;
189
+ return <Cell key={column.key} highlight={isTotal}>-</Cell>;
179
190
  };
180
191
 
181
- const FrozenTableReport4A = ({ rows = [], tabKey = 'kumule', isFullscreen = false }) => {
182
- const { width: screenWidth } = useWindowDimensions();
183
- const config = TAB_TABLE_CONFIG[tabKey] || TAB_TABLE_CONFIG.kumule;
184
-
185
- const layout = useMemo(() => {
186
- const safeWidth = Math.max(280, screenWidth - (isFullscreen ? 32 : 24));
187
-
188
- const frozenColumnWidth = isFullscreen
189
- ? Math.max(160, Math.min(220, safeWidth * 0.3))
190
- : Math.max(128, Math.min(156, safeWidth * 0.38));
191
-
192
- const dataColumnWidth = isFullscreen
193
- ? Math.max(96, Math.min(142, safeWidth * 0.18))
194
- : Math.max(92, Math.min(116, (safeWidth - frozenColumnWidth) / 2));
192
+ const FrozenTableReport4A = ({ rows = [], tabKey = 'kumule' }) => {
193
+ const config = TABLE_CONFIG[tabKey] || TABLE_CONFIG.kumule;
195
194
 
196
- return {
197
- frozenColumnWidth,
198
- dataColumnWidth,
199
- rowHeight: isFullscreen ? 42 : 38,
200
- headerHeight: isFullscreen ? 54 : 46,
201
- };
202
- }, [isFullscreen, screenWidth]);
203
-
204
- if (!rows.length) {
205
- return <Text style={styles.noData}>No data available</Text>;
195
+ if (!rows || rows.length === 0) {
196
+ return (
197
+ <Text style={styles.emptyText}>
198
+ No data available
199
+ </Text>
200
+ );
206
201
  }
207
202
 
208
203
  return (
209
- <View style={[styles.wrapper, isFullscreen && styles.wrapperFullscreen]}>
210
- <Text style={styles.tableTitle}>{config.title}</Text>
211
-
212
- <View style={styles.tableContainer}>
213
- <View style={[styles.frozenColumn, { width: layout.frozenColumnWidth }]}>
214
- <View
215
- style={[
216
- styles.nameCell,
217
- styles.headerCell,
218
- { height: layout.headerHeight },
219
- ]}
220
- >
221
- <Text style={styles.headerText}>ŞİRKET / İŞTİPİ</Text>
222
- </View>
204
+ <View>
205
+ <Text style={styles.title}>{config.title}</Text>
223
206
 
207
+ <View style={styles.container}>
208
+ <View style={styles.frozenColumn}>
209
+ <Cell bold width={180}>ŞİRKET / İŞTİPİ</Cell>
224
210
  {rows.map((row, index) => {
225
- const isTotal = row.rowType === 1 || row.rowType === 3;
211
+ const total = isTotalRow(row);
226
212
  return (
227
- <View
228
- key={`name-${row.sortOrder || index}`}
229
- style={[
230
- styles.nameCell,
231
- rowTypeStyle(row, index),
232
- { height: layout.rowHeight },
233
- ]}
213
+ <Cell
214
+ key={`${row.sortOrder || index}-name`}
215
+ bold={total}
216
+ highlight={total}
217
+ width={180}
234
218
  >
235
- <View style={styles.nameCellContent}>
236
- <Text style={styles.star}>{isTotal ? '★' : ''}</Text>
237
- <Text
238
- numberOfLines={1}
239
- adjustsFontSizeToFit
240
- minimumFontScale={0.78}
241
- style={styles.nameText}
242
- >
243
- {row.name}
244
- </Text>
245
- </View>
246
- </View>
219
+ {row.name}
220
+ </Cell>
247
221
  );
248
222
  })}
249
223
  </View>
250
224
 
251
225
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
252
226
  <View>
253
- <View style={styles.row}>
227
+ <View style={styles.headerRow}>
254
228
  {config.columns.map((column) => (
255
- <View
256
- key={column.key}
257
- style={[
258
- styles.dataCell,
259
- styles.headerCell,
260
- {
261
- width: layout.dataColumnWidth,
262
- height: layout.headerHeight,
263
- },
264
- ]}
265
- >
266
- <Text numberOfLines={2} style={styles.headerText}>
267
- {column.label}
268
- </Text>
269
- </View>
229
+ <Cell key={column.key} bold>
230
+ {column.label}
231
+ </Cell>
270
232
  ))}
271
233
  </View>
272
234
 
273
235
  {rows.map((row, index) => {
274
- const rowStyle = rowTypeStyle(row, index);
275
-
236
+ const total = isTotalRow(row);
276
237
  return (
277
- <View key={`row-${row.sortOrder || index}`} style={styles.row}>
278
- {config.columns.map((column) => (
279
- <DataCell
280
- key={`${row.sortOrder || index}-${column.key}`}
281
- rowStyle={rowStyle}
282
- cellStyle={{
283
- width: layout.dataColumnWidth,
284
- height: layout.rowHeight,
285
- }}
286
- >
287
- {renderCellValue(row, column)}
288
- </DataCell>
289
- ))}
238
+ <View key={`${row.sortOrder || index}-row`} style={styles.dataRow}>
239
+ {config.columns.map((column) => renderDataCell(row, column, total))}
290
240
  </View>
291
241
  );
292
242
  })}
@@ -300,105 +250,72 @@ const FrozenTableReport4A = ({ rows = [], tabKey = 'kumule', isFullscreen = fals
300
250
  export default FrozenTableReport4A;
301
251
 
302
252
  const styles = StyleSheet.create({
303
- wrapper: {
304
- backgroundColor: '#f4f7fb',
305
- borderRadius: 10,
306
- borderWidth: 1,
307
- borderColor: '#ccd8e4',
308
- padding: 6,
309
- },
310
- wrapperFullscreen: {
311
- padding: 8,
312
- },
313
- tableTitle: {
253
+ title: {
314
254
  textAlign: 'center',
315
- fontSize: 14,
255
+ fontSize: 16,
316
256
  fontWeight: '700',
317
- color: '#223648',
318
- marginBottom: 6,
257
+ color: '#2e2e2e',
258
+ marginBottom: 8,
259
+ marginTop: 4,
319
260
  },
320
- tableContainer: {
261
+ container: {
321
262
  flexDirection: 'row',
322
263
  borderWidth: 1,
323
- borderColor: '#b8c6d4',
324
- borderRadius: 8,
264
+ borderColor: '#ddd',
265
+ borderRadius: 10,
325
266
  overflow: 'hidden',
326
- backgroundColor: '#e7edf3',
267
+ marginVertical: 12,
268
+ backgroundColor: '#fff',
327
269
  },
328
270
  frozenColumn: {
271
+ width: 180,
272
+ backgroundColor: '#f4f6f8',
329
273
  borderRightWidth: 1,
330
- borderRightColor: '#ecf1f6',
274
+ borderColor: '#ddd',
331
275
  },
332
- row: {
276
+ headerRow: {
333
277
  flexDirection: 'row',
278
+ backgroundColor: '#4E79A7',
334
279
  },
335
- nameCell: {
336
- justifyContent: 'center',
337
- borderBottomWidth: 1,
338
- borderBottomColor: '#edf2f7',
339
- paddingHorizontal: 6,
340
- },
341
- nameCellContent: {
280
+ dataRow: {
342
281
  flexDirection: 'row',
343
- alignItems: 'center',
344
- },
345
- nameText: {
346
- flex: 1,
347
- fontSize: 11.5,
348
- color: '#203040',
349
- },
350
- star: {
351
- width: 14,
352
- textAlign: 'center',
353
- color: '#b7791f',
354
- fontSize: 13,
355
- marginRight: 2,
356
282
  },
357
- dataCell: {
283
+ cell: {
284
+ width: 100,
285
+ paddingVertical: 12,
286
+ paddingHorizontal: 8,
358
287
  justifyContent: 'center',
359
- alignItems: 'center',
360
- paddingHorizontal: 4,
361
288
  borderBottomWidth: 1,
362
- borderBottomColor: '#edf2f7',
289
+ borderColor: '#e0e0e0',
363
290
  },
364
- dataCellText: {
365
- fontSize: 11.5,
366
- color: '#2b3d4e',
291
+ cellText: {
292
+ fontSize: 12,
367
293
  textAlign: 'center',
294
+ color: '#333',
368
295
  },
369
- headerCell: {
370
- backgroundColor: '#5f7f9f',
296
+ boldCell: {
297
+ backgroundColor: '#e9f0f8',
371
298
  },
372
- headerText: {
373
- color: '#ffffff',
299
+ boldText: {
374
300
  fontWeight: '700',
375
- textAlign: 'center',
376
- fontSize: 11,
377
301
  },
378
- evenRow: {
379
- backgroundColor: '#e6eaef',
302
+ highlightCell: {
303
+ backgroundColor: '#e9f0f8',
380
304
  },
381
- oddRow: {
382
- backgroundColor: '#dde3e9',
305
+ percentText: {
306
+ fontWeight: '700',
307
+ fontSize: 12,
308
+ textAlign: 'center',
383
309
  },
384
- totalRow: {
385
- backgroundColor: '#a7bdd2',
310
+ percentUp: {
311
+ color: '#2e7d32',
386
312
  },
387
- trendWrapper: {
388
- flexDirection: 'row',
389
- alignItems: 'center',
390
- justifyContent: 'center',
391
- },
392
- trendIcon: {
393
- fontSize: 13,
394
- fontWeight: '700',
395
- marginRight: 3,
396
- marginTop: -1,
313
+ percentDown: {
314
+ color: '#d32f2f',
397
315
  },
398
- noData: {
316
+ emptyText: {
399
317
  textAlign: 'center',
318
+ padding: 20,
400
319
  color: '#666',
401
- paddingVertical: 20,
402
- fontSize: 14,
403
320
  },
404
321
  });
@@ -11,6 +11,7 @@ import {
11
11
  } from 'react-native';
12
12
  import fetchReport4 from '../api/report4Fetcher';
13
13
  import FrozenTableReport4A from '../components/FrozenTableReport4A';
14
+ import Report1Card from '../components/Report1Card';
14
15
 
15
16
  const TABS = [
16
17
  { key: 'kumule', label: 'KÜMÜLE' },
@@ -18,6 +19,42 @@ const TABS = [
18
19
  { key: 'fg', label: 'FG / BRÜT KAR ORANI' },
19
20
  ];
20
21
 
22
+ const mapRowToCardItem = (row, tabKey) => {
23
+ if (tabKey === 'faaliyet') {
24
+ return {
25
+ name: row.name,
26
+ actual2024: row.fk2024,
27
+ actual2025: row.fk2025,
28
+ actualChangePercent: row.changePercent ?? 0,
29
+ budget2025: row.budget2025,
30
+ budgetVariancePercent: row.budgetVariancePercent ?? 0,
31
+ };
32
+ }
33
+
34
+ if (tabKey === 'fg') {
35
+ const ratioDiff = (row.ratio2025 ?? 0) - (row.ratio2024 ?? 0);
36
+ return {
37
+ name: row.name,
38
+ actual2024: row.gross2024,
39
+ actual2025: row.gross2025,
40
+ actualChangePercent: ratioDiff,
41
+ budget2025: row.fk2025,
42
+ budgetVariancePercent: ratioDiff,
43
+ opexToGrossProfitPercent: row.ratio2025,
44
+ };
45
+ }
46
+
47
+ return {
48
+ name: row.name,
49
+ actual2024: row.gross2024,
50
+ actual2025: row.gross2025,
51
+ actualChangePercent: row.grossChangePercent ?? 0,
52
+ budget2025: row.budgetGross2025,
53
+ budgetVariancePercent: row.budgetGrossVariancePercent ?? 0,
54
+ opexToGrossProfitPercent: row.ratio2025,
55
+ };
56
+ };
57
+
21
58
  const Report4AScreen = ({ api, token, onBack }) => {
22
59
  const { width, height } = useWindowDimensions();
23
60
  const [activeTab, setActiveTab] = useState('kumule');
@@ -85,7 +122,7 @@ const Report4AScreen = ({ api, token, onBack }) => {
85
122
  <TouchableOpacity onPress={onBack} style={styles.backButton}>
86
123
  <Text style={styles.backIcon}>‹</Text>
87
124
  </TouchableOpacity>
88
- <Text style={styles.headerTitle}>New report Formate</Text>
125
+ <Text style={styles.headerTitle}>Performans Raporu (USD) - NEW</Text>
89
126
  </View>
90
127
 
91
128
  <View style={styles.tabsContainer}>
@@ -138,6 +175,14 @@ const Report4AScreen = ({ api, token, onBack }) => {
138
175
  </View>
139
176
 
140
177
  <FrozenTableReport4A rows={activeRows} tabKey={activeTab} />
178
+
179
+ <Text style={styles.sectionTitle}>Individual Reports</Text>
180
+ {activeRows.map((row, index) => (
181
+ <Report1Card
182
+ key={`card-${row.sortOrder || index}`}
183
+ item={mapRowToCardItem(row, activeTab)}
184
+ />
185
+ ))}
141
186
  </ScrollView>
142
187
  ) : null}
143
188
  </View>
@@ -279,6 +324,13 @@ const styles = StyleSheet.create({
279
324
  marginTop: 8,
280
325
  marginBottom: 6,
281
326
  },
327
+ sectionTitle: {
328
+ fontSize: 16,
329
+ fontWeight: '700',
330
+ marginTop: 8,
331
+ marginBottom: 14,
332
+ color: '#111',
333
+ },
282
334
  fullViewButton: {
283
335
  backgroundColor: '#4E79A7',
284
336
  borderRadius: 7,
@@ -8,16 +8,11 @@ import {
8
8
  } from 'react-native';
9
9
 
10
10
  const REPORTS = [
11
-
12
- {
13
- id: '1A',
14
- title: 'Performans Raporu (USD)',
15
- desc: 'Option 1',
16
- },
11
+
17
12
  {
18
- id: 1,
19
- title: 'Performans Raporu (USD)',
20
- desc: 'Option 2',
13
+ id: '4A',
14
+ title: 'Performans Raporu (USD) - NEW',
15
+ desc: 'New report formate',
21
16
  },
22
17
 
23
18
  {
@@ -41,11 +36,18 @@ const REPORTS = [
41
36
  title: 'Transportation Business Analysis',
42
37
  desc: 'Option 2',
43
38
  },
39
+
44
40
  {
45
- id: '4A',
46
- title: 'New performance Report',
47
- desc: 'New report formate',
41
+ id: '1A',
42
+ title: 'Performans Raporu (USD) - OLD',
43
+ desc: 'Option 1',
48
44
  },
45
+ {
46
+ id: 1,
47
+ title: 'Performans Raporu (USD) - OLD',
48
+ desc: 'Option 2',
49
+ },
50
+
49
51
  ];
50
52
 
51
53
  const ReportListScreen = ({ onSelect, onExit }) => {