Update CBS Mobile App codebase
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
|
||||
import type { TransactionRecord } from '../../types/app';
|
||||
import { useTheme } from '../../theme';
|
||||
import { useTheme, textStyles } from '../../theme';
|
||||
import { formatCurrency, formatDate } from '../../utils/formatters';
|
||||
|
||||
interface TransactionItemProps {
|
||||
@@ -28,48 +28,59 @@ const TransactionItemComponent = ({ item }: TransactionItemProps) => {
|
||||
}, [item.id]);
|
||||
|
||||
const riskConfig = {
|
||||
safe: { color: theme.colors.success, label: 'SECURE', icon: 'shield-checkmark' as const },
|
||||
medium: { color: theme.colors.warning, label: 'FLAGGED', icon: 'warning' as const },
|
||||
high: { color: theme.colors.danger, label: 'HIGH RISK', icon: 'alert-circle' as const },
|
||||
safe: {
|
||||
color: theme.colors.success,
|
||||
surface: theme.colors.successSurface,
|
||||
border: theme.colors.successBorder,
|
||||
label: 'SECURE',
|
||||
icon: 'shield-checkmark' as const,
|
||||
},
|
||||
medium: {
|
||||
color: theme.colors.warning,
|
||||
surface: theme.colors.warningSurface,
|
||||
border: theme.colors.warningBorder,
|
||||
label: 'FLAGGED',
|
||||
icon: 'warning' as const,
|
||||
},
|
||||
high: {
|
||||
color: theme.colors.danger,
|
||||
surface: theme.colors.dangerSurface,
|
||||
border: theme.colors.dangerBorder,
|
||||
label: 'HIGH RISK',
|
||||
icon: 'alert-circle' as const,
|
||||
},
|
||||
}[riskLevel];
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.wrapper,
|
||||
{
|
||||
borderBottomColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<View style={[styles.wrapper, { borderBottomColor: theme.colors.cardBorder }]}>
|
||||
<View style={styles.leading}>
|
||||
<View
|
||||
style={[
|
||||
styles.icon,
|
||||
{
|
||||
backgroundColor: isCredit
|
||||
? `${theme.colors.success}10`
|
||||
: 'rgba(255, 255, 255, 0.05)',
|
||||
borderColor: isCredit ? `${theme.colors.success}30` : 'rgba(255, 255, 255, 0.1)',
|
||||
? theme.colors.successSurface
|
||||
: theme.colors.surfaceMuted,
|
||||
borderColor: isCredit ? theme.colors.successBorder : theme.colors.cardBorder,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Ionicons
|
||||
name={isCredit ? 'chevron-down' : 'chevron-up'}
|
||||
size={18}
|
||||
color={isCredit ? theme.colors.success : theme.colors.white}
|
||||
color={isCredit ? theme.colors.success : theme.colors.textSecondary}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.copy}>
|
||||
<View style={styles.titleRow}>
|
||||
<Text style={[styles.title, { color: theme.colors.white }]}>{item.title}</Text>
|
||||
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>{item.title}</Text>
|
||||
</View>
|
||||
<View style={styles.subtitleRow}>
|
||||
<Text style={[styles.subtitle, { color: 'rgba(255, 255, 255, 0.5)' }]}>
|
||||
<Text style={[styles.subtitle, { color: theme.colors.textMuted }]}>
|
||||
{item.counterparty}
|
||||
</Text>
|
||||
<View style={styles.dot} />
|
||||
<Text style={[styles.subtitle, { color: 'rgba(255, 255, 255, 0.5)' }]}>
|
||||
<View style={[styles.dot, { backgroundColor: theme.colors.textMuted }]} />
|
||||
<Text style={[styles.subtitle, { color: theme.colors.textMuted }]}>
|
||||
{formatDate(item.occurredAt)}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -80,13 +91,18 @@ const TransactionItemComponent = ({ item }: TransactionItemProps) => {
|
||||
<Text
|
||||
style={[
|
||||
styles.amount,
|
||||
{ color: isCredit ? theme.colors.success : theme.colors.white },
|
||||
{ color: isCredit ? theme.colors.success : theme.colors.textPrimary },
|
||||
]}
|
||||
>
|
||||
{isCredit ? '+' : '-'}
|
||||
{formatCurrency(item.amount)}
|
||||
</Text>
|
||||
<View style={[styles.riskBadge, { backgroundColor: `${riskConfig.color}10`, borderColor: `${riskConfig.color}20` }]}>
|
||||
<View
|
||||
style={[
|
||||
styles.riskBadge,
|
||||
{ backgroundColor: riskConfig.surface, borderColor: riskConfig.border },
|
||||
]}
|
||||
>
|
||||
<Text style={[styles.riskText, { color: riskConfig.color }]}>{riskConfig.label}</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -125,9 +141,7 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: '800',
|
||||
letterSpacing: -0.3,
|
||||
...textStyles.h3,
|
||||
},
|
||||
subtitleRow: {
|
||||
flexDirection: 'row',
|
||||
@@ -138,20 +152,17 @@ const styles = StyleSheet.create({
|
||||
width: 3,
|
||||
height: 3,
|
||||
borderRadius: 1.5,
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.2)',
|
||||
backgroundColor: 'transparent', // set from the theme at the call site
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 12,
|
||||
fontWeight: '500',
|
||||
...textStyles.caption,
|
||||
},
|
||||
trailing: {
|
||||
alignItems: 'flex-end',
|
||||
gap: 4,
|
||||
},
|
||||
amount: {
|
||||
fontSize: 16,
|
||||
fontWeight: '800',
|
||||
letterSpacing: -0.2,
|
||||
...textStyles.money,
|
||||
},
|
||||
riskBadge: {
|
||||
paddingHorizontal: 6,
|
||||
@@ -159,9 +170,17 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 6,
|
||||
borderWidth: 1,
|
||||
},
|
||||
// Takes its family and casing from `eyebrow`, then overrides the size.
|
||||
//
|
||||
// 8pt is below the scale's floor of 11 and the scale has no entry for it on
|
||||
// purpose — at this size the label is decoration, not something a customer
|
||||
// can be expected to read. Left at 8 rather than snapped up to 11 because
|
||||
// the badge is laid out around it; worth revisiting as a design question,
|
||||
// since a risk flag nobody can read is not doing its job.
|
||||
riskText: {
|
||||
...textStyles.eyebrow,
|
||||
fontSize: 8,
|
||||
fontWeight: '900',
|
||||
lineHeight: 11,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user