Skip to content
Snippets Groups Projects
Commit 9fe85f2e authored by neyney2810's avatar neyney2810
Browse files

database config

parent c54332ac
Branches
No related tags found
No related merge requests found
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
import React, { useState, createContext, useContext, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { View, ActivityIndicator } from 'react-native';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './config/firebase';
import Login from './screens/Login';
import Signup from './screens/Signup';
import Chat from './screens/Chat';
import Home from './screens/Home';
import React, { useState, createContext, useContext, useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { View, ActivityIndicator } from "react-native";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "./config/firebase";
import Login from "./screens/auth/Login";
import Signup from "./screens/auth/Signup";
import Chat from "./screens/tabs/Chat";
import Home from "./screens/tabs/Home";
import ChatList from "./screens/tabs/ChatList";
import Catsitter from "./screens/tabs/Catsitter";
const Stack = createStackNavigator();
const AuthenticatedUserContext = createContext({});
const AuthenticatedUserProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AuthenticatedUserContext.Provider value={{ user, setUser }}>
{children}
</AuthenticatedUserContext.Provider>
);
return <AuthenticatedUserContext.Provider value={{ user, setUser }}>{children}</AuthenticatedUserContext.Provider>;
};
function ChatStack() {
return (
<Stack.Navigator defaultScreenOptions={Home}>
<Stack.Screen name='Home' component={Home} />
<Stack.Screen name='Chat' component={Chat} />
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Catsitter" component={Catsitter} />
<Stack.Screen name="Chat" component={ChatList} />
<Stack.Screen name="ChatDetail" component={Chat} />
</Stack.Navigator>
);
}
......@@ -33,8 +33,8 @@ function ChatStack() {
function AuthStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name='Login' component={Login} />
<Stack.Screen name='Signup' component={Signup} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Signup" component={Signup} />
</Stack.Navigator>
);
}
......@@ -44,29 +44,22 @@ function RootNavigator() {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// onAuthStateChanged returns an unsubscriber
const unsubscribeAuth = onAuthStateChanged(
auth,
async authenticatedUser => {
const unsubscribeAuth = onAuthStateChanged(auth, async (authenticatedUser) => {
authenticatedUser ? setUser(authenticatedUser) : setUser(null);
setIsLoading(false);
}
);
});
// unsubscribe auth listener on unmount
return unsubscribeAuth;
}, [user]);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size='large' />
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<NavigationContainer>
{user ? <ChatStack /> : <AuthStack />}
</NavigationContainer>
);
return <NavigationContainer>{user ? <ChatStack /> : <AuthStack />}</NavigationContainer>;
}
export default function App() {
......
......
import 'dotenv/config';
import "dotenv/config";
export default {
"expo": {
"name": "catMe",
"slug": "catMe",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
expo: {
name: "catMe",
slug: "catMe",
version: "1.0.0",
orientation: "portrait",
icon: "./assets/icon.png",
splash: {
image: "./assets/splash.png",
resizeMode: "contain",
backgroundColor: "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
updates: {
fallbackToCacheTimeout: 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
assetBundlePatterns: ["**/*"],
ios: {
supportsTablet: true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#FFFFFF"
}
},
"web": {
"favicon": "./assets/favicon.png"
web: {
favicon: "./assets/favicon.png"
},
extra: {
apiKey: process.env.API_KEY,
......@@ -39,4 +37,4 @@ export default {
appId: process.env.APP_ID
}
}
}
};
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
presets: ["babel-preset-expo"]
};
};
export default {
primary: '#f57c00',
gray: '#C5C5C7',
mediumGray: '#F6F7FB',
lightGray: '#FAFAFA'
primary: "#f57c00",
gray: "#C5C5C7",
mediumGray: "#F6F7FB",
lightGray: "#FAFAFA"
};
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { initializeApp, getApp } from "firebase/app";
import { initializeAuth, getAuth, getReactNativePersistence } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import Constants from "expo-constants";
import ReactNativeAsyncStorage from "@react-native-async-storage/async-storage";
// Firebase config
const firebaseConfig = {
apiKey: Constants.expoConfig.extra.apiKey,
......@@ -10,10 +12,17 @@ const firebaseConfig = {
storageBucket: Constants.expoConfig.extra.storageBucket,
messagingSenderId: Constants.expoConfig.extra.messagingSenderId,
appId: Constants.expoConfig.extra.appId,
databaseURL: Constants.expoConfig.extra.databaseURL,
databaseURL: Constants.expoConfig.extra.databaseURL
// @deprecated is deprecated Constants.manifest
};
// initialize Firebase App
const app = initializeApp(firebaseConfig);
// initialize Firebase Auth for that app immediately
export const auth = initializeAuth(app, {
persistence: getReactNativePersistence(ReactNativeAsyncStorage)
});
// initialize firebase
initializeApp(firebaseConfig);
export const auth = getAuth();
export const database = getFirestore();
This diff is collapsed.
import React, {
useState,
useEffect,
useLayoutEffect,
useCallback
} from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import {
collection,
addDoc,
orderBy,
query,
onSnapshot
} from 'firebase/firestore';
import { signOut } from 'firebase/auth';
import { auth, database } from '../config/firebase';
import { useNavigation } from '@react-navigation/native';
import { AntDesign } from '@expo/vector-icons';
import colors from '../colors';
export default function Chat() {
const [messages, setMessages] = useState([]);
const navigation = useNavigation();
const onSignOut = () => {
signOut(auth).catch(error => console.log('Error logging out: ', error));
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity
style={{
marginRight: 10
}}
onPress={onSignOut}
>
<AntDesign name="logout" size={24} color={colors.gray} style={{marginRight: 10}}/>
</TouchableOpacity>
)
});
}, [navigation]);
useLayoutEffect(() => {
const collectionRef = collection(database, 'chats');
const q = query(collectionRef, orderBy('createdAt', 'desc'));
const unsubscribe = onSnapshot(q, querySnapshot => {
console.log('querySnapshot unsusbscribe');
setMessages(
querySnapshot.docs.map(doc => ({
_id: doc.data()._id,
createdAt: doc.data().createdAt.toDate(),
text: doc.data().text,
user: doc.data().user
}))
);
});
return unsubscribe;
}, []);
const onSend = useCallback((messages = []) => {
setMessages(previousMessages =>
GiftedChat.append(previousMessages, messages)
);
// setMessages([...messages, ...messages]);
const { _id, createdAt, text, user } = messages[0];
addDoc(collection(database, 'chats'), {
_id,
createdAt,
text,
user
});
}, []);
return (
// <>
// {messages.map(message => (
// <Text key={message._id}>{message.text}</Text>
// ))}
// </>
<GiftedChat
messages={messages}
showAvatarForEveryMessage={false}
showUserAvatar={false}
onSend={messages => onSend(messages)}
messagesContainerStyle={{
backgroundColor: '#fff'
}}
textInputStyle={{
backgroundColor: '#fff',
borderRadius: 20,
}}
user={{
_id: auth?.currentUser?.email,
avatar: 'https://i.pravatar.cc/300'
}}
/>
);
}
import React, { useEffect } from "react";
import { View, TouchableOpacity, Text, Image, StyleSheet } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { FontAwesome } from '@expo/vector-icons';
import colors from '../colors';
import { Entypo } from '@expo/vector-icons';
const catImageUrl = "https://i.guim.co.uk/img/media/26392d05302e02f7bf4eb143bb84c8097d09144b/446_167_3683_2210/master/3683.jpg?width=1200&height=1200&quality=85&auto=format&fit=crop&s=49ed3252c0b2ffb49cf8b508892e452d";
const Home = () => {
const navigation = useNavigation();
useEffect(() => {
navigation.setOptions({
headerLeft: () => (
<FontAwesome name="search" size={24} color={colors.gray} style={{marginLeft: 15}}/>
),
headerRight: () => (
<Image
source={{ uri: catImageUrl }}
style={{
width: 40,
height: 40,
marginRight: 15,
}}
/>
),
});
}, [navigation]);
return (
<View style={styles.container}>
<TouchableOpacity
onPress={() => navigation.navigate("Chat")}
style={styles.chatButton}
>
<Entypo name="chat" size={24} color={colors.lightGray} />
</TouchableOpacity>
</View>
);
};
export default Home;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'flex-end',
backgroundColor: "#fff",
},
chatButton: {
backgroundColor: colors.primary,
height: 50,
width: 50,
borderRadius: 25,
alignItems: 'center',
justifyContent: 'center',
shadowColor: colors.primary,
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: .9,
shadowRadius: 8,
marginRight: 20,
marginBottom: 50,
}
});
\ No newline at end of file
import React, { useState } from "react";
import { StyleSheet, Text, View, Button, TextInput, Image, SafeAreaView, TouchableOpacity, StatusBar, Alert } from "react-native";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../config/firebase";
const backImage = require("../assets/backImage.png");
import { auth } from "../../config/firebase";
export default function Login({ navigation }) {
const backImage = require("../../assets/backImage.png");
export default function Login({ navigation }) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
......@@ -44,12 +44,12 @@ export default function Login({ navigation }) {
onChangeText={(text) => setPassword(text)}
/>
<TouchableOpacity style={styles.button} onPress={onHandleLogin}>
<Text style={{fontWeight: 'bold', color: '#fff', fontSize: 18}}> Log In</Text>
<Text style={{ fontWeight: "bold", color: "#fff", fontSize: 18 }}> Log In</Text>
</TouchableOpacity>
<View style={{marginTop: 20, flexDirection: 'row', alignItems: 'center', alignSelf: 'center'}}>
<Text style={{color: 'gray', fontWeight: '600', fontSize: 14}}>Don't have an account? </Text>
<View style={{ marginTop: 20, flexDirection: "row", alignItems: "center", alignSelf: "center" }}>
<Text style={{ color: "gray", fontWeight: "600", fontSize: 14 }}>Don't have an account? </Text>
<TouchableOpacity onPress={() => navigation.navigate("Signup")}>
<Text style={{color: '#f57c00', fontWeight: '600', fontSize: 14}}> Sign Up</Text>
<Text style={{ color: "#f57c00", fontWeight: "600", fontSize: 14 }}> Sign Up</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
......@@ -60,14 +60,14 @@ export default function Login({ navigation }) {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
backgroundColor: "#fff"
},
title: {
fontSize: 36,
fontWeight: 'bold',
fontWeight: "bold",
color: "orange",
alignSelf: "center",
paddingBottom: 24,
paddingBottom: 24
},
input: {
backgroundColor: "#F6F7FB",
......@@ -75,34 +75,34 @@ const styles = StyleSheet.create({
marginBottom: 20,
fontSize: 16,
borderRadius: 10,
padding: 12,
padding: 12
},
backImage: {
width: "100%",
height: 340,
position: "absolute",
top: 0,
resizeMode: 'cover',
resizeMode: "cover"
},
whiteSheet: {
width: '100%',
height: '75%',
width: "100%",
height: "75%",
position: "absolute",
bottom: 0,
backgroundColor: '#fff',
borderTopLeftRadius: 60,
backgroundColor: "#fff",
borderTopLeftRadius: 60
},
form: {
flex: 1,
justifyContent: 'center',
marginHorizontal: 30,
justifyContent: "center",
marginHorizontal: 30
},
button: {
backgroundColor: '#f57c00',
backgroundColor: "#f57c00",
height: 58,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
justifyContent: "center",
alignItems: "center",
marginTop: 40
}
});
import React, { useState } from 'react';
import React, { useState } from "react";
import { StyleSheet, Text, View, Button, TextInput, Image, SafeAreaView, TouchableOpacity, StatusBar, Alert } from "react-native";
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../config/firebase';
const backImage = require("../assets/backImage.png");
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../config/firebase";
const backImage = require("../../assets/backImage.png");
export default function Signup({ navigation }) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const onHandleSignup = () => {
if (email !== '' && password !== '') {
if (email !== "" && password !== "") {
createUserWithEmailAndPassword(auth, email, password)
.then(() => console.log('Signup success'))
.then(() => console.log("Signup success"))
.catch((err) => Alert.alert("Login error", err.message));
}
};
......@@ -44,12 +43,12 @@ const onHandleSignup = () => {
onChangeText={(text) => setPassword(text)}
/>
<TouchableOpacity style={styles.button} onPress={onHandleSignup}>
<Text style={{fontWeight: 'bold', color: '#fff', fontSize: 18}}> Sign Up</Text>
<Text style={{ fontWeight: "bold", color: "#fff", fontSize: 18 }}> Sign Up</Text>
</TouchableOpacity>
<View style={{marginTop: 20, flexDirection: 'row', alignItems: 'center', alignSelf: 'center'}}>
<Text style={{color: 'gray', fontWeight: '600', fontSize: 14}}>Don't have an account? </Text>
<View style={{ marginTop: 20, flexDirection: "row", alignItems: "center", alignSelf: "center" }}>
<Text style={{ color: "gray", fontWeight: "600", fontSize: 14 }}>Don't have an account? </Text>
<TouchableOpacity onPress={() => navigation.navigate("Login")}>
<Text style={{color: '#f57c00', fontWeight: '600', fontSize: 14}}> Log In</Text>
<Text style={{ color: "#f57c00", fontWeight: "600", fontSize: 14 }}> Log In</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
......@@ -60,14 +59,14 @@ const onHandleSignup = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
backgroundColor: "#fff"
},
title: {
fontSize: 36,
fontWeight: 'bold',
fontWeight: "bold",
color: "orange",
alignSelf: "center",
paddingBottom: 24,
paddingBottom: 24
},
input: {
backgroundColor: "#F6F7FB",
......@@ -75,34 +74,34 @@ const styles = StyleSheet.create({
marginBottom: 20,
fontSize: 16,
borderRadius: 10,
padding: 12,
padding: 12
},
backImage: {
width: "100%",
height: 340,
position: "absolute",
top: 0,
resizeMode: 'cover',
resizeMode: "cover"
},
whiteSheet: {
width: '100%',
height: '75%',
width: "100%",
height: "75%",
position: "absolute",
bottom: 0,
backgroundColor: '#fff',
borderTopLeftRadius: 60,
backgroundColor: "#fff",
borderTopLeftRadius: 60
},
form: {
flex: 1,
justifyContent: 'center',
marginHorizontal: 30,
justifyContent: "center",
marginHorizontal: 30
},
button: {
backgroundColor: '#f57c00',
backgroundColor: "#f57c00",
height: 58,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
justifyContent: "center",
alignItems: "center",
marginTop: 40
}
});
import { StyleSheet, Text, View } from "react-native";
import React, { useState, useLayoutEffect } from "react";
import { collection, query, onSnapshot, where, getDoc } from "firebase/firestore";
import { auth, database } from "../../config/firebase";
const Catsitter = ({ route }) => {
const { id } = route.params;
const [catsitter, setCatsitter] = useState({});
useLayoutEffect(() => {
if (!id) return;
const collectionRef = collection(database, "cat-sitters");
const q = query(collectionRef, where("__name__", "==", id));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setCatsitter(querySnapshot.docs[0].data());
});
return unsubscribe;
}, []);
return (
<View>
<Text>
Catsitter: {id} {JSON.stringify(catsitter)}
</Text>
</View>
);
};
export default Catsitter;
const styles = StyleSheet.create({});
import React, { useState, useEffect, useLayoutEffect, useCallback } from "react";
import { TouchableOpacity, Text } from "react-native";
import { GiftedChat } from "react-native-gifted-chat";
import { collection, addDoc, orderBy, query, onSnapshot, doc, where } from "firebase/firestore";
import { signOut } from "firebase/auth";
import { auth, database } from "../../config/firebase";
import { useNavigation } from "@react-navigation/native";
import { AntDesign } from "@expo/vector-icons";
import colors from "../../colors";
export default function Chat({ route }) {
const { id } = route.params;
const [messages, setMessages] = useState([]);
const navigation = useNavigation();
const onSignOut = () => {
signOut(auth).catch((error) => console.log("Error logging out: ", error));
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity
style={{
marginRight: 10
}}
onPress={onSignOut}>
<AntDesign name="logout" size={24} color={colors.gray} style={{ marginRight: 10 }} />
</TouchableOpacity>
)
});
}, [navigation]);
useLayoutEffect(() => {
if (!id) return;
const collectionRef = collection(database, "messages");
const chatRef = doc(database, "chats", id);
const q = query(collectionRef, where("chatId", "==", chatRef), orderBy("createdAt", "desc"));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setMessages(
querySnapshot.docs.map((doc) => ({
_id: doc.id,
createdAt: doc.data().createdAt.toDate(),
text: doc.data().text,
user: doc.data().user
}))
);
});
return unsubscribe;
}, []);
const onSend = useCallback((messages = []) => {
setMessages((previousMessages) => GiftedChat.append(previousMessages, messages));
// setMessages([...messages, ...messages]);
const { _id, createdAt, text, user } = messages[0];
addDoc(collection(database, "messages"), {
_id,
createdAt,
text,
user
});
}, []);
return (
// <>
// {messages.map(message => (
// <Text key={message._id}>{message.text}</Text>
// ))}
// </>
<>
<GiftedChat
messages={messages}
showAvatarForEveryMessage={false}
showUserAvatar={false}
onSend={(messages) => onSend(messages)}
messagesContainerStyle={{
backgroundColor: "#fff"
}}
textInputStyle={{
backgroundColor: "#fff",
borderRadius: 20
}}
user={{
_id: auth?.currentUser?.email,
avatar: "https://i.pravatar.cc/300"
}}
/>
</>
);
}
import React, { useEffect, useState, useLayoutEffect } from "react";
import { View, TouchableOpacity, Image, StyleSheet, Text, TextInput, FlatList } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { FontAwesome } from "@expo/vector-icons";
import colors from "../../colors";
import { collection, query, onSnapshot, orderBy, where } from "firebase/firestore";
import { database, auth } from "../../config/firebase";
const catImageUrl =
"https://i.guim.co.uk/img/media/26392d05302e02f7bf4eb143bb84c8097d09144b/446_167_3683_2210/master/3683.jpg?width=1200&height=1200&quality=85&auto=format&fit=crop&s=49ed3252c0b2ffb49cf8b508892e452d";
const ChatList = () => {
const navigation = useNavigation();
const [chats, setChats] = useState([]);
useEffect(() => {
navigation.setOptions({
headerLeft: () => <FontAwesome name="search" size={24} color={colors.gray} style={{ marginLeft: 15 }} />,
headerRight: () => (
<Image
source={{ uri: catImageUrl }}
style={{
width: 40,
height: 40,
marginRight: 15
}}
/>
)
});
}, [navigation]);
useLayoutEffect(() => {
const collectionRef = collection(database, "chats");
const q = query(collectionRef, where("participant", "array-contains", auth.currentUser.uid), orderBy("updatedAt", "desc"));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setChats(
querySnapshot.docs.map((doc) => ({
_id: doc.id,
content: doc.data()
}))
);
});
return unsubscribe;
}, []);
return (
<View style={styles.container}>
<FlatList
data={chats}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => navigation.navigate("ChatDetail", { id: item._id })}>
<Text>{JSON.stringify(item)}</Text>
</TouchableOpacity>
)}
/>
</View>
);
};
export default ChatList;
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff",
position: "relative"
},
chatButton: {
position: "absolute",
bottom: 0,
right: 0,
backgroundColor: colors.primary,
height: 50,
width: 50,
borderRadius: 25,
alignItems: "center",
justifyContent: "center",
shadowColor: colors.primary,
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.9,
shadowRadius: 8,
marginRight: 20,
marginBottom: 50
},
input: {
backgroundColor: "#F6F7FB",
height: 58,
marginBottom: 20,
fontSize: 16,
borderRadius: 10,
padding: 12
}
});
import React, { useEffect, useState, useLayoutEffect } from "react";
import { View, TouchableOpacity, Image, StyleSheet, Text, TextInput, FlatList } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { FontAwesome } from "@expo/vector-icons";
import colors from "../../colors";
import { collection, query, onSnapshot, orderBy } from "firebase/firestore";
import { Entypo } from "@expo/vector-icons";
import { database } from "../../config/firebase";
const catImageUrl =
"https://i.guim.co.uk/img/media/26392d05302e02f7bf4eb143bb84c8097d09144b/446_167_3683_2210/master/3683.jpg?width=1200&height=1200&quality=85&auto=format&fit=crop&s=49ed3252c0b2ffb49cf8b508892e452d";
const Home = () => {
const navigation = useNavigation();
const [catsitters, setCatsitters] = useState([]);
const [keyword, setKeyword] = useState("");
useEffect(() => {
navigation.setOptions({
headerLeft: () => <FontAwesome name="search" size={24} color={colors.gray} style={{ marginLeft: 15 }} />,
headerRight: () => (
<Image
source={{ uri: catImageUrl }}
style={{
width: 40,
height: 40,
marginRight: 15
}}
/>
)
});
}, [navigation]);
useLayoutEffect(() => {
const collectionRef = collection(database, "cat-sitters");
const q = query(collectionRef, orderBy("createdAt", "desc"));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setCatsitters(
querySnapshot.docs.map((doc) => ({
_id: doc.id,
content: doc.data()
}))
);
});
return unsubscribe;
}, []);
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => navigation.navigate("Chat")} style={styles.chatButton}>
<Entypo name="chat" size={24} color={colors.lightGray} />
</TouchableOpacity>
<Text>Cat sitter near your home</Text>
<View style={{ display: "flex", flexDirection: "row" }}>
<Entypo name="chat" size={20} color={colors.lightGray} />
<View>
<Text>Current Location</Text>
<Text>New York, USA</Text>
</View>
</View>
<TextInput style={styles.input} placeholder="Search" autoCapitalize="none" autoFocus={true} value={keyword} onChangeText={(text) => setKeyword(text)} />
<FlatList
data={catsitters}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => navigation.navigate("Catsitter", { id: item._id })}>
<Text>{JSON.stringify(item)}</Text>
</TouchableOpacity>
)}
/>
</View>
);
};
export default Home;
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff",
position: "relative"
},
chatButton: {
position: "absolute",
bottom: 0,
right: 0,
backgroundColor: colors.primary,
height: 50,
width: 50,
borderRadius: 25,
alignItems: "center",
justifyContent: "center",
shadowColor: colors.primary,
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.9,
shadowRadius: 8,
marginRight: 20,
marginBottom: 50,
zIndex: 1000
},
input: {
backgroundColor: "#F6F7FB",
height: 58,
marginBottom: 20,
fontSize: 16,
borderRadius: 10,
padding: 12
}
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment