Skip to content

Commit 2e2f8ad

Browse files
EmekaManuelEmeka ManuelL03TJ3
authored
Wallet Detail - Action Summary & Action Logs for stewards #221 (#297)
* chore(): implemented rerouting and Ui components * chore(): implemented the links * chore(): fixed the toggle feature * chore(): added the nft id as name since there's no name data returned * chore(): edited the actions font colot * chore(): corrected the regex * chore(): cleanup * chore(): added logs to debug - would remove later * chore(): fixed the nft details url * chore(): reverted deploymeny.json and added it to prettier ignore to prevent future formatting changes * chore(): implemented the changed requested from the PR review * chore(): removed hardcoded data and getting the nft contract address from the deployment.json file * chore(): removed incorrect comment * chore(): cleanup on the useActivityLogData hook and moved specified functions into utils file * Update packages/app/src/components/ActivityLog.tsx * refactor(ActivityLog): replace date formatting logic with utility function for improved readability * fix(ActivityLog): update formatNftId to include creation timestamp for accurate year representation * refactor(ActivityLog): simplify user identifier logic by removing full name fetching * refactor(ActivityLog): optimize collective statistics calculation and display logic using useMemo and useEffect * refactor(ActivityLog): remove formatAmount utility and update payment amount calculation for better precision * refactor(ActivityLog): replace formatDate utility with formatTime for improved timestamp formatting * refactor(ActivityLog): update display name logic, payment amount format for clarity and nft details link * refactor(ActivityLog): enhance payment amount display format for clarity * refactor(ActivityLog): update NFT details link to use nftHash for improved accuracy --------- Co-authored-by: Emeka Manuel <[email protected]> Co-authored-by: Lewis B <[email protected]>
1 parent 4128f2b commit 2e2f8ad

File tree

13 files changed

+747
-118
lines changed

13 files changed

+747
-118
lines changed

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
**/*.yaml
1+
**/*.yaml
2+
deployment.json
Lines changed: 284 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,318 @@
1-
import { Image, Text, View, StyleSheet } from 'react-native';
2-
import { InterRegular, InterSemiBold } from '../utils/webFonts';
1+
import { useState } from 'react';
2+
import { StyleSheet, Text, TouchableOpacity, View, Image, Linking } from 'react-native';
33
import { Colors } from '../utils/colors';
4+
import { ChevronDownIcon } from 'native-base';
5+
import { InterMedium, InterSemiBold, InterSmall } from '../utils/webFonts';
6+
import { getProvableNFTAddress } from '../models/constants';
7+
import env from '../lib/env';
8+
import { formatTime } from '../lib/formatTime';
49

5-
const ReceiveIconUri = `data:image/svg+xml;utf8,<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect width="32" height="32" rx="16" fill="#95EED8"/> <path d="M19.048 14.6186C18.7453 14.3159 18.2546 14.3159 17.952 14.6186L16.775 15.7956V9.33325C16.775 8.90523 16.428 8.55825 16 8.55825C15.572 8.55825 15.225 8.90523 15.225 9.33325V15.7956L14.048 14.6186C13.7453 14.3159 13.2546 14.3159 12.952 14.6186C12.6493 14.9212 12.6493 15.4119 12.952 15.7146L15.452 18.2146C15.7546 18.5172 16.2453 18.5172 16.548 18.2146L19.048 15.7146C19.3507 15.4119 19.3507 14.9212 19.048 14.6186ZM23.4417 15.9999C23.4417 15.5719 23.0947 15.2249 22.6667 15.2249C22.2386 15.2249 21.8917 15.5719 21.8917 15.9999C21.8917 19.2538 19.2539 21.8916 16 21.8916C12.7461 21.8916 10.1083 19.2538 10.1083 15.9999C10.1083 15.5719 9.76135 15.2249 9.33333 15.2249C8.90531 15.2249 8.55833 15.5719 8.55833 15.9999C8.55833 20.1098 11.8901 23.4416 16 23.4416C20.1099 23.4416 23.4417 20.1098 23.4417 15.9999Z" fill="#27564B" stroke="#5BBAA3" stroke-width="0.3"/> </svg> `;
10+
const ReceiveIconUri =
11+
'data:image/svg+xml;utf8,<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect width="32" height="32" rx="16" fill="#95EED8"/> <path d="M19.048 14.6186C18.7453 14.3159 18.2546 14.3159 17.952 14.6186L16.775 15.7956V9.33325C16.775 8.90523 16.428 8.55825 16 8.55825C15.572 8.55825 15.225 8.90523 15.225 9.33325V15.7956L14.048 14.6186C13.7453 14.3159 13.2546 14.3159 12.952 14.6186C12.6493 14.9212 12.6493 15.4119 12.952 15.7146L15.452 18.2146C15.7546 18.5172 16.2453 18.5172 16.548 18.2146L19.048 15.7146C19.3507 15.4119 19.3507 14.9212 19.048 14.6186ZM23.4417 15.9999C23.4417 15.5719 23.0947 15.2249 22.6667 15.2249C22.2386 15.2249 21.8917 15.5719 21.8917 15.9999C21.8917 19.2538 19.2539 21.8916 16 21.8916C12.7461 21.8916 10.1083 19.2538 10.1083 15.9999C10.1083 15.5719 9.76135 15.2249 9.33333 15.2249C8.90531 15.2249 8.55833 15.5719 8.55833 15.9999C8.55833 20.1098 11.8901 23.4416 16 23.4416C20.1099 23.4416 23.4417 20.1098 23.4417 15.9999Z" fill="#27564B" stroke="#5BBAA3" stroke-width="0.3"/> </svg> ';
612

713
interface ActivityLogProps {
814
name: string;
915
id: string;
1016
creationDate: string;
17+
nftId: string;
18+
transactionHash: string;
19+
ipfsHash: string;
20+
paymentAmount: string;
21+
collective: {
22+
id: string;
23+
name: string;
24+
};
25+
nftHash: string;
26+
timestamp: number;
1127
}
1228

13-
function ActivityLog({}: ActivityLogProps) {
29+
function ActivityLog({
30+
name,
31+
nftId,
32+
transactionHash,
33+
collective,
34+
ipfsHash,
35+
nftHash,
36+
paymentAmount,
37+
timestamp,
38+
}: ActivityLogProps) {
39+
const networkName = env.REACT_APP_NETWORK || 'development-celo';
40+
const NFT_CA = getProvableNFTAddress(networkName);
41+
const [isExpanded, setIsExpanded] = useState(false);
42+
43+
const toggleExpanded = () => {
44+
setIsExpanded(!isExpanded);
45+
};
46+
47+
const openExternalLink = async (url: string) => {
48+
try {
49+
const supported = await Linking.canOpenURL(url);
50+
if (supported) {
51+
await Linking.openURL(url);
52+
} else {
53+
console.warn(`Don't know how to open URL: ${url}`);
54+
}
55+
} catch (error) {
56+
console.error('Error opening URL:', error);
57+
}
58+
};
59+
60+
const handlePaymentTransactionPress = () => {
61+
if (transactionHash) {
62+
openExternalLink(`https://celoscan.io/tx/${transactionHash}`);
63+
}
64+
};
65+
66+
const handleNftDetailsPress = () => {
67+
if (nftHash) {
68+
openExternalLink(`https://celoscan.io/nft/${NFT_CA}/${nftHash}`);
69+
}
70+
};
71+
72+
const displayName = nftHash || name;
73+
const truncatedName =
74+
displayName.length > 20
75+
? `${displayName.substring(0, 8)}...${displayName.substring(displayName.length - 8)}`
76+
: displayName;
77+
78+
const handleIpfsPress = async () => {
79+
if (ipfsHash) {
80+
const cleanHash = ipfsHash.startsWith('0x') ? ipfsHash.slice(2) : ipfsHash;
81+
const gateways = [
82+
`https://ipfs.io/ipfs/${cleanHash}`,
83+
`https://gateway.pinata.cloud/ipfs/${cleanHash}`,
84+
`https://cloudflare-ipfs.com/ipfs/${cleanHash}`,
85+
];
86+
87+
try {
88+
await openExternalLink(gateways[0]);
89+
} catch (error) {
90+
try {
91+
await openExternalLink(gateways[1]);
92+
} catch (secondError) {
93+
console.warn('IPFS gateways failed');
94+
}
95+
}
96+
}
97+
};
98+
99+
const displayDate = formatTime(timestamp);
100+
14101
return (
15102
<View style={styles.container}>
16-
<View style={styles.row}>
17-
<View style={styles.bar} />
18-
<Image style={styles.icon} source={{ uri: ReceiveIconUri }} />
19-
<Text style={styles.logProfileDetails}>
20-
<Text style={styles.name}>Silvi Tree Claim {'\n'}</Text>
21-
<Text style={styles.id}>0x723a86c93838c1facse.....</Text>
22-
</Text>
23-
<View style={styles.logDate}>
24-
<Text style={styles.date}>July 3, 2023</Text>
25-
</View>
103+
<View style={styles.leftBorder} />
104+
105+
<View style={styles.contentContainer}>
106+
<TouchableOpacity onPress={toggleExpanded} style={styles.actionRow}>
107+
<View style={styles.leftSection}>
108+
<View style={styles.iconContainer}>
109+
<Image style={styles.icon} source={{ uri: ReceiveIconUri }} />
110+
</View>
111+
112+
<View style={styles.actionInfo}>
113+
<Text style={styles.collectiveName}>{collective.name}</Text>
114+
115+
<View style={styles.titleRow}>
116+
<Text style={styles.actionName}>{truncatedName}</Text>
117+
<Text style={styles.actionDate}>{displayDate}</Text>
118+
</View>
119+
120+
{paymentAmount && <Text style={styles.paymentAmount}>G$ {paymentAmount.split(' ')[0]} transferred</Text>}
121+
122+
<View style={styles.chevronContainer}>
123+
<ChevronDownIcon
124+
size={4}
125+
color={Colors.gray[200]}
126+
style={{
127+
transform: [{ rotate: isExpanded ? '180deg' : '0deg' }],
128+
}}
129+
/>
130+
</View>
131+
</View>
132+
</View>
133+
</TouchableOpacity>
134+
135+
{isExpanded && (
136+
<View style={styles.expandedContent}>
137+
<TouchableOpacity
138+
style={styles.linkButton}
139+
onPress={handlePaymentTransactionPress}
140+
disabled={!transactionHash}>
141+
<Text style={transactionHash ? styles.linkText : styles.linkTextDisabled}>Payment Transaction</Text>
142+
</TouchableOpacity>
143+
144+
<TouchableOpacity style={styles.linkButton} onPress={handleNftDetailsPress} disabled={!nftId}>
145+
<Text style={nftId ? styles.linkText : styles.linkTextDisabled}>NFT Details</Text>
146+
</TouchableOpacity>
147+
148+
<TouchableOpacity style={styles.linkButton} onPress={handleIpfsPress} disabled={!ipfsHash}>
149+
<Text style={ipfsHash ? styles.linkText : styles.linkTextDisabled}>
150+
IPFS Claim and Proof of Verification
151+
</Text>
152+
</TouchableOpacity>
153+
154+
<TouchableOpacity onPress={toggleExpanded} style={styles.collapseButton}>
155+
<Text style={styles.collapseIcon}></Text>
156+
</TouchableOpacity>
157+
</View>
158+
)}
26159
</View>
27160
</View>
28161
);
29162
}
30163

31164
const styles = StyleSheet.create({
32165
container: {
33-
width: '100%',
34166
backgroundColor: Colors.white,
35-
paddingLeft: 16,
36-
paddingRight: 16,
167+
borderRadius: 12,
168+
marginBottom: 12,
169+
shadowColor: Colors.black,
170+
shadowOffset: {
171+
width: 0,
172+
height: 2,
173+
},
174+
shadowOpacity: 0.1,
175+
shadowRadius: 4,
176+
elevation: 3,
177+
overflow: 'hidden',
37178
},
38-
row: {
39-
width: '100%',
40-
flex: 1,
41-
flexDirection: 'row',
42-
gap: 8,
43-
backgroundColor: Colors.white,
179+
180+
contentContainer: {
181+
paddingLeft: 8,
182+
paddingRight: 8,
183+
paddingBottom: 8,
184+
paddingTop: 8,
185+
},
186+
187+
icon: {
188+
width: 32,
189+
height: 32,
44190
},
45-
bar: {
191+
192+
leftBorder: {
193+
position: 'absolute',
194+
left: 0,
195+
top: 0,
196+
bottom: 0,
197+
width: 4,
46198
backgroundColor: Colors.green[100],
47-
width: 6,
48-
height: 40,
49-
alignSelf: 'flex-start',
199+
borderTopLeftRadius: 12,
200+
borderBottomLeftRadius: 12,
201+
zIndex: 1,
50202
},
51-
icon: {
203+
204+
actionRow: {
205+
flexDirection: 'row',
206+
alignItems: 'center',
207+
justifyContent: 'space-between',
208+
padding: 16,
209+
},
210+
211+
leftSection: {
212+
flexDirection: 'row',
213+
alignItems: 'center',
214+
flex: 1,
215+
},
216+
217+
iconContainer: {
52218
width: 32,
53219
height: 32,
220+
borderRadius: 16,
221+
backgroundColor: Colors.green[100],
222+
justifyContent: 'center',
223+
alignItems: 'center',
224+
marginRight: 12,
54225
},
55-
name: {
56-
color: Colors.black,
226+
227+
downloadIcon: {
228+
color: Colors.green[200],
229+
fontSize: 18,
230+
fontWeight: 'bold',
231+
},
232+
233+
actionInfo: {
234+
flex: 1,
235+
},
236+
237+
titleRow: {
238+
flexDirection: 'row',
239+
justifyContent: 'space-between',
240+
alignItems: 'center',
241+
width: '100%',
242+
marginBottom: 4,
243+
},
244+
245+
actionName: {
57246
fontSize: 16,
58-
lineHeight: 24,
247+
color: Colors.black,
59248
...InterSemiBold,
60-
width: '100%',
249+
flex: 1,
61250
},
62-
date: {
63-
color: Colors.gray[100],
251+
252+
actionDate: {
253+
fontSize: 12,
254+
color: Colors.gray[500],
255+
...InterSmall,
256+
},
257+
258+
collectiveName: {
64259
fontSize: 14,
65-
lineHeight: 21,
66-
textAlign: 'left',
67-
width: '100%',
68-
...InterSemiBold,
260+
paddingBottom: 4,
261+
color: Colors.gray[200],
262+
...InterMedium,
263+
marginBottom: 2,
69264
},
70-
id: {
71-
fontSize: 10,
72-
lineHeight: 15,
73-
...InterRegular,
265+
266+
paymentAmount: {
267+
fontSize: 12,
268+
color: Colors.blue[200],
269+
...InterSmall,
270+
marginBottom: 4,
271+
},
272+
273+
chevronContainer: {
274+
padding: 0,
275+
display: 'flex',
276+
alignItems: 'center',
277+
justifyContent: 'center',
278+
marginLeft: 0,
279+
},
280+
281+
expandedContent: {
282+
borderTopWidth: 1,
283+
borderTopColor: Colors.gray[200],
284+
paddingVertical: 8,
285+
},
286+
287+
linkButton: {
288+
backgroundColor: 'transparent',
289+
paddingVertical: 8,
290+
paddingHorizontal: 16,
291+
},
292+
293+
linkText: {
294+
fontSize: 14,
295+
color: Colors.blue[200],
296+
textDecorationLine: 'underline',
297+
...InterMedium,
298+
},
299+
300+
linkTextDisabled: {
301+
fontSize: 14,
302+
color: Colors.gray[400],
303+
...InterMedium,
304+
},
305+
306+
collapseButton: {
307+
alignSelf: 'center',
308+
padding: 8,
309+
marginTop: 8,
310+
},
311+
312+
collapseIcon: {
313+
fontSize: 16,
314+
color: Colors.gray[400],
74315
},
75-
logProfileDetails: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },
76-
logDate: { alignItems: 'flex-end' },
77316
});
317+
78318
export default ActivityLog;

0 commit comments

Comments
 (0)