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,
+},
});