Skip to content

Commit ddda2ad

Browse files
author
Codex
committed
changes
1 parent 70b7af4 commit ddda2ad

24 files changed

Lines changed: 5588 additions & 1215 deletions

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{
2+
}

app.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
],
2323
"NSMicrophoneUsageDescription": "HeySalad® Wallet uses the microphone for voice payments with Selina.",
2424
"NSFaceIDUsageDescription": "HeySalad® Wallet uses Face ID to securely authorize transactions.",
25+
"NSBluetoothAlwaysUsageDescription": "HeySalad® Wallet uses Bluetooth to connect to payment terminals.",
26+
"NSBluetoothPeripheralUsageDescription": "HeySalad® Wallet uses Bluetooth to connect to payment terminals.",
2527
"ITSAppUsesNonExemptEncryption": false,
2628
"NSCameraUsageDescription": "HeySalad® Wallet uses the camera to scan QR codes.",
2729
"NSAppTransportSecurity": {
@@ -46,7 +48,10 @@
4648
"android.permission.MODIFY_AUDIO_SETTINGS",
4749
"android.permission.WAKE_LOCK",
4850
"android.permission.BLUETOOTH",
51+
"android.permission.BLUETOOTH_ADMIN",
52+
"android.permission.BLUETOOTH_SCAN",
4953
"android.permission.BLUETOOTH_CONNECT",
54+
"android.permission.ACCESS_FINE_LOCATION",
5055
"android.permission.USE_BIOMETRIC",
5156
"android.permission.USE_FINGERPRINT",
5257
"CAMERA",
@@ -97,6 +102,14 @@
97102
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
98103
"recordAudioAndroid": true
99104
}
105+
],
106+
[
107+
"react-native-ble-plx",
108+
{
109+
"isBackgroundEnabled": true,
110+
"modes": ["peripheral", "central"],
111+
"bluetoothAlwaysPermission": "Allow $(PRODUCT_NAME) to connect to payment terminals via Bluetooth."
112+
}
100113
]
101114
],
102115
"experiments": {
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
// app/(tabs)/(wallet)/asset-detail.tsx
2+
// Asset detail screen showing token information, network, balance, and actions
3+
4+
import React from 'react';
5+
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Alert } from 'react-native';
6+
import { useLocalSearchParams, router } from 'expo-router';
7+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
8+
import { ArrowLeft, ArrowUp, ArrowDown, Repeat, ShoppingBag } from 'lucide-react-native';
9+
import Colors from '@/constants/colors';
10+
import SmartCryptoIcon from '@/components/SmartCryptoIcon';
11+
12+
export default function AssetDetailScreen() {
13+
const params = useLocalSearchParams();
14+
const insets = useSafeAreaInsets();
15+
16+
// Parse params
17+
const symbol = params.symbol as string;
18+
const name = params.name as string;
19+
const balance = parseFloat(params.balance as string);
20+
const balanceGBP = parseFloat(params.balanceGBP as string);
21+
const price = parseFloat(params.price as string);
22+
const change24h = parseFloat(params.change24h as string);
23+
const blockchain = params.blockchain as string;
24+
25+
const networkName = blockchain.charAt(0).toUpperCase() + blockchain.slice(1);
26+
27+
const handleSend = () => {
28+
Alert.alert('Send', `Send ${symbol} coming soon`);
29+
};
30+
31+
const handleReceive = () => {
32+
Alert.alert('Receive', `Receive ${symbol} coming soon`);
33+
};
34+
35+
const handleSwap = () => {
36+
Alert.alert('Swap', `Swap ${symbol} coming soon`);
37+
};
38+
39+
const handleBuy = () => {
40+
Alert.alert('Buy', `Buy ${symbol} coming soon`);
41+
};
42+
43+
return (
44+
<View style={[styles.container, { paddingTop: insets.top }]}>
45+
{/* Header */}
46+
<View style={styles.header}>
47+
<TouchableOpacity onPress={() => router.back()} style={styles.backButton}>
48+
<ArrowLeft color={Colors.brand.ink} size={24} />
49+
</TouchableOpacity>
50+
<Text style={styles.headerTitle}>{name}</Text>
51+
<View style={{ width: 40 }} />
52+
</View>
53+
54+
<ScrollView style={styles.content} contentContainerStyle={{ paddingBottom: insets.bottom + 20 }}>
55+
{/* Token Icon and Info */}
56+
<View style={styles.tokenSection}>
57+
<SmartCryptoIcon symbol={symbol} size={64} />
58+
<Text style={styles.tokenName}>{name}</Text>
59+
<Text style={styles.tokenSymbol}>{symbol}</Text>
60+
<View style={styles.networkBadge}>
61+
<Text style={styles.networkText}>{networkName} Network</Text>
62+
</View>
63+
</View>
64+
65+
{/* Balance Section */}
66+
<View style={styles.balanceSection}>
67+
<Text style={styles.balanceLabel}>Balance</Text>
68+
<Text style={styles.balanceAmount}>
69+
{balance.toFixed(6)} {symbol}
70+
</Text>
71+
<Text style={styles.balanceValue}>£{balanceGBP.toFixed(2)}</Text>
72+
</View>
73+
74+
{/* Price Section */}
75+
<View style={styles.priceSection}>
76+
<View style={styles.priceRow}>
77+
<Text style={styles.priceLabel}>Current Price</Text>
78+
<Text style={styles.priceAmount}>£{price.toFixed(2)}</Text>
79+
</View>
80+
<View style={styles.priceRow}>
81+
<Text style={styles.priceLabel}>24h Change</Text>
82+
<Text style={[styles.priceChange, change24h >= 0 ? styles.priceChangePositive : styles.priceChangeNegative]}>
83+
{change24h >= 0 ? '+' : ''}{change24h.toFixed(2)}%
84+
</Text>
85+
</View>
86+
</View>
87+
88+
{/* Action Buttons */}
89+
<View style={styles.actionsSection}>
90+
<TouchableOpacity style={styles.actionButton} onPress={handleSend}>
91+
<View style={[styles.actionIcon, styles.actionIconSend]}>
92+
<ArrowUp color={Colors.brand.white} size={20} />
93+
</View>
94+
<Text style={styles.actionText}>Send</Text>
95+
</TouchableOpacity>
96+
97+
<TouchableOpacity style={styles.actionButton} onPress={handleReceive}>
98+
<View style={[styles.actionIcon, styles.actionIconReceive]}>
99+
<ArrowDown color={Colors.brand.white} size={20} />
100+
</View>
101+
<Text style={styles.actionText}>Receive</Text>
102+
</TouchableOpacity>
103+
104+
<TouchableOpacity style={styles.actionButton} onPress={handleSwap}>
105+
<View style={[styles.actionIcon, styles.actionIconSwap]}>
106+
<Repeat color={Colors.brand.white} size={20} />
107+
</View>
108+
<Text style={styles.actionText}>Swap</Text>
109+
</TouchableOpacity>
110+
111+
<TouchableOpacity style={styles.actionButton} onPress={handleBuy}>
112+
<View style={[styles.actionIcon, styles.actionIconBuy]}>
113+
<ShoppingBag color={Colors.brand.white} size={20} />
114+
</View>
115+
<Text style={styles.actionText}>Buy</Text>
116+
</TouchableOpacity>
117+
</View>
118+
119+
{/* Transaction History Placeholder */}
120+
<View style={styles.historySection}>
121+
<Text style={styles.historyTitle}>Transaction History</Text>
122+
<View style={styles.emptyState}>
123+
<Text style={styles.emptyStateText}>No transactions yet</Text>
124+
<Text style={styles.emptyStateSubtext}>
125+
Your {symbol} transactions will appear here
126+
</Text>
127+
</View>
128+
</View>
129+
</ScrollView>
130+
</View>
131+
);
132+
}
133+
134+
const styles = StyleSheet.create({
135+
container: {
136+
flex: 1,
137+
backgroundColor: Colors.brand.white,
138+
},
139+
header: {
140+
flexDirection: 'row',
141+
alignItems: 'center',
142+
justifyContent: 'space-between',
143+
paddingHorizontal: 20,
144+
paddingVertical: 16,
145+
borderBottomWidth: 1,
146+
borderBottomColor: Colors.brand.lightPeach,
147+
},
148+
backButton: {
149+
width: 40,
150+
height: 40,
151+
alignItems: 'center',
152+
justifyContent: 'center',
153+
},
154+
headerTitle: {
155+
fontSize: 18,
156+
fontWeight: '700' as const,
157+
color: Colors.brand.ink,
158+
},
159+
content: {
160+
flex: 1,
161+
},
162+
tokenSection: {
163+
alignItems: 'center',
164+
paddingVertical: 32,
165+
borderBottomWidth: 1,
166+
borderBottomColor: Colors.brand.lightPeach,
167+
},
168+
tokenName: {
169+
fontSize: 24,
170+
fontWeight: '900' as const,
171+
color: Colors.brand.ink,
172+
marginTop: 16,
173+
},
174+
tokenSymbol: {
175+
fontSize: 16,
176+
fontWeight: '600' as const,
177+
color: Colors.brand.inkMuted,
178+
marginTop: 4,
179+
},
180+
networkBadge: {
181+
backgroundColor: Colors.brand.lightPeach,
182+
borderRadius: 20,
183+
paddingHorizontal: 16,
184+
paddingVertical: 6,
185+
marginTop: 12,
186+
},
187+
networkText: {
188+
fontSize: 13,
189+
fontWeight: '600' as const,
190+
color: Colors.brand.ink,
191+
},
192+
balanceSection: {
193+
alignItems: 'center',
194+
paddingVertical: 32,
195+
borderBottomWidth: 1,
196+
borderBottomColor: Colors.brand.lightPeach,
197+
},
198+
balanceLabel: {
199+
fontSize: 14,
200+
fontWeight: '600' as const,
201+
color: Colors.brand.inkMuted,
202+
marginBottom: 8,
203+
},
204+
balanceAmount: {
205+
fontSize: 32,
206+
fontWeight: '900' as const,
207+
color: Colors.brand.ink,
208+
marginBottom: 8,
209+
},
210+
balanceValue: {
211+
fontSize: 18,
212+
fontWeight: '600' as const,
213+
color: Colors.brand.inkMuted,
214+
},
215+
priceSection: {
216+
paddingHorizontal: 20,
217+
paddingVertical: 24,
218+
borderBottomWidth: 1,
219+
borderBottomColor: Colors.brand.lightPeach,
220+
},
221+
priceRow: {
222+
flexDirection: 'row',
223+
justifyContent: 'space-between',
224+
alignItems: 'center',
225+
marginBottom: 12,
226+
},
227+
priceLabel: {
228+
fontSize: 14,
229+
fontWeight: '600' as const,
230+
color: Colors.brand.inkMuted,
231+
},
232+
priceAmount: {
233+
fontSize: 16,
234+
fontWeight: '700' as const,
235+
color: Colors.brand.ink,
236+
},
237+
priceChange: {
238+
fontSize: 16,
239+
fontWeight: '700' as const,
240+
},
241+
priceChangePositive: {
242+
color: '#10b981',
243+
},
244+
priceChangeNegative: {
245+
color: Colors.brand.cherryRed,
246+
},
247+
actionsSection: {
248+
flexDirection: 'row',
249+
justifyContent: 'space-around',
250+
paddingHorizontal: 20,
251+
paddingVertical: 32,
252+
borderBottomWidth: 1,
253+
borderBottomColor: Colors.brand.lightPeach,
254+
},
255+
actionButton: {
256+
alignItems: 'center',
257+
gap: 8,
258+
},
259+
actionIcon: {
260+
width: 56,
261+
height: 56,
262+
borderRadius: 28,
263+
alignItems: 'center',
264+
justifyContent: 'center',
265+
},
266+
actionIconSend: {
267+
backgroundColor: Colors.brand.cherryRed,
268+
},
269+
actionIconReceive: {
270+
backgroundColor: '#10b981',
271+
},
272+
actionIconSwap: {
273+
backgroundColor: '#3b82f6',
274+
},
275+
actionIconBuy: {
276+
backgroundColor: '#8b5cf6',
277+
},
278+
actionText: {
279+
fontSize: 13,
280+
fontWeight: '600' as const,
281+
color: Colors.brand.ink,
282+
},
283+
historySection: {
284+
padding: 20,
285+
},
286+
historyTitle: {
287+
fontSize: 18,
288+
fontWeight: '900' as const,
289+
color: Colors.brand.ink,
290+
marginBottom: 16,
291+
},
292+
emptyState: {
293+
alignItems: 'center',
294+
paddingVertical: 48,
295+
},
296+
emptyStateText: {
297+
fontSize: 16,
298+
fontWeight: '600' as const,
299+
color: Colors.brand.inkMuted,
300+
marginBottom: 8,
301+
},
302+
emptyStateSubtext: {
303+
fontSize: 13,
304+
color: Colors.brand.inkMuted,
305+
textAlign: 'center',
306+
},
307+
});

0 commit comments

Comments
 (0)