Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/models/explore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface Topic {
title: string;
id: number;
abbreviated_title: string;
}

export interface MainTopic extends Topic {
topics: Topic[];
}
3 changes: 3 additions & 0 deletions src/navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import UserProfile from "./screens/user-profile";
import { User } from "./models/channel";
import IsWaitlisted from "./screens/is-waitlisted";
import Register from "./screens/signup";
import Explore from "./screens/explore";

export type StackParamList = {
Login: undefined;
Expand All @@ -24,6 +25,7 @@ export type StackParamList = {
UserProfile: { user_id: number; user: User };
IsWaitlisted: undefined;
Register: undefined;
Explore: undefined;
};

const Stack = createStackNavigator<StackParamList>();
Expand Down Expand Up @@ -82,6 +84,7 @@ const Navigator = () => {
component={UserProfile}
options={{ title: "" }}
/>
<Stack.Screen name="Explore" component={Explore} />
</>
)
) : (
Expand Down
216 changes: 216 additions & 0 deletions src/screens/explore.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import React, { useState } from "react";
import {
ActivityIndicator,
Dimensions,
Image,
LayoutAnimation,
StyleSheet,
Text,
TextInput,
View,
} from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import Screen from "../components/screen";
import req from "../utils/req";
import { APIResult } from "../models/api";
import { useQuery } from "react-query";
import { ScrollView } from "react-native-gesture-handler";
import { MainTopic, Topic } from "../models/explore";
import { User } from "../models/channel";
import defaultAvatar from "../assets/default-avatar";
import Flex from "../components/flex";
import Touchable from "../components/touchable";

const dims = Dimensions.get("window");

const Explore = () => {
const {
isLoading: loadingAllTopics,

data: topics,
} = useQuery("topics", () => getAllTopics());
const {
isLoading: loadingSuggestedFollows,
data: suggestedFollows,
} = useQuery("suggestedFollows", () => getSuggestedFollows());
const [numFollowsShown, setNumFollowsShown] = useState(3);

const getAllTopics = async () => {
const res = await req("/get_all_topics", {
method: "GET",
});
const resJson: APIResult<{ topics: MainTopic[] }> = await res.json();
console.log("all topics", resJson);
return resJson.topics;
};

const getSuggestedFollows = async () => {
const res = await req("/get_suggested_follows_all", {
method: "GET",
});
const resJson: APIResult<{ users: User[] }> = await res.json();
console.log("all suggested follows", resJson);
return resJson.users;
};

const showMoreFollow = () => {
setNumFollowsShown(numFollowsShown + 7);
LayoutAnimation.easeInEaseOut();
};

return (
<Screen style={styles.container}>
<View style={styles.searchInputContainer}>
<MaterialCommunityIcons name="magnify" size={22} />
<TextInput placeholder="Find People and Clubs" />
</View>
<ScrollView>
<Text style={styles.sectionTitle}>PEOPLE TO FOLLOW</Text>
<View style={styles.peopleToFollowContainer}>
{!loadingSuggestedFollows &&
suggestedFollows?.slice(0, numFollowsShown)?.map((user) => (
<View style={styles.userContainer}>
<Image
source={{ uri: user.photo_url ?? defaultAvatar }}
style={styles.userAvatar}
/>
<Flex style={{ marginLeft: 16 }}>
<Text style={styles.userFullName}>{user.name}</Text>
<Text>@{user.username}</Text>
</Flex>

<Touchable style={styles.followBtn}>
<Text style={styles.followBtnTitle}>Follow</Text>
</Touchable>
</View>
))}
<Touchable style={styles.showMoreFollowsBtn} onPress={showMoreFollow}>
<Text style={styles.showMoreFollowsBtnTitle}>Show more people</Text>
</Touchable>
</View>

<Text style={[styles.sectionTitle, {}]}>
FIND CONVERSATIONS ABOUT...
</Text>
<View style={styles.topicsContainer}>
{loadingAllTopics ? (
<ActivityIndicator />
) : (
topics?.map((topic) => (
<View style={styles.topic}>
<Text style={styles.topicTitle}>{topic.title}</Text>
<Text style={styles.topicInfo} numberOfLines={2}>
{topic.topics.map((t) => t.abbreviated_title).join(", ")}
</Text>
</View>
))
)}
</View>
</ScrollView>
</Screen>
);
};

const styles = StyleSheet.create({
container: {},
searchInputContainer: {
backgroundColor: "#E1E0D9",
borderRadius: 8,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 8,
marginHorizontal: 16,
},
sectionTitle: {
fontFamily: "Nunito-Bold",
marginLeft: 16,
marginTop: 24,
marginBottom: 8,
color: "#8D866C",
},
peopleToFollowContainer: {
width: "100%",
backgroundColor: "#fff",
paddingVertical: 16,
marginBottom: 16,
},
userContainer: {
width: "100%",
alignItems: "center",
paddingHorizontal: 16,
flexDirection: "row",
marginBottom: 16,
},
userAvatar: {
width: 60,
height: 60,
borderRadius: 28,
},
userFullName: {
fontFamily: "Nunito-Bold",
fontSize: 15,
color: "#070707",
},
username: {
fontFamily: "Nunito-Regular",
},
followBtn: {
borderWidth: 2,
borderColor: "#6180B0",
borderRadius: 360,
paddingHorizontal: 16,
paddingVertical: 3,
marginLeft: "auto",
},
followBtnTitle: {
fontFamily: "Nunito-Regular",
color: "#6180B0",
},
showMoreFollowsBtn: {
backgroundColor: "#E7E3D5",
borderRadius: 360,
paddingVertical: 8,
paddingHorizontal: 16,
alignSelf: "center",
position: "absolute",
bottom: -16,
},
showMoreFollowsBtnTitle: {
color: "#766B50",
fontFamily: "Nunito-Regular",
},
topicsContainer: {
width: "100%",
flexDirection: "row",
flexWrap: "wrap",
paddingLeft: 16,
},
topic: {
width: dims.width / 2 - 24,
marginRight: 16,
backgroundColor: "#fff",
borderRadius: 8,
marginBottom: 16,
shadowColor: "rgba(0,0,0,5)",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.1,
shadowRadius: 0.1,
elevation: 1,
padding: 10,
},
topicTitle: {
fontFamily: "Nunito-Bold",
color: "#353535",
fontSize: 15,
},
topicInfo: {
fontFamily: "Nunito-SemiBold",
color: "#808080",
marginTop: 4,
},
});

export default Explore;
28 changes: 28 additions & 0 deletions src/screens/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const Home: FC<Props> = ({ navigation }) => {
return resJson;
};

const navigateToExplore = () => navigate("Explore");

const renderChannel = ({ item, index }: { item: Channel; index: number }) => (
<Touchable
key={item.channel}
Expand Down Expand Up @@ -113,6 +115,17 @@ const Home: FC<Props> = ({ navigation }) => {
</Touchable>
);

const renderExploreButton = () => (
<Touchable style={styles.exploreButton} onPress={navigateToExplore}>
<MaterialCommunityIcons
name="earth"
size={18}
style={{ marginRight: 4 }}
/>
<Text style={styles.exploreButtonTitle}>Explore</Text>
</Touchable>
);

return (
<Screen
style={{
Expand Down Expand Up @@ -154,6 +167,7 @@ const Home: FC<Props> = ({ navigation }) => {
refreshControl={
<RefreshControl refreshing={isLoading} onRefresh={refetch} />
}
ListFooterComponent={renderExploreButton()}
/>
<RoomMiniPlayer />
</Screen>
Expand All @@ -178,6 +192,7 @@ const styles = StyleSheet.create({
},
channelsContainer: {
paddingHorizontal: 16,
paddingBottom: 80,
},
channel: {
width: "100%",
Expand Down Expand Up @@ -231,6 +246,19 @@ const styles = StyleSheet.create({
fontFamily: "Nunito-SemiBold",
color: "#49464A",
},

exploreButton: {
backgroundColor: "#E8E3D7",
borderRadius: 16,
flexDirection: "row",
padding: 8,
paddingHorizontal: 16,
alignSelf: "center",
},
exploreButtonTitle: {
fontFamily: "Nunito-SemiBold",
color: "#8D8773",
},
});

export default Home;