diff --git a/frontend/App.js b/frontend/App.js
index 4e1bd0c..dce42bb 100644
--- a/frontend/App.js
+++ b/frontend/App.js
@@ -16,11 +16,23 @@ import Login from './app/screens/Login';
import ForgotPassword from './app/screens/ForgotPassword';
import SignupStepOne from './app/screens/signupStepOne';
import SignupStepTwo from './app/screens/signupStepTwo';
-
+import CreateCommunity from './app/screens/CreateCommunity';
const Stack = createNativeStackNavigator();
const BottomTab = createBottomTabNavigator();
+const CommunityStack = createNativeStackNavigator();
+const CommunityStackGroup = () => {
+ return (
+
+
+
+
+ );
+}
const BottomTabGroup = () => {
return (
{
-
+
);
}
diff --git a/frontend/app/screens/CreateCommunity.js b/frontend/app/screens/CreateCommunity.js
new file mode 100644
index 0000000..e1e0180
--- /dev/null
+++ b/frontend/app/screens/CreateCommunity.js
@@ -0,0 +1,332 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { View, Text, StyleSheet, ScrollView, Image, TouchableOpacity, TextInput, SafeAreaView, KeyboardAvoidingView, Platform } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+import * as ImagePicker from 'expo-image-picker';
+
+const CreateCommunity = () => {
+ // State management for form inputs
+ const [communityName, setCommunityName] = useState('');
+ const [description, setDescription] = useState('');
+ const [selectedIcon, setSelectedIcon] = useState(null);
+ const [category, setCategory] = useState('');
+
+ const nameInputRef = useRef(null);
+ const navigation = useNavigation();
+
+ useEffect(() => {
+ setTimeout(() => {
+ if(nameInputRef.current) {
+ nameInputRef.current.focus();
+ }
+ },100);
+ }, []);
+
+ // Function to handle icon selection
+ const selectIcon = async () => {
+ // Request permission to access media library
+ const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
+
+ if (!permissionResult.granted) {
+ alert("Permission to access media library is required!");
+ return;
+ }
+
+ // Launch the image picker
+ const pickerResult = await ImagePicker.launchImageLibraryAsync({
+ mediaTypes: ImagePicker.MediaTypeOptions.Images,
+ allowsEditing: true,
+ aspect: [1, 1], // Square aspect ratio
+ quality: 1, // High quality
+ });
+
+ if (!pickerResult.canceled) {
+ // Set the selected image URI
+ setSelectedIcon(pickerResult.assets[0].uri);
+ }
+ };
+
+ const handleCreateCommunity = () => {
+ // Validation checks for required fields
+ if (!communityName.trim()) {
+ alert("Please enter a name for your community");
+ return;
+ }
+
+ if (!description.trim()) {
+ alert("Please enter a description for your community");
+ return;
+ }
+
+ if (!category.trim()) {
+ alert("Please select a category for your community");
+ return;
+ }
+
+ // Create community object with all form data
+ const community = {
+ name: communityName,
+ description: description,
+ icon: selectedIcon,
+ category: category,
+ createdAt: new Date().toISOString(),
+ };
+
+ // Log new community details and navigate back
+ // In a real app, this would likely save to a database
+ console.log("Creating community:", community);
+ alert("Community created successfully!");
+ navigation.goBack();
+ };
+ return (
+
+
+ {/* Header Section with back button and title */}
+
+ navigation.goBack()} style={styles.backButton}>
+ ←
+
+ Create Community
+
+
+
+
+ {/* Icon Selection Section */}
+
+
+ {selectedIcon ? (
+
+ ) : (
+
+ Add Icon
+
+ )}
+
+
+
+ {/* Community Name Input */}
+ Community Name*
+
+
+ {/* Description Input - Multiline text area */}
+ Description*
+
+
+ {/* Category Input */}
+ Category*
+
+
+ {/* Private Community option has been removed */}
+
+ {/* Community Guidelines/Rules Section */}
+
+ Community Guidelines
+
+ • Be respectful and supportive to other members
+ {"\n"}• No spam or self-promotion
+ {"\n"}• Keep discussions relevant to the community purpose
+
+
+
+
+ {/* Create Button Section - Footer */}
+
+
+ Create Community
+
+
+
+
+ );
+};
+
+// Styles definition and component export
+const styles = StyleSheet.create({
+ // Container and layout styles
+ container: {
+ flex: 1,
+ backgroundColor: "#fff"
+ },
+ keyboardAvoidingView: {
+ flex: 1
+ },
+ header: {
+ height: 60,
+ borderBottomWidth: 1,
+ borderBottomColor: "#E0E0E0",
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ paddingHorizontal: 16
+ },
+ backButton: {
+ padding: 8,
+ },
+ backButtonText: {
+ fontSize: 24,
+ fontWeight: "bold",
+ },
+ headerTitle: {
+ fontSize: 18,
+ fontWeight: "bold"
+ },
+ placeholder: {
+ width: 40,
+ },
+ scrollView: {
+ flex: 1,
+ padding: 16
+ },
+
+ // Icon section styles
+ iconSection: {
+ alignItems: "center",
+ marginBottom: 24,
+ },
+ iconPicker: {
+ width: 100,
+ height: 100,
+ borderRadius: 50,
+ overflow: "hidden",
+ borderWidth: 2,
+ borderColor: "#4CAF50",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ iconPreview: {
+ width: "100%",
+ height: "100%",
+ },
+ iconPlaceholder: {
+ backgroundColor: "#F2F2F2",
+ width: "100%",
+ height: "100%",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ iconPlaceholderText: {
+ fontSize: 14,
+ color: "#4CAF50",
+ textAlign: "center",
+ },
+
+ // Form input styles
+ inputLabel: {
+ fontSize: 16,
+ fontWeight: "600",
+ marginBottom: 8,
+ color: "#333",
+ },
+ input: {
+ borderWidth: 1,
+ borderColor: "#E0E0E0",
+ borderRadius: 8,
+ padding: 12,
+ fontSize: 16,
+ marginBottom: 16,
+ },
+ descriptionInput: {
+ borderWidth: 1,
+ borderColor: "#E0E0E0",
+ borderRadius: 8,
+ padding: 12,
+ fontSize: 16,
+ minHeight: 100,
+ marginBottom: 16,
+ },
+
+ // Privacy section styles
+ privacySection: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ backgroundColor: "#F8F8F8",
+ borderRadius: 8,
+ padding: 16,
+ marginBottom: 16,
+ },
+ privacyTextContainer: {
+ flex: 1,
+ },
+ privacyTitle: {
+ fontSize: 16,
+ fontWeight: "600",
+ },
+ privacyDescription: {
+ fontSize: 14,
+ color: "#666",
+ marginTop: 4,
+ },
+
+ // Rules section styles
+ rulesSection: {
+ borderWidth: 1,
+ borderColor: "#E0E0E0",
+ borderRadius: 8,
+ padding: 16,
+ marginBottom: 32,
+ },
+ rulesTitle: {
+ fontSize: 16,
+ fontWeight: "600",
+ marginBottom: 8,
+ },
+ rulesText: {
+ fontSize: 14,
+ lineHeight: 22,
+ color: "#666",
+ },
+
+ // Footer and button styles
+ footer: {
+ padding: 16,
+ borderTopWidth: 1,
+ borderTopColor: "#E0E0E0",
+ },
+ createButton: {
+ backgroundColor: "#4CAF50",
+ borderRadius: 8,
+ paddingVertical: 14,
+ alignItems: "center",
+ },
+ createButtonDisabled: {
+ backgroundColor: "#BDBDBD",
+ },
+ createButtonText: {
+ color: "white",
+ fontWeight: "bold",
+ fontSize: 16,
+ },
+});
+
+export default CreateCommunity;
\ No newline at end of file
diff --git a/frontend/app/screens/tabs/Community.js b/frontend/app/screens/tabs/Community.js
index b9214c4..131bfbc 100644
--- a/frontend/app/screens/tabs/Community.js
+++ b/frontend/app/screens/tabs/Community.js
@@ -1,140 +1,304 @@
-import React from "react";
-import { View, Image, StyleSheet, Text, TextInput } from "react-native";
+import React, { useState } from "react";
+import {
+ View,
+ Image,
+ StyleSheet,
+ Text,
+ TextInput,
+ ScrollView,
+ TouchableOpacity,
+} from "react-native";
import Card from "../../fragments/card";
+import { useNavigation} from "@react-navigation/native";
+import AntDesign from '@expo/vector-icons/AntDesign';
// Main community card(ReWire Community)
export default function Community() {
-
- return (
-
-
-
- console.log("Searching for:", text)}
- />
-
- Main Community
- console.log("Card Pressed")} style={styles.communitycard}>
-
-
- ReWire Community
-
-
-
- Joined Community
- console.log("Card Pressed")} style={styles.communitycard}>
-
-
- Braking Habits
-
-
-
- console.log("Card Pressed")} style={styles.communitycard}>
-
-
- Fight For Freedom
-
-
-
- Suggestions
- console.log("Card Pressed")} style={styles.communitycard}>
-
-
- Rise from Darkness
-
-
-
- console.log("Card Pressed")}style={styles.communitycard}>
-
-
- Better Future Together
-
-
-
- console.log("Create Community Pressed")} style={styles.CreateCommCard}>
-
-
- Create Community
-
-
-
- );
-}
+ const navigation = useNavigation();
-// Card stylesheet
-const styles = StyleSheet.create({
- searchContainer: {
- flexDirection: "row",
- alignItems: "center",
- backgroundColor: "#D9D9D6",
- borderRadius: 30,
- padding: 10,
- marginBottom: 5,
- },
- searchIcon: {
- width: 20,
- height: 20,
- marginRight: 10,
- },
- searchInput: {
- flex: 1,
- fontSize: 16,
+ const [joinedCommunities, setJoinedCommunities] = useState([
+ {
+ id: "0001",
+ name: 'Braking Habits',
+ image: require("../../assets/habits.jpeg"),
+ members: 100,
},
-
- titleContainer: {
- flexDirection: "row",
- alignItems: "center",
- gap: 30,
+ {
+ id: "0002",
+ name: 'Fight For Freedom',
+ image: require("../../assets/freedom.jpeg"),
+ members: 67,
},
+ ]);
- communitycard: {
- borderRadius: 30,
+ const [suggestedCommunities, setSuggestedCommunities] = useState([
+ {
+ id: "0003",
+ name: 'Rise from Darkness',
+ image: require("../../assets/rise.png"),
+ members: 45,
},
- image: {
- width: 40,
- height: 40,
- borderRadius: 40,
- borderColor: "green",
- borderWidth: 2,
- },
- text: {
- color: "grey",
- fontSize: 14,
- paddingLeft: 5,
- paddingBottom: 10,
- textAlign: "left",
- },
- CreateCommCard: {
- backgroundColor: '#D9D9D6',
- padding: 10,
- borderRadius: 45,
- marginTop: 10,
+ {
+ id: "0004",
+ name: 'Better Future Together',
+ image: require("../../assets/better future.jpeg"),
+ members: 23,
},
- createCommContainer:{
- flexDirection: "row",
- alignItems: "center",
- justifyContent: "center",
- padding: 10,
+ {
+ id: "0005",
+ name: 'Better Future Together',
+ image: require("../../assets/better future.jpeg"),
+ members: 23,
},
- CommunityImage: {
- width: 50,
- height: 50,
- marginRight: 10,
- },
- commmunityText: {
- color: "green",
- fontSize: 18,
- fontWeight: "bold",
- paddingLeft: 5,
+ ]);
+
+ const [maincommunity, setMainCommunity] = useState([
+ {
+ id: "0000",
+ name: 'ReWire Community',
+ image: require("../../assets/rewire-logo.png"),
+ members: 200,
},
+ ]);
+
+ const handleJoinCommunity = (community) => {
+ setJoinedCommunities([...joinedCommunities, community]);
+ setSuggestedCommunities(suggestedCommunities.filter(c => c.id !== community.id));
+ };
+
+ const handleLeaveCommunity = (community) => {
+ setJoinedCommunities(joinedCommunities.filter(c => c.id !== community.id));
+ setSuggestedCommunities([...suggestedCommunities, community]);
+ };
+
+ const communityCard = (item, section) => (
+ console.log(item.name + " Card Pressed")}
+ style={styles.communitycard}
+ >
+
+
+
+
+ {item.name}
+ {item.members && {item.members} members}
+
+
+ {section !== 'mainCommunity' && (
+ {
+ e.stopPropagation();
+ section === 'joinedCommunities'
+ ? handleLeaveCommunity(item)
+ : handleJoinCommunity(item);
+ }}
+ >
+
+ {section === 'joinedCommunities' ? 'Joined' : 'Join'}
+
+
+ )}
+
+
+ );
+
+ return (
+
+
+
+ {/* Search bar */}
+
+
+ console.log("Searching for:", text)}
+ />
+
+
+ {/* Communities */}
+ Main Community
+ {communityCard(maincommunity[0], 'mainCommunity')}
+
+ Joined Community
+ {joinedCommunities.map((item) =>
+ communityCard(item, 'joinedCommunities')
+ )}
+
+ Suggestions
+ {suggestedCommunities.map((item) =>
+ communityCard(item, 'suggestedCommunities')
+ )}
+
+ {/* Create Community button as a card */}
+ {
+ console.log("Create Community pressed");
+ navigation.navigate("CreateCommunity");
+ }}
+ style={styles.CreateCard}
+ >
+
+
+ Create Community
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ borderRadius: 20,
+
+ },
+ searchBar: {
+ flexDirection: "row",
+ alignItems: "center",
+ backgroundColor: "#D9D9D6",
+ borderRadius: 15,
+ padding: 10,
+ marginBottom: 16,
+ marginTop: 5,
+ marginVertical: 10,
+ },
+ searchIcon: {
+ width: 20,
+ height: 20,
+ marginRight: 10,
+ },
+ searchInput: {
+ flex: 1,
+ fontSize: 16,
+ },
+ heading: {
+ color: "#333",
+ fontSize: 16,
+ fontWeight: "500",
+ paddingLeft: 5,
+ paddingVertical: 10,
+ },
+ card: {
+ borderRadius: 15,
+ marginBottom: 10,
+ backgroundColor: "#fff",
+ padding: 12,
+ shadowColor: "#000",
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.2,
+ shadowRadius: 2,
+ elevation: 2,
+ },
+ cardRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ },
+ leftContent: {
+ flexDirection: "row",
+ alignItems: "center",
+ flex: 1,
+ },
+ avatar: {
+ width: 40,
+ height: 40,
+ borderRadius: 40,
+ borderColor: "#4CAF50",
+ borderWidth: 2,
+ },
+ textBox: {
+ marginLeft: 15,
+ },
+ members: {
+ color: "grey",
+ fontSize: 12,
+ marginTop: -5,
+ },
+ button: {
+ paddingVertical: 6,
+ paddingHorizontal: 30,
+ borderRadius: 15,
+ borderWidth: 1,
+ },
+ greenButton: {
+ backgroundColor: "#4CAF50",
+ borderColor: "#4CAF50",
+ },
+ greenBorder: {
+ backgroundColor: "transparent",
+ borderColor: "#4CAF50",
+ },
+ buttonText: {
+ fontWeight: "bold",
+ fontSize: 12,
+ },
+ whiteText: {
+ color: "#fff",
+ },
+ greenText: {
+ color: "#4CAF50",
+ },
+ createCard: {
+ backgroundColor: "#D9D9D6",
+ marginTop: 5,
+ marginBottom: 10,
+ },
+ createContent: {
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ padding: 10,
+ },
+ createIcon: {
+ width: 50,
+ height: 50,
+ marginRight: 10,
+ },
+ createText: {
+ color: "green",
+ fontSize: 18,
+ fontWeight: "bold",
+ paddingLeft: 5,
+ },
+ scrollContent: {
+ paddingHorizontal: 16,
+ },
+ communitycard: {
+ marginBottom: 10,
+ borderRadius: 15,
+ padding: 12,
+ backgroundColor: "#fff",
+ shadowColor: "#000",
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.2,
+ shadowRadius: 2,
+ elevation: 2,
+ },
+ CreateCard: {
+ backgroundColor: "#D9D9D6",
+ marginTop: 10,
+ marginBottom: 20,
+ borderRadius: 15,
+ padding: 12,
+ },
});
\ No newline at end of file
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 21056f1..b93712c 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -17,6 +17,7 @@
"@rneui/base": "^4.0.0-rc.7",
"@rneui/themed": "^4.0.0-rc.8",
"expo": "~52.0.23",
+ "expo-image-picker": "^16.0.6",
"expo-status-bar": "~2.0.1",
"react": "18.3.1",
"react-dom": "18.3.1",
@@ -5982,6 +5983,27 @@
"react": "*"
}
},
+ "node_modules/expo-image-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.0.0.tgz",
+ "integrity": "sha512-Eg+5FHtyzv3Jjw9dHwu2pWy4xjf8fu3V0Asyy42kO+t/FbvW/vjUixpTjPtgKQLQh+2/9Nk4JjFDV6FwCnF2ZA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-image-picker": {
+ "version": "16.0.6",
+ "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.0.6.tgz",
+ "integrity": "sha512-HN4xZirFjsFDIsWFb12AZh19fRzuvZjj2ll17cGr19VNRP06S/VPQU3Tdccn5vwUzQhOBlLu704CnNm278boiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-image-loader": "~5.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-keep-awake": {
"version": "14.0.3",
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.3.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 6438063..2c96752 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -18,6 +18,7 @@
"@rneui/base": "^4.0.0-rc.7",
"@rneui/themed": "^4.0.0-rc.8",
"expo": "~52.0.23",
+ "expo-image-picker": "^16.0.6",
"expo-status-bar": "~2.0.1",
"react": "18.3.1",
"react-dom": "18.3.1",