Skip to content

Commit

Permalink
Merge pull request #474 from bounswe/MOBILE-466
Browse files Browse the repository at this point in the history
feat(mobile): Tab Layout, Profile Page Design, Quiz Card Component
  • Loading branch information
aoengin authored Nov 11, 2024
2 parents 20ac49b + 652efe0 commit a1e119c
Show file tree
Hide file tree
Showing 30 changed files with 2,021 additions and 361 deletions.
18 changes: 2 additions & 16 deletions mobile/bulingo/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@ import FontAwesome from '@expo/vector-icons/FontAwesome';
import { Tabs } from 'expo-router';
import React, {useState} from 'react';
import {TouchableOpacity} from 'react-native';
import { ModalOverlay } from '../modalOverlay';

export default function TabLayout() {
const [isModalVisible, setIsModalVisible] = useState(false);

const openModal = () => setIsModalVisible(true);
const closeModal = () => setIsModalVisible(false);


return (
<>
<Tabs screenOptions={{ tabBarActiveTintColor: 'red' }}>
<Tabs screenOptions={{ tabBarActiveTintColor: 'red', headerShown: false, tabBarStyle:{paddingBottom:5, paddingTop: 5}}}>
<Tabs.Screen
name="index"
options={{
Expand All @@ -24,6 +17,7 @@ export default function TabLayout() {
<Tabs.Screen
name="quizzes"
options={{
headerShown: false,
title: 'Quizzes',
tabBarIcon: ({ color }) => <FontAwesome size={28} name="question" color={color} />,
}}
Expand All @@ -47,17 +41,9 @@ export default function TabLayout() {
options={{
title: 'Profile',
tabBarIcon: ({ color }) => <FontAwesome size={28} name="user" color={color} />,
headerRight: () => (
<TouchableOpacity onPress={openModal} style={{width: 40}}>
<FontAwesome size={28} name="ellipsis-v"/>
</TouchableOpacity>
),
}}
/>
</Tabs>
{isModalVisible && (
<ModalOverlay closeModal={closeModal} />
)}
</>
);
}
118 changes: 114 additions & 4 deletions mobile/bulingo/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,127 @@
import { View, Text, StyleSheet } from 'react-native';
import React, {useState} from 'react';
import {Image, Pressable, StyleSheet, Text, View} from 'react-native';
import { router } from "expo-router";
import TokenManager from '../TokenManager';

export default function Home() {
const handleRegister = () => {
router.navigate("/register")
};
const username = TokenManager.getUsername();

const handleLogOut = () => {
console.log("logout pressed");
TokenManager.setUsername(null);
TokenManager.clearTokens();
router.navigate('/')
}


export default function Tab() {
return (
<View style={styles.container}>
<Text>Home</Text>
<View style={styles.page}>
<View style={styles.profilePictureContainer}>
<Image
source={require('@/assets/images/profile-icon.png')}
style={styles.profilePicture}
/>
</View>
<View style={styles.messageContainer}>
<Text style={styles.bigText}>Welcome!</Text>
<Text style={username? styles.username : styles.text}>{username ? username :"You are not logged in. Register or Log In to access all features."}</Text>
</View>
{username ?
<View style={styles.buttonsContainer}>
<Pressable style={styles.rectangularButton} onPress={handleLogOut}>
<Text style={styles.buttonText}>Log Out</Text>
</Pressable>
</View> :
<View style={styles.buttonsContainer}>
<Pressable style={[styles.rectangularButton, {'backgroundColor': 'gray'}]} onPress={handleRegister} disabled={true}>
<Text style={styles.buttonText}>Register</Text>
</Pressable>
<Pressable style={styles.rectangularButton} onPress={() => { router.navigate("/login") }}>
<Text style={styles.buttonText}>Log In</Text>
</Pressable>
</View>
}

</View>
</View>
);
}


const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "flex-start",
padding: 20,
backgroundColor: '#fff'
},
page: {
flex: 1,
justifyContent: "flex-start",
alignItems: 'center',
padding: 20,
backgroundColor: '#fff'
},
profilePictureContainer:{
justifyContent: 'center',
margin: 10,
height: 200,
alignItems: 'center',
},
messageContainer:{
borderColor: '#000',
borderWidth: 3,
borderRadius: 16,
width: "90%",
height: 120,
padding: 3,
backgroundColor: '#b2f2bb',
margin: 10,
},
profilePicture: {
width: 192,
height: 192,
borderWidth: 4,
borderColor: '#000',
borderRadius: 96,
},
bigText: {
fontSize: 24,
textAlign: 'center',
},
text: {
fontSize: 16,
margin: 3,
textAlign: 'center',
},
rectangularButton: {
backgroundColor: "#9775fa",
width: '90%',
height: 50,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
borderWidth: 3,
borderColor: "#222",
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
fontSize: 22,
},
username: {
fontSize: 28,
textAlign: 'center',
},
buttonsContainer: {
width: '100%',
flex:1,
justifyContent: 'center',
alignItems: 'center'
},
});
});
65 changes: 65 additions & 0 deletions mobile/bulingo/app/(tabs)/profile/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Stack } from 'expo-router';
import { TouchableOpacity, StyleSheet } from 'react-native';
import React, {useState} from 'react';
import FontAwesome from '@expo/vector-icons/FontAwesome';
import { ModalOverlay } from './modalOverlay';

