├── .env ├── .gitignore ├── .idea ├── chatbot-frontend.iml ├── modules.xml ├── vcs.xml └── workspace.xml ├── App.js ├── adapters ├── chats │ └── chats.js ├── language │ └── language.js └── tabs │ └── tabs.js ├── app.json ├── assets ├── adaptive-icon.png ├── avatar.png ├── banner.jpg ├── favicon.png ├── icon.png ├── icons │ ├── BackArrow.jsx │ ├── CameraIcon.jsx │ ├── CommunityIcon.jsx │ ├── Loader.jsx │ ├── MenuIcon.jsx │ └── SearchIcon.jsx └── splash.png ├── babel.config.js ├── components ├── ChatBox.jsx ├── ChatMessages.jsx ├── GetcontactAccess.jsx ├── LanguageItem.jsx ├── Navbar.jsx ├── Paths.jsx ├── TabLists.jsx └── Waiting.jsx ├── ipconfig.js ├── main.js ├── package.json ├── redux ├── authentication │ ├── auth.action.js │ ├── auth.types.js │ └── reducer.js ├── redux.js ├── room │ ├── reducer.js │ ├── room.action.js │ └── room.types.js └── user │ ├── reducer.js │ ├── user.action.js │ └── user.types.js ├── view ├── AgreeAndContinue.jsx ├── Authentication.jsx ├── CallScreen.jsx ├── ChatPanel.jsx ├── ChatScreen.jsx ├── OtpAndFormFilling.jsx ├── StatusScreen.jsx └── Welcome.jsx └── yarn.lock /.env: -------------------------------------------------------------------------------- 1 | API_BASE_URL_DEV = "http://192.168.68.110:3000" 2 | API_BASE_URL_PROD = "https://whatsapp-clone-hvpn.onrender.com/" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | yarn.lock 13 | package-lock.json 14 | 15 | # macOS 16 | .DS_Store 17 | 18 | # Temporary files created by Metro to check the health of the file watcher 19 | .metro-health-check* 20 | -------------------------------------------------------------------------------- /.idea/chatbot-frontend.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 21 | 22 | 23 | 26 | 36 | 37 | 38 | 39 | 40 | 1679682263495 41 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import { Provider } from "react-redux"; 2 | import Main from "./main"; 3 | import store from "./redux/redux"; 4 | 5 | export default function App() { 6 | return ( 7 | 8 |
9 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /adapters/chats/chats.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 1, 4 | chatfrom: 1, 5 | chatto: 2, 6 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 7 | lastMessage: "this is the last", 8 | avatar: "", 9 | title: "fake user", 10 | ispin: false, 11 | lastSeen: "4:53pm", 12 | }, 13 | { 14 | id: 2, 15 | chatfrom: 1, 16 | chatto: 2, 17 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 18 | lastMessage: "this is the last", 19 | avatar: "", 20 | title: "fake user", 21 | ispin: false, 22 | lastSeen: "4:53pm", 23 | }, 24 | { 25 | id: 3, 26 | chatfrom: 1, 27 | chatto: 2, 28 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 29 | lastMessage: "this is the last", 30 | avatar: "", 31 | title: "fake user", 32 | ispin: false, 33 | lastSeen: "4:53pm", 34 | }, 35 | { 36 | id: 4, 37 | chatfrom: 1, 38 | chatto: 2, 39 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 40 | lastMessage: "this is the last", 41 | avatar: "", 42 | title: "fake user", 43 | ispin: false, 44 | lastSeen: "4:53pm", 45 | }, 46 | { 47 | id: 5, 48 | chatfrom: 1, 49 | chatto: 2, 50 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 51 | lastMessage: "this is the last", 52 | avatar: "", 53 | title: "fake user", 54 | ispin: false, 55 | lastSeen: "4:53pm", 56 | }, 57 | { 58 | id: 6, 59 | chatfrom: 1, 60 | chatto: 2, 61 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 62 | lastMessage: "this is the last", 63 | avatar: "", 64 | title: "fake user", 65 | ispin: false, 66 | lastSeen: "4:53pm", 67 | }, 68 | { 69 | id: 7, 70 | chatfrom: 1, 71 | chatto: 2, 72 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 73 | lastMessage: "this is the last", 74 | avatar: "", 75 | title: "fake user", 76 | ispin: false, 77 | lastSeen: "4:53pm", 78 | }, 79 | { 80 | id: 8, 81 | chatfrom: 1, 82 | chatto: 2, 83 | data: [{ key: "value" }, { key: "value" }, { key: "value" }], 84 | lastMessage: "this is the last", 85 | avatar: "", 86 | title: "fake user", 87 | ispin: false, 88 | lastSeen: "4:53pm", 89 | }, 90 | ]; 91 | -------------------------------------------------------------------------------- /adapters/language/language.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { primaryLanguage: "English", secondaryLanguage: "English" }, 3 | { primaryLanguage: "हिन्दी", secondaryLanguage: "Hindi" }, 4 | { primaryLanguage: "বাংলা", secondaryLanguage: "Bengali" }, 5 | { primaryLanguage: "मराठी", secondaryLanguage: "Marathi" }, 6 | { primaryLanguage: "తెలుగు", secondaryLanguage: "Telugu" }, 7 | { primaryLanguage: "தமிழ்", secondaryLanguage: "Tamil" }, 8 | { primaryLanguage: "ગુજરાતી", secondaryLanguage: "Gujarati" }, 9 | { primaryLanguage: "ಕನ್ನಡ", secondaryLanguage: "Kannada" }, 10 | { primaryLanguage: "ଓଡ଼ିଆ", secondaryLanguage: "Odia" }, 11 | { primaryLanguage: "ਪੰਜਾਬੀ", secondaryLanguage: "Punjabi" }, 12 | { primaryLanguage: "മലയാളം", secondaryLanguage: "Malayalam" }, 13 | { primaryLanguage: "اردو", secondaryLanguage: "Urdu" }, 14 | { primaryLanguage: "संस्कृतम्", secondaryLanguage: "Sanskrit" }, 15 | { primaryLanguage: "नेपाली", secondaryLanguage: "Nepali" }, 16 | { primaryLanguage: "सिन्धी", secondaryLanguage: "Sindhi" }, 17 | { primaryLanguage: "କାଶ୍ମିରୀ", secondaryLanguage: "Kashmiri" }, 18 | { primaryLanguage: "मैथिली", secondaryLanguage: "Maithili" }, 19 | { primaryLanguage: "संताली", secondaryLanguage: "Santali" }, 20 | { primaryLanguage: "गोंडी", secondaryLanguage: "Gondi" }, 21 | { primaryLanguage: "મરાઠી", secondaryLanguage: "Marathi" }, 22 | { primaryLanguage: "कोंकणी", secondaryLanguage: "Konkani" }, 23 | { primaryLanguage: "कर्नाटका", secondaryLanguage: "Karnataka" }, 24 | { primaryLanguage: "तुलु", secondaryLanguage: "Tulu" }, 25 | { primaryLanguage: "मणिपुरी", secondaryLanguage: "Manipuri" }, 26 | { primaryLanguage: "खड़ी बोली", secondaryLanguage: "Khasi" }, 27 | { primaryLanguage: "मिजो", secondaryLanguage: "Mizo" }, 28 | { primaryLanguage: "नागा", secondaryLanguage: "Naga" }, 29 | ]; 30 | -------------------------------------------------------------------------------- /adapters/tabs/tabs.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 1, 4 | areaName: "Chats", 5 | isDot: false, 6 | notSeen: { 7 | is: false, 8 | count: 0, 9 | }, 10 | chatRoute : "chatScreen" 11 | }, 12 | { 13 | id: 2, 14 | areaName: "Status", 15 | isDot: false, 16 | notSeen: { 17 | is: false, 18 | count: 0, 19 | }, 20 | chatRoute : "StatusScreen" 21 | 22 | }, 23 | { 24 | id: 3, 25 | areaName: "Calls", 26 | isDot: false, 27 | notSeen: { 28 | is: false, 29 | count: 0, 30 | }, 31 | chatRoute : "CallScreen" 32 | 33 | }, 34 | ]; 35 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "chatbot-frontend", 4 | "slug": "chatbot-frontend", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "assetBundlePatterns": [ 15 | "**/*" 16 | ], 17 | "ios": { 18 | "supportsTablet": true 19 | }, 20 | "android": { 21 | "adaptiveIcon": { 22 | "foregroundImage": "./assets/adaptive-icon.png", 23 | "backgroundColor": "#ffffff" 24 | } 25 | }, 26 | "web": { 27 | "favicon": "./assets/favicon.png" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/adaptive-icon.png -------------------------------------------------------------------------------- /assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/avatar.png -------------------------------------------------------------------------------- /assets/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/banner.jpg -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/favicon.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/icon.png -------------------------------------------------------------------------------- /assets/icons/BackArrow.jsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React from "react"; 3 | import Icon from "react-native-vector-icons/AntDesign"; 4 | 5 | const BackArrow = () => { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | }; 12 | 13 | export default BackArrow; 14 | -------------------------------------------------------------------------------- /assets/icons/CameraIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import Icon from "react-native-vector-icons/SimpleLineIcons"; 4 | 5 | const CameraIcon = () => { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default CameraIcon; 14 | -------------------------------------------------------------------------------- /assets/icons/CommunityIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { StyleSheet, View } from "react-native"; 3 | import Icon from "react-native-vector-icons/Ionicons"; 4 | 5 | const CommunityIcon = () => { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | }; 12 | const styles = StyleSheet.create({ 13 | icon: { 14 | width: "10%", 15 | display: "flex", 16 | justifyContent : "center", 17 | alignItems : "center", 18 | }, 19 | }); 20 | 21 | export default CommunityIcon; 22 | -------------------------------------------------------------------------------- /assets/icons/Loader.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { ActivityIndicator, MD2Colors } from "react-native-paper"; 3 | 4 | const Loader = () => ( 5 | 6 | ); 7 | 8 | export default Loader; 9 | -------------------------------------------------------------------------------- /assets/icons/MenuIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import Icon from "react-native-vector-icons/Entypo"; 4 | 5 | const MenuIcon = ({ color }) => { 6 | return ( 7 | 8 | 13 | 14 | ); 15 | }; 16 | 17 | export default MenuIcon; 18 | -------------------------------------------------------------------------------- /assets/icons/SearchIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import Icon from "react-native-vector-icons/Feather"; 4 | 5 | const SearchIcon = () => { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | }; 12 | 13 | export default SearchIcon; 14 | -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepumandal/chatbot-frontend/6eafabc0bb5e231aeecdf5179d6a01692a03c7e3/assets/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /components/ChatBox.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { Image, StyleSheet, Text, TouchableOpacity, View } from "react-native"; 3 | import img from "../assets/avatar.png"; 4 | import { useNavigation } from "@react-navigation/native"; 5 | import { useDispatch } from "react-redux"; 6 | import { activeRoom } from "../redux/room/room.action"; 7 | const ChatBox = ({ title, lastMessage, isActive, user }) => { 8 | const navigate = useNavigation(); 9 | const [press, setPress] = useState(false); 10 | const dispatch = useDispatch(); 11 | const pressMyevent = () => { 12 | setPress((press) => !press); 13 | }; 14 | 15 | return ( 16 | { 20 | navigate.navigate("chatpanel", user); 21 | dispatch(activeRoom(user)); 22 | }} 23 | style={[style.Container, press ? style.pressContainer : null]} 24 | > 25 | 26 | 27 | 28 | 29 | {title} 30 | {lastMessage} 31 | 32 | { 33 | isActive ? "online" : "offline" 34 | } 35 | 36 | ); 37 | }; 38 | 39 | const style = StyleSheet.create({ 40 | lastSeen: { 41 | position: "absolute", 42 | top: 10, 43 | right: 13, 44 | fontSize: 12, 45 | fontWeight: 600, 46 | color: "#8696a0", 47 | }, 48 | pressContainer: { 49 | backgroundColor: "#D6D5D4", 50 | }, 51 | Container: { 52 | width: "100%", 53 | height: 80, 54 | paddingLeft: 6, 55 | paddingRight: 6, 56 | display: "flex", 57 | justifyContent: "flex-start", 58 | alignItems: "center", 59 | flexDirection: "row", 60 | paddingTop: 10, 61 | paddingBottom: 10, 62 | marginTop: 4, 63 | }, 64 | avatarBox: { 65 | borderRadius: 50, 66 | overflow: "hidden", 67 | width: "16%", 68 | marginRight: 16, 69 | marginLeft: 12, 70 | }, 71 | avatar: { 72 | width: 60, 73 | height: 60, 74 | }, 75 | textContainer: { 76 | // borderWidth: 1, 77 | // borderColor: "black", 78 | width: "70%", 79 | height: 48, 80 | justifyContent: "space-between", 81 | }, 82 | header: { 83 | fontSize: 18, 84 | fontWeight: 700, 85 | color: "#111b21", 86 | }, 87 | lastmessage: { 88 | fontSize: 15, 89 | fontWeight: 400, 90 | color: "#3b4a54", 91 | }, 92 | }); 93 | 94 | export default ChatBox; 95 | -------------------------------------------------------------------------------- /components/ChatMessages.jsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React, { useEffect } from "react"; 3 | import { useDispatch, useSelector } from "react-redux"; 4 | import { socket } from "../view/ChatScreen"; 5 | import { getlateschat } from "../redux/room/room.action"; 6 | 7 | const ChatMessages = () => { 8 | const socketObj = useSelector((store) => store.socket); 9 | const store = useSelector((store) => store.auth); 10 | const user = useSelector((store) => store.user); 11 | const dispatch = useDispatch(); 12 | useEffect(() => { 13 | socket.on("getMessage", (msg) => alert(msg)); 14 | let id = store.userData.body._id; 15 | let subject = socketObj.subjectSocket; 16 | socket.on("getMessage", (msg) => dispatch(getlateschat(id, subject))); 17 | }, []); 18 | 19 | // useEffect(() => { 20 | // // trigger last message here 21 | // socket.on("getMessage", (msg) => dispatch(getlateschat(id, subject))); 22 | // }, []); 23 | 24 | return ( 25 | 26 | {socketObj.currentChat?.data?.map((item, index) => { 27 | return ( 28 | 37 | {item.value} 38 | 39 | ); 40 | })} 41 | 42 | ); 43 | }; 44 | 45 | export default ChatMessages; 46 | -------------------------------------------------------------------------------- /components/GetcontactAccess.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TouchableOpacity, 5 | Alert, 6 | PermissionsAndroid, 7 | } from "react-native"; 8 | import React, { useEffect } from "react"; 9 | 10 | const GetcontactAccess = ({ ContactAccess, setContactAccess }) => { 11 | const onPressEvent = async () => { 12 | try { 13 | const granted = await PermissionsAndroid.request( 14 | PermissionsAndroid.PERMISSIONS.READ_CONTACTS, 15 | // PermissionsAndroid.PERMISSIONS.READ_MEDIA_IMAGES, 16 | { 17 | title: "Contacts Permission", 18 | message: 19 | "This app needs access to your contacts to be able to function properly.", 20 | buttonNeutral: "Ask Me Later", 21 | buttonNegative: "Cancel", 22 | buttonPositive: "OK", 23 | } 24 | ); 25 | 26 | if (granted === PermissionsAndroid.RESULTS.GRANTED) { 27 | console.log("Contacts permission granted"); 28 | setContactAccess(() => !ContactAccess); 29 | } else { 30 | console.log("Contacts permission denied"); 31 | } 32 | } catch (err) { 33 | console.warn(err); 34 | } 35 | }; 36 | 37 | return ( 38 | 49 | 58 | 66 | {" "} 67 | Contacts and media{" "} 68 | 69 | 70 | 78 | To easily sene messages and photos to friends and family, allow 79 | chatify to access your contact, photos and other media. 80 | 81 | 82 | 95 | 96 | 102 | {" "} 103 | Not now 104 | 105 | 106 | 107 | 113 | Continue 114 | 115 | 116 | 117 | 118 | 119 | ); 120 | }; 121 | 122 | export default GetcontactAccess; 123 | -------------------------------------------------------------------------------- /components/LanguageItem.jsx: -------------------------------------------------------------------------------- 1 | import { View, Text, StyleSheet, TouchableOpacity } from "react-native"; 2 | import React from "react"; 3 | import { RadioButton } from "react-native-paper"; 4 | 5 | const LanguageItem = ({ setLanguage, primaryLanguage, secondaryLanguage }) => { 6 | return ( 7 | 8 | 9 | setLanguage(primaryLanguage)} 12 | style={style.textcontainer} 13 | > 14 | {primaryLanguage} 15 | {secondaryLanguage} 16 | 17 | 18 | ); 19 | }; 20 | 21 | const style = StyleSheet.create({ 22 | itemBox: { 23 | width: "100%", 24 | height: 70, 25 | marginTop: 6, 26 | paddingLeft: 14, 27 | paddingRight: 14, 28 | display: "flex", 29 | flexDirection: "row", 30 | alignItems: "center", 31 | }, 32 | textcontainer: { 33 | marginLeft: 18, 34 | width: "100%", 35 | height: "100%", 36 | paddingTop: 15, 37 | }, 38 | primary: { 39 | fontSize: 16, 40 | fontWeight: 500, 41 | color: "#111b21", 42 | }, 43 | secondary: { 44 | fontSize: 16, 45 | fontWeight: 300, 46 | color: "#3b4a54", 47 | }, 48 | }); 49 | 50 | export default LanguageItem; 51 | -------------------------------------------------------------------------------- /components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from "react"; 2 | import { StyleSheet, Text, View } from "react-native"; 3 | import CameraIcon from "../assets/icons/CameraIcon"; 4 | import SearchIcon from "../assets/icons/SearchIcon"; 5 | import MenuIcon from "../assets/icons/MenuIcon"; 6 | import TabLists from "./TabLists"; 7 | import Paths from "./Paths"; 8 | 9 | const Navbar = ({ children }) => { 10 | return ( 11 | 12 | 13 | 14 | WhatsApp 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | }; 25 | 26 | const styles = StyleSheet.create({ 27 | Headers: { 28 | width: "100%", 29 | height: "14%", 30 | paddingTop: 53, 31 | backgroundColor: "#00a884", 32 | justifyContent: "space-between", 33 | }, 34 | NavSection: { 35 | height: 90, 36 | justifyContent: "space-between", 37 | }, 38 | navbar: { 39 | width: "100%", 40 | display: "flex", 41 | flexDirection: "row", 42 | paddingLeft: 17, 43 | paddingRight: 17, 44 | justifyContent: "space-between", 45 | }, 46 | heading: { 47 | color: "white", 48 | fontFamily: "Roboto", 49 | fontSize: 24, 50 | fontWeight: 700, 51 | }, 52 | features: { 53 | display: "flex", 54 | flexDirection: "row", 55 | justifyContent: "space-between", 56 | alignItems: "center", 57 | gap: 25, 58 | }, 59 | }); 60 | 61 | export default Navbar; 62 | -------------------------------------------------------------------------------- /components/Paths.jsx: -------------------------------------------------------------------------------- 1 | // import React from "react"; 2 | // // import { NativeRouter, Route, Routes } from "react-router-native"; 3 | // import ChatLists from "../view/ChatLists"; 4 | // import StatusComp from "../view/StatusComp"; 5 | 6 | // const Paths = () => { 7 | // return ( 8 | // // 9 | // // 10 | // // 11 | // // 12 | // // 13 | // // 14 | // ); 15 | // }; 16 | 17 | // export default Paths; 18 | -------------------------------------------------------------------------------- /components/TabLists.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { StyleSheet, Text, TouchableOpacity, View } from "react-native"; 3 | import tabs from "../adapters/tabs/tabs.js"; 4 | import CommunityIcon from "../assets/icons/CommunityIcon.jsx"; 5 | import { useSelector } from "react-redux"; 6 | import { useNavigation } from "@react-navigation/native"; 7 | const TabLists = () => { 8 | const store = useSelector((store) => store); 9 | const navigate = useNavigation(); 10 | return ( 11 | 12 | 13 | {tabs.map((item) => { 14 | return ( 15 | navigate.navigate(item.chatRoute)} 17 | key={item.id} 18 | style={TabStyle.Tab} 19 | > 20 | {item.areaName} 21 | 22 | ); 23 | })} 24 | 25 | ); 26 | }; 27 | 28 | const TabStyle = StyleSheet.create({ 29 | TabContainer: { 30 | width: "100%", 31 | height: 35, 32 | display: "flex", 33 | flexDirection: "row", 34 | justifyContent: "space-between", 35 | backgroundColor: "#00a884", 36 | }, 37 | Tab: { 38 | width: "27%", 39 | display: "flex", 40 | justifyContent: "center", 41 | alignItems: "center", 42 | paddingRight: 10, 43 | }, 44 | areaName: { 45 | color: "white", 46 | fontWeight: 700, 47 | fontSize: 16, 48 | }, 49 | }); 50 | 51 | export default TabLists; 52 | -------------------------------------------------------------------------------- /components/Waiting.jsx: -------------------------------------------------------------------------------- 1 | import { View, Text, StyleSheet } from "react-native"; 2 | import React from "react"; 3 | import Loader from "../assets/icons/Loader"; 4 | 5 | const Waiting = ({ name }) => { 6 | return ( 7 | 8 | 9 | 16 | 17 | 18 | {name} 19 | 20 | 21 | ); 22 | }; 23 | const styles = StyleSheet.create({ 24 | loadercontainer: { 25 | backgroundColor: "rgb(210, 210, 210)", 26 | position: "absolute", 27 | width: "100%", 28 | height: "100%", 29 | display: "flex", 30 | flexDirection: "row", 31 | justifyContent: "center", 32 | alignItems: "center", 33 | }, 34 | loader: { 35 | width: "70%", 36 | backgroundColor: "white", 37 | textAlign: "center", 38 | display: "flex", 39 | flexDirection: "row", 40 | justifyContent: "space-between", 41 | }, 42 | name: { 43 | fontSize: 15, 44 | fontWeight: 700, 45 | borderRadius: 10, 46 | width: "70%", 47 | paddingVertical: 20, 48 | }, 49 | }); 50 | 51 | export default Waiting; 52 | -------------------------------------------------------------------------------- /ipconfig.js: -------------------------------------------------------------------------------- 1 | // import NetworkUtility from "react-native-network-utility"; 2 | // export default getIp = async () => { 3 | // const ip = await NetworkUtility.getIPAddress(); 4 | // return ip; 5 | // } 6 | 7 | // export default `http://192.168.1.22:3000`; 8 | // export default `http://192.168.68.118:3000`; 9 | export default `http://192.168.68.108:3000`; 10 | // 192.168.1.22 11 | // 192.168.1.22 -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import { StatusBar } from "expo-status-bar"; 2 | import { AppState, StyleSheet, Text, View } from "react-native"; 3 | import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs"; 4 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 5 | 6 | import Navbar from "./components/Navbar"; 7 | import TabLists from "./components/TabLists"; 8 | import { NavigationContainer } from "@react-navigation/native"; 9 | import ChatScreen, { socket } from "./view/ChatScreen"; 10 | import StatusScreen from "./view/StatusScreen"; 11 | import CallScreen from "./view/CallScreen"; 12 | import Welcome from "./view/Welcome"; 13 | import { useSelector } from "react-redux"; 14 | import AgreeAndContinue from "./view/AgreeAndContinue"; 15 | import Authentication from "./view/Authentication"; 16 | import OtpAndFormFilling from "./view/OtpAndFormFilling"; 17 | import ChatPanel from "./view/ChatPanel"; 18 | import React, { useEffect } from "react"; 19 | function ChatTabStack() { 20 | const Stack = createNativeStackNavigator(); 21 | 22 | return ( 23 | <> 24 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | 38 | const Main = () => { 39 | const Tab = createMaterialTopTabNavigator(); 40 | const store = useSelector((store) => store.auth); 41 | const Stack = createNativeStackNavigator(); 42 | const { isActive } = useSelector((store) => store.socket); 43 | const isAuthenticated = store?.userData?.isAuthenticated; 44 | 45 | useEffect(() => { 46 | return () => { 47 | console.log("second i am out"); 48 | }; 49 | }, []); 50 | 51 | return ( 52 | 53 | {isAuthenticated && !isActive && } 54 | 55 | {isAuthenticated && !isActive && } 56 | {!isAuthenticated ? ( 57 | 64 | 69 | 74 | 79 | 84 | 85 | ) : ( 86 | 96 | 101 | 106 | 111 | 112 | )} 113 | 114 | 115 | 116 | 117 | ); 118 | }; 119 | 120 | const styles = StyleSheet.create({ 121 | container: { 122 | flex: 2, 123 | }, 124 | Headers: { 125 | width: "100%", 126 | height: "18%", 127 | paddingTop: 53, 128 | backgroundColor: "#00a884", 129 | justifyContent: "space-between", 130 | }, 131 | navbar: { 132 | width: "100%", 133 | display: "flex", 134 | flexDirection: "row", 135 | paddingLeft: 17, 136 | paddingRight: 17, 137 | justifyContent: "space-between", 138 | }, 139 | heading: { 140 | color: "white", 141 | fontFamily: "Roboto", 142 | fontSize: 24, 143 | fontWeight: 700, 144 | }, 145 | features: { 146 | display: "flex", 147 | flexDirection: "row", 148 | justifyContent: "space-between", 149 | alignItems: "center", 150 | gap: 25, 151 | }, 152 | }); 153 | export default Main; 154 | 155 | // return ( 156 | // 157 | // 158 | // 165 | // 170 | // 175 | // 180 | // 181 | // 182 | // 183 | // ); 184 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatbot-frontend", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web" 10 | }, 11 | "dependencies": { 12 | "@react-native-community/netinfo": "^9.3.7", 13 | "@react-navigation/material-top-tabs": "^6.6.2", 14 | "@react-navigation/native": "^6.1.6", 15 | "@react-navigation/native-stack": "^6.9.12", 16 | "axios": "^1.3.4", 17 | "cross-spawn": "^7.0.3", 18 | "dotenv": "^16.0.3", 19 | "expo": "~48.0.6", 20 | "expo-linear-gradient": "~12.1.2", 21 | "expo-status-bar": "~1.4.4", 22 | "react": "18.2.0", 23 | "react-native": "^0.71.4", 24 | "react-native-linear-gradient": "^2.6.2", 25 | "react-native-pager-view": "6.1.2", 26 | "react-native-paper": "^5.5.0", 27 | "react-native-safe-area-context": "4.5.0", 28 | "react-native-screens": "~3.20.0", 29 | "react-native-tab-view": "^3.5.1", 30 | "react-native-translation": "^1.1.0", 31 | "react-native-vector-icons": "^9.2.0", 32 | "react-redux": "^8.0.5", 33 | "redux": "^4.2.1", 34 | "redux-thunk": "^2.4.2", 35 | "socket.io-client": "^4.6.1" 36 | }, 37 | "devDependencies": { 38 | "@babel/core": "^7.20.0", 39 | "remote-redux-devtools": "^0.5.16" 40 | }, 41 | "private": true 42 | } 43 | -------------------------------------------------------------------------------- /redux/authentication/auth.action.js: -------------------------------------------------------------------------------- 1 | import { 2 | LOGIN_ERROR, 3 | LOGIN_LOADING, 4 | LOGIN_SUCCESS, 5 | OTP_ERROR, 6 | OTP_LOADING, 7 | OTP_SUCCESS, 8 | } from "./auth.types"; 9 | import axios from "axios"; 10 | 11 | import url from "../../ipconfig.js"; 12 | import { io } from "socket.io-client"; 13 | import { socket } from "../../view/ChatScreen"; 14 | 15 | // process.env.NODE_ENV == "production" 16 | // ? process.env.API_BASE_URL_PROD 17 | // : process.env.API_BASE_URL_DEV; 18 | 19 | export const GetOtp = (number) => (dispatch) => { 20 | dispatch({ type: OTP_LOADING }); 21 | setTimeout(() => { 22 | dispatch({ type: OTP_SUCCESS, payload: number }); 23 | // dispatch({ type: OTP_ERROR }); 24 | }, 1000); 25 | }; 26 | 27 | export const CreateNewAccount = (body) => (dispatch) => { 28 | dispatch({ type: LOGIN_LOADING }); 29 | axios 30 | .post(`${url}/authentication/newuser`, body) 31 | .then((response) => { 32 | let body = response.data; 33 | 34 | dispatch({ type: LOGIN_SUCCESS, payload: body }); 35 | 36 | getConnection(); 37 | 38 | console.log(body); 39 | }) 40 | .catch((error) => { 41 | dispatch({ type: LOGIN_ERROR, payload: error.message }); 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /redux/authentication/auth.types.js: -------------------------------------------------------------------------------- 1 | export const LOGIN_LOADING = "LOGIN_LOADING"; 2 | export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; 3 | export const LOGIN_ERROR = "LOGIN_ERROR"; 4 | export const LOGOUT = "LOGOUT"; 5 | 6 | export const OTP_LOADING = "OTP_LOADING"; 7 | export const OTP_SUCCESS = "OTP_SUCCESS"; 8 | export const OTP_ERROR = "OTP_ERROR"; 9 | -------------------------------------------------------------------------------- /redux/authentication/reducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | LOGIN_ERROR, 3 | LOGIN_LOADING, 4 | LOGIN_SUCCESS, 5 | OTP_ERROR, 6 | OTP_LOADING, 7 | OTP_SUCCESS, 8 | } from "./auth.types"; 9 | 10 | const initialState = { 11 | loginLoading: false, 12 | loginError: false, 13 | errorMessage: "nil", 14 | userData: { 15 | isAuthenticated: false, 16 | number: "", 17 | body: {} 18 | }, 19 | otpLoading: false, 20 | otpError: false, 21 | otpMessage: "nil", 22 | }; 23 | 24 | const myReducer = (state = initialState, action) => { 25 | switch (action.type) { 26 | // otp here 27 | case OTP_LOADING: { 28 | return { 29 | ...state, 30 | otpLoading: true, 31 | otpError: false, 32 | }; 33 | } 34 | case OTP_SUCCESS: { 35 | alert("Otp"); 36 | console.log("Otp", action.payload); 37 | return { 38 | ...state, 39 | otpLoading: false, 40 | otpMessage: "validation successfully", 41 | userData: { 42 | ...state.userData, 43 | number: action.payload, 44 | }, 45 | }; 46 | } 47 | case OTP_ERROR: { 48 | return { 49 | ...state, 50 | otpError: true, 51 | otpLoading: false, 52 | otpMessage: "wrong otp entered", 53 | }; 54 | } 55 | case LOGIN_LOADING: { 56 | return { 57 | ...state, 58 | loginLoading: true, 59 | loginError: false, 60 | }; 61 | } 62 | case LOGIN_SUCCESS: { 63 | return { 64 | ...state, 65 | loginLoading: false, 66 | errorMessage: "validation successfully", 67 | userData: { 68 | ...state.userData, 69 | body: action.payload, 70 | isAuthenticated: true, 71 | }, 72 | }; 73 | } 74 | case LOGIN_ERROR: { 75 | return { 76 | ...state, 77 | loginError: true, 78 | loginLoading: false, 79 | errorMessage: "wrong otp entered", 80 | }; 81 | } 82 | default: 83 | return state; 84 | } 85 | }; 86 | 87 | export default myReducer; 88 | -------------------------------------------------------------------------------- /redux/redux.js: -------------------------------------------------------------------------------- 1 | import { legacy_createStore, applyMiddleware, combineReducers } from "redux"; 2 | import authReducer from "./authentication/reducer"; 3 | import UserReducer from "./user/reducer.js"; 4 | // import { composeWithDevTools } from "remote-redux-devtools"; 5 | import thunkMiddleware from "redux-thunk"; 6 | import socketReducer from "./room/reducer"; 7 | 8 | const rootReducer = combineReducers({ 9 | auth: authReducer, 10 | user: UserReducer, 11 | socket: socketReducer, 12 | }); 13 | 14 | const store = legacy_createStore(rootReducer, applyMiddleware(thunkMiddleware)); 15 | 16 | export default store; 17 | -------------------------------------------------------------------------------- /redux/room/reducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | CLOSE_ROOM, 3 | GET_CHAT, 4 | ROOM_ACTIVE, 5 | ROOM_ERROR, 6 | ROOM_LOADING, 7 | ROOM_SUCCESS, 8 | } from "./room.types.js"; 9 | 10 | const initialState = { 11 | Loading: false, 12 | Error: false, 13 | errorMessage: "nil", 14 | activeSocket: "", 15 | subjectSocket: "", 16 | isActive: false, 17 | currentChat: {}, 18 | }; 19 | 20 | const socketReducer = (state = initialState, action) => { 21 | switch (action.type) { 22 | case ROOM_LOADING: { 23 | return { 24 | ...state, 25 | Loading: true, 26 | Error: false, 27 | }; 28 | } 29 | case ROOM_SUCCESS: { 30 | return { 31 | ...state, 32 | Loading: false, 33 | errorMessage: "validation successfully", 34 | activeSocket: action.payload, 35 | isActive: false, 36 | }; 37 | } 38 | case ROOM_ERROR: { 39 | return { 40 | ...state, 41 | Error: true, 42 | Loading: false, 43 | errorMessage: "something went wrong", 44 | }; 45 | } 46 | case ROOM_ACTIVE: { 47 | return { 48 | ...state, 49 | subjectSocket: action.payload, 50 | isActive: true, 51 | }; 52 | } 53 | case CLOSE_ROOM: { 54 | return { 55 | ...state, 56 | subjectSocket: "", 57 | isActive: false, 58 | }; 59 | } 60 | case GET_CHAT: { 61 | console.log(JSON.stringify(action.payload, null, 2)); 62 | return { 63 | ...state, 64 | currentChat: action.payload[0], 65 | }; 66 | } 67 | default: 68 | return state; 69 | } 70 | }; 71 | 72 | export default socketReducer; 73 | -------------------------------------------------------------------------------- /redux/room/room.action.js: -------------------------------------------------------------------------------- 1 | import { 2 | GET_CHAT, 3 | ROOM_ACTIVE, 4 | ROOM_ERROR, 5 | ROOM_LOADING, 6 | ROOM_SUCCESS, 7 | } from "./room.types.js"; 8 | import axios from "axios"; 9 | 10 | import url from "../../ipconfig.js"; 11 | 12 | export const activeRoom = (user) => (dispatch) => { 13 | dispatch({ type: ROOM_ACTIVE, payload: user._id }); 14 | }; 15 | export const sendMessage = (userId) => (dispatch) => { 16 | dispatch({ type: ROOM_LOADING }); 17 | // socket connection here 18 | }; 19 | 20 | export const getlateschat = (id, subject) => (dispatch) => { 21 | // GET_CHAT 22 | axios 23 | .post(`${url}/user/getdata`, { 24 | id, 25 | subject, 26 | }) 27 | .then((response) => { 28 | // console.log("GET_CHAT", JSON.stringify(response.data, null, 2)); 29 | dispatch({ type: GET_CHAT, payload: response.data }); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /redux/room/room.types.js: -------------------------------------------------------------------------------- 1 | export const ROOM_LOADING = "ROOM_LOADING"; 2 | export const ROOM_SUCCESS = "ROOM_SUCCESS"; 3 | export const ROOM_ERROR = "ROOM_ERROR"; 4 | export const ROOM_LOGOUT = "ROOM_LOGOUT"; 5 | export const ROOM_ACTIVE = "ROOM_ACTIVE"; 6 | export const CLOSE_ROOM = "CLOSE_ROOM"; 7 | export const GET_CHAT = "GET_CHAT"; 8 | -------------------------------------------------------------------------------- /redux/user/reducer.js: -------------------------------------------------------------------------------- 1 | import { USER_ERROR, USER_LOADING, USER_SUCCESS } from "./user.types.js"; 2 | 3 | const initialState = { 4 | Loading: false, 5 | Error: false, 6 | errorMessage: "nil", 7 | data: [], 8 | }; 9 | 10 | const UserReducer = (state = initialState, action) => { 11 | switch (action.type) { 12 | case USER_LOADING: { 13 | return { 14 | ...state, 15 | Loading: true, 16 | Error: false, 17 | }; 18 | } 19 | case USER_SUCCESS: { 20 | return { 21 | ...state, 22 | Loading: false, 23 | errorMessage: "validation successfully", 24 | data: action.payload, 25 | }; 26 | } 27 | case USER_ERROR: { 28 | return { 29 | ...state, 30 | Error: true, 31 | Loading: false, 32 | errorMessage: "wrong otp entered", 33 | }; 34 | } 35 | default: 36 | return state; 37 | } 38 | }; 39 | 40 | export default UserReducer; 41 | -------------------------------------------------------------------------------- /redux/user/user.action.js: -------------------------------------------------------------------------------- 1 | import { USER_ERROR, USER_LOADING, USER_SUCCESS } from "./user.types.js"; 2 | import axios from "axios"; 3 | 4 | import url from "../../ipconfig.js"; 5 | 6 | export const GetAllUser = (user) => (dispatch) => { 7 | dispatch({ type: USER_LOADING }); 8 | axios 9 | .get(`${url}/user`) 10 | .then((response) => { 11 | let body = response.data; 12 | let data = body?.filter((item) => item._id !== user._id); 13 | dispatch({ type: USER_SUCCESS, payload: data }); 14 | // console.log(JSON.stringify(response.data, null, 2)); 15 | }) 16 | .catch((error) => { 17 | dispatch({ type: USER_ERROR, payload: error.message }); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /redux/user/user.types.js: -------------------------------------------------------------------------------- 1 | export const LOGIN_LOADING = "LOGIN_LOADING"; 2 | export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; 3 | export const LOGIN_ERROR = "LOGIN_ERROR"; 4 | export const LOGOUT = "LOGOUT"; 5 | 6 | export const USER_LOADING = "USER_LOADING"; 7 | export const USER_SUCCESS = "USER_SUCCESS"; 8 | export const USER_ERROR = "USER_ERROR"; 9 | 10 | export const OTP_LOADING = "OTP_LOADING"; 11 | export const OTP_SUCCESS = "OTP_SUCCESS"; 12 | export const OTP_ERROR = "OTP_ERROR"; 13 | -------------------------------------------------------------------------------- /view/AgreeAndContinue.jsx: -------------------------------------------------------------------------------- 1 | import { useNavigation } from "@react-navigation/native"; 2 | import React from "react"; 3 | import { 4 | View, 5 | Text, 6 | StyleSheet, 7 | ImageBackground, 8 | TouchableOpacity, 9 | } from "react-native"; 10 | 11 | const AgreeAndContinue = () => { 12 | const navigate = useNavigation(); 13 | return ( 14 | 15 | 16 | 25 | 26 | Welcome to Chatify 27 | 28 | 34 | Read our 35 | 36 | Privacy policy 37 | 38 | . Tap "Agree and continue" 39 | 40 | 47 | to accept the 48 | 49 | 54 | Terms of Service 55 | 56 | 57 | 58 | 59 | navigate.navigate("authentication")} 61 | // onPressIn={onclick} 62 | // onPressOut={onclick} 63 | activeOpacity={1} 64 | style={style.button} 65 | > 66 | 73 | Agree and Continue 74 | 75 | 76 | 77 | ); 78 | }; 79 | 80 | const style = StyleSheet.create({ 81 | container: { 82 | width: "100%", 83 | height: "100%", 84 | display: "flex", 85 | flexDirection: "column", 86 | justifyContent: "flex-start", 87 | alignItems: "center", 88 | backgroundColor: "white", 89 | }, 90 | imageContainer: { 91 | width: "100%", 92 | height: "55%", 93 | display: "flex", 94 | justifyContent: "flex-end", 95 | alignItems: "center", 96 | }, 97 | heading: { 98 | fontSize: 25, 99 | lineHeight: 50, 100 | fontWeight: 600, 101 | color: "#111b21", 102 | // backgroundColor: "white", 103 | }, 104 | instruction: { 105 | fontSize: 15, 106 | lineHeight: 20, 107 | fontWeight: 400, 108 | color: "#3b4a54", 109 | backgroundColor: "white", 110 | }, 111 | button: { 112 | backgroundColor: "green", 113 | borderRadius: 50, 114 | width: "70%", 115 | paddingVertical: 10, 116 | alignItems: "center", 117 | justifyContent: "center", 118 | marginTop: 60, 119 | }, 120 | text: { 121 | color: "white", 122 | fontSize: 14, 123 | fontWeight: "bold", 124 | }, 125 | }); 126 | 127 | export default AgreeAndContinue; 128 | -------------------------------------------------------------------------------- /view/Authentication.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | StyleSheet, 5 | TextInput, 6 | TouchableOpacity, 7 | } from "react-native"; 8 | import React, { useState } from "react"; 9 | import { useDispatch, useSelector } from "react-redux"; 10 | import { GetOtp } from "../redux/authentication/auth.action"; 11 | import { useNavigation } from "@react-navigation/native"; 12 | import Waiting from "../components/Waiting"; 13 | 14 | let otp = 1234; 15 | 16 | const Authentication = () => { 17 | const [value, setValue] = useState(""); 18 | const auth = useSelector((store) => store.auth); 19 | const dispatch = useDispatch(); 20 | const navigate = useNavigation(); 21 | const handleInputChange = (text) => { 22 | setValue(text.replace(/[^0-9]/g, "")); 23 | }; 24 | const submitVaue = () => { 25 | if (value.length !== 10) return alert("Please enter 10 digit number"); 26 | dispatch(GetOtp(value)); 27 | setTimeout(() => { 28 | navigate.navigate("OtpVarification"); 29 | }, 1000); 30 | }; 31 | return ( 32 | 33 | Enter your Phone number 34 | {auth.otpLoading && } 35 | 36 | 37 | India 38 | 39 | 40 | 45 | {" "} 46 | +{" "} 47 | 48 | 53 | {" "} 54 | 91{" "} 55 | 56 | 57 | 65 | 66 | submitVaue()} 68 | style={style.button} 69 | activeOpacity={1} 70 | > 71 | {/*