@suflon/rnmd-reporting 0.0.4 → 0.0.5
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 +1 -1
- package/src/modules/ManagementReport/components/AnalyticsChartView.tsx +287 -51
- package/src/modules/ManagementReport/components/DetailsListingView.tsx +1 -1
- package/src/modules/ManagementReport/components/DoctorFilterDropdown.tsx +1 -1
- package/src/modules/ManagementReport/components/TimeframeDropdown.tsx +1 -1
- package/src/modules/Reporting/component/ReportChart.tsx +1 -1
- package/src/modules/Reporting/component/ReportFilterModal.tsx +1 -1
- package/src/modules/Reporting/component/ReportingDetail.tsx +1 -1
- package/src/modules/Reporting/index.tsx +1 -1
- package/src/navigation/index.tsx +3 -3
package/package.json
CHANGED
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
TouchableOpacity,
|
|
7
7
|
ActivityIndicator,
|
|
8
8
|
useColorScheme,
|
|
9
|
+
Dimensions,
|
|
9
10
|
} from 'react-native';
|
|
11
|
+
import Svg, { Path, Circle, Defs, LinearGradient, Stop, Line as SvgLine } from 'react-native-svg';
|
|
10
12
|
import {
|
|
11
13
|
IManagementReportDetail,
|
|
12
14
|
Icon,
|
|
@@ -25,6 +27,29 @@ interface ChartItemData {
|
|
|
25
27
|
value: number;
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
function formatLabel(label: string): string {
|
|
31
|
+
if (!label) return '-';
|
|
32
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(label)) {
|
|
33
|
+
const parts = label.split('-');
|
|
34
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
35
|
+
const m = parseInt(parts[1], 10) - 1;
|
|
36
|
+
return `${parts[2]} ${months[m] || parts[1]}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return label
|
|
40
|
+
.replace(/_/g, ' ')
|
|
41
|
+
.replace(/([A-Z])/g, ' $1')
|
|
42
|
+
.replace(/\b\w/g, (c) => c.toUpperCase())
|
|
43
|
+
.trim();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function formatYAxisValue(val: number): string {
|
|
47
|
+
if (val >= 1000000) return `${(val / 1000000).toFixed(1)}M`;
|
|
48
|
+
if (val >= 1000) return `${(val / 1000).toFixed(1)}k`;
|
|
49
|
+
if (Number.isInteger(val)) return String(val);
|
|
50
|
+
return val.toFixed(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
28
53
|
function parseChartData(rows: any[]): ChartItemData[] {
|
|
29
54
|
if (!rows || rows.length === 0) return [];
|
|
30
55
|
|
|
@@ -48,6 +73,8 @@ function parseChartData(rows: any[]): ChartItemData[] {
|
|
|
48
73
|
'department',
|
|
49
74
|
'category',
|
|
50
75
|
'group_key',
|
|
76
|
+
'appointment_type',
|
|
77
|
+
'severity',
|
|
51
78
|
].includes(k.toLowerCase())
|
|
52
79
|
) || keys[0];
|
|
53
80
|
|
|
@@ -62,13 +89,14 @@ function parseChartData(rows: any[]): ChartItemData[] {
|
|
|
62
89
|
'net_amount',
|
|
63
90
|
'sum',
|
|
64
91
|
'metric_value',
|
|
92
|
+
'patients',
|
|
65
93
|
].includes(k.toLowerCase())
|
|
66
94
|
) || keys[1] || keys[0];
|
|
67
95
|
|
|
68
96
|
const val = Number(r[valueKey]) || 0;
|
|
69
|
-
const
|
|
97
|
+
const rawLbl = String(r[labelKey] || `Item ${i + 1}`);
|
|
70
98
|
|
|
71
|
-
return { label:
|
|
99
|
+
return { label: formatLabel(rawLbl), value: val };
|
|
72
100
|
}
|
|
73
101
|
|
|
74
102
|
return { label: `Item ${i + 1}`, value: 0 };
|
|
@@ -114,8 +142,49 @@ const SingleChartCard: React.FC<{
|
|
|
114
142
|
[chartData]
|
|
115
143
|
);
|
|
116
144
|
|
|
145
|
+
// Generate 4 evenly spaced Y-axis ticks
|
|
146
|
+
const yTicks = useMemo(() => {
|
|
147
|
+
return [
|
|
148
|
+
maxValue,
|
|
149
|
+
Math.round(maxValue * 0.66),
|
|
150
|
+
Math.round(maxValue * 0.33),
|
|
151
|
+
0,
|
|
152
|
+
];
|
|
153
|
+
}, [maxValue]);
|
|
154
|
+
|
|
117
155
|
const isBusy = loading || fetching;
|
|
118
156
|
const title = detail.report?.name || detail.report_num || 'Performance Metric';
|
|
157
|
+
const isCompact = chartData.length <= 4;
|
|
158
|
+
const chartHeight = 130;
|
|
159
|
+
const cardWidth = Dimensions.get('window').width - 90;
|
|
160
|
+
const svgWidth = Math.max(cardWidth, chartData.length * 64);
|
|
161
|
+
|
|
162
|
+
// SVG Line / Trend calculations
|
|
163
|
+
const svgPoints = useMemo(() => {
|
|
164
|
+
if (chartData.length === 0) return [];
|
|
165
|
+
const step = chartData.length > 1 ? svgWidth / (chartData.length - 1) : svgWidth / 2;
|
|
166
|
+
const paddingBottom = 15;
|
|
167
|
+
const paddingTop = 15;
|
|
168
|
+
const availableHeight = chartHeight - paddingTop - paddingBottom;
|
|
169
|
+
|
|
170
|
+
return chartData.map((d, i) => {
|
|
171
|
+
const x = chartData.length === 1 ? svgWidth / 2 : i * step;
|
|
172
|
+
const y = chartHeight - paddingBottom - (d.value / maxValue) * availableHeight;
|
|
173
|
+
return { x, y, value: d.value, label: d.label };
|
|
174
|
+
});
|
|
175
|
+
}, [chartData, maxValue, svgWidth, chartHeight]);
|
|
176
|
+
|
|
177
|
+
const linePath = useMemo(() => {
|
|
178
|
+
if (svgPoints.length === 0) return '';
|
|
179
|
+
return svgPoints.reduce((acc, p, i) => `${acc} ${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`, '');
|
|
180
|
+
}, [svgPoints]);
|
|
181
|
+
|
|
182
|
+
const areaPath = useMemo(() => {
|
|
183
|
+
if (svgPoints.length === 0) return '';
|
|
184
|
+
const lastX = svgPoints[svgPoints.length - 1].x;
|
|
185
|
+
const firstX = svgPoints[0].x;
|
|
186
|
+
return `${linePath} L ${lastX},${chartHeight - 10} L ${firstX},${chartHeight - 10} Z`;
|
|
187
|
+
}, [linePath, svgPoints, chartHeight]);
|
|
119
188
|
|
|
120
189
|
return (
|
|
121
190
|
<View className="p-3.5 rounded-3xl bg-white dark:bg-background-darkSecondaryBg border border-slate-100 dark:border-slate-800 mb-3.5">
|
|
@@ -195,67 +264,234 @@ const SingleChartCard: React.FC<{
|
|
|
195
264
|
</Text>
|
|
196
265
|
</View>
|
|
197
266
|
) : (
|
|
198
|
-
<View className="pt-
|
|
199
|
-
{/*
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return (
|
|
210
|
-
<View
|
|
211
|
-
key={idx}
|
|
212
|
-
className="items-center justify-end mr-3.5"
|
|
213
|
-
style={{ width: 44 }}
|
|
267
|
+
<View className="pt-1">
|
|
268
|
+
{/* Main Chart Body: Left Y-Axis Scale Column + Chart Canvas */}
|
|
269
|
+
<View className="flex-row">
|
|
270
|
+
{/* 1. Left Y-Axis Labels Column */}
|
|
271
|
+
<View className="w-9 justify-between items-end pr-1.5 pb-6" style={{ height: chartHeight + 24 }}>
|
|
272
|
+
{yTicks.map((tick, i) => (
|
|
273
|
+
<Text
|
|
274
|
+
key={i}
|
|
275
|
+
style={{ color: isDark ? '#64748B' : '#94A3B8' }}
|
|
276
|
+
className="text-[9px] font-mono font-medium text-right"
|
|
277
|
+
numberOfLines={1}
|
|
214
278
|
>
|
|
215
|
-
{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
279
|
+
{formatYAxisValue(tick)}
|
|
280
|
+
</Text>
|
|
281
|
+
))}
|
|
282
|
+
</View>
|
|
283
|
+
|
|
284
|
+
{/* 2. Chart Grid & Plot Area */}
|
|
285
|
+
<View className="flex-1 relative">
|
|
286
|
+
{/* Background Horizontal Guide Lines */}
|
|
287
|
+
<View className="absolute inset-0 justify-between pb-6 pointer-events-none" style={{ height: chartHeight + 24 }}>
|
|
288
|
+
{yTicks.map((_, i) => (
|
|
225
289
|
<View
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
290
|
+
key={i}
|
|
291
|
+
style={{
|
|
292
|
+
height: 1,
|
|
293
|
+
backgroundColor: i === yTicks.length - 1
|
|
294
|
+
? (isDark ? '#475569' : '#cbd5e1')
|
|
295
|
+
: (isDark ? '#1e293b' : '#f1f5f9'),
|
|
296
|
+
}}
|
|
297
|
+
className="w-full"
|
|
232
298
|
/>
|
|
299
|
+
))}
|
|
300
|
+
</View>
|
|
301
|
+
|
|
302
|
+
{/* Chart Mode Rendering */}
|
|
303
|
+
{chartType === 'bar' ? (
|
|
304
|
+
isCompact ? (
|
|
305
|
+
/* Balanced Full-Width Grid for 2-4 items */
|
|
306
|
+
<View>
|
|
307
|
+
<View className="flex-row justify-around items-end px-1" style={{ height: chartHeight }}>
|
|
308
|
+
{chartData.map((item, idx) => {
|
|
309
|
+
const barHeight = Math.max(14, Math.round((item.value / maxValue) * (chartHeight - 30)));
|
|
310
|
+
const isTopValue = item.value === maxValue;
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<View
|
|
314
|
+
key={idx}
|
|
315
|
+
className="items-center justify-end flex-1 max-w-[68px] px-1"
|
|
316
|
+
>
|
|
317
|
+
<Text
|
|
318
|
+
style={{
|
|
319
|
+
color: isTopValue ? (isDark ? '#A78BFA' : '#7C3AED') : (isDark ? '#E2E8F0' : '#475569'),
|
|
320
|
+
}}
|
|
321
|
+
className="text-[9px] font-extrabold mb-1 font-mono"
|
|
322
|
+
numberOfLines={1}
|
|
323
|
+
>
|
|
324
|
+
{formatYAxisValue(item.value)}
|
|
325
|
+
</Text>
|
|
233
326
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
327
|
+
<View
|
|
328
|
+
style={{ height: barHeight }}
|
|
329
|
+
className={`w-full rounded-t-xl ${
|
|
330
|
+
isTopValue
|
|
331
|
+
? 'bg-violet-600 dark:bg-violet-500'
|
|
332
|
+
: 'bg-violet-400/80 dark:bg-violet-600/60'
|
|
333
|
+
}`}
|
|
334
|
+
/>
|
|
335
|
+
</View>
|
|
336
|
+
);
|
|
337
|
+
})}
|
|
338
|
+
</View>
|
|
339
|
+
|
|
340
|
+
{/* Continuous X-Axis Baseline */}
|
|
341
|
+
<View className="w-full h-[1.5px] bg-slate-300 dark:bg-slate-700" />
|
|
342
|
+
|
|
343
|
+
{/* Category Labels below Baseline */}
|
|
344
|
+
<View className="flex-row justify-around px-1 pt-1.5">
|
|
345
|
+
{chartData.map((item, idx) => (
|
|
346
|
+
<View key={idx} className="flex-1 max-w-[68px] items-center px-0.5">
|
|
347
|
+
<Text
|
|
348
|
+
style={{ color: isDark ? '#E2E8F0' : '#475569' }}
|
|
349
|
+
className="text-[9px] font-semibold text-center leading-tight"
|
|
350
|
+
numberOfLines={2}
|
|
351
|
+
>
|
|
352
|
+
{item.label}
|
|
353
|
+
</Text>
|
|
354
|
+
</View>
|
|
355
|
+
))}
|
|
356
|
+
</View>
|
|
357
|
+
</View>
|
|
358
|
+
) : (
|
|
359
|
+
/* Horizontal Scroll for > 4 items */
|
|
360
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
361
|
+
<View>
|
|
362
|
+
<View className="flex-row items-end px-1" style={{ height: chartHeight }}>
|
|
363
|
+
{chartData.map((item, idx) => {
|
|
364
|
+
const barHeight = Math.max(14, Math.round((item.value / maxValue) * (chartHeight - 30)));
|
|
365
|
+
const isTopValue = item.value === maxValue;
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<View
|
|
369
|
+
key={idx}
|
|
370
|
+
className="items-center justify-end mr-3"
|
|
371
|
+
style={{ width: 52 }}
|
|
372
|
+
>
|
|
373
|
+
<Text
|
|
374
|
+
style={{
|
|
375
|
+
color: isTopValue ? (isDark ? '#A78BFA' : '#7C3AED') : (isDark ? '#E2E8F0' : '#475569'),
|
|
376
|
+
}}
|
|
377
|
+
className="text-[9px] font-extrabold mb-1 font-mono"
|
|
378
|
+
numberOfLines={1}
|
|
379
|
+
>
|
|
380
|
+
{formatYAxisValue(item.value)}
|
|
381
|
+
</Text>
|
|
382
|
+
|
|
383
|
+
<View
|
|
384
|
+
style={{ height: barHeight }}
|
|
385
|
+
className={`w-full rounded-t-xl ${
|
|
386
|
+
isTopValue
|
|
387
|
+
? 'bg-violet-600 dark:bg-violet-500'
|
|
388
|
+
: 'bg-violet-400/80 dark:bg-violet-600/60'
|
|
389
|
+
}`}
|
|
390
|
+
/>
|
|
391
|
+
</View>
|
|
392
|
+
);
|
|
393
|
+
})}
|
|
394
|
+
</View>
|
|
395
|
+
|
|
396
|
+
{/* Continuous X-Axis Baseline */}
|
|
397
|
+
<View className="w-full h-[1.5px] bg-slate-300 dark:bg-slate-700" />
|
|
398
|
+
|
|
399
|
+
{/* Category Labels below Baseline */}
|
|
400
|
+
<View className="flex-row px-1 pt-1.5">
|
|
401
|
+
{chartData.map((item, idx) => (
|
|
402
|
+
<View key={idx} style={{ width: 52 }} className="mr-3 items-center">
|
|
403
|
+
<Text
|
|
404
|
+
style={{ color: isDark ? '#E2E8F0' : '#475569' }}
|
|
405
|
+
className="text-[9px] font-semibold text-center leading-tight"
|
|
406
|
+
numberOfLines={2}
|
|
407
|
+
>
|
|
408
|
+
{item.label}
|
|
409
|
+
</Text>
|
|
410
|
+
</View>
|
|
411
|
+
))}
|
|
412
|
+
</View>
|
|
413
|
+
</View>
|
|
414
|
+
</ScrollView>
|
|
415
|
+
)
|
|
416
|
+
) : (
|
|
417
|
+
/* LINE / TREND SVG GRAPH MODE */
|
|
418
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
419
|
+
<View style={{ width: svgWidth }}>
|
|
420
|
+
<Svg width={svgWidth} height={chartHeight}>
|
|
421
|
+
<Defs>
|
|
422
|
+
<LinearGradient id="gradientArea" x1="0" y1="0" x2="0" y2="1">
|
|
423
|
+
<Stop offset="0%" stopColor="#7c3aed" stopOpacity="0.35" />
|
|
424
|
+
<Stop offset="100%" stopColor="#7c3aed" stopOpacity="0.0" />
|
|
425
|
+
</LinearGradient>
|
|
426
|
+
</Defs>
|
|
427
|
+
|
|
428
|
+
{/* Continuous X-Axis Baseline */}
|
|
429
|
+
<SvgLine
|
|
430
|
+
x1="0"
|
|
431
|
+
y1={chartHeight - 10}
|
|
432
|
+
x2={svgWidth}
|
|
433
|
+
y2={chartHeight - 10}
|
|
434
|
+
stroke={isDark ? '#475569' : '#cbd5e1'}
|
|
435
|
+
strokeWidth="1.5"
|
|
436
|
+
/>
|
|
437
|
+
|
|
438
|
+
{/* Trend Area Gradient Underfill */}
|
|
439
|
+
{chartType === 'trend' && (
|
|
440
|
+
<Path d={areaPath} fill="url(#gradientArea)" />
|
|
441
|
+
)}
|
|
442
|
+
|
|
443
|
+
{/* Line Path */}
|
|
444
|
+
<Path
|
|
445
|
+
d={linePath}
|
|
446
|
+
fill="none"
|
|
447
|
+
stroke="#7c3aed"
|
|
448
|
+
strokeWidth="2.5"
|
|
449
|
+
strokeLinecap="round"
|
|
450
|
+
strokeLinejoin="round"
|
|
451
|
+
/>
|
|
452
|
+
|
|
453
|
+
{/* Data Points */}
|
|
454
|
+
{svgPoints.map((p, i) => (
|
|
455
|
+
<Circle
|
|
456
|
+
key={i}
|
|
457
|
+
cx={p.x}
|
|
458
|
+
cy={p.y}
|
|
459
|
+
r="4"
|
|
460
|
+
fill={isDark ? '#1C1C1E' : '#FFFFFF'}
|
|
461
|
+
stroke="#7c3aed"
|
|
462
|
+
strokeWidth="2"
|
|
463
|
+
/>
|
|
464
|
+
))}
|
|
465
|
+
</Svg>
|
|
466
|
+
|
|
467
|
+
{/* Data Labels under Points */}
|
|
468
|
+
<View className="flex-row justify-between w-full px-1 pt-1.5">
|
|
469
|
+
{svgPoints.map((p, i) => (
|
|
470
|
+
<View key={i} style={{ width: 56, alignItems: 'center' }}>
|
|
471
|
+
<Text style={{ color: isDark ? '#E2E8F0' : '#475569' }} className="text-[8px] font-semibold text-center" numberOfLines={1}>
|
|
472
|
+
{p.label}
|
|
473
|
+
</Text>
|
|
474
|
+
<Text style={{ color: isDark ? '#FFFFFF' : '#0F172A' }} className="text-[9px] font-mono font-bold mt-0.5">
|
|
475
|
+
{formatYAxisValue(p.value)}
|
|
476
|
+
</Text>
|
|
477
|
+
</View>
|
|
478
|
+
))}
|
|
479
|
+
</View>
|
|
480
|
+
</View>
|
|
481
|
+
</ScrollView>
|
|
482
|
+
)}
|
|
483
|
+
</View>
|
|
484
|
+
</View>
|
|
249
485
|
|
|
250
486
|
{/* Subtitle / Legend Footer */}
|
|
251
|
-
<View className="flex-row items-center justify-between pt-2 mt-2 border-t border-slate-100 dark:border-slate-800">
|
|
487
|
+
<View className="flex-row items-center justify-between pt-2.5 mt-2 border-t border-slate-100 dark:border-slate-800">
|
|
252
488
|
<Text style={{ color: isDark ? '#9CA3AF' : '#94A3B8' }} className="text-[10px] font-medium">
|
|
253
489
|
Peak: <Text style={{ color: isDark ? '#FFFFFF' : '#0F172A' }} className="font-bold">{maxValue.toLocaleString()}</Text>
|
|
254
490
|
</Text>
|
|
255
491
|
<View className="flex-row items-center gap-1">
|
|
256
492
|
<View className="w-2 h-2 rounded-full bg-violet-600" />
|
|
257
493
|
<Text style={{ color: isDark ? '#9CA3AF' : '#94A3B8' }} className="text-[10px] font-semibold">
|
|
258
|
-
{timeframe} Trend
|
|
494
|
+
{chartType === 'bar' ? `${timeframe} Comparison` : chartType === 'line' ? 'Line Trajectory' : 'Trend Area'}
|
|
259
495
|
</Text>
|
|
260
496
|
</View>
|
|
261
497
|
</View>
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
Icon,
|
|
13
13
|
useManagementReportStore,
|
|
14
14
|
} from '@suflon/native-ui';
|
|
15
|
-
import { themeColors } from '
|
|
15
|
+
import { themeColors } from '../../../theme/colors';
|
|
16
16
|
import { TimeframeDropdown, TimeframeOption, getTimeframeDateFilter } from './TimeframeDropdown';
|
|
17
17
|
|
|
18
18
|
interface DetailsListingViewProps {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
useColorScheme,
|
|
11
11
|
} from 'react-native';
|
|
12
12
|
import { Icon } from '@suflon/native-ui';
|
|
13
|
-
import { themeColors } from '
|
|
13
|
+
import { themeColors } from '../../../theme/colors';
|
|
14
14
|
|
|
15
15
|
interface DoctorFilterDropdownProps {
|
|
16
16
|
selectedDoctor: string;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
useColorScheme,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
import { Icon } from '@suflon/native-ui';
|
|
12
|
-
import { themeColors } from '
|
|
12
|
+
import { themeColors } from '../../../theme/colors';
|
|
13
13
|
|
|
14
14
|
export type TimeframeOption = 'Daily' | 'Weekly' | 'Monthly';
|
|
15
15
|
export const TIMEFRAMES: TimeframeOption[] = ['Daily', 'Weekly', 'Monthly'];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useMemo } from 'react';
|
|
2
2
|
import { View, Text, Dimensions, TouchableOpacity, ScrollView, PanResponder } from 'react-native';
|
|
3
3
|
import Svg, { Path, Circle, G, Line as SvgLine, Text as SvgText } from 'react-native-svg';
|
|
4
|
-
import { themeColors } from '
|
|
4
|
+
import { themeColors } from '../../../theme/colors';
|
|
5
5
|
import { Icon } from '@suflon/native-ui';
|
|
6
6
|
|
|
7
7
|
interface ChartData {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
useStaffStore,
|
|
12
12
|
IReportMetadata
|
|
13
13
|
} from '@suflon/native-ui';
|
|
14
|
-
import { themeColors } from '
|
|
14
|
+
import { themeColors } from '../../../theme/colors';
|
|
15
15
|
|
|
16
16
|
const CustomView = View;
|
|
17
17
|
const CustomText = ({ variant, className, style, ...props }: any) => <Text style={style} {...props} />;
|
|
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useMemo, useContext } from 'react';
|
|
|
2
2
|
import { ScrollView, View, Text, TouchableOpacity, SafeAreaView, useColorScheme } from 'react-native';
|
|
3
3
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
4
4
|
import { useReportStore, IReport, Header, SearchFilter, Loader, Icon } from '@suflon/native-ui';
|
|
5
|
-
import { themeColors } from '
|
|
5
|
+
import { themeColors } from '../../../theme/colors';
|
|
6
6
|
import ReportChart from './ReportChart';
|
|
7
7
|
import ReportFilterModal from './ReportFilterModal';
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
|
|
2
2
|
import { ScrollView, TouchableOpacity, View, Text, SafeAreaView, useColorScheme } from 'react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
4
|
import { useReportStore, IReport, Header, SearchFilter, Loader, Icon } from '@suflon/native-ui';
|
|
5
|
-
import { themeColors } from '
|
|
5
|
+
import { themeColors } from '../../theme/colors';
|
|
6
6
|
import { SUB_CLASS_ICON_MAP, SUB_CLASS_LABEL_MAP } from './utils';
|
|
7
7
|
|
|
8
8
|
const Reporting = ({ onBackPress }: { onBackPress?: () => void } = {}) => {
|
package/src/navigation/index.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View, StyleSheet } from 'react-native';
|
|
3
3
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
4
|
-
import Reporting from '
|
|
5
|
-
import ReportingDetail from '
|
|
6
|
-
import ManagementReport from '
|
|
4
|
+
import Reporting from '../modules/Reporting';
|
|
5
|
+
import ReportingDetail from '../modules/Reporting/component/ReportingDetail';
|
|
6
|
+
import ManagementReport from '../modules/ManagementReport';
|
|
7
7
|
|
|
8
8
|
export type AppNavigationProps = {
|
|
9
9
|
onBackPress?: () => void;
|