feat: initialize React Native mobile app with Expo
Core features implemented: - Expo cross-platform setup (iOS, Android, Web) - Bottom tab navigation (Home, Resources, Community, Profile) - Home screen with all major sections: * Hero section with mission statement * Happy Mail integration * Connect/Support section * Podcast information * Features grid * Wings of Remembrance - Resources screen with curated support materials - Community screen with support groups and circles - Profile screen with user account management - Auth layout structure (login, signup, forgot password) Ready for: - Authentication integration with FastAPI backend - API integration for community features - Database connectivity - Testing on iOS, Android, and Web
This commit is contained in:
parent
229fd6ced4
commit
7eaacb08e1
8 changed files with 17382 additions and 0 deletions
17
mobile/app/(auth)/_layout.tsx
Normal file
17
mobile/app/(auth)/_layout.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Stack } from 'expo-router';
|
||||||
|
|
||||||
|
export default function AuthLayout() {
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: false,
|
||||||
|
gestureEnabled: false,
|
||||||
|
animationEnabled: true,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack.Screen name="login" />
|
||||||
|
<Stack.Screen name="signup" />
|
||||||
|
<Stack.Screen name="forgot-password" />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
69
mobile/app/(tabs)/_layout.tsx
Normal file
69
mobile/app/(tabs)/_layout.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Tabs } from 'expo-router';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
|
||||||
|
export default function TabLayout() {
|
||||||
|
return (
|
||||||
|
<Tabs
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: true,
|
||||||
|
tabBarActiveTintColor: '#0066cc',
|
||||||
|
tabBarInactiveTintColor: '#999',
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
borderBottomColor: '#e0e0e0',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
headerTitleStyle: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="index"
|
||||||
|
options={{
|
||||||
|
title: 'Home',
|
||||||
|
tabBarLabel: 'Home',
|
||||||
|
headerTitle: 'MoreThanADiagnosis',
|
||||||
|
tabBarIcon: ({ color, size }) => (
|
||||||
|
<Ionicons name="home" size={size} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs.Screen
|
||||||
|
name="resources"
|
||||||
|
options={{
|
||||||
|
title: 'Resources',
|
||||||
|
tabBarLabel: 'Resources',
|
||||||
|
tabBarIcon: ({ color, size }) => (
|
||||||
|
<Ionicons name="book" size={size} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs.Screen
|
||||||
|
name="community"
|
||||||
|
options={{
|
||||||
|
title: 'Community',
|
||||||
|
tabBarLabel: 'Community',
|
||||||
|
tabBarIcon: ({ color, size }) => (
|
||||||
|
<Ionicons name="people" size={size} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs.Screen
|
||||||
|
name="profile"
|
||||||
|
options={{
|
||||||
|
title: 'Profile',
|
||||||
|
tabBarLabel: 'Profile',
|
||||||
|
tabBarIcon: ({ color, size }) => (
|
||||||
|
<Ionicons name="person" size={size} color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
161
mobile/app/(tabs)/community.tsx
Normal file
161
mobile/app/(tabs)/community.tsx
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
SafeAreaView,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from 'react-native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
padding: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e0e0e0',
|
||||||
|
},
|
||||||
|
headerTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
communityCard: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
communityCardHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
communityIcon: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 20,
|
||||||
|
backgroundColor: '#f0f0f0',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginRight: 12,
|
||||||
|
},
|
||||||
|
communityTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
},
|
||||||
|
communityDescription: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 20,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
memberCount: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#999',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
joinButton: {
|
||||||
|
backgroundColor: '#0066cc',
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
borderRadius: 6,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
joinButtonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function CommunityScreen() {
|
||||||
|
const communities = [
|
||||||
|
{
|
||||||
|
title: 'Support Group',
|
||||||
|
description: 'Join our growing community of folks navigating chronic illness and cancer. Connect, share, and find strength together.',
|
||||||
|
members: '2,341 members',
|
||||||
|
icon: '👥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'The Living Room',
|
||||||
|
description: 'Exclusive support circle for members. A safe space to share your journey, connect with others, and find support.',
|
||||||
|
members: '856 members',
|
||||||
|
icon: '🛋️',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'The Journal',
|
||||||
|
description: 'Read inspiring stories from our community members as they navigate their journeys. Share your own story.',
|
||||||
|
members: '1,203 stories',
|
||||||
|
icon: '📖',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Podcast Community',
|
||||||
|
description: 'Discuss episodes of our podcast and connect with listeners who share your experiences.',
|
||||||
|
members: '432 members',
|
||||||
|
icon: '🎙️',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Text style={styles.headerTitle}>Community</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Join Our Communities</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{communities.map((community, index) => (
|
||||||
|
<View key={index} style={styles.section}>
|
||||||
|
<View style={styles.communityCard}>
|
||||||
|
<View style={styles.communityCardHeader}>
|
||||||
|
<View style={styles.communityIcon}>
|
||||||
|
<Text style={{ fontSize: 20 }}>{community.icon}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.communityTitle}>{community.title}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.communityDescription}>{community.description}</Text>
|
||||||
|
<Text style={styles.memberCount}>{community.members}</Text>
|
||||||
|
<TouchableOpacity style={styles.joinButton}>
|
||||||
|
<Text style={styles.joinButtonText}>Join Community</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<View style={[styles.section, { marginBottom: 40 }]}>
|
||||||
|
<View style={styles.communityCard}>
|
||||||
|
<Text style={styles.communityTitle}>Community Guidelines</Text>
|
||||||
|
<Text style={[styles.communityDescription, { marginTop: 8 }]}>
|
||||||
|
• Be respectful and supportive{'\n'}
|
||||||
|
• Share your authentic story{'\n'}
|
||||||
|
• Respect others' privacy{'\n'}
|
||||||
|
• No medical advice{'\n'}
|
||||||
|
• Check in, not out
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
244
mobile/app/(tabs)/index.tsx
Normal file
244
mobile/app/(tabs)/index.tsx
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
SafeAreaView,
|
||||||
|
StatusBar,
|
||||||
|
} from 'react-native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
},
|
||||||
|
scrollContent: {
|
||||||
|
paddingBottom: 20,
|
||||||
|
},
|
||||||
|
heroSection: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
padding: 20,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e0e0e0',
|
||||||
|
},
|
||||||
|
heroTitle: {
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
heroSubtitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 24,
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
primaryButton: {
|
||||||
|
backgroundColor: '#0066cc',
|
||||||
|
paddingVertical: 12,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
borderRadius: 8,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
primaryButtonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginTop: 20,
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
sectionDescription: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 20,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
cardContainer: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
marginBottom: 12,
|
||||||
|
borderLeftWidth: 4,
|
||||||
|
borderLeftColor: '#0066cc',
|
||||||
|
},
|
||||||
|
cardTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
cardDescription: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 18,
|
||||||
|
},
|
||||||
|
featureGrid: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
featureCard: {
|
||||||
|
width: '48%',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
marginBottom: 12,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
featureIcon: {
|
||||||
|
fontSize: 32,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
featureTitle: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
ctaButton: {
|
||||||
|
backgroundColor: '#0066cc',
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
borderRadius: 6,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
ctaButtonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function HomeScreen() {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<StatusBar barStyle="dark-content" backgroundColor="#fff" />
|
||||||
|
<ScrollView style={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
||||||
|
{/* Hero Section */}
|
||||||
|
<View style={styles.heroSection}>
|
||||||
|
<Text style={styles.heroTitle}>You are more than a diagnosis.</Text>
|
||||||
|
<Text style={styles.heroSubtitle}>
|
||||||
|
Connecting Through Stories, Thriving Through Community
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.primaryButton}>
|
||||||
|
<Text style={styles.primaryButtonText}>Join Our Community</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Happy Mail Section */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>💌 Happy Mail</Text>
|
||||||
|
<View style={styles.cardContainer}>
|
||||||
|
<Text style={styles.cardTitle}>Free Joy-Filled Snail Mail</Text>
|
||||||
|
<Text style={styles.cardDescription}>
|
||||||
|
Nerisa sends personalized snail mail to folks navigating cancer and chronic illness.
|
||||||
|
</Text>
|
||||||
|
<Text style={[styles.cardDescription, { marginTop: 8, fontWeight: '600' }]}>
|
||||||
|
Who can receive:
|
||||||
|
</Text>
|
||||||
|
<Text style={[styles.cardDescription, { marginTop: 4 }]}>
|
||||||
|
✓ Cancer diagnosis or treatment{'\n'}
|
||||||
|
✓ Chronic illness or rare disease{'\n'}
|
||||||
|
✓ Medical limbo or recovery
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.ctaButton}>
|
||||||
|
<Text style={styles.ctaButtonText}>Order Happy Mail</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Connect Section */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>🤝 Connect</Text>
|
||||||
|
<View style={styles.cardContainer}>
|
||||||
|
<Text style={styles.cardTitle}>Safe & Supportive Space</Text>
|
||||||
|
<Text style={styles.cardDescription}>
|
||||||
|
"We're here to create a safe, supportive space where you can connect with others, share your story, and find hope. Cancer and chronic illness can feel so isolating, but together, we're stronger."
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.ctaButton}>
|
||||||
|
<Text style={styles.ctaButtonText}>Learn More</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Podcast Section */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>🎙️ Podcast</Text>
|
||||||
|
<View style={styles.cardContainer}>
|
||||||
|
<Text style={styles.cardTitle}>More Than A Diagnosis Podcast</Text>
|
||||||
|
<Text style={styles.cardDescription}>
|
||||||
|
Hosted by Jes and Den, who share real stories about life beyond the medical chart.
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.ctaButton}>
|
||||||
|
<Text style={styles.ctaButtonText}>Listen Now</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Features Grid */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>What We Offer</Text>
|
||||||
|
<View style={styles.featureGrid}>
|
||||||
|
<View style={styles.featureCard}>
|
||||||
|
<Text style={styles.featureIcon}>📚</Text>
|
||||||
|
<Text style={styles.featureTitle}>Resources</Text>
|
||||||
|
<Text style={{ fontSize: 12, color: '#999', marginTop: 4 }}>
|
||||||
|
Curated support materials
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.featureCard}>
|
||||||
|
<Text style={styles.featureIcon}>👥</Text>
|
||||||
|
<Text style={styles.featureTitle}>Community</Text>
|
||||||
|
<Text style={{ fontSize: 12, color: '#999', marginTop: 4 }}>
|
||||||
|
Support groups & circles
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.featureCard}>
|
||||||
|
<Text style={styles.featureIcon}>📖</Text>
|
||||||
|
<Text style={styles.featureTitle}>Stories</Text>
|
||||||
|
<Text style={{ fontSize: 12, color: '#999', marginTop: 4 }}>
|
||||||
|
The Journal & experiences
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.featureCard}>
|
||||||
|
<Text style={styles.featureIcon}>🎁</Text>
|
||||||
|
<Text style={styles.featureTitle}>Shop</Text>
|
||||||
|
<Text style={{ fontSize: 12, color: '#999', marginTop: 4 }}>
|
||||||
|
Purpose-driven apparel
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Wings of Remembrance */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>🕊️ Wings of Remembrance</Text>
|
||||||
|
<View style={styles.cardContainer}>
|
||||||
|
<Text style={styles.cardTitle}>Honor Those Who Shaped Us</Text>
|
||||||
|
<Text style={styles.cardDescription}>
|
||||||
|
Share a tribute, memory, or reflection to honor those who shaped our journey.
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.ctaButton}>
|
||||||
|
<Text style={styles.ctaButtonText}>Share Your Tribute</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
260
mobile/app/(tabs)/profile.tsx
Normal file
260
mobile/app/(tabs)/profile.tsx
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
SafeAreaView,
|
||||||
|
TouchableOpacity,
|
||||||
|
Alert,
|
||||||
|
} from 'react-native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
},
|
||||||
|
profileHeader: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingVertical: 24,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e0e0e0',
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
borderRadius: 40,
|
||||||
|
backgroundColor: '#0066cc',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
avatarText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
profileName: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
profileStatus: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#666',
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#999',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
menuItem: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingVertical: 14,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#f0f0f0',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
menuItemFirst: {
|
||||||
|
borderTopLeftRadius: 12,
|
||||||
|
borderTopRightRadius: 12,
|
||||||
|
},
|
||||||
|
menuItemLast: {
|
||||||
|
borderBottomLeftRadius: 12,
|
||||||
|
borderBottomRightRadius: 12,
|
||||||
|
borderBottomWidth: 0,
|
||||||
|
},
|
||||||
|
menuIcon: {
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginRight: 12,
|
||||||
|
},
|
||||||
|
menuLabel: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: '#000',
|
||||||
|
flex: 1,
|
||||||
|
fontWeight: '500',
|
||||||
|
},
|
||||||
|
menuArrow: {
|
||||||
|
color: '#999',
|
||||||
|
},
|
||||||
|
signOutButton: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingVertical: 12,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 8,
|
||||||
|
borderRadius: 12,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#ff4444',
|
||||||
|
},
|
||||||
|
signOutText: {
|
||||||
|
color: '#ff4444',
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function ProfileScreen() {
|
||||||
|
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||||
|
|
||||||
|
const handleSignOut = () => {
|
||||||
|
Alert.alert('Sign Out', 'Are you sure you want to sign out?', [
|
||||||
|
{ text: 'Cancel', onPress: () => {} },
|
||||||
|
{
|
||||||
|
text: 'Sign Out',
|
||||||
|
onPress: () => {
|
||||||
|
setIsLoggedIn(false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isLoggedIn) {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<View style={styles.profileHeader}>
|
||||||
|
<View style={styles.avatar}>
|
||||||
|
<Ionicons name="person" size={40} color="#fff" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.profileName}>Welcome</Text>
|
||||||
|
<Text style={styles.profileStatus}>Sign in to access your profile</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.menuItem, styles.menuItemFirst, styles.menuItemLast]}
|
||||||
|
onPress={() => setIsLoggedIn(true)}
|
||||||
|
>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="log-in" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Sign In</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>About</Text>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemFirst]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="information-circle" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>About Us</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.menuItem}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="shield-checkmark" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Privacy Policy</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemLast]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="document-text" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Terms of Service</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
|
<View style={styles.profileHeader}>
|
||||||
|
<View style={styles.avatar}>
|
||||||
|
<Text style={styles.avatarText}>👤</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.profileName}>John Doe</Text>
|
||||||
|
<Text style={styles.profileStatus}>Active Member</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Account</Text>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemFirst]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="person" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Edit Profile</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.menuItem}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="notifications" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Notifications</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemLast]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="lock-closed" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Change Password</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Preferences</Text>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemFirst]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="moon" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Dark Mode</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemLast]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="language" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Language</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.section}>
|
||||||
|
<Text style={styles.sectionTitle}>Help</Text>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemFirst]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="help-circle" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Help & Support</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={[styles.menuItem, styles.menuItemLast]}>
|
||||||
|
<View style={styles.menuIcon}>
|
||||||
|
<Ionicons name="mail" size={20} color="#0066cc" />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.menuLabel}>Contact Us</Text>
|
||||||
|
<Ionicons name="chevron-forward" size={20} style={styles.menuArrow} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={[styles.section, { marginBottom: 40 }]}>
|
||||||
|
<TouchableOpacity style={styles.signOutButton} onPress={handleSignOut}>
|
||||||
|
<Text style={styles.signOutText}>Sign Out</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
136
mobile/app/(tabs)/resources.tsx
Normal file
136
mobile/app/(tabs)/resources.tsx
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
SafeAreaView,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
padding: 16,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e0e0e0',
|
||||||
|
},
|
||||||
|
headerTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
headerDescription: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 20,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
resourceCard: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 16,
|
||||||
|
marginBottom: 12,
|
||||||
|
borderLeftWidth: 4,
|
||||||
|
borderLeftColor: '#0066cc',
|
||||||
|
},
|
||||||
|
resourceTitle: {
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#000',
|
||||||
|
marginBottom: 6,
|
||||||
|
},
|
||||||
|
resourceDescription: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#666',
|
||||||
|
lineHeight: 18,
|
||||||
|
},
|
||||||
|
resourceLink: {
|
||||||
|
marginTop: 10,
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
backgroundColor: '#f0f0f0',
|
||||||
|
borderRadius: 6,
|
||||||
|
},
|
||||||
|
resourceLinkText: {
|
||||||
|
color: '#0066cc',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function ResourcesScreen() {
|
||||||
|
const resources = [
|
||||||
|
{
|
||||||
|
title: 'Financial Support',
|
||||||
|
description: 'Resources for managing medical costs and financial burdens',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mental Health',
|
||||||
|
description: 'Mental health services and counseling resources',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Medical Information',
|
||||||
|
description: 'Reliable health information and diagnosis resources',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Support Groups',
|
||||||
|
description: 'Connect with others on similar health journeys',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Nutrition & Wellness',
|
||||||
|
description: 'Health and wellness resources during treatment',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Legal Resources',
|
||||||
|
description: 'Information about health law and patient rights',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Text style={styles.headerTitle}>Resources</Text>
|
||||||
|
<Text style={styles.headerDescription}>
|
||||||
|
We know how scary and overwhelming it can be to receive a diagnosis. We've curated helpful resources to make your journey a little easier.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{resources.map((resource, index) => (
|
||||||
|
<View key={index} style={styles.section}>
|
||||||
|
<View style={styles.resourceCard}>
|
||||||
|
<Text style={styles.resourceTitle}>{resource.title}</Text>
|
||||||
|
<Text style={styles.resourceDescription}>{resource.description}</Text>
|
||||||
|
<TouchableOpacity style={styles.resourceLink}>
|
||||||
|
<Text style={styles.resourceLinkText}>Learn More →</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<View style={[styles.section, { marginBottom: 40 }]}>
|
||||||
|
<Text style={styles.sectionTitle}>More Coming Soon</Text>
|
||||||
|
<Text style={{ fontSize: 14, color: '#666', lineHeight: 20 }}>
|
||||||
|
Be sure to check back often or sign up to receive updates as we're adding new resources all the time!
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
mobile/app/_layout.tsx
Normal file
23
mobile/app/_layout.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Stack } from 'expo-router';
|
||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
export const unstable_settings = {
|
||||||
|
initialRouteName: '(tabs)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout() {
|
||||||
|
useEffect(() => {
|
||||||
|
// Setup any global configuration here
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StatusBar barStyle="dark-content" />
|
||||||
|
<Stack>
|
||||||
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||||
|
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
16472
mobile/package-lock.json
generated
Normal file
16472
mobile/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue