@dhiraj0720/report1chart 3.0.4 → 3.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
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Modal,
|
|
4
4
|
View,
|
|
@@ -12,6 +12,12 @@ import {
|
|
|
12
12
|
const MonthFilterModal = ({ visible, months, selected, onApply, onClose }) => {
|
|
13
13
|
const [local, setLocal] = useState(selected || []);
|
|
14
14
|
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (visible) {
|
|
17
|
+
setLocal(Array.isArray(selected) ? selected : []);
|
|
18
|
+
}
|
|
19
|
+
}, [visible, selected]);
|
|
20
|
+
|
|
15
21
|
const toggle = (m) => {
|
|
16
22
|
if (local.includes(m)) {
|
|
17
23
|
setLocal(local.filter(x => x !== m));
|
|
@@ -20,7 +26,7 @@ const MonthFilterModal = ({ visible, months, selected, onApply, onClose }) => {
|
|
|
20
26
|
}
|
|
21
27
|
};
|
|
22
28
|
|
|
23
|
-
const selectAll = () => setLocal(months);
|
|
29
|
+
const selectAll = () => setLocal([...(months || [])]);
|
|
24
30
|
const clearAll = () => setLocal([]);
|
|
25
31
|
|
|
26
32
|
return (
|
|
@@ -160,4 +166,4 @@ const styles = StyleSheet.create({
|
|
|
160
166
|
},
|
|
161
167
|
});
|
|
162
168
|
|
|
163
|
-
export default MonthFilterModal;
|
|
169
|
+
export default MonthFilterModal;
|
package/src/index.jsx
CHANGED
|
@@ -4,6 +4,7 @@ import SafeScreen from './components/SafeScreen';
|
|
|
4
4
|
import ReportListScreen from './screens/ReportListScreen';
|
|
5
5
|
import Report1Screen from './screens/Report1Screen';
|
|
6
6
|
import Report2Screen from './screens/Report2Screen';
|
|
7
|
+
import Report2ModernScreen from './screens/Report2ModernScreen';
|
|
7
8
|
import Report3Screen from './screens/Report3Screen';
|
|
8
9
|
import Report1AScreen from './screens/Report1AScreen';
|
|
9
10
|
import Report2AScreen from './screens/Report2AScreen';
|
|
@@ -85,6 +86,18 @@ if (active === '2A') {
|
|
|
85
86
|
);
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
if (active === '2N1') {
|
|
90
|
+
return (
|
|
91
|
+
<SafeScreen>
|
|
92
|
+
<Report2ModernScreen
|
|
93
|
+
api={config.report2}
|
|
94
|
+
token={config.token}
|
|
95
|
+
onBack={() => setActive(null)}
|
|
96
|
+
/>
|
|
97
|
+
</SafeScreen>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
|
|
89
102
|
// 👉 REPORT 2
|
|
90
103
|
if (active === 2) {
|
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ActivityIndicator,
|
|
4
|
+
RefreshControl,
|
|
5
|
+
ScrollView,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
Text,
|
|
8
|
+
TouchableOpacity,
|
|
9
|
+
View,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
import { getDivisions, getTable } from '../api/report2Fetcher';
|
|
12
|
+
import DivisionFilterModal from '../components/DivisionFilterModal';
|
|
13
|
+
import MonthFilterModal from '../components/MonthFilterModal';
|
|
14
|
+
import { formatNumber } from '../utils/formatNumber';
|
|
15
|
+
|
|
16
|
+
const toNumber = (value) => {
|
|
17
|
+
const numeric = Number(value);
|
|
18
|
+
return Number.isFinite(numeric) ? numeric : 0;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const toPercent = (current, previous) => {
|
|
22
|
+
if (!previous) return 0;
|
|
23
|
+
return ((current - previous) / Math.abs(previous)) * 100;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const TrendBadge = ({ value }) => {
|
|
27
|
+
const positive = value >= 0;
|
|
28
|
+
return (
|
|
29
|
+
<View style={[styles.trendBadge, positive ? styles.trendUp : styles.trendDown]}>
|
|
30
|
+
<Text style={[styles.trendText, positive ? styles.trendTextUp : styles.trendTextDown]}>
|
|
31
|
+
{positive ? '+' : '-'} {Math.abs(value).toFixed(1)}%
|
|
32
|
+
</Text>
|
|
33
|
+
</View>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const KpiCard = ({ label, value, hint, tone }) => {
|
|
38
|
+
const toneStyle = tone === 'warm' ? styles.kpiWarm : tone === 'mint' ? styles.kpiMint : styles.kpiCool;
|
|
39
|
+
return (
|
|
40
|
+
<View style={[styles.kpiCard, toneStyle]}>
|
|
41
|
+
<Text style={styles.kpiLabel}>{label}</Text>
|
|
42
|
+
<Text style={styles.kpiValue}>{value}</Text>
|
|
43
|
+
<Text style={styles.kpiHint}>{hint}</Text>
|
|
44
|
+
</View>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const MetricCell = ({ label, value, accent }) => (
|
|
49
|
+
<View style={styles.metricCell}>
|
|
50
|
+
<Text style={styles.metricLabel}>{label}</Text>
|
|
51
|
+
<Text style={[styles.metricValue, accent && styles.metricValueAccent]}>{value}</Text>
|
|
52
|
+
</View>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const ModernBars = ({ rows, metric }) => {
|
|
56
|
+
const key2024 = metric === 'profit' ? 'profitUsd2024' : 'teu2024';
|
|
57
|
+
const key2025 = metric === 'profit' ? 'profitUsd2025' : 'teu2025';
|
|
58
|
+
const maxValue = Math.max(
|
|
59
|
+
1,
|
|
60
|
+
...rows.map((row) => Math.max(toNumber(row[key2024]), toNumber(row[key2025]))),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<View style={styles.chartCard}>
|
|
65
|
+
<View style={styles.chartHeader}>
|
|
66
|
+
<Text style={styles.chartTitle}>
|
|
67
|
+
{metric === 'profit' ? 'Profit Trend by Month' : 'TEU Trend by Month'}
|
|
68
|
+
</Text>
|
|
69
|
+
<View style={styles.legendRow}>
|
|
70
|
+
<Text style={styles.legendTextOrange}>2024</Text>
|
|
71
|
+
<Text style={styles.legendTextBlue}>2025</Text>
|
|
72
|
+
</View>
|
|
73
|
+
</View>
|
|
74
|
+
|
|
75
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
76
|
+
<View style={styles.chartColumns}>
|
|
77
|
+
{rows.map((row) => {
|
|
78
|
+
const value2024 = toNumber(row[key2024]);
|
|
79
|
+
const value2025 = toNumber(row[key2025]);
|
|
80
|
+
const pct = toPercent(value2025, value2024);
|
|
81
|
+
const bar2024Height = Math.max(6, (value2024 / maxValue) * 122);
|
|
82
|
+
const bar2025Height = Math.max(6, (value2025 / maxValue) * 122);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<View key={row.monthLabel} style={styles.chartGroup}>
|
|
86
|
+
<View style={styles.barPair}>
|
|
87
|
+
<View style={styles.barTrack}>
|
|
88
|
+
<View style={[styles.barFill2024, { height: bar2024Height }]} />
|
|
89
|
+
</View>
|
|
90
|
+
<View style={styles.barTrack}>
|
|
91
|
+
<View style={[styles.barFill2025, { height: bar2025Height }]} />
|
|
92
|
+
</View>
|
|
93
|
+
</View>
|
|
94
|
+
<Text style={styles.chartMonthText}>{row.monthLabel.slice(0, 3)}</Text>
|
|
95
|
+
<Text style={[styles.chartDelta, pct >= 0 ? styles.deltaUp : styles.deltaDown]}>
|
|
96
|
+
{pct >= 0 ? '+' : ''}
|
|
97
|
+
{pct.toFixed(0)}%
|
|
98
|
+
</Text>
|
|
99
|
+
</View>
|
|
100
|
+
);
|
|
101
|
+
})}
|
|
102
|
+
</View>
|
|
103
|
+
</ScrollView>
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const Report2ModernScreen = ({ api, token, onBack }) => {
|
|
109
|
+
const [divisionModal, setDivisionModal] = useState(false);
|
|
110
|
+
const [monthsModal, setMonthsModal] = useState(false);
|
|
111
|
+
const [divisions, setDivisions] = useState([]);
|
|
112
|
+
const [division, setDivision] = useState(null);
|
|
113
|
+
const [table, setTable] = useState(null);
|
|
114
|
+
const [loading, setLoading] = useState(true);
|
|
115
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
116
|
+
const [selectedMonths, setSelectedMonths] = useState([]);
|
|
117
|
+
const [focusMonth, setFocusMonth] = useState('ALL');
|
|
118
|
+
const [metric, setMetric] = useState('profit');
|
|
119
|
+
|
|
120
|
+
const loadDivisions = useCallback(async () => {
|
|
121
|
+
const data = await getDivisions(api.divisions, token);
|
|
122
|
+
setDivisions(data);
|
|
123
|
+
setDivision((prev) => prev || data[0]?.code || prev);
|
|
124
|
+
}, [api.divisions, token]);
|
|
125
|
+
|
|
126
|
+
const loadTable = useCallback(async (divisionCode) => {
|
|
127
|
+
const reportTable = await getTable(api.table, divisionCode, token);
|
|
128
|
+
setTable(reportTable);
|
|
129
|
+
const monthLabels = (reportTable?.rows || [])
|
|
130
|
+
.filter((row) => row.monthLabel && row.monthLabel !== 'Total')
|
|
131
|
+
.map((row) => row.monthLabel);
|
|
132
|
+
setSelectedMonths(monthLabels);
|
|
133
|
+
setFocusMonth('ALL');
|
|
134
|
+
}, [api.table, token]);
|
|
135
|
+
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
setLoading(true);
|
|
138
|
+
loadDivisions()
|
|
139
|
+
.catch(() => {})
|
|
140
|
+
.finally(() => setLoading(false));
|
|
141
|
+
}, [loadDivisions]);
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
if (!division) return;
|
|
145
|
+
setLoading(true);
|
|
146
|
+
loadTable(division)
|
|
147
|
+
.catch(() => {})
|
|
148
|
+
.finally(() => setLoading(false));
|
|
149
|
+
}, [division, loadTable]);
|
|
150
|
+
|
|
151
|
+
const onRefresh = useCallback(async () => {
|
|
152
|
+
if (!division) return;
|
|
153
|
+
setRefreshing(true);
|
|
154
|
+
try {
|
|
155
|
+
await loadTable(division);
|
|
156
|
+
} finally {
|
|
157
|
+
setRefreshing(false);
|
|
158
|
+
}
|
|
159
|
+
}, [division, loadTable]);
|
|
160
|
+
|
|
161
|
+
const divisionName = useMemo(() => {
|
|
162
|
+
return divisions.find((item) => item.code === division)?.displayName || 'Division';
|
|
163
|
+
}, [division, divisions]);
|
|
164
|
+
|
|
165
|
+
const baseRows = useMemo(() => {
|
|
166
|
+
return (table?.rows || []).filter((row) => row.monthLabel && row.monthLabel !== 'Total');
|
|
167
|
+
}, [table]);
|
|
168
|
+
|
|
169
|
+
const rows = useMemo(() => {
|
|
170
|
+
let filtered = baseRows;
|
|
171
|
+
if (selectedMonths.length > 0) {
|
|
172
|
+
filtered = filtered.filter((row) => selectedMonths.includes(row.monthLabel));
|
|
173
|
+
}
|
|
174
|
+
if (focusMonth !== 'ALL') {
|
|
175
|
+
filtered = filtered.filter((row) => row.monthLabel === focusMonth);
|
|
176
|
+
}
|
|
177
|
+
return filtered;
|
|
178
|
+
}, [baseRows, focusMonth, selectedMonths]);
|
|
179
|
+
|
|
180
|
+
const total2024Profit = useMemo(() => rows.reduce((sum, row) => sum + toNumber(row.profitUsd2024), 0), [rows]);
|
|
181
|
+
const total2025Profit = useMemo(() => rows.reduce((sum, row) => sum + toNumber(row.profitUsd2025), 0), [rows]);
|
|
182
|
+
const total2025Budget = useMemo(() => rows.reduce((sum, row) => sum + toNumber(row.budgetProfitUsd2025), 0), [rows]);
|
|
183
|
+
const budgetRate = total2025Budget ? (total2025Profit / total2025Budget) * 100 : 0;
|
|
184
|
+
const yoyPercent = toPercent(total2025Profit, total2024Profit);
|
|
185
|
+
|
|
186
|
+
const bestMonth = useMemo(() => {
|
|
187
|
+
if (!rows.length) return null;
|
|
188
|
+
return rows.reduce((best, row) => {
|
|
189
|
+
if (!best) return row;
|
|
190
|
+
const bestPct = toNumber(best.profitChangePercent);
|
|
191
|
+
const currentPct = toNumber(row.profitChangePercent);
|
|
192
|
+
return currentPct > bestPct ? row : best;
|
|
193
|
+
}, null);
|
|
194
|
+
}, [rows]);
|
|
195
|
+
|
|
196
|
+
const quickMonths = useMemo(() => ['ALL', ...selectedMonths.slice(0, 5)], [selectedMonths]);
|
|
197
|
+
|
|
198
|
+
if (loading && !table) {
|
|
199
|
+
return (
|
|
200
|
+
<View style={styles.loaderWrap}>
|
|
201
|
+
<ActivityIndicator size="large" color="#144a8a" />
|
|
202
|
+
</View>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<View style={styles.screen}>
|
|
208
|
+
<View style={styles.hero}>
|
|
209
|
+
<View style={styles.heroDotLarge} />
|
|
210
|
+
<View style={styles.heroDotSmall} />
|
|
211
|
+
<TouchableOpacity onPress={onBack} style={styles.backButton}>
|
|
212
|
+
<Text style={styles.backIcon}>‹</Text>
|
|
213
|
+
</TouchableOpacity>
|
|
214
|
+
<Text style={styles.heroTitle}>Gross Profit Dashboard</Text>
|
|
215
|
+
<Text style={styles.heroSubtitle}>Modern view - interactive monthly insights</Text>
|
|
216
|
+
</View>
|
|
217
|
+
|
|
218
|
+
<ScrollView
|
|
219
|
+
style={styles.content}
|
|
220
|
+
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
|
221
|
+
showsVerticalScrollIndicator={false}
|
|
222
|
+
>
|
|
223
|
+
<View style={styles.filterRow}>
|
|
224
|
+
<TouchableOpacity
|
|
225
|
+
style={[styles.filterChip, styles.filterChipSpacing]}
|
|
226
|
+
onPress={() => setDivisionModal(true)}
|
|
227
|
+
activeOpacity={0.9}
|
|
228
|
+
>
|
|
229
|
+
<Text style={styles.filterChipLabel}>Division</Text>
|
|
230
|
+
<Text style={styles.filterChipValue}>{divisionName}</Text>
|
|
231
|
+
</TouchableOpacity>
|
|
232
|
+
<TouchableOpacity
|
|
233
|
+
style={styles.filterChip}
|
|
234
|
+
onPress={() => setMonthsModal(true)}
|
|
235
|
+
activeOpacity={0.9}
|
|
236
|
+
>
|
|
237
|
+
<Text style={styles.filterChipLabel}>Months</Text>
|
|
238
|
+
<Text style={styles.filterChipValue}>
|
|
239
|
+
{selectedMonths.length}/{baseRows.length || selectedMonths.length}
|
|
240
|
+
</Text>
|
|
241
|
+
</TouchableOpacity>
|
|
242
|
+
</View>
|
|
243
|
+
|
|
244
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.kpiScroll}>
|
|
245
|
+
<KpiCard
|
|
246
|
+
label="2024 Profit"
|
|
247
|
+
value={formatNumber(total2024Profit)}
|
|
248
|
+
hint="Baseline"
|
|
249
|
+
tone="warm"
|
|
250
|
+
/>
|
|
251
|
+
<KpiCard
|
|
252
|
+
label="2025 Profit"
|
|
253
|
+
value={formatNumber(total2025Profit)}
|
|
254
|
+
hint="Current"
|
|
255
|
+
tone="cool"
|
|
256
|
+
/>
|
|
257
|
+
<KpiCard
|
|
258
|
+
label="Budget Coverage"
|
|
259
|
+
value={`${budgetRate.toFixed(1)}%`}
|
|
260
|
+
hint="2025 vs Budget"
|
|
261
|
+
tone="mint"
|
|
262
|
+
/>
|
|
263
|
+
</ScrollView>
|
|
264
|
+
|
|
265
|
+
<View style={styles.insightStrip}>
|
|
266
|
+
<View>
|
|
267
|
+
<Text style={styles.insightTitle}>YoY Profit Change</Text>
|
|
268
|
+
<TrendBadge value={yoyPercent} />
|
|
269
|
+
</View>
|
|
270
|
+
<View>
|
|
271
|
+
<Text style={styles.insightTitle}>Best Month</Text>
|
|
272
|
+
<Text style={styles.insightValue}>{bestMonth?.monthLabel || '-'}</Text>
|
|
273
|
+
</View>
|
|
274
|
+
</View>
|
|
275
|
+
|
|
276
|
+
<View style={styles.metricSwitch}>
|
|
277
|
+
<TouchableOpacity
|
|
278
|
+
style={[styles.metricButton, metric === 'profit' && styles.metricButtonActive]}
|
|
279
|
+
onPress={() => setMetric('profit')}
|
|
280
|
+
>
|
|
281
|
+
<Text style={[styles.metricButtonText, metric === 'profit' && styles.metricButtonTextActive]}>
|
|
282
|
+
Profit
|
|
283
|
+
</Text>
|
|
284
|
+
</TouchableOpacity>
|
|
285
|
+
<TouchableOpacity
|
|
286
|
+
style={[styles.metricButton, metric === 'teu' && styles.metricButtonActive]}
|
|
287
|
+
onPress={() => setMetric('teu')}
|
|
288
|
+
>
|
|
289
|
+
<Text style={[styles.metricButtonText, metric === 'teu' && styles.metricButtonTextActive]}>
|
|
290
|
+
TEU
|
|
291
|
+
</Text>
|
|
292
|
+
</TouchableOpacity>
|
|
293
|
+
</View>
|
|
294
|
+
|
|
295
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.monthQuickScroll}>
|
|
296
|
+
{quickMonths.map((month) => (
|
|
297
|
+
<TouchableOpacity
|
|
298
|
+
key={month}
|
|
299
|
+
style={[styles.monthChip, focusMonth === month && styles.monthChipActive]}
|
|
300
|
+
onPress={() => setFocusMonth(month)}
|
|
301
|
+
>
|
|
302
|
+
<Text style={[styles.monthChipText, focusMonth === month && styles.monthChipTextActive]}>
|
|
303
|
+
{month}
|
|
304
|
+
</Text>
|
|
305
|
+
</TouchableOpacity>
|
|
306
|
+
))}
|
|
307
|
+
</ScrollView>
|
|
308
|
+
|
|
309
|
+
<ModernBars rows={rows} metric={metric} />
|
|
310
|
+
|
|
311
|
+
<Text style={styles.sectionTitle}>Monthly insight cards</Text>
|
|
312
|
+
{rows.map((row) => (
|
|
313
|
+
<View key={row.monthLabel} style={styles.monthCard}>
|
|
314
|
+
<View style={styles.monthCardHeader}>
|
|
315
|
+
<Text style={styles.monthCardTitle}>{row.monthLabel}</Text>
|
|
316
|
+
<TrendBadge value={toNumber(row.profitChangePercent)} />
|
|
317
|
+
</View>
|
|
318
|
+
|
|
319
|
+
<View style={styles.metricGrid}>
|
|
320
|
+
<MetricCell label="2024 Profit" value={formatNumber(row.profitUsd2024)} />
|
|
321
|
+
<MetricCell label="2025 Profit" value={formatNumber(row.profitUsd2025)} />
|
|
322
|
+
<MetricCell label="2025 Budget" value={formatNumber(row.budgetProfitUsd2025)} />
|
|
323
|
+
<MetricCell
|
|
324
|
+
label="Budget Delta"
|
|
325
|
+
value={`${toNumber(row.budgetChangePercent).toFixed(1)}%`}
|
|
326
|
+
accent
|
|
327
|
+
/>
|
|
328
|
+
</View>
|
|
329
|
+
|
|
330
|
+
<View style={styles.progressTrack}>
|
|
331
|
+
<View
|
|
332
|
+
style={[
|
|
333
|
+
styles.progressFill,
|
|
334
|
+
{
|
|
335
|
+
width: `${Math.min(
|
|
336
|
+
100,
|
|
337
|
+
Math.max(
|
|
338
|
+
0,
|
|
339
|
+
(toNumber(row.profitUsd2025) / Math.max(1, toNumber(row.budgetProfitUsd2025))) * 100,
|
|
340
|
+
),
|
|
341
|
+
)}%`,
|
|
342
|
+
},
|
|
343
|
+
]}
|
|
344
|
+
/>
|
|
345
|
+
</View>
|
|
346
|
+
</View>
|
|
347
|
+
))}
|
|
348
|
+
|
|
349
|
+
{!rows.length ? (
|
|
350
|
+
<View style={styles.emptyWrap}>
|
|
351
|
+
<Text style={styles.emptyText}>No months selected. Please update month filters.</Text>
|
|
352
|
+
</View>
|
|
353
|
+
) : null}
|
|
354
|
+
</ScrollView>
|
|
355
|
+
|
|
356
|
+
<DivisionFilterModal
|
|
357
|
+
visible={divisionModal}
|
|
358
|
+
divisions={divisions}
|
|
359
|
+
selected={division}
|
|
360
|
+
onSelect={setDivision}
|
|
361
|
+
onClose={() => setDivisionModal(false)}
|
|
362
|
+
/>
|
|
363
|
+
|
|
364
|
+
<MonthFilterModal
|
|
365
|
+
visible={monthsModal}
|
|
366
|
+
months={baseRows.map((row) => row.monthLabel)}
|
|
367
|
+
selected={selectedMonths}
|
|
368
|
+
onApply={setSelectedMonths}
|
|
369
|
+
onClose={() => setMonthsModal(false)}
|
|
370
|
+
/>
|
|
371
|
+
</View>
|
|
372
|
+
);
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const styles = StyleSheet.create({
|
|
376
|
+
screen: {
|
|
377
|
+
flex: 1,
|
|
378
|
+
backgroundColor: '#f1f5fb',
|
|
379
|
+
},
|
|
380
|
+
loaderWrap: {
|
|
381
|
+
flex: 1,
|
|
382
|
+
justifyContent: 'center',
|
|
383
|
+
alignItems: 'center',
|
|
384
|
+
backgroundColor: '#f1f5fb',
|
|
385
|
+
},
|
|
386
|
+
hero: {
|
|
387
|
+
backgroundColor: '#0d3d77',
|
|
388
|
+
paddingHorizontal: 16,
|
|
389
|
+
paddingTop: 14,
|
|
390
|
+
paddingBottom: 16,
|
|
391
|
+
overflow: 'hidden',
|
|
392
|
+
},
|
|
393
|
+
heroDotLarge: {
|
|
394
|
+
position: 'absolute',
|
|
395
|
+
width: 180,
|
|
396
|
+
height: 180,
|
|
397
|
+
borderRadius: 90,
|
|
398
|
+
right: -64,
|
|
399
|
+
top: -90,
|
|
400
|
+
backgroundColor: '#1f65ae',
|
|
401
|
+
},
|
|
402
|
+
heroDotSmall: {
|
|
403
|
+
position: 'absolute',
|
|
404
|
+
width: 120,
|
|
405
|
+
height: 120,
|
|
406
|
+
borderRadius: 60,
|
|
407
|
+
left: -40,
|
|
408
|
+
bottom: -70,
|
|
409
|
+
backgroundColor: '#2d7ac8',
|
|
410
|
+
},
|
|
411
|
+
backButton: {
|
|
412
|
+
width: 42,
|
|
413
|
+
height: 42,
|
|
414
|
+
borderRadius: 21,
|
|
415
|
+
backgroundColor: 'rgba(255,255,255,0.18)',
|
|
416
|
+
justifyContent: 'center',
|
|
417
|
+
alignItems: 'center',
|
|
418
|
+
},
|
|
419
|
+
backIcon: {
|
|
420
|
+
fontSize: 28,
|
|
421
|
+
color: '#fff',
|
|
422
|
+
fontWeight: '700',
|
|
423
|
+
marginTop: -2,
|
|
424
|
+
},
|
|
425
|
+
heroTitle: {
|
|
426
|
+
marginTop: 10,
|
|
427
|
+
fontSize: 22,
|
|
428
|
+
fontWeight: '800',
|
|
429
|
+
color: '#fff',
|
|
430
|
+
},
|
|
431
|
+
heroSubtitle: {
|
|
432
|
+
marginTop: 6,
|
|
433
|
+
fontSize: 13,
|
|
434
|
+
color: '#cfe5ff',
|
|
435
|
+
fontWeight: '500',
|
|
436
|
+
},
|
|
437
|
+
content: {
|
|
438
|
+
flex: 1,
|
|
439
|
+
paddingHorizontal: 14,
|
|
440
|
+
paddingTop: 14,
|
|
441
|
+
},
|
|
442
|
+
filterRow: {
|
|
443
|
+
flexDirection: 'row',
|
|
444
|
+
marginBottom: 12,
|
|
445
|
+
},
|
|
446
|
+
filterChip: {
|
|
447
|
+
flex: 1,
|
|
448
|
+
backgroundColor: '#fff',
|
|
449
|
+
borderRadius: 14,
|
|
450
|
+
paddingVertical: 10,
|
|
451
|
+
paddingHorizontal: 12,
|
|
452
|
+
borderWidth: 1,
|
|
453
|
+
borderColor: '#d2deee',
|
|
454
|
+
},
|
|
455
|
+
filterChipSpacing: {
|
|
456
|
+
marginRight: 10,
|
|
457
|
+
},
|
|
458
|
+
filterChipLabel: {
|
|
459
|
+
fontSize: 11,
|
|
460
|
+
color: '#5e6878',
|
|
461
|
+
marginBottom: 3,
|
|
462
|
+
},
|
|
463
|
+
filterChipValue: {
|
|
464
|
+
fontSize: 14,
|
|
465
|
+
color: '#14253d',
|
|
466
|
+
fontWeight: '700',
|
|
467
|
+
},
|
|
468
|
+
kpiScroll: {
|
|
469
|
+
marginBottom: 12,
|
|
470
|
+
},
|
|
471
|
+
kpiCard: {
|
|
472
|
+
width: 165,
|
|
473
|
+
borderRadius: 16,
|
|
474
|
+
paddingHorizontal: 12,
|
|
475
|
+
paddingVertical: 12,
|
|
476
|
+
marginRight: 10,
|
|
477
|
+
borderWidth: 1,
|
|
478
|
+
},
|
|
479
|
+
kpiCool: {
|
|
480
|
+
backgroundColor: '#eaf2ff',
|
|
481
|
+
borderColor: '#94baff',
|
|
482
|
+
},
|
|
483
|
+
kpiWarm: {
|
|
484
|
+
backgroundColor: '#fff1e7',
|
|
485
|
+
borderColor: '#ffc89f',
|
|
486
|
+
},
|
|
487
|
+
kpiMint: {
|
|
488
|
+
backgroundColor: '#ebfff8',
|
|
489
|
+
borderColor: '#9fe8ca',
|
|
490
|
+
},
|
|
491
|
+
kpiLabel: {
|
|
492
|
+
fontSize: 12,
|
|
493
|
+
color: '#30425a',
|
|
494
|
+
marginBottom: 8,
|
|
495
|
+
},
|
|
496
|
+
kpiValue: {
|
|
497
|
+
fontSize: 18,
|
|
498
|
+
fontWeight: '800',
|
|
499
|
+
color: '#11253f',
|
|
500
|
+
},
|
|
501
|
+
kpiHint: {
|
|
502
|
+
marginTop: 6,
|
|
503
|
+
fontSize: 11,
|
|
504
|
+
color: '#57667b',
|
|
505
|
+
},
|
|
506
|
+
insightStrip: {
|
|
507
|
+
backgroundColor: '#fff',
|
|
508
|
+
borderRadius: 14,
|
|
509
|
+
borderWidth: 1,
|
|
510
|
+
borderColor: '#d2deee',
|
|
511
|
+
paddingVertical: 12,
|
|
512
|
+
paddingHorizontal: 12,
|
|
513
|
+
flexDirection: 'row',
|
|
514
|
+
justifyContent: 'space-between',
|
|
515
|
+
marginBottom: 12,
|
|
516
|
+
},
|
|
517
|
+
insightTitle: {
|
|
518
|
+
fontSize: 11,
|
|
519
|
+
color: '#65748a',
|
|
520
|
+
marginBottom: 6,
|
|
521
|
+
},
|
|
522
|
+
insightValue: {
|
|
523
|
+
fontSize: 14,
|
|
524
|
+
fontWeight: '700',
|
|
525
|
+
color: '#152842',
|
|
526
|
+
},
|
|
527
|
+
trendBadge: {
|
|
528
|
+
borderRadius: 999,
|
|
529
|
+
paddingVertical: 4,
|
|
530
|
+
paddingHorizontal: 8,
|
|
531
|
+
alignSelf: 'flex-start',
|
|
532
|
+
},
|
|
533
|
+
trendUp: {
|
|
534
|
+
backgroundColor: '#e4f8ef',
|
|
535
|
+
},
|
|
536
|
+
trendDown: {
|
|
537
|
+
backgroundColor: '#ffe9ea',
|
|
538
|
+
},
|
|
539
|
+
trendText: {
|
|
540
|
+
fontSize: 12,
|
|
541
|
+
fontWeight: '700',
|
|
542
|
+
},
|
|
543
|
+
trendTextUp: {
|
|
544
|
+
color: '#1f8b58',
|
|
545
|
+
},
|
|
546
|
+
trendTextDown: {
|
|
547
|
+
color: '#c0393f',
|
|
548
|
+
},
|
|
549
|
+
metricSwitch: {
|
|
550
|
+
flexDirection: 'row',
|
|
551
|
+
borderRadius: 12,
|
|
552
|
+
borderWidth: 1,
|
|
553
|
+
borderColor: '#d2deee',
|
|
554
|
+
backgroundColor: '#fff',
|
|
555
|
+
padding: 4,
|
|
556
|
+
marginBottom: 10,
|
|
557
|
+
},
|
|
558
|
+
metricButton: {
|
|
559
|
+
flex: 1,
|
|
560
|
+
paddingVertical: 10,
|
|
561
|
+
borderRadius: 10,
|
|
562
|
+
alignItems: 'center',
|
|
563
|
+
},
|
|
564
|
+
metricButtonActive: {
|
|
565
|
+
backgroundColor: '#174b8f',
|
|
566
|
+
},
|
|
567
|
+
metricButtonText: {
|
|
568
|
+
fontSize: 13,
|
|
569
|
+
fontWeight: '700',
|
|
570
|
+
color: '#3a4a62',
|
|
571
|
+
},
|
|
572
|
+
metricButtonTextActive: {
|
|
573
|
+
color: '#fff',
|
|
574
|
+
},
|
|
575
|
+
monthQuickScroll: {
|
|
576
|
+
marginBottom: 10,
|
|
577
|
+
},
|
|
578
|
+
monthChip: {
|
|
579
|
+
backgroundColor: '#fff',
|
|
580
|
+
borderRadius: 999,
|
|
581
|
+
borderWidth: 1,
|
|
582
|
+
borderColor: '#d5dfed',
|
|
583
|
+
paddingVertical: 7,
|
|
584
|
+
paddingHorizontal: 12,
|
|
585
|
+
marginRight: 8,
|
|
586
|
+
},
|
|
587
|
+
monthChipActive: {
|
|
588
|
+
backgroundColor: '#133f79',
|
|
589
|
+
borderColor: '#133f79',
|
|
590
|
+
},
|
|
591
|
+
monthChipText: {
|
|
592
|
+
fontSize: 12,
|
|
593
|
+
fontWeight: '700',
|
|
594
|
+
color: '#3f4f64',
|
|
595
|
+
},
|
|
596
|
+
monthChipTextActive: {
|
|
597
|
+
color: '#fff',
|
|
598
|
+
},
|
|
599
|
+
chartCard: {
|
|
600
|
+
backgroundColor: '#fff',
|
|
601
|
+
borderRadius: 14,
|
|
602
|
+
borderWidth: 1,
|
|
603
|
+
borderColor: '#d2deee',
|
|
604
|
+
padding: 12,
|
|
605
|
+
marginBottom: 14,
|
|
606
|
+
},
|
|
607
|
+
chartHeader: {
|
|
608
|
+
flexDirection: 'row',
|
|
609
|
+
justifyContent: 'space-between',
|
|
610
|
+
alignItems: 'center',
|
|
611
|
+
marginBottom: 8,
|
|
612
|
+
},
|
|
613
|
+
chartTitle: {
|
|
614
|
+
fontSize: 14,
|
|
615
|
+
fontWeight: '800',
|
|
616
|
+
color: '#142a45',
|
|
617
|
+
},
|
|
618
|
+
legendRow: {
|
|
619
|
+
flexDirection: 'row',
|
|
620
|
+
},
|
|
621
|
+
legendTextOrange: {
|
|
622
|
+
marginRight: 12,
|
|
623
|
+
color: '#e57d2f',
|
|
624
|
+
fontSize: 12,
|
|
625
|
+
fontWeight: '700',
|
|
626
|
+
},
|
|
627
|
+
legendTextBlue: {
|
|
628
|
+
color: '#2e74c4',
|
|
629
|
+
fontSize: 12,
|
|
630
|
+
fontWeight: '700',
|
|
631
|
+
},
|
|
632
|
+
chartColumns: {
|
|
633
|
+
flexDirection: 'row',
|
|
634
|
+
paddingTop: 8,
|
|
635
|
+
},
|
|
636
|
+
chartGroup: {
|
|
637
|
+
alignItems: 'center',
|
|
638
|
+
width: 46,
|
|
639
|
+
marginRight: 8,
|
|
640
|
+
},
|
|
641
|
+
barPair: {
|
|
642
|
+
flexDirection: 'row',
|
|
643
|
+
alignItems: 'flex-end',
|
|
644
|
+
marginBottom: 7,
|
|
645
|
+
},
|
|
646
|
+
barTrack: {
|
|
647
|
+
width: 12,
|
|
648
|
+
height: 126,
|
|
649
|
+
borderRadius: 10,
|
|
650
|
+
justifyContent: 'flex-end',
|
|
651
|
+
backgroundColor: '#eef3fa',
|
|
652
|
+
marginHorizontal: 2,
|
|
653
|
+
overflow: 'hidden',
|
|
654
|
+
},
|
|
655
|
+
barFill2024: {
|
|
656
|
+
backgroundColor: '#f19a54',
|
|
657
|
+
borderRadius: 10,
|
|
658
|
+
},
|
|
659
|
+
barFill2025: {
|
|
660
|
+
backgroundColor: '#2f7cca',
|
|
661
|
+
borderRadius: 10,
|
|
662
|
+
},
|
|
663
|
+
chartMonthText: {
|
|
664
|
+
fontSize: 10,
|
|
665
|
+
color: '#4f6078',
|
|
666
|
+
fontWeight: '700',
|
|
667
|
+
},
|
|
668
|
+
chartDelta: {
|
|
669
|
+
marginTop: 3,
|
|
670
|
+
fontSize: 10,
|
|
671
|
+
fontWeight: '700',
|
|
672
|
+
},
|
|
673
|
+
deltaUp: {
|
|
674
|
+
color: '#229060',
|
|
675
|
+
},
|
|
676
|
+
deltaDown: {
|
|
677
|
+
color: '#cb4346',
|
|
678
|
+
},
|
|
679
|
+
sectionTitle: {
|
|
680
|
+
fontSize: 15,
|
|
681
|
+
fontWeight: '800',
|
|
682
|
+
color: '#152a43',
|
|
683
|
+
marginBottom: 8,
|
|
684
|
+
},
|
|
685
|
+
monthCard: {
|
|
686
|
+
backgroundColor: '#fff',
|
|
687
|
+
borderRadius: 14,
|
|
688
|
+
borderWidth: 1,
|
|
689
|
+
borderColor: '#d2deee',
|
|
690
|
+
padding: 12,
|
|
691
|
+
marginBottom: 10,
|
|
692
|
+
},
|
|
693
|
+
monthCardHeader: {
|
|
694
|
+
flexDirection: 'row',
|
|
695
|
+
justifyContent: 'space-between',
|
|
696
|
+
alignItems: 'center',
|
|
697
|
+
marginBottom: 10,
|
|
698
|
+
},
|
|
699
|
+
monthCardTitle: {
|
|
700
|
+
fontSize: 15,
|
|
701
|
+
fontWeight: '800',
|
|
702
|
+
color: '#132844',
|
|
703
|
+
},
|
|
704
|
+
metricGrid: {
|
|
705
|
+
flexDirection: 'row',
|
|
706
|
+
flexWrap: 'wrap',
|
|
707
|
+
marginHorizontal: -4,
|
|
708
|
+
},
|
|
709
|
+
metricCell: {
|
|
710
|
+
width: '50%',
|
|
711
|
+
paddingHorizontal: 4,
|
|
712
|
+
marginBottom: 10,
|
|
713
|
+
},
|
|
714
|
+
metricLabel: {
|
|
715
|
+
fontSize: 11,
|
|
716
|
+
color: '#62738a',
|
|
717
|
+
marginBottom: 3,
|
|
718
|
+
},
|
|
719
|
+
metricValue: {
|
|
720
|
+
fontSize: 13,
|
|
721
|
+
color: '#12263f',
|
|
722
|
+
fontWeight: '700',
|
|
723
|
+
},
|
|
724
|
+
metricValueAccent: {
|
|
725
|
+
color: '#0f5ba5',
|
|
726
|
+
},
|
|
727
|
+
progressTrack: {
|
|
728
|
+
height: 8,
|
|
729
|
+
borderRadius: 999,
|
|
730
|
+
backgroundColor: '#ecf2fa',
|
|
731
|
+
overflow: 'hidden',
|
|
732
|
+
},
|
|
733
|
+
progressFill: {
|
|
734
|
+
height: '100%',
|
|
735
|
+
backgroundColor: '#3f8fe0',
|
|
736
|
+
},
|
|
737
|
+
emptyWrap: {
|
|
738
|
+
paddingVertical: 18,
|
|
739
|
+
alignItems: 'center',
|
|
740
|
+
},
|
|
741
|
+
emptyText: {
|
|
742
|
+
color: '#63748a',
|
|
743
|
+
fontSize: 13,
|
|
744
|
+
},
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
export default Report2ModernScreen;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -7,53 +7,61 @@ import {
|
|
|
7
7
|
ScrollView,
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const OLD_REPORTS = [
|
|
12
11
|
{
|
|
13
12
|
id: '4A',
|
|
14
13
|
title: 'Performans Raporu (USD) - NEW',
|
|
15
|
-
desc: '
|
|
14
|
+
desc: 'Current package flow',
|
|
16
15
|
},
|
|
17
|
-
|
|
18
16
|
{
|
|
19
17
|
id: '2A',
|
|
20
18
|
title: 'Gross Profit by Company & Division',
|
|
21
|
-
desc: '
|
|
19
|
+
desc: 'Current option 1',
|
|
22
20
|
},
|
|
23
21
|
{
|
|
24
22
|
id: 2,
|
|
25
23
|
title: 'Gross Profit by Company & Division',
|
|
26
|
-
desc: '
|
|
24
|
+
desc: 'Current option 2',
|
|
27
25
|
},
|
|
28
|
-
|
|
29
26
|
{
|
|
30
27
|
id: '3A',
|
|
31
28
|
title: 'Transportation Business Analysis',
|
|
32
|
-
desc: '
|
|
29
|
+
desc: 'Current option 1',
|
|
33
30
|
},
|
|
34
31
|
{
|
|
35
32
|
id: 3,
|
|
36
33
|
title: 'Transportation Business Analysis',
|
|
37
|
-
desc: '
|
|
34
|
+
desc: 'Current option 2',
|
|
38
35
|
},
|
|
39
|
-
|
|
40
36
|
{
|
|
41
37
|
id: '1A',
|
|
42
38
|
title: 'Performans Raporu (USD) - OLD',
|
|
43
|
-
desc: '
|
|
39
|
+
desc: 'Current option 1',
|
|
44
40
|
},
|
|
45
41
|
{
|
|
46
42
|
id: 1,
|
|
47
43
|
title: 'Performans Raporu (USD) - OLD',
|
|
48
|
-
desc: '
|
|
44
|
+
desc: 'Current option 2',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const NEW_REPORTS = [
|
|
49
|
+
{
|
|
50
|
+
id: '2N1',
|
|
51
|
+
title: 'Gross Profit by Company & Division',
|
|
52
|
+
desc: 'Modern interactive layout',
|
|
49
53
|
},
|
|
50
|
-
|
|
51
54
|
];
|
|
52
55
|
|
|
53
56
|
const ReportListScreen = ({ onSelect, onExit }) => {
|
|
57
|
+
const [activeMode, setActiveMode] = useState('old');
|
|
58
|
+
|
|
59
|
+
const reports = useMemo(() => {
|
|
60
|
+
return activeMode === 'old' ? OLD_REPORTS : NEW_REPORTS;
|
|
61
|
+
}, [activeMode]);
|
|
62
|
+
|
|
54
63
|
return (
|
|
55
64
|
<View style={styles.container}>
|
|
56
|
-
{/* HEADER */}
|
|
57
65
|
<View style={styles.header}>
|
|
58
66
|
<TouchableOpacity
|
|
59
67
|
onPress={onExit}
|
|
@@ -64,19 +72,52 @@ const ReportListScreen = ({ onSelect, onExit }) => {
|
|
|
64
72
|
</TouchableOpacity>
|
|
65
73
|
|
|
66
74
|
<Text style={styles.title}>Analytics Reports</Text>
|
|
75
|
+
<View style={styles.headerSpacer} />
|
|
76
|
+
</View>
|
|
77
|
+
|
|
78
|
+
<Text style={styles.subtitle}>
|
|
79
|
+
Select report mode before opening report tabs
|
|
80
|
+
</Text>
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
<
|
|
82
|
+
<View style={styles.modeRow}>
|
|
83
|
+
<TouchableOpacity
|
|
84
|
+
style={[styles.modeBtn, activeMode === 'old' && styles.modeBtnActive]}
|
|
85
|
+
onPress={() => setActiveMode('old')}
|
|
86
|
+
>
|
|
87
|
+
<Text
|
|
88
|
+
style={[
|
|
89
|
+
styles.modeBtnText,
|
|
90
|
+
activeMode === 'old' && styles.modeBtnTextActive,
|
|
91
|
+
]}
|
|
92
|
+
>
|
|
93
|
+
Option 1 - Old
|
|
94
|
+
</Text>
|
|
95
|
+
</TouchableOpacity>
|
|
96
|
+
<TouchableOpacity
|
|
97
|
+
style={[styles.modeBtn, activeMode === 'new' && styles.modeBtnActive]}
|
|
98
|
+
onPress={() => setActiveMode('new')}
|
|
99
|
+
>
|
|
100
|
+
<Text
|
|
101
|
+
style={[
|
|
102
|
+
styles.modeBtnText,
|
|
103
|
+
activeMode === 'new' && styles.modeBtnTextActive,
|
|
104
|
+
]}
|
|
105
|
+
>
|
|
106
|
+
Option 2 - New
|
|
107
|
+
</Text>
|
|
108
|
+
</TouchableOpacity>
|
|
70
109
|
</View>
|
|
71
110
|
|
|
72
|
-
{/* REPORT CARDS */}
|
|
73
111
|
<ScrollView showsVerticalScrollIndicator={false}>
|
|
74
|
-
{
|
|
112
|
+
{reports.map((report) => (
|
|
75
113
|
<TouchableOpacity
|
|
76
114
|
key={report.id}
|
|
77
|
-
style={
|
|
115
|
+
style={[
|
|
116
|
+
styles.card,
|
|
117
|
+
activeMode === 'new' && styles.cardNewTheme,
|
|
118
|
+
]}
|
|
78
119
|
onPress={() => onSelect(report.id)}
|
|
79
|
-
activeOpacity={0.
|
|
120
|
+
activeOpacity={0.88}
|
|
80
121
|
>
|
|
81
122
|
<Text style={styles.cardTitle}>{report.title}</Text>
|
|
82
123
|
<Text style={styles.cardDesc}>{report.desc}</Text>
|
|
@@ -92,28 +133,23 @@ export default ReportListScreen;
|
|
|
92
133
|
const styles = StyleSheet.create({
|
|
93
134
|
container: {
|
|
94
135
|
flex: 1,
|
|
95
|
-
backgroundColor: '#
|
|
136
|
+
backgroundColor: '#edf1f7',
|
|
96
137
|
padding: 16,
|
|
97
138
|
},
|
|
98
|
-
|
|
99
|
-
/* HEADER */
|
|
100
139
|
header: {
|
|
101
140
|
flexDirection: 'row',
|
|
102
141
|
alignItems: 'center',
|
|
103
|
-
marginBottom:
|
|
142
|
+
marginBottom: 6,
|
|
104
143
|
},
|
|
105
|
-
|
|
106
144
|
backBtn: {
|
|
107
145
|
width: 28,
|
|
108
146
|
alignItems: 'flex-start',
|
|
109
147
|
},
|
|
110
|
-
|
|
111
148
|
back: {
|
|
112
149
|
fontSize: 28,
|
|
113
150
|
fontWeight: '700',
|
|
114
151
|
color: '#111',
|
|
115
152
|
},
|
|
116
|
-
|
|
117
153
|
title: {
|
|
118
154
|
flex: 1,
|
|
119
155
|
textAlign: 'center',
|
|
@@ -121,34 +157,65 @@ const styles = StyleSheet.create({
|
|
|
121
157
|
fontWeight: '700',
|
|
122
158
|
color: '#111',
|
|
123
159
|
},
|
|
124
|
-
|
|
125
|
-
|
|
160
|
+
headerSpacer: {
|
|
161
|
+
width: 28,
|
|
162
|
+
},
|
|
163
|
+
subtitle: {
|
|
164
|
+
fontSize: 12,
|
|
165
|
+
color: '#5b6570',
|
|
166
|
+
marginBottom: 14,
|
|
167
|
+
textAlign: 'center',
|
|
168
|
+
},
|
|
169
|
+
modeRow: {
|
|
170
|
+
flexDirection: 'row',
|
|
171
|
+
backgroundColor: '#dce3ed',
|
|
172
|
+
borderRadius: 12,
|
|
173
|
+
padding: 4,
|
|
174
|
+
marginBottom: 16,
|
|
175
|
+
},
|
|
176
|
+
modeBtn: {
|
|
177
|
+
flex: 1,
|
|
178
|
+
borderRadius: 10,
|
|
179
|
+
paddingVertical: 10,
|
|
180
|
+
alignItems: 'center',
|
|
181
|
+
},
|
|
182
|
+
modeBtnActive: {
|
|
183
|
+
backgroundColor: '#0f3d75',
|
|
184
|
+
},
|
|
185
|
+
modeBtnText: {
|
|
186
|
+
fontSize: 13,
|
|
187
|
+
fontWeight: '700',
|
|
188
|
+
color: '#2f3a46',
|
|
189
|
+
},
|
|
190
|
+
modeBtnTextActive: {
|
|
191
|
+
color: '#fff',
|
|
192
|
+
},
|
|
126
193
|
card: {
|
|
127
194
|
backgroundColor: '#fff',
|
|
128
195
|
padding: 18,
|
|
129
196
|
borderRadius: 14,
|
|
130
197
|
marginBottom: 14,
|
|
131
|
-
|
|
132
198
|
borderWidth: 1,
|
|
133
|
-
borderColor: '#
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
shadowOffset: { width: 0, height: 3 },
|
|
199
|
+
borderColor: '#d9e0ea',
|
|
200
|
+
shadowColor: '#0b1f3a',
|
|
201
|
+
shadowOpacity: 0.08,
|
|
202
|
+
shadowRadius: 10,
|
|
203
|
+
shadowOffset: { width: 0, height: 4 },
|
|
139
204
|
elevation: 2,
|
|
140
205
|
},
|
|
141
|
-
|
|
206
|
+
cardNewTheme: {
|
|
207
|
+
borderColor: '#8bb4ff',
|
|
208
|
+
backgroundColor: '#f4f8ff',
|
|
209
|
+
},
|
|
142
210
|
cardTitle: {
|
|
143
211
|
fontSize: 16,
|
|
144
212
|
fontWeight: '700',
|
|
145
213
|
marginBottom: 6,
|
|
146
214
|
color: '#111',
|
|
147
215
|
},
|
|
148
|
-
|
|
149
216
|
cardDesc: {
|
|
150
217
|
fontSize: 13,
|
|
151
|
-
color: '#
|
|
218
|
+
color: '#4e5968',
|
|
152
219
|
lineHeight: 18,
|
|
153
220
|
},
|
|
154
221
|
});
|