export default function StackLayout(){
const [isModalVisible, setIsModalVisible] = useState(false);

const openModal = () => setIsModalVisible(true);
const closeModal = () => setIsModalVisible(false);


return (
<>
<Stack>
<Stack.Screen
name='index'
options={{
title: 'profile',
headerTitleStyle: styles.titleText,
headerRight: () => (
<TouchableOpacity onPress={openModal} style={styles.moreOptions}>
<FontAwesome size={28} name="ellipsis-v"/>
</TouchableOpacity>
),
}}
/>
<Stack.Screen
name="followers"
options={{
title: 'profile',
}}
/>
<Stack.Screen
name="following"
options={{
title: 'profile',
}}
/>
<Stack.Screen
name="editProfile"
options={{
title: 'profile',
}}
/>
</Stack>
{isModalVisible && (
<ModalOverlay closeModal={closeModal} />
)}
</>
);
};

const styles =StyleSheet.create({
moreOptions: {
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 10,
paddingVertical: 5,
},
titleText: {
fontWeight: 'bold',
},
});
103 changes: 103 additions & 0 deletions mobile/bulingo/app/(tabs)/profile/bookmarkedPostsAndComments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React, { useState, useEffect } from 'react';
import {Text, StyleSheet, FlatList, View, TouchableWithoutFeedback, ActivityIndicator } from 'react-native';

type BookmarkedPostsAndCommentsInfoPlaceholder = { // Placeholder, remove when post/comment Card is ready.
name: string,
};

export default function Followers() {
const [isLoading, setIsLoading] = useState(true);
const [bookmarkedPostsAndComments, setBoormarkedPostAndComments] = useState<BookmarkedPostsAndCommentsInfoPlaceholder[]>([
{name: 'Post 1'}, // Placeholder
{name: 'Post 2'}, // Placeholder
{name: 'Comment 1'}, // Placeholder
{name: 'Comment 2'}, // Placeholder
])

useEffect(() => {
const ENDPOINT_URL = "http://161.35.208.249:8000/bookmarkedpostsandcomments"; // Placeholder
const fetchFollowers = async () => {
const params = {
// TODO
};
try {
const response = await fetch(ENDPOINT_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});

if (response.ok){
setBoormarkedPostAndComments(await response.json());
} else {
console.log(response.status)
};
} catch (error) {
console.error(error);
}
setIsLoading(false);
};
fetchFollowers();
}, []);

if(isLoading){
return (
<TouchableWithoutFeedback>
<View style={styles.overlay}>
<ActivityIndicator size="large" color="#fff" />
</View>
</TouchableWithoutFeedback>
);
};

return (
<FlatList
data={bookmarkedPostsAndComments}
keyExtractor={(item) => item.name} // Placeholder, change with post/comment card
renderItem={({item}) => { // Placeholder, replace with post/comment card
return (
<View style={{height: 100, borderWidth: 3, borderColor: 'black', borderRadius: 15, justifyContent: 'center', alignItems: 'center', marginHorizontal: 15, marginVertical: 5,}}>
<Text>Placeholder Item: {item.name}</Text>
</View>
);
}}
ListHeaderComponent={
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Bookmarked Posts And Comments</Text>
</View>
}
style={styles.list}
/>
);
}

const styles = StyleSheet.create({
list: {
margin: 0,
padding: 5,
},
headerContainer: {
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 10,
},
headerText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
},
overlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1,
},
});

Loading

0 comments on commit a1e119c

Please sign in to comment.