diff --git a/apps/mobile/src/components/ProfileLink.tsx b/apps/mobile/src/components/ProfileLink.tsx new file mode 100644 index 0000000..4cc5f8c --- /dev/null +++ b/apps/mobile/src/components/ProfileLink.tsx @@ -0,0 +1,79 @@ +// components/ProfileLink.tsx + +import React from 'react'; +import { + Linking, + Pressable, + Text, + View, + StyleSheet, +} from 'react-native'; + +type ProfileLinkProps = { + platform: string; + username: string; + url: string; + onPress?: () => void; +}; +import { + COLORS, + SPACING, + FONT_SIZE, + BORDER_RADIUS, +} from '../theme/tokens'; +export default function ProfileLink({ + platform, + username, + url, + onPress, +}: ProfileLinkProps) { + const handlePress = () => { + if (onPress) { + onPress(); + return; + } + + Linking.openURL(url); + }; + + return ( + + + {platform} + {username} + + + Open + + ); +} + +const styles = StyleSheet.create({ + card: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: SPACING.md, + borderRadius: BORDER_RADIUS.md, + backgroundColor: COLORS.bgCard, + marginBottom: SPACING.sm, + }, + + platform: { + fontSize: FONT_SIZE.md, + fontWeight: '600', + color: COLORS.textPrimary, + }, + + username: { + marginTop: SPACING.xs, + fontSize: FONT_SIZE.sm, + color: COLORS.textMuted, + }, + + link: { + fontSize: FONT_SIZE.sm, + fontWeight: '600', + color: COLORS.primary, + }, +}); \ No newline at end of file diff --git a/apps/mobile/src/screens/HomeScreen.tsx b/apps/mobile/src/screens/HomeScreen.tsx index 80de203..c840ff2 100644 --- a/apps/mobile/src/screens/HomeScreen.tsx +++ b/apps/mobile/src/screens/HomeScreen.tsx @@ -18,6 +18,8 @@ import { PLATFORMS } from '@devcard/shared'; import { APP_URL, API_BASE_URL } from '../config'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import type { RootStackParamList } from '../navigation/MainTabs'; +import ProfileLink from '../components/ProfileLink'; + type Props = { navigation: NativeStackNavigationProp; @@ -38,7 +40,7 @@ export default function HomeScreen({ navigation }: Props) { const [showQR, setShowQR] = useState(false); const [refreshing, setRefreshing] = useState(false); - const profileUrl = user?.defaultCardId + const profileUrl = user?.defaultCardId ? `${APP_URL}/devcard/${user.defaultCardId}` : `${APP_URL}/u/${user?.username}`; @@ -133,95 +135,98 @@ export default function HomeScreen({ navigation }: Props) { {user?.bio && {user.bio}} - {/* Platform Links Summary */} - + {/* Platform Links */} + {links.slice(0, 4).map(link => { const platform = PLATFORMS[link.platform]; + return ( - - - {platform?.name || link.platform} - - + ); })} - {links.length > 4 && ( - - +{links.length - 4} - - )} + {links.length > 4 && ( + + +{links.length - 4} + + )} + - {/* QR Code Section */} + {/* QR Code Section */} + setShowQR(!showQR)} + activeOpacity={0.85}> + {showQR ? ( + + + Scan to open your DevCard + + ) : ( + + 📱 + Tap to show QR code + + )} + + + {/* Action Buttons */} + setShowQR(!showQR)} + style={styles.actionButton} + onPress={handleShare} activeOpacity={0.85}> - {showQR ? ( - - - Scan to open your DevCard - - ) : ( - - 📱 - Tap to show QR code - - )} + 📤 + Share Card - {/* Action Buttons */} - - - 📤 - Share Card - + (navigation as any).navigate('Views')} + activeOpacity={0.85}> + 📈 + Analytics + - (navigation as any).navigate('Views')} - activeOpacity={0.85}> - 📈 - Analytics - + (navigation as any).navigate('DevCardView', { username: user?.username || '' })} + activeOpacity={0.85}> + 👁️ + Preview + + - (navigation as any).navigate('DevCardView', { username: user?.username || '' })} - activeOpacity={0.85}> - 👁️ - Preview - + {/* Stats */} + + + {links.length} + Links - - {/* Stats */} - - - {links.length} - Links - - - - {analytics?.totalViews || 0} - Views - - - - {analytics?.followsCount || 0} - Follows - + + + {analytics?.totalViews || 0} + Views + + + + {analytics?.followsCount || 0} + Follows - - + + + ); } @@ -299,4 +304,8 @@ const styles = StyleSheet.create({ statNumber: { fontSize: FONT_SIZE.xl, fontWeight: '800', color: COLORS.primary }, statLabel: { fontSize: FONT_SIZE.xs, color: COLORS.textMuted, marginTop: 4 }, statDivider: { width: 1, backgroundColor: COLORS.border }, + linksContainer: { + marginTop: SPACING.md, + gap: SPACING.sm, +}, });