Commit 04fbca71 authored by Malsha Rathnasiri's avatar Malsha Rathnasiri

Merge branch 'master' of http://gitlab.sliit.lk/2022-240/240

parents 9f4ce84c 888e41c8
...@@ -8,3 +8,4 @@ ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffprobe.exe ...@@ -8,3 +8,4 @@ ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffprobe.exe
ffmpeg/ffprobe.exe ffmpeg/ffprobe.exe
ffmpeg/ffmpeg.exe ffmpeg/ffmpeg.exe
ffmpeg/ffplay.exe ffmpeg/ffplay.exe
backend/db.sqlite3
{
"e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true,
"af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true,
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
node_modules/
node_modules2/
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import useCachedResources from './hooks/useCachedResources';
import useColorScheme from './hooks/useColorScheme';
import Navigation from './navigation/index';
import { NativeBaseProvider, Box } from "native-base";
export default function App() {
const isLoadingComplete = useCachedResources();
const colorScheme = useColorScheme();
if (!isLoadingComplete) {
return null;
} else {
return (
<NativeBaseProvider>
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar />
</SafeAreaProvider>
</NativeBaseProvider>
);
}
}
import React, { createContext, useContext, useState, useEffect, useLayoutEffect } from "react";
import axios from "axios";
import { BACKEND_URL } from "./constants";
// import { nexlAxios } from "../../constants/helper";
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Platform } from 'react-native'
// import {
// IAuthContext,
// IAuthRequest,
// STORAGE_BEARER_TOKEN,
// UNINITIALISED,
// USER_EMAIL,
// } from "./IAuthContext";
// import { Loading } from "./state/Loading";
// import { getEnvironment } from "../../constants/variables";
// import { AxiosError, AxiosResponse } from "axios";
// import { rollbar } from "./ErrorBoundary";
// import { ENDPOINT as endpoint } from "./constants";
// const AuthContext = createContext({
// isLoggedIn: false,
// token: "",
// email: "",
// error: "",
// loading: false,
// initialised: false,
// login: UNINITIALISED,
// logout: UNINITIALISED,
// });
// export const useAuthContext = () => useContext(AuthContext);
// export const AuthConsumer = AuthContext.Consumer;
// interface IProps {
// children: any;
// }
// interface ILoginData {
// error: string;
// user: {
// email: string;
// id: string;
// first_name: string;
// last_name: string;
// };
// }
// const endpoint = getEnvironment().endpoint;
export const isLoggedIn = async () => {
const token = await AsyncStorage.getItem('access_token')
console.log({ token, has: !!token })
return !!token
}
export const login = async (username, password) => {
const endpoint = false ? 'register' : 'login';
const payload = { username: username, password: password }
const headers = new Headers({ "Content-Type": 'application./json', 'mode': 'no-cors', 'Access-Control-Allow-Headers': '*' })
const options = { method: 'POST', data: payload, headers }
axios.defaults.baseURL = BACKEND_URL;
axios.defaults.timeout = 1500;
console.log({ payload })
return axios.post('/api/auth/token/obtain/', payload)
.then(async (response) => {
const { access, refresh, user } = response.data;
axios.defaults.headers.common.Authorization = `Token ${access}`;
await AsyncStorage.setItem('user_id', String(user.id))
await AsyncStorage.setItem('username', user.username)
await AsyncStorage.setItem('user_email', user.email)
await AsyncStorage.setItem('access_token', access)
await AsyncStorage.setItem('refresh_token', refresh)
console.log("login successful")
return true
// Actions.main();
})
.catch(error => {
console.log('error in login authentication')
throw Error(error)
});
}
export const logout = async () => {
await AsyncStorage.clear()
}
// export const AuthProvider = ({ children }) => {
// const [isLoggedIn, setIsLoggedIn] = useState(false);
// const [token, setToken] = useState("");
// const [email, setEmail] = useState("");
// const [error, setError] = useState("");
// const [loading, setLoading] = useState(false);
// const [initialised, setInitialised] = useState(false);
// const login = async ({ email, password, rememberMe }) => {
// setLoading(true);
// nexlAxios(false)
// .post(`${endpoint}/accounts/sign_in.json`, {
// source: "iOS app",
// account: {
// email,
// password,
// remember_me: rememberMe ? "1" : "0",
// },
// })
// .then(async (response) => {
// setLoading(false);
// const user = response.data.user;
// user.email && setIsLoggedIn(true);
// const token = response.headers["authorization"];
// setToken(token);
// await AsyncStorage.setItem(USER_EMAIL, email);
// setEmail(email);
// rollbar.setPerson(user.id, `${user.first_name} ${user.last_name}`, user.email);
// })
// .catch((result) => {
// setLoading(false);
// setError(
// result?.response?.data?.error || result?.message || "An unknown error has occurred.",
// );
// });
// };
// const loginWithBearerToken = async (bearer) => {
// if (bearer) {
// setLoading(true);
// await nexlAxios(false, bearer)
// .post(`${endpoint}/accounts/sign_in.json`, undefined, {
// headers: {
// Authorization: bearer,
// },
// })
// .then((response) => {
// setLoading(false);
// const user = response.data.user;
// user.email && setIsLoggedIn(true);
// rollbar.setPerson(user.id, `${user.first_name} ${user.last_name}`, user.email);
// })
// .catch(() => {
// setLoading(false);
// setToken("");
// });
// }
// };
// const logout = async () => {
// const token = await AsyncStorage.getItem(STORAGE_BEARER_TOKEN);
// token && (await nexlAxios(false, token).post(`${endpoint}/sign_out.json`));
// setToken("");
// setIsLoggedIn(false);
// await AsyncStorage.removeItem(STORAGE_BEARER_TOKEN);
// rollbar.clearPerson();
// };
// // look if token / email exist in local storage on initialising the app
// // if token exists, try log in with token
// useLayoutEffect(() => {
// let isMounted = true;
// const initialise = async () => {
// const bearerToken = await AsyncStorage.getItem(STORAGE_BEARER_TOKEN);
// setToken(bearerToken || "");
// const userEmail = await AsyncStorage.getItem(USER_EMAIL);
// setEmail(userEmail || "");
// bearerToken && (await loginWithBearerToken(bearerToken));
// setInitialised(true);
// };
// if (isMounted) {
// initialise();
// }
// return () => {
// isMounted = false;
// };
// }, []);
// // update token to local storage on token change
// useEffect(() => {
// AsyncStorage.setItem(STORAGE_BEARER_TOKEN, token);
// }, [token]);
// return (
// <AuthContext.Provider
// value={{
// login,
// isLoggedIn,
// logout,
// token,
// email: email.toLowerCase(),
// loading,
// error,
// initialised,
// }}
// >
// {initialised ? children : <Loading copy="Logging in..." />}
// </AuthContext.Provider>
// );
// };
\ No newline at end of file
import { BACKEND_URL } from "./constants"
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from "@react-navigation/native";
import axios from "axios";
//"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjYxMzU2NDA5LCJpYXQiOjE2NjAxNDY4MDksImp0aSI6ImFhMTljMmY2ZDNkMzRiNDdhZmZmM2FjMzVjNzI4MWJhIiwidXNlcl9pZCI6MX0.IVzibo_Rf2xzoT1J5o1L3zwu3mco6ODcNPC-7imu3Lo"
// const headers =
const getHeaders = async () => {
var token = await AsyncStorage.getItem('access_token')
return {
Authorization: `JWT ${token}`, 'Content-Type': 'application/json',
// "Access-Control-Allow-Methods": "DELETE, POST, GET, OPTIONS",
// "Access-Control-Allow-Headers": "Content-Type, Authorization, Access-Control-Allow-Methods",
// "Access-Control-Allow-Origin": "*",
}
}
export const addChats = async (values) => {
const headers = await getHeaders()
console.log({ headers }, 'create')
console.log({values})
try {
return fetch(`${BACKEND_URL}/chats/add_chats/`, { method: 'POST', body: JSON.stringify(values), headers })
// return Axios.post(`${BACKEND_URL}/${resource}/`, values)
}
catch (e) {
console.log(e)
}
}
export const create = async (resource, values) => {
const headers = await getHeaders()
console.log({ headers }, 'create')
console.log({values})
try {
return fetch(`${BACKEND_URL}/${resource}/`, { method: 'POST', body: JSON.stringify(values), headers })
// return Axios.post(`${BACKEND_URL}/${resource}/`, values)
}
catch (e) {
console.log(e)
}
}
export const getList = async (resource, params) => {
const url = new URL(`${BACKEND_URL}/${resource}/`)
if (params) {
Object.keys(params).map(key => {
url.searchParams.append(key, params[key])
})
}
const headers = await getHeaders()
console.log(headers, 'getList')
return fetch(url, { method: 'GET', headers: headers })
return axios.get(url.toString(), null, { headers })
}
export const getOne = async (resource, id) => {
const url = new URL(`${BACKEND_URL}/${resource}/${id}/`)
const headers = await getHeaders()
console.log(headers, 'getONe')
return fetch(url, { method: "GET", headers: headers })
}
\ No newline at end of file
// export const BACKEND_URL = "http://192.168.8.103:8000"
import { Platform } from 'react-native'
export const BACKEND_ADDRESS = Platform.OS == 'web' ? "http://127.0.0.1:8000" : "https://21a1-112-134-220-172.ap.ngrok.io"
export const BACKEND_URL = `${BACKEND_ADDRESS}`
{
"expo": {
"name": "DriverApp",
"slug": "DriverApp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "myapp",
"userInterfaceStyle": "automatic",
"splash": {
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"favicon": "./assets/images/favicon.png"
}
}
}
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo']
};
};
import React from 'react'
import { Text, View, StyleSheet, Button } from 'react-native';
import { Audio } from 'expo-av';
import { createIconSetFromFontello } from '@expo/vector-icons';
import * as FileSystem from 'expo-file-system';
import { BACKEND_URL } from '../api/constants';
export const AudioRecorder = ({ setDetectedText }) => {
const [recording, setRecording] = React.useState();
const [sound, setSound] = React.useState();
async function startRecording() {
try {
console.log('Requesting permissions..');
await Audio.requestPermissionsAsync();
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
console.log('Starting recording..');
const { recording } = await Audio.Recording.createAsync(
Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
);
setRecording(recording);
console.log('Recording started');
} catch (err) {
console.error('Failed to start recording', err);
}
}
async function stopRecording() {
console.log('Stopping recording..');
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log('Recording stopped and stored at', uri)
//console.log(recording)
const headers = {
'Content-Type': 'multipart/form-data'
// 'Content-Type': 'application/x-www-form-urlencoded',
}
playSound(uri)
FileSystem.uploadAsync(`${BACKEND_URL}/mlmodels/detect/`, uri, { headers: headers, uploadType: FileSystem.FileSystemUploadType.MULTIPART })
.then(data => JSON.parse(data.body))
.then(data => {
// console.log({ result: data });
setDetectedText(data.result);
// setTimeout(() => setDetectedText(''), 1000)
})
.catch(err => console.log({ err }))
}
async function playSound(uri) {
console.log('Loading Sound');
// const { sound } = await Audio.Sound.createAsync(
// require(uri)
// );
// setSound(sound);
// console.log('Playing Sound');
// await sound.playAsync();
}
return (
<Button
style={{ height: '100%', padding: 5 }}
title={recording ? 'Stop' : 'Record'}
onPress={recording ? stopRecording : startRecording}
/>
);
}
\ No newline at end of file
import * as WebBrowser from 'expo-web-browser';
import { StyleSheet, TouchableOpacity } from 'react-native';
import Colors from '../constants/Colors';
import { MonoText } from './StyledText';
import { Text, View } from './Themed';
export default function EditScreenInfo({ path }: { path: string }) {
return (
<View>
<View style={styles.getStartedContainer}>
<Text
style={styles.getStartedText}
lightColor="rgba(0,0,0,0.8)"
darkColor="rgba(255,255,255,0.8)">
Open up the code for this screen:
</Text>
<View
style={[styles.codeHighlightContainer, styles.homeScreenFilename]}
darkColor="rgba(255,255,255,0.05)"
lightColor="rgba(0,0,0,0.05)">
<MonoText>{path}</MonoText>
</View>
<Text
style={styles.getStartedText}
lightColor="rgba(0,0,0,0.8)"
darkColor="rgba(255,255,255,0.8)">
Change any of the text, save the file, and your app will automatically update.
</Text>
</View>
<View style={styles.helpContainer}>
<TouchableOpacity onPress={handleHelpPress} style={styles.helpLink}>
<Text style={styles.helpLinkText} lightColor={Colors.light.tint}>
Tap here if your app doesn't automatically update after making changes
</Text>
</TouchableOpacity>
</View>
</View>
);
}
function handleHelpPress() {
WebBrowser.openBrowserAsync(
'https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet'
);
}
const styles = StyleSheet.create({
getStartedContainer: {
alignItems: 'center',
marginHorizontal: 50,
},
homeScreenFilename: {
marginVertical: 7,
},
codeHighlightContainer: {
borderRadius: 3,
paddingHorizontal: 4,
},
getStartedText: {
fontSize: 17,
lineHeight: 24,
textAlign: 'center',
},
helpContainer: {
marginTop: 15,
marginHorizontal: 20,
alignItems: 'center',
},
helpLink: {
paddingVertical: 15,
},
helpLinkText: {
textAlign: 'center',
},
});
import { Ionicons } from "@expo/vector-icons";
import React, { useState } from "react";
import { View } from "react-native";
import { CONVO_DEFAULT_ICON_COLOR, CONVO_STOP_ICON_COLOR, styles } from "../util/styles";
import * as Speech from 'expo-speech';
export const PlayMessage = ({ message }) => {
const [isPlaying, setIsPlaying] = useState(false)
const [isTtsReady, setIsTtsReady] = useState(false)
// // Tts.setDucking(true);
// Tts.addEventListener('tts-start', (event) => console.log("start"));
// Tts.addEventListener('tts-finish', (event) => console.log("finish"));
// const synth = window.speechSynthesis;
// const speech = new SpeechSynthesisUtterance(message)
// speech.lang = 'en'
// speech.onend((e) => console.log('end'))
const onSpeechDone = (props) => {
setIsPlaying(false)
}
const onPlayPress = () => {
setIsPlaying(true)
// synth.speak(speech)
Speech.speak(message, { onDone: onSpeechDone });
// speech.onend((e) => console.log('end'))
}
const onStopPress = () => {
Speech.stop()
setIsPlaying(false)
}
if (!isPlaying) {
return (
<Ionicons name="play" size={15} style={styles.chatIcon} onPress={onPlayPress} color={CONVO_DEFAULT_ICON_COLOR} />
)
}
else {
return (
<Ionicons name="stop" size={15} style={styles.chatIcon} onPress={onStopPress} color={CONVO_STOP_ICON_COLOR} />
)
}
}
\ No newline at end of file
import { Text, TextProps } from './Themed';
export function MonoText(props: TextProps) {
return <Text {...props} style={[props.style, { fontFamily: 'space-mono' }]} />;
}
/**
* Learn more about Light and Dark modes:
* https://docs.expo.io/guides/color-schemes/
*/
import { Text as DefaultText, View as DefaultView } from 'react-native';
import Colors from '../constants/Colors';
import useColorScheme from '../hooks/useColorScheme';
export function useThemeColor(
props: { light?: string; dark?: string },
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
) {
const theme = useColorScheme();
const colorFromProps = props[theme];
if (colorFromProps) {
return colorFromProps;
} else {
return Colors[theme][colorName];
}
}
type ThemeProps = {
lightColor?: string;
darkColor?: string;
};
export type TextProps = ThemeProps & DefaultText['props'];
export type ViewProps = ThemeProps & DefaultView['props'];
export function Text(props: TextProps) {
const { style, lightColor, darkColor, ...otherProps } = props;
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
return <DefaultText style={[{ color }, style]} {...otherProps} />;
}
export function View(props: ViewProps) {
const { style, lightColor, darkColor, ...otherProps } = props;
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
}
import React, { useEffect, useState } from 'react'
import { View, Text, ActivityIndicator } from 'react-native'
import AsyncStorage from '@react-native-async-storage/async-storage'
export const UserProfile = () => {
const [loading, setLoading] = useState(true)
const [username, setUsername] = useState("")
const [modalVisible, setModalVisible] = useState(false)
useEffect(() => {
AsyncStorage.getItem('username').then((username) => {
setUsername(username)
setLoading(false)
})
})
if (loading) {
return <ActivityIndicator />
}
return (
<>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
setModalVisible(!modalVisible);
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}>
<Text style={styles.textStyle}>Hide Modal</Text>
</Pressable>
</View>
</View>
</Modal>
</>
)
}
\ No newline at end of file
import * as React from 'react';
import renderer from 'react-test-renderer';
import { MonoText } from '../StyledText';
it(`renders correctly`, () => {
const tree = renderer.create(<MonoText>Snapshot test!</MonoText>).toJSON();
expect(tree).toMatchSnapshot();
});
const tintColorLight = '#2f95dc';
const tintColorDark = '#fff';
export default {
light: {
text: '#000',
background: '#fff',
tint: tintColorLight,
tabIconDefault: '#ccc',
tabIconSelected: tintColorLight,
},
dark: {
text: '#fff',
background: '#000',
tint: tintColorDark,
tabIconDefault: '#ccc',
tabIconSelected: tintColorDark,
},
};
import { Dimensions } from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
export default {
window: {
width,
height,
},
isSmallDevice: width < 375,
};
import { FontAwesome } from '@expo/vector-icons';
import * as Font from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect, useState } from 'react';
export default function useCachedResources() {
const [isLoadingComplete, setLoadingComplete] = useState(false);
// Load any resources or data that we need prior to rendering the app
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHideAsync();
// Load fonts
await Font.loadAsync({
...FontAwesome.font,
'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'),
});
} catch (e) {
// We might want to provide this error information to an error reporting service
console.warn(e);
} finally {
setLoadingComplete(true);
SplashScreen.hideAsync();
}
}
loadResourcesAndDataAsync();
}, []);
return isLoadingComplete;
}
import { ColorSchemeName, useColorScheme as _useColorScheme } from 'react-native';
// The useColorScheme value is always either light or dark, but the built-in
// type suggests that it can be null. This will not happen in practice, so this
// makes it a bit easier to work with.
export default function useColorScheme(): NonNullable<ColorSchemeName> {
return _useColorScheme() as NonNullable<ColorSchemeName>;
}
/**
* Learn more about deep linking with React Navigation
* https://reactnavigation.org/docs/deep-linking
* https://reactnavigation.org/docs/configuring-links
*/
import { LinkingOptions } from '@react-navigation/native';
import * as Linking from 'expo-linking';
import { RootStackParamList } from '../types';
const linking: LinkingOptions<RootStackParamList> = {
prefixes: [Linking.makeUrl('/')],
config: {
screens: {
Root: {
screens: {
TabOne: {
screens: {
TabOneScreen: 'one',
},
},
TabTwo: {
screens: {
TabTwoScreen: 'two',
},
},
},
},
Modal: 'modal',
NotFound: '*',
},
},
};
export default linking;
/**
* If you are not familiar with React Navigation, refer to the "Fundamentals" guide:
* https://reactnavigation.org/docs/getting-started
*
*/
import { FontAwesome } from '@expo/vector-icons';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Center, Toast } from 'native-base';
import * as React from 'react';
import { ColorSchemeName, Pressable, View, Button, Text, Image } from 'react-native';
import { isLoggedIn, login, logout } from '../api/Authentication';
import Colors from '../constants/Colors';
import useColorScheme from '../hooks/useColorScheme';
import { LoginScreen } from '../screens/loginScreen';
import ModalScreen from '../screens/ModalScreen';
import NotFoundScreen from '../screens/NotFoundScreen';
import { SignupScreen } from '../screens/SignupScreen';
import ChatScreen from '../screens/TabOneScreen';
import TabTwoScreen from '../screens/TabTwoScreen';
import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types';
import { ERROR_TOAST_PROPS } from '../util/util';
import LinkingConfiguration from './LinkingConfiguration';
import Small_logo from '../assets/images/Logo_small.jpeg'
import { PRIMARY_COLOR } from '../util/styles';
import InnerNavigator from '../screens/InnerNavigator';
export default function Navigation({ colorScheme }) {
return (
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' && false ? DarkTheme : DefaultTheme}>
<RootNavigator />
</NavigationContainer>
);
}
/**
* A root stack navigator is often used for displaying modals on top of all other content.
* https://reactnavigation.org/docs/modal
*/
const Stack = createNativeStackNavigator();
function RootNavigator() {
const [isAuthenticated, setIsAutheticated] = React.useState(false)
// console.log({ isLogged })
React.useEffect(() => {
isLoggedIn().then((res) => { setIsAutheticated(res), console.log({ setIs: res }) })
}, [])
const onLogin = async (username, password) => {
await login(username, password).then(() => setIsAutheticated(true)).catch(e => {
console.log(e)
Toast.show({ title: 'Error logging in! Try again', ...ERROR_TOAST_PROPS })
})
// setTimeout(() => setIsAutheticated(true), 2000)
}
const onLogout = () => {
logout()
setIsAutheticated(false)
}
return (
<Stack.Navigator >
{isAuthenticated ? <Stack.Screen name="Root" options={{ headerShown: false }}>{(props) => <BottomTabNavigator {...props} onLogout={onLogout} />}</Stack.Screen> :
<Stack.Screen name='Root' options={{ headerShown: false }}>{(props) => <LoginScreen {...props} onLogin={onLogin} />}</Stack.Screen>}
<Stack.Screen name='Signup' component={SignupScreen} options={{ headerShown: false, title: 'Sign up' }} />
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group>
</Stack.Navigator>
);
}
/**
* A bottom tab navigator displays tab buttons on the bottom of the display to switch screens.
* https://reactnavigation.org/docs/bottom-tab-navigator
*/
const BottomTab = createBottomTabNavigator();
function BottomTabNavigator({ onLogout }) {
const colorScheme = useColorScheme();
return (
<BottomTab.Navigator
initialRouteName="TabOne"
screenOptions={{
// tabBarActiveBackgroundColor: 'lightgray',
tabBarActiveTintColor: PRIMARY_COLOR //Colors[colorScheme].tint,
}}>
<BottomTab.Screen
name="TabTwo"
component={InnerNavigator}
hide
options={{
title: 'Journey',
headerShown: true,
headerTitle: '',
tabBarIcon: ({ color }) => <TabBarIcon name="map" color={color} />,
headerLeft: () => (<Image source={Small_logo} style={{ height: 40, width: 70, marginLeft: 20 }} />),
headerRight: () => (
<Pressable
// onPress={() => navigation.navigate('Modal')}
onPress={onLogout}
style={({ pressed }) => ({
opacity: pressed ? 0.5 : 1,
})}>
{/* <Text>Logout</Text> */}
<FontAwesome
name="info-circle"
size={25}
// color={Colors[colorScheme].text}
style={{ marginRight: 15 }}
/>
</Pressable>
),
}}
/>
<BottomTab.Screen
name="TabOne"
component={ChatScreen}
options={({ navigation }) => ({
title: 'Chat',
headerTitleAlign: 'center',
tabBarIcon: ({ color }) => <TabBarIcon name="comments" color={color} />,
headerLeft: () => (<Image source={Small_logo} style={{ height: 40, width: 70, marginLeft: 20 }} />),
headerRight: () => (
<Pressable
// onPress={() => navigation.navigate('Modal')}
onPress={onLogout}
style={({ pressed }) => ({
opacity: pressed ? 0.5 : 1,
})}>
{/* <Text>Logout</Text> */}
<FontAwesome
name="info-circle"
size={25}
// color={Colors[colorScheme].text}
style={{ marginRight: 15 }}
/>
</Pressable>
),
})}
/>
</BottomTab.Navigator>
);
}
/**
* You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
*/
function TabBarIcon(props) {
return <FontAwesome size={30} style={{ marginBottom: -3 }} {...props} />;
}
{
"name": "mobileapp",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"test": "jest --watchAll"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/slider": "4.2.1",
"@react-navigation/bottom-tabs": "^6.0.5",
"@react-navigation/native": "^6.0.2",
"@react-navigation/native-stack": "^6.1.0",
"axios": "^0.27.2",
"expo": "^45.0.0",
"expo-asset": "~8.5.0",
"expo-av": "~11.2.3",
"expo-constants": "~13.1.1",
"expo-file-system": "~14.0.0",
"expo-font": "~10.1.0",
"expo-linking": "~3.1.0",
"expo-media-library": "~14.1.0",
"expo-speech": "~10.2.0",
"expo-splash-screen": "~0.15.1",
"expo-status-bar": "~1.3.0",
"expo-web-browser": "~10.2.1",
"jwt-decode": "^3.1.2",
"native-base": "^3.4.11",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-native": "0.68.2",
"react-native-multi-selectbox": "^1.5.0",
"react-native-safe-area-context": "4.2.4",
"react-native-screens": "~3.11.1",
"react-native-svg": "12.3.0",
"react-native-web": "0.17.7",
"styled-system": "^5.1.5"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@types/react": "~17.0.21",
"@types/react-native": "~0.67.6",
"jest": "^26.6.3",
"jest-expo": "^45.0.0",
"react-test-renderer": "17.0.1",
"typescript": "~4.3.5"
},
"private": true
}
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { alignContent, flex, flexDirection, width } from 'styled-system';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR, BORDER_COLOR } = colors
function Home() {
const navigation = useNavigation();
return (
<View style={styles.container}>
<View style={styles.TopView}>
<Image style={styles.imageStyle} source={require('../assets/logo.jpg')} alt="image" />
</View>
<View style={styles.Info} >
<Text style={{ fontSize: 20, marginTop: 20, color: '#8e8e8e' }}>Keep a safe distance from vehicles!</Text>
</View>
<View style={styles.weatherDetails}>
<View style={styles.weatherDetailsRow}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="seatbelt" size={30} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("RegInfo")} >
<Text style={styles.textSecondary}>Seat Reservation</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<FontAwesome5 name="route" size={25} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("RouteInfo")} >
<Text style={styles.textSecondary}>Route Info</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
<View style={{ ...styles.weatherDetailsRow, borderTopWidth: 1, borderTopColor: BORDER_COLOR }}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="comment-account-outline" size={30} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("#")} >
<Text style={styles.textSecondary}>Driver feedback</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="map-marker-radius-outline" size={30} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("#")} >
<Text style={styles.textSecondary}>Find Vehicle</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</View>
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<Home />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
main: {
marginTop: 200,
justifyContent: 'center',
},
Icon: {
width: 100,
height: 100,
},
Info: {
alignItems: 'center',
},
weatherDetails: {
marginTop: 100,
margin: 15,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
weatherDetailsRow: {
flexDirection: 'row',
alignItems: 'stretch'
},
weatherDetailsBox: {
flex: 1,
padding: 20,
},
weatherDetailsItems: {
alignItems: 'center',
alignItems: 'stretch',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
alignItems: 'center',
},
buttonStyleX: {
marginTop: 12,
marginLeft: 15,
marginRight: 15
},
buttonDesign: {
backgroundColor: '#026efd'
},
buttonStyle: {
marginTop: 30,
marginLeft: 15,
marginRight: 15
},
TopView: {
width: '100%',
height: '30%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
imageStyle: {
width: '60%',
resizeMode: 'contain',
alignItems: 'center',
top: 100,
},
})
\ No newline at end of file
import React from 'react';
import RegInfo from './RegInfo';
import RouteInfo from './RouteInfo';
import Home from './Home';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function App() {
return (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Root" component={Home} />
<Stack.Screen name="RegInfo" component={RegInfo} />
<Stack.Screen name="RouteInfo" component={RouteInfo} />
</Stack.Navigator>
);
}
export default () => {
return (
<NavigationContainer independent>
<App />
</NavigationContainer>
)
}
import { StatusBar } from 'expo-status-bar';
import { Platform, StyleSheet } from 'react-native';
import EditScreenInfo from '../components/EditScreenInfo';
import { Text, View } from '../components/Themed';
export default function ModalScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Modal</Text>
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
<EditScreenInfo path="/screens/ModalScreen.tsx" />
{/* Use a light status bar on iOS to account for the black space above the modal */}
<StatusBar style={Platform.OS === 'ios' ? 'light' : 'auto'} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
});
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../components/Themed';
import { RootStackScreenProps } from '../types';
export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Root')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 20,
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
link: {
marginTop: 15,
paddingVertical: 15,
},
linkText: {
fontSize: 14,
color: '#2e78b7',
},
});
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR, BORDER_COLOR } = colors
function RegInfo() {
const navigation = useNavigation();
return (
<View style={styles.container}>
<View style={styles.main}>
<View style={styles.Info} >
<Image style={styles.Icon} source={require('../assets/successful.jpg')} alt="image" />
<Text style={{ fontSize: 20, marginTop: 20, color: 'green' }}>Seat Reservation completed</Text>
<Text style={{ fontSize: 12, marginTop: 10, color: '#8e8e8e' }}>Ref# 837110243</Text>
<Text style={{ fontSize: 20, fontWeight: 'bold', marginTop: 30, color: 'green' }}>Your Seat Number</Text>
<Text style={{ fontSize: 45, fontWeight: 'bold', marginTop: 5, color: '#ff304f' }}>25</Text>
</View>
</View>
<View style={styles.weatherDetails}>
<View style={styles.weatherDetailsRow}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<FontAwesome5 name="car" size={25} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Vehicle Number</Text>
<Text style={styles.textSecondary}>BDA - 0713</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<FontAwesome5 name="user-secret" size={25} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Driver name</Text>
<Text style={styles.textSecondary}>Anura Kumara</Text>
</View>
</View>
</View>
</View>
<View style={{ ...styles.weatherDetailsRow, borderTopWidth: 1, borderTopColor: BORDER_COLOR }}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="message-star-outline" size={30} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Rating</Text>
<Text style={styles.textSecondary}>4.5/5</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="cellphone" size={30} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Call </Text>
<Text style={styles.textSecondary}>077 567 6002</Text>
</View>
</View>
</View>
</View>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Root")}>
Home
</Button>
</View>
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<RegInfo />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
main: {
marginTop: 10,
justifyContent: 'center',
},
Icon: {
width: 100,
height: 100,
},
Info: {
alignItems: 'center',
},
weatherDetails: {
marginTop: 60,
margin: 15,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
weatherDetailsRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
weatherDetailsBox: {
flex: 1,
padding: 20,
},
weatherDetailsItems: {
alignItems: 'flex-end',
justifyContent: 'flex-end',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
},
buttonStyleX: {
marginTop: 12,
marginLeft: 15,
marginRight: 15
},
buttonDesign: {
backgroundColor: '#026efd'
},
buttonStyle: {
marginTop: 30,
marginLeft: 15,
marginRight: 15
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { useNavigation } from '@react-navigation/native';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors
function RouteInfo() {
const navigation = useNavigation();
return (
<View style={styles.container}>
<View style={styles.Head}>
<Text style={styles.HeadText}>Journey</Text>
</View>
<View style={styles.lineStyle}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 120, textAlign: 'right', fontWeight:'bold', fontSize:15}}>Travel History</Text>
</View>
</View>
<View style={styles.summeryDetails}>
<View style={styles.summeryDetailsRow}>
<View style={{ ...styles.summeryDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.summeryDetailsRow}>
<View style={styles.summeryDetailsItems}>
<Text style={{color:'#8e8e8e',fontWeight: '700'}}>This Week</Text>
<Text style={{ fontSize: 15,color: 'orange',fontWeight: '700', margin: 7}}>4 Days</Text>
</View>
</View>
</View>
<View style={{...styles.summeryDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR}}>
<View style={styles.summeryDetailsRow}>
<View style={styles.summeryDetailsItems}>
<Text style={{color:'#8e8e8e',fontWeight: '700'}}>Last Week</Text>
<Text style={{fontSize: 15,color: 'green',fontWeight: '700', margin: 7}}>3 Days</Text>
</View>
</View>
</View>
<View style={styles.summeryDetailsBox}>
<View style={styles.summeryDetailsRow}>
<View style={styles.summeryDetailsItems}>
<Text style={{color:'#8e8e8e',fontWeight: '700'}}>Last Month</Text>
<Text style={{fontSize: 15,color: 'purple',fontWeight: '700', margin: 7}}>15 Days</Text>
</View>
</View>
</View>
</View>
</View>
<View style={styles.lineStyle}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 110, textAlign: 'right', fontWeight:'bold', fontSize:15}}>Travel Details</Text>
</View>
</View>
<View style={styles.summeryDetails}>
<View style={styles.summeryDetailsRow}>
<View style={{ ...styles.summeryDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.summeryDetailsRow}>
<View>
<Text style={{color:'#8e8e8e',textAlign: 'left', fontWeight:'bold' }}>Route: From Malabe to Colombo</Text>
<Text style={{color:'#8e8e8e',textAlign: 'left', fontWeight:'bold',marginTop: 7}}>Type: Return</Text>
<Text style={{color:'blue', textAlign: 'left',fontSize: 15, fontWeight: '700', marginTop: 7}}>You have used our service for 4 days for this week.</Text>
</View>
</View>
</View>
</View>
</View>
<View style={styles.lineStyle}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 75, textAlign: 'right', fontWeight:'bold', fontSize:15}}>Total Fee</Text>
</View>
</View>
<View style={styles.summeryDetails}>
<View style={styles.summeryDetailsRow}>
<View style={{ ...styles.summeryDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.summeryDetailsRow}>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Fee per Trip :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>500.00 LKR</Text>
</View>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Total Trips :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>16</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Total Fee :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>8000.00 LKR</Text>
</View>
</View>
</View>
</View>
</View>
{/* Button */}
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Root")}>
Home
</Button>
</View>
<StatusBar style="auto" />
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<RouteInfo />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
HeadText: {
marginTop:10,
fontSize:30,
fontWeight:'bold',
},
Head:{
// alignItems:'left',
justifyContent:'center',
marginLeft:15,
},
lineStyle:{
flexDirection:'row',
marginTop:15,
marginLeft:15,
marginRight:15,
alignItems:'center'
},
summeryDetails: {
marginTop: 15,
margin: 15,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
summeryDetailsRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
summeryDetailsBox: {
flex: 1,
padding: 10,
},
summeryDetailsItems: {
alignItems: 'flex-end',
justifyContent: 'flex-end',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
},
row: {
flexDirection: "row",
paddingRight: 12,
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
buttonStyle:{
marginTop:20,
marginLeft:15,
marginRight:15
},
})
\ No newline at end of file
import React, { useEffect, useState } from "react";
import {
FlatList,
StyleSheet,
TextInput,
SectionList,
Button,
ActivityIndicator,
View,
Text,
SafeAreaView,
TouchableOpacity,
} from "react-native";
import { AudioRecorder } from "../components/AudioRecorder";
import _ from "lodash";
import EditScreenInfo from "../components/EditScreenInfo";
// import { Text, View } from '../components/Themed';
import { RootTabScreenProps } from "../types";
import { addChats, create, getList, getOne } from "../api/api";
import { BACKEND_ADDRESS } from "../api/constants";
import Ionicons from "@expo/vector-icons/Ionicons";
import { CONVO_DEFAULT_ICON_COLOR, styles } from "../util/styles";
import { StatusBar } from "expo-status-bar";
import Slider from "@react-native-community/slider";
import { PlayMessage } from "../components/PlayMessage";
import { Toast, Input, PresenceTransition } from "native-base";
import { ERROR_TOAST_PROPS } from "../util/util";
import AsyncStorage from "@react-native-async-storage/async-storage";
export default function ChatScreen({ navigation }) {
const currentTime = new Date();
const defaultChatData = [
{
id: 1,
from_user: 2,
to_user: 1,
message: "How many passengers?",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 1).valueOf(),
},
{
id: 2,
from_user: 1,
to_user: 2,
message: "Three",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 2).valueOf(),
is_detected: true,
},
{
id: 3,
from_user: 2,
to_user: 1,
message: "Should i turn left or right here?",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 3).valueOf(),
is_detected: false,
},
{
id: 4,
from_user: 1,
to_user: 2,
message: "Left",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 4).valueOf(),
is_detected: true,
},
{
id: 5,
from_user: 1,
to_user: 2,
message: "Please hurry",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 5).valueOf(),
},
{
id: 6,
from_user: 2,
to_user: 1,
message: "Ok",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 6).valueOf(),
},
// { from_user: 1, to_user: 2, message: 'msg1', timestamp: currentTime.setDate(currentTime.getDate() - 1).valueOf() },
// { from_user: 1, to_user: 2, message: 'msg2', timestamp: currentTime.setDate(currentTime.getDate() - 2).valueOf() },
// { from_user: 2, to_user: 1, message: 'msg3', timestamp: currentTime.setDate(currentTime.getDate() - 3).valueOf() },
// { from_user: 1, to_user: 2, message: 'msg4', timestamp: currentTime.setDate(currentTime.getDate() - 4).valueOf() },
// { from_user: 2, to_user: 1, message: 'msg5', timestamp: currentTime.setDate(currentTime.getDate() - 5).valueOf() },
];
const [detectedText, setDetectedText] = useState("");
const [playinId, setPlayingId] = useState();
const [chatDetails, setChatDetails] = useState(null);
const [conversations, setConversations] = useState([]);
const [users, setUsers] = useState([]);
const [chats, setChats] = useState([]);
const [input, setInput] = useState("test");
const [loading, setLoading] = useState(true);
const loadSampleChats = () => {
const chats_ = defaultChatData; //res.results
const sections = [
...new Set(
chats_.map((chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0))
),
];
const sectionChats = sections.map((section) => {
console.log({ section });
return {
title: section,
data: chats_
.filter((chat) => {
console.log({ chat });
return (
new Date(chat.timestamp).setHours(0, 0, 0, 0).valueOf() == section
);
})
.sort((a, b) => {
return a.timestamp - b.timestamp;
}),
};
});
console.log({ chats_, sections, sectionChats });
setChats(sectionChats);
console.log({ chats });
};
useEffect(() => {
if (chatDetails) {
loadChats();
// setLoading(false);
}
}, [chatDetails]);
// const ws = new WebSocket(`ws://${BACKEND_ADDRESS}/chatSocket/`)
useEffect(() => {
loadChatDetails();
// startWebsocket()
// loadSampleChats()
}, []);
// const startWebsocket = () => {
// ws.onopen = () => {
// // on connecting, do nothing but log it to the console
// console.log('connected')
// }
// ws.onmessage = evt => {
// // listen to data sent from the websocket server
// const message = JSON.parse(evt.data)
// // setState({ dataFromServer: message })
// console.log(message)
// }
// ws.onclose = () => {
// console.log('disconnected')
// // automatically try to reconnect on connection loss
// }
// }
useEffect(() => {
const interval = setInterval(() => {
loadChats();
}, 2000);
return () => {
clearInterval(interval);
};
}, []);
const loadChatDetails = async () => {
await getList("users")
.then((res) => res.json())
.then((res) => {
console.log({ users: res });
setUsers(res.results);
});
await getList("conversations")
.then((res) => {
return res.json();
})
.then((res) => {
console.log({ res });
AsyncStorage.getItem("user_id").then((user_id) => {
console.log("chat details", user_id);
const converted = res.results.map((res) => {
if (res.from_user == user_id) {
return res;
} else {
const n_res = {
...res,
from_user: res.to_user,
to_user: res.from_user,
};
return n_res;
}
});
setConversations(converted);
// //change from user and to user depending on the current user
// if (res[0].from_user == user_id) {
// setChatDetails(res)
// }
// else {
// const n_res = { ...res[0], from_user: res[0].to_user, to_user: res[0].from_user }
// setChatDetails(n_res)
// }
});
});
};
const loadChats = () => {
// setLoading(true);
getList("chats", { conversation: chatDetails?.id })
.then((res) => {
return res.json();
})
.then((res) => {
console.log("load chats", res.results);
const chats = res.results.slice(-20) || [];
const sections = [
...new Set(
chats.map((chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0))
),
];
const sectionChats = sections.map((section) => ({
title: section,
data: chats.filter(
(chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0) == section
),
}));
setChats(sectionChats);
})
.then(() => {
setLoading(false);
})
.catch((e) => {
console.log(e);
});
};
const onSendPress = () => {
try {
addChats({
message: input,
from_user: chatDetails.from_user,
to_user: chatDetails.to_user,
conversation: chatDetails?.id,
}).then((response) => {
// console.log(response)
});
setLoading(true);
setInput("");
loadChats();
} catch (e) {
Toast.show({
title: "Error sending message. try again!",
...ERROR_TOAST_PROPS,
});
}
};
if (!chatDetails && users) {
return (
<View>
<PresenceTransition
initial={{
opacity: 0,
}}
animate={{
opacity: 1,
transition: {
duration: 500,
},
}}
visible={!chatDetails}
>
<Text
style={{
backgroundColor: "grey",
padding: 20,
borderRadius: 10,
fontSize: 20,
fontWeight: "bold",
}}
>
Passengers
</Text>
<FlatList
data={conversations}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => {
setChatDetails(item);
setChats([]);
}}
>
<Text style={{ padding: 20 }}>
{
users?.find((user) => {
// console.log({ user }, user.id == item.to_user);
return user?.id == item?.to_user;
})?.username
}
</Text>
</TouchableOpacity>
);
}}
/>
</PresenceTransition>
</View>
);
}
return (
<View style={styles.container}>
{/* <Text style={styles.title}>Tab One</Text>
<View style={{height: 70, width: 100, backgroundColor: ''}}><TextInput style={{borderColor: 'white', borderWidth: 1, alignSelf: }} onChange={() => console.log('change')}></TextInput></View>
<View style={styles.separator} lightColor="#000" darkColor="rgba(255,0,255,0.1)" />
<EditScreenInfo path="/screens/TabOneScreen.tsx" /> */}
<PresenceTransition
initial={{
opacity: 0,
}}
animate={{
opacity: 1,
transition: {
duration: 100,
},
}}
visible={!!chatDetails}
style={{ flex: 1, width: "100%" }}
>
<View
style={{
display: "flex",
flex: 0.9,
justifyContent: "space-between",
// backgroundColor: "red",
}}
>
<TouchableOpacity
style={{
backgroundColor: "gray",
padding: 5,
margin: 5,
borderRadius: 5,
flexDirection: "row",
justifyContent: "space-between",
}}
onPress={() => {
setChatDetails();
}}
>
<View
style={{
flex: 0.25,
alignContent: "center",
justifyContent: "center",
}}
>
<Ionicons name="chevron-back-outline" size={20} />
</View>
{/* <Text>Back to chats</Text> */}
<View style={{ justifyContent: "center" }}>
<Text style={{ fontSize: 20 }}>
{
users.find((user) => user.id == chatDetails?.to_user)
?.username
}
</Text>
</View>
<View style={{ flex: 0.25 }}></View>
</TouchableOpacity>
<StatusBar />
{loading ? (
<ActivityIndicator />
) : (
<SectionList
initialNumToRender={10}
refreshing={loading}
onRefresh={() => {
// loadChatDetails() //remove
loadChats();
}}
sections={chats.slice(-10)}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => {
// console.log({ item })
const timeString = new Date(
item.timestamp
).toLocaleTimeString();
const time = timeString.slice(0, 5);
return (
<View style={{ margin: 5, padding: 5 }}>
<Text
style={[
{
textAlign:
chatDetails.from_user == item.from_user
? "right"
: "left",
backgroundColor:
chatDetails.from_user == item.from_user
? "lightgray"
: "#FFDE03",
borderRadius: 5,
padding: 5,
},
chatDetails.from_user == item.from_user
? { marginLeft: "auto" }
: { marginRight: "auto" },
]}
key={item.timestamp}
>
{item.message}
</Text>
<View
style={{
flex: 1,
flexDirection:
chatDetails.from_user == item.from_user
? "row-reverse"
: "row",
textAlign:
chatDetails.from_user == item.from_user
? "right"
: "left",
}}
>
<Text
style={{
textAlign:
chatDetails.from_user == item.from_user
? "right"
: "left",
color: "gray",
fontSize: 11,
}}
>
{time}
</Text>
{item.is_detected && (
<Ionicons
name="mic"
size={15}
color={CONVO_DEFAULT_ICON_COLOR}
/>
)}
{chatDetails.to_user == item.from_user && (
<PlayMessage message={item.message} />
)}
</View>
</View>
);
}}
invertStickyHeaders
inverted
contentContainerStyle={{ flexDirection: "column-reverse" }}
renderSectionHeader={({ section: { title } }) => {
var date = "";
if (
new Date(title).toLocaleDateString() ==
new Date().toLocaleDateString()
) {
date = "Today";
} else {
date = new Date(title).toLocaleDateString();
}
return <Text style={styles.header}>{date}</Text>;
}}
/>
)}
</View>
<View style={{ flex: 0.075, padding: 0, backgroundColor: "white" }}>
<View
style={{ flexDirection: "row", display: "flex", height: "100%" }}
>
<SafeAreaView
style={{
flex: 0.8,
height: "100%",
flexDirection: "column-reverse",
}}
>
{/* <TextInput
style={{ borderWidth: 2, borderColor: 'gray', color: 'black', marginHorizontal: 5, paddingHorizontal: 10, borderRadius: 5 }}
defaultValue={input}
onChange={(e) => setInput(e.target.value)}></TextInput> */}
<Input
style={{ height: 30 }}
value={input}
w="100%"
onChangeText={setInput}
placeholder=""
/>
</SafeAreaView>
{input ? (
<View
style={{
flex: 0.2,
height: "100%",
flexDirection: "column-reverse",
}}
>
<Button
style={{ width: "100%", height: "100%" }}
title="Send"
onPress={onSendPress}
/>
</View>
) : (
<View
style={{
flex: 0.2,
height: "100%",
flexDirection: "column-reverse",
}}
>
<AudioRecorder setDetectedText={setInput} />
</View>
)}
</View>
</View>
</PresenceTransition>
</View>
);
}
import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import EditScreenInfo from '../components/EditScreenInfo';
import { Text, View } from '../components/Themed';
export default function TabTwoScreen() {
return (
<View style={styles.container}>
<StatusBar />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
});
import React, { useState } from "react";
import {
StyleSheet,
TextInput,
Button,
Image,
Dimensions,
View,
Text,
ActivityIndicator,
} from "react-native";
import EditScreenInfo from "../components/EditScreenInfo";
// import { Text, View } from '../components/Themed';
import { TouchableOpacity } from "react-native";
import { ScrollView, Toast } from "native-base";
import { ERROR_TOAST_PROPS } from "../util/util";
import { screenWidth, styles } from "../util/styles";
import TTS_logo from "../assets/images/TTS_logo.jpeg";
export const LoginScreen = ({ onLogin, navigation }) => {
return (
<ScrollView style={styles.loginScreenContainer}>
<View style={{ alignContent: "center", justifyContent: "center" }}>
<Text
style={{
padding: 10,
textAlign: "center",
fontWeight: "bold",
fontSize: 30,
}}
>
Driver App
</Text>
<Image
source={TTS_logo}
style={{
height: screenWidth - 30,
width: screenWidth - 30,
margin: "auto",
}}
/>
</View>
<Text
style={{
padding: 10,
textAlign: "center",
// fontWeight: 'bold',
fontSize: 40,
}}
>
Login
</Text>
<View
style={{ flexDirection: "row", padding: 10, justifyContent: "center" }}
>
<Text style={{ textAlign: "center" }}>Don't have an account? </Text>
<Text
style={{ fontWeight: "bold", textAlign: "center" }}
onPress={() => navigation.replace("Signup")}
>
Sign up
</Text>
</View>
<View style={styles.formContainer}>
<LoginForm onLogin={onLogin} />
</View>
</ScrollView>
);
};
const LoginForm = ({ onLogin, navigation }) => {
var passwordInput;
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const onSubmit = () => {
console.log({ username, password });
setLoading(true);
if (!username || !password) {
Toast.show({
title: "Please fill in all the fields!",
...ERROR_TOAST_PROPS,
});
} else {
onLogin(username, password);
}
setLoading(false);
};
return (
<View>
<TextInput
style={styles.input}
defaultValue={username}
onChangeText={(e) => {
console.log(e);
setUsername(e);
}}
autoCapitalize="none"
onSubmitEditing={() => passwordInput.focus()}
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
placeholder="Email"
// placeholderTextColor='rgba(225,225,225,0.7)'
/>
<TextInput
style={styles.input}
defaultValue={password}
onChangeText={(e) => setPassword(e)}
returnKeyType="go"
autoCapitalize="none"
ref={(input) => (passwordInput = input)}
placeholder="Password"
onSubmitEditing={onSubmit}
// placeholderTextColor='rgba(225,225,225,0.7)'
secureTextEntry
/>
<TouchableOpacity
style={styles.buttonContainer}
// onPress={onButtonPress}
// disabled={!username || !password}
onPress={onSubmit}
disabled={loading}
>
{loading ? (
<ActivityIndicator />
) : (
<Text style={styles.buttonText}>LOGIN</Text>
)}
</TouchableOpacity>
</View>
// define your styles
);
};
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}
/**
* Learn more about using TypeScript with React Navigation:
* https://reactnavigation.org/docs/typescript/
*/
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
export type RootStackParamList = {
Root: NavigatorScreenParams<RootTabParamList> | undefined;
Modal: undefined;
Login: undefined;
NotFound: undefined;
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>;
export type RootTabParamList = {
TabOne: undefined;
TabTwo: undefined;
};
export type RootTabScreenProps<Screen extends keyof RootTabParamList> = CompositeScreenProps<
BottomTabScreenProps<RootTabParamList, Screen>,
NativeStackScreenProps<RootStackParamList>
>;
export const colors = {
PRIMARY_COLOR: '#ff304f',
SECONDARY_COLOR: '#002651',
BORDER_COLOR: '#dbdbdb',
}
\ No newline at end of file
import { StyleSheet, Dimensions } from "react-native"
export const screenWidth = Dimensions.get('window').width
export const screenHeight = Dimensions.get('window').height
export const PRIMARY_COLOR = '#2f95dc'
export const COLOR1 = '#fff'//'#2c3e50'
export const CONVO_DEFAULT_ICON_COLOR = '#000'
export const CONVO_STOP_ICON_COLOR = '#f00'
export const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: COLOR1,
},
loginContainer: {
alignItems: 'center',
flexGrow: 1,
justifyContent: 'center',
backgroundColor: 'blue'
},
logo: {
position: 'absolute',
width: 300,
height: 100
},
loginScreenContainer: {
padding: 20,
backgroundColor: 'white',
flex: 1,
},
formContainer: {
// backgroundColor: 'green'
},
input: {
height: 40,
backgroundColor: 'rgba(225,225,225,0.2)',
marginBottom: 10,
padding: 10,
// color: '#fff',
borderRadius: 5,
},
buttonContainer: {
backgroundColor: '#2980b6',
paddingVertical: 15,
borderRadius: 5
},
buttonText: {
// color: '#fff',
textAlign: 'center',
fontWeight: '700'
},
chatIcon: {
paddingHorizontal: 4
},
// container: {
// flex: 1,
// alignItems: 'center',
// justifyContent: 'center',
// },
title: {
fontSize: 20,
fontWeight: 'bold',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
convoFooter: {
},
header: { textAlign: 'center', backgroundColor: 'gray', marginRight: 'auto', marginLeft: 'auto', padding: 3, borderRadius: 5 }
})
\ No newline at end of file
export const TOAST_PROPS = {placement : 'top'}
export const ERROR_TOAST_PROPS = {...TOAST_PROPS, style:{backgroundColor: '#B00020'}}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
// export const BACKEND_URL = "http://192.168.8.103:8000" // export const BACKEND_URL = "http://192.168.8.103:8000"
import { Platform } from 'react-native' import { Platform } from 'react-native'
export const BACKEND_ADDRESS = Platform.OS == 'web' ? "http://127.0.0.1:8000" : "https://4c61-2401-dd00-10-20-7542-a875-30e7-8931.ap.ngrok.io" export const BACKEND_ADDRESS = Platform.OS == 'web' ? "http://127.0.0.1:8000" : "https://21a1-112-134-220-172.ap.ngrok.io"
export const BACKEND_URL = `${BACKEND_ADDRESS}` export const BACKEND_URL = `${BACKEND_ADDRESS}`
const { getDefaultConfig } = require("@expo/metro-config");
const defaultConfig = getDefaultConfig(__dirname);
defaultConfig.resolver.assetExts.push("cjs");
module.exports = defaultConfig;
\ No newline at end of file
...@@ -18,7 +18,7 @@ import useColorScheme from '../hooks/useColorScheme'; ...@@ -18,7 +18,7 @@ import useColorScheme from '../hooks/useColorScheme';
import { LoginScreen } from '../screens/loginScreen'; import { LoginScreen } from '../screens/loginScreen';
import ModalScreen from '../screens/ModalScreen'; import ModalScreen from '../screens/ModalScreen';
import NotFoundScreen from '../screens/NotFoundScreen'; import NotFoundScreen from '../screens/NotFoundScreen';
import { SignupScreen } from '../screens/SignupScreen'; // import { SignupScreen } from '../screens/SignupScreen';
import ChatScreen from '../screens/TabOneScreen'; import ChatScreen from '../screens/TabOneScreen';
import TabTwoScreen from '../screens/TabTwoScreen'; import TabTwoScreen from '../screens/TabTwoScreen';
import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types'; import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types';
...@@ -28,6 +28,7 @@ import LinkingConfiguration from './LinkingConfiguration'; ...@@ -28,6 +28,7 @@ import LinkingConfiguration from './LinkingConfiguration';
import Small_logo from '../assets/images/Logo_small.jpeg' import Small_logo from '../assets/images/Logo_small.jpeg'
import { PRIMARY_COLOR } from '../util/styles'; import { PRIMARY_COLOR } from '../util/styles';
import InnerNavigator from '../screens/InnerNavigator'; import InnerNavigator from '../screens/InnerNavigator';
import Signup from '../screens/Signup';
export default function Navigation({ colorScheme }) { export default function Navigation({ colorScheme }) {
return ( return (
...@@ -74,11 +75,12 @@ function RootNavigator() { ...@@ -74,11 +75,12 @@ function RootNavigator() {
<Stack.Navigator > <Stack.Navigator >
{isAuthenticated ? <Stack.Screen name="Root" options={{ headerShown: false }}>{(props) => <BottomTabNavigator {...props} onLogout={onLogout} />}</Stack.Screen> : {isAuthenticated ? <Stack.Screen name="Root" options={{ headerShown: false }}>{(props) => <BottomTabNavigator {...props} onLogout={onLogout} />}</Stack.Screen> :
<Stack.Screen name='Root' options={{ headerShown: false }}>{(props) => <LoginScreen {...props} onLogin={onLogin} />}</Stack.Screen>} <Stack.Screen name='Root' options={{ headerShown: false }}>{(props) => <LoginScreen {...props} onLogin={onLogin} />}</Stack.Screen>}
<Stack.Screen name='Signup' component={SignupScreen} options={{ headerShown: false, title: 'Sign up' }} /> {/* <Stack.Screen name='Signup' component={Signup} options={{ headerShown: false, title: 'Sign up' }} /> */}
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} /> <Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
<Stack.Group screenOptions={{ presentation: 'modal' }}> <Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} /> <Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group> </Stack.Group>
<Stack.Screen name="Signup" component={Signup} />
</Stack.Navigator> </Stack.Navigator>
); );
} }
......
...@@ -14,43 +14,49 @@ ...@@ -14,43 +14,49 @@
"preset": "jest-expo" "preset": "jest-expo"
}, },
"dependencies": { "dependencies": {
"@expo/vector-icons": "^12.0.0", "@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "~1.15.0", "@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/slider": "4.1.12", "@react-native-community/slider": "4.2.1",
"@react-navigation/bottom-tabs": "^6.0.5", "@react-navigation/bottom-tabs": "^6.0.5",
"@react-navigation/native": "^6.0.2", "@react-navigation/native": "^6.0.2",
"@react-navigation/native-stack": "^6.1.0", "@react-navigation/native-stack": "^6.1.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"expo": "~44.0.0", "expo": "^45.0.0",
"expo-asset": "~8.4.4", "expo-asset": "~8.5.0",
"expo-av": "~10.2.0", "expo-av": "~11.2.3",
"expo-constants": "~13.0.0", "expo-barcode-scanner": "^12.0.0",
"expo-file-system": "~13.1.4", "expo-constants": "~13.1.1",
"expo-font": "~10.0.4", "expo-file-system": "~14.0.0",
"expo-linking": "~3.0.0", "expo-font": "~10.1.0",
"expo-media-library": "~14.0.0", "expo-linking": "~3.1.0",
"expo-speech": "~10.1.0", "expo-media-library": "~14.1.0",
"expo-splash-screen": "~0.14.0", "expo-speech": "~10.2.0",
"expo-status-bar": "~1.2.0", "expo-splash-screen": "~0.15.1",
"expo-web-browser": "~10.1.0", "expo-status-bar": "~1.3.0",
"expo-web-browser": "~10.2.1",
"firebase": "^9.14.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"native-base": "^3.4.11", "native-base": "^3.4.11",
"react": "17.0.1", "react": "17.0.2",
"react-dom": "17.0.1", "react-dom": "17.0.2",
"react-native": "0.64.3", "react-native": "0.68.2",
"react-native-google-places-autocomplete": "^2.5.1",
"react-native-maps": "^1.3.2",
"react-native-multi-selectbox": "^1.5.0", "react-native-multi-selectbox": "^1.5.0",
"react-native-safe-area-context": "3.3.2", "react-native-radio-form": "^1.1.0",
"react-native-screens": "~3.10.1", "react-native-safe-area-context": "4.2.4",
"react-native-svg": "12.1.1", "react-native-screens": "~3.11.1",
"react-native-web": "0.17.1", "react-native-sqlite-storage": "^6.0.1",
"react-native-svg": "12.3.0",
"react-native-web": "0.17.7",
"styled-system": "^5.1.5" "styled-system": "^5.1.5"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.9", "@babel/core": "^7.12.9",
"@types/react": "~17.0.21", "@types/react": "~17.0.21",
"@types/react-native": "~0.64.12", "@types/react-native": "~0.67.6",
"jest": "^26.6.3", "jest": "^26.6.3",
"jest-expo": "~44.0.1", "jest-expo": "^45.0.0",
"react-test-renderer": "17.0.1", "react-test-renderer": "17.0.1",
"typescript": "~4.3.5" "typescript": "~4.3.5"
}, },
......
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
const Comment = (props) => {
return (
<View style={styles.item}>
<View style={styles.itemLeft}>
<View style={styles.square}></View>
<Text style={styles.itemText}>{props.text}</Text>
</View>
<View style={styles.circular}></View>
</View>
)
}
const styles = StyleSheet.create({
item: {
backgroundColor: '#FFF',
padding: 15,
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
},
itemLeft: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap'
},
square: {
width: 24,
height: 24,
backgroundColor: '#55BCF6',
opacity: 0.4,
borderRadius: 5,
marginRight: 15,
},
itemText: {
maxWidth: '80%',
},
circular: {
width: 12,
height: 12,
borderColor: '#55BCF6',
borderWidth: 2,
borderRadius: 5,
},
});
export default Comment;
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View, TouchableOpacity, TextInput } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { alignContent, flex, flexDirection, marginBottom, width } from 'styled-system';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors;
import { useRoute } from '@react-navigation/native';
function ConfirmPayment() {
const navigation = useNavigation();
const route = useRoute();
seatNo= 9;
const data= route.params.data;
const accData= data.split(/\r?\n/)
console.log(accData);
const [amount, setAmount] = useState('');
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
accNo = accData[1]
const conPayment = () => {
navigation.navigate('PaymentStatus', {
amount,accNo
});
};
return (
<View style={styles.container}>
<View style={styles.main}>
<View style={styles.Info} >
<Text style={{fontSize: 20 , marginTop: 20, color:'green'}}>payment amount </Text>
<TextInput style={styles.input}
onChangeText={(value) => setAmount(value)}
placeholder = " amount "
keyboardType="numeric"
/>
</View>
</View>
<View style={styles.weatherDetails}>
<View style={styles.weatherDetailsRow}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="card-account-details-outline" size={25} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Acc Number</Text>
<Text style={styles.textSecondary}>{accData[1]}</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="bank" size={25} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Bank name</Text>
<Text style={styles.textSecondary}>{accData[2]}</Text>
</View>
</View>
</View>
</View>
<View style={{ ...styles.weatherDetailsRow, borderTopWidth: 1, borderTopColor: BORDER_COLOR }}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="map-marker" size={30} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>Branch name</Text>
<Text style={styles.textSecondary}>{accData[3]}</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<MaterialCommunityIcons name="qrcode" size={30} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}>
<Text>QR Tpye </Text>
<Text style={styles.textSecondary}>{route.params.type}</Text>
</View>
</View>
</View>
</View>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={conPayment}>
Confirm Payment
</Button>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
Cancel Payment
</Button>
</View>
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<ConfirmPayment />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
main: {
marginTop: 200,
justifyContent: 'center',
},
Icon: {
width: 100,
height: 100,
},
Info: {
alignItems: 'center',
},
weatherDetails: {
marginTop: 50,
margin: 5,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
weatherDetailsRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
weatherDetailsBox: {
flex: 1,
padding: 20,
},
weatherDetailsItems: {
alignItems: 'flex-end',
justifyContent: 'flex-end',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd',
marginBottom: 12
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
input: {
height: 40,
marginTop: 12,
borderWidth: 1,
padding: 10,
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, Keyboard, KeyboardAvoidingView,TextInput } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import SQLite from 'react-native-sqlite-storage';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors
import Comment from './Comment';
import { marginBottom } from 'styled-system';
import { useRoute } from '@react-navigation/native';
function DriverInfo() {
const navigation = useNavigation();
seatNo= 9;
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
const [comment, setComment] = useState();
const [commentItems, setCcommentItems] = useState([]);
const handleAddComment = () => {
Keyboard.dismiss();
setCcommentItems([...commentItems, comment])
setComment(null);
}
const completeComment = (index) => {
let itemsCopy = [...commentItems];
itemsCopy.splice(index, 1);
setCcommentItems(itemsCopy)
}
return (
<View style={styles.container}>
<View style={styles.TopView}>
<Image style={styles.imageStyle} source={require('../assets/driver.png')} alt="image" />
</View>
<View style={styles.Middle}>
<Text style={styles.LoginText}>Gayan Peris</Text>
</View>
<View style={styles.weatherDetails}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<Text style={styles.textSecondary}>Years</Text>
<Text style={styles.textSecondary}>4+</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<Text style={styles.textSecondary}>Rating</Text>
<Text style={styles.textSecondary}>4.8</Text>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<Text style={styles.textSecondary}>Vehicle</Text>
<Text style={{ marginTop:5,justifyContent:'flex-start', fontSize: 15, fontWeight: '700', color: SECONDARY_COLOR,}}>BDA - 0713</Text>
</View>
</View>
</View>
</View>
</View>
<ScrollView
contentContainerStyle={{ flexGrow: 1}} keyboardShouldPersistTaps='handled'
>
<View style={styles.tasksWrapper}>
<Text style={styles.sectionTitle}>feedback</Text>
<View style={styles.items}>
{/* This is where the tasks will go! */}
{
commentItems.map((item, index) => {
return (
<TouchableOpacity key={index} onPress={() => completeComment(index)}>
<Comment text={item} />
</TouchableOpacity>
)
})
}
</View>
</View>
</ScrollView>
{/* Write a task */}
{/* Uses a keyboard avoiding view which ensures the keyboard does not cover the items on screen */}
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.writeTaskWrapper}
>
<TextInput style={styles.input} placeholder={'Write a comment'} value={comment} onChangeText={text => setComment(text)} />
<TouchableOpacity onPress={() => handleAddComment()}>
<View style={styles.addWrapper}>
<Text style={styles.addText}>+</Text>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
{/* Button */}
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
Home
</Button>
</View>
<StatusBar style="auto" />
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<DriverInfo />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
LoginText: {
marginTop:30,
fontSize:30,
fontWeight:'bold',
},
Middle:{
alignItems:'center',
justifyContent:'center',
},
text2:{
flexDirection:'row',
justifyContent:'center',
paddingTop:5
},
buttonStyle:{
marginLeft:15,
marginRight:15,
marginBottom:15,
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
lineStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
alignItems:'center'
},
imageStyle:{
width:80,
height:80,
marginLeft:20,
},
boxStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
justifyContent:'space-around'
},
TopView:{
width:'100%',
height:'30%',
display:'flex',
justifyContent:'center',
alignItems:'center',
},
imageStyle:{
width:'50%',
resizeMode:'contain',
alignItems:'center',
top: 50,
},
weatherDetails: {
marginTop: 30,
margin: 5,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
weatherDetailsRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
weatherDetailsBox: {
flex: 1,
padding: 10,
},
weatherDetailsItems: {
alignItems: 'flex-end',
justifyContent: 'flex-end',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
},
tasksWrapper: {
paddingTop: 30,
paddingHorizontal: 10,
},
sectionTitle: {
fontSize: 24,
fontWeight: 'bold'
},
items: {
marginTop: 10,
},
writeTaskWrapper: {
position: 'absolute',
bottom: 60,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center'
},
input: {
paddingVertical: 15,
paddingHorizontal: 15,
backgroundColor: '#FFF',
borderRadius: 60,
borderColor: '#C0C0C0',
borderWidth: 1,
width: 250,
},
addWrapper: {
width: 60,
height: 60,
backgroundColor: '#FFF',
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
borderColor: '#C0C0C0',
borderWidth: 1,
},
addText: {},
});
import { useNavigation } from '@react-navigation/native';
import React from 'react';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { useRoute } from '@react-navigation/native';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors
function GenerateSeatNo() {
const navigation = useNavigation();
const route = useRoute();
seatNo= 'NA'
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
const confirmSeatNo = () => {
navigation.navigate('RegInfo', {
seatNo
});
};
const people = [
{'name':"ruwan",'age':26,'gender':"F",'job':"IT"},
{'name':"madush",'age':28,'gender':"F",'job':"HR"},
{'name':"gayan",'age':32,'gender':"M",'job':"IT"},
{'name':"yohan",'age':29,'gender':"F",'job':"Engineer"},
{'name':"rukshan",'age':34,'gender':"M",'job':"HR"},
{'name':"namal",'age':38,'gender':"F",'job':"IT"},
{'name':"kasun",'age':45,'gender':"M",'job':"Engineer"},
{'name':"nuwan",'age':55,'gender':"M",'job':"Engineer"}
]
const newPeople= {'name': route.params.username,'age':route.params.age,'gender':route.params.genderx,'job':route.params.selectedProfession.item}
console.log(newPeople);
const addPeople = [].concat(people, newPeople)
console.log(addPeople);
const age_30= addPeople.filter(function(element){
return element.age < 30 && element.age>0 ;
});
const sortedAge_30 = [...age_30].sort((a, b) => a.age - b.age || a.gender - b.gender);
/*console.log('sortedAge_30', sortedAge_30);*/
const age_40= addPeople.filter(function(element){
return element.age < 40 && element.age>30;
});
const sortedAge_40 = [...age_40].sort((a, b) => a.age - b.age || a.gender - b.gender);
/*console.log('sortedAge_40', sortedAge_40);*/
const age_50= addPeople.filter(function(element){
return element.age < 50 && element.age>40;
});
const sortedAge_50 = [...age_50].sort((a, b) => a.age - b.age || a.gender - b.gender);
/*console.log('sortedAge_50', sortedAge_50);*/
const age_60= addPeople.filter(function(element){
return element.age < 60 && element.age>50;
});
const sortedAge_60 = [...age_60].sort((a, b) => a.age - b.age || a.gender - b.gender);
/*console.log('sortedAge_60', sortedAge_60);*/
const merged = [].concat(sortedAge_30, sortedAge_40,sortedAge_50,sortedAge_60);
console.log('mm',merged);
const index = merged.findIndex(object => {
return object.name === route.params.username;
});
seatNo= index+1;
function GenSeatNo() {
console.log(final_list);
}
return (
<View style={styles.container}>
<View style={styles.lineStyle}>
<View>
<Text style={{width: 120, textAlign: 'left', fontWeight:'bold', fontSize:15, marginTop: 100}}>Your Data</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black', marginTop: 100}} />
</View>
<View style={styles.summeryDetails}>
<View style={styles.summeryDetailsRow}>
<View style={{ ...styles.summeryDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.summeryDetailsRow}>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Name :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.username}</Text>
</View>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Email :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.email}</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Age :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.age}</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Gender :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.genderx}</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Job :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.selectedProfession.item}</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Pickup :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.selectedPickLoc.item}</Text>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{color:'#8e8e8e',fontSize: 15 , textAlign: 'left',fontWeight:'bold',marginTop: 3}}>Pickup :</Text>
</View>
<View style={{ margin: 20, marginVertical: 20 }}>
<Text style={{color:'#8e8e8e',fontSize: 15 ,textAlign: 'right',fontWeight:'bold', marginTop: 3}}>{route.params.selectedDropLoc.item}</Text>
</View>
</View>
</View>
</View>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={confirmSeatNo}>
Save Reservation
</Button>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
Cancel Reservation
</Button>
</View>
</View>
)
}
export default () => {
return (
<NativeBaseProvider>
<GenerateSeatNo />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
TopView:{
width:'100%',
height:'30%',
display:'flex',
justifyContent:'center',
alignItems:'center',
},
summeryDetails: {
marginTop: 30,
margin: 15,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
summeryDetailsRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
summeryDetailsBox: {
flex: 1,
padding: 20,
},
summeryDetailsItems: {
alignItems: 'flex-end',
justifyContent: 'flex-end',
},
lineStyle:{
flexDirection:'row',
marginTop:15,
marginLeft:15,
marginRight:15,
alignItems:'center'
},
imageStyle:{
width:80,
height:80,
marginLeft:20,
},
row: {
flexDirection: "row",
paddingRight: 12,
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { alignContent, flex, flexDirection, width } from 'styled-system';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors
import { useRoute } from '@react-navigation/native';
function Home() {
const navigation = useNavigation();
const route = useRoute();
seatNo= route.params.seatNo;
console.log(seatNo);
const saveSeatNo = () => {
navigation.navigate('RegInfo', {
seatNo
});
};
return (
<View style={styles.container}>
<View style={styles.TopView}>
<Image style={styles.imageStyle} source={require('../assets/logo.jpg')} alt="image" />
</View>
<View style={styles.Info} >
<Text style={{fontSize: 20 , marginTop: 20, color:'#8e8e8e'}}>Keep a safe distance from vehicles!</Text>
</View>
<View style={styles.weatherDetails}>
<View style={styles.weatherDetailsRow}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="seatbelt" size={30} color='#3366ff' />
<TouchableOpacity onPress={saveSeatNo} >
<Text style={styles.textSecondary}>Seat Reservation</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<FontAwesome5 name="route" size={25} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("RouteInfo")} >
<Text style={styles.textSecondary}>Route Info</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
<View style={{ ...styles.weatherDetailsRow, borderTopWidth: 1, borderTopColor: BORDER_COLOR }}>
<View style={{ ...styles.weatherDetailsBox, borderRightWidth: 1, borderRightColor: BORDER_COLOR }}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="comment-account-outline" size={30} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("DriverInfo")} >
<Text style={styles.textSecondary}>Driver feedback</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.weatherDetailsBox}>
<View style={styles.weatherDetailsRow}>
<View style={styles.weatherDetailsItems}>
<MaterialCommunityIcons name="map-marker-radius-outline" size={30} color='#3366ff' />
<TouchableOpacity onPress={() => navigation.navigate("Location")} >
<Text style={styles.textSecondary}>Find Vehicle</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Login")}>
Logout
</Button>
</View>
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<Home />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
main: {
marginTop: 200,
justifyContent: 'center',
},
Icon: {
width: 100,
height: 100,
},
Info: {
alignItems: 'center',
},
weatherDetails: {
marginTop: 100,
margin: 15,
borderWidth: 1,
borderColor: BORDER_COLOR,
borderRadius: 10,
},
weatherDetailsRow: {
flexDirection: 'row',
alignItems: 'stretch'
},
weatherDetailsBox: {
flex: 1,
padding: 20,
},
weatherDetailsItems: {
alignItems: 'center',
justifyContent: 'stretch',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
alignItems:'center',
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
TopView:{
width:'100%',
height:'30%',
display:'flex',
justifyContent:'center',
alignItems:'center',
},
imageStyle:{
width:'60%',
resizeMode:'contain',
alignItems:'center',
top: 100,
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
})
\ No newline at end of file
import React from 'react'; import React from "react";
import RegInfo from './RegInfo';
import RouteInfo from './RouteInfo';
import Home from './Home';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import RegInfo from "./RegInfo";
import RouteInfo from "./RouteInfo";
import Home from "./Home";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import DriverInfo from "./DriverInfo";
import GenerateSeatNo from "./GenerateSeatNo";
import PaymentQR from "./PaymentQR";
import ConfirmPayment from "./ConfirmPayment";
import PaymentStatus from "./PaymentStatus";
import Location from "./Location";
const Stack = createNativeStackNavigator(); const Stack = createNativeStackNavigator();
function App() { function App() {
return ( return (
<Stack.Navigator screenOptions={{headerShown: false}}> <Stack.Navigator screenOptions={{ headerShown: false }} initialRouteName={"Home"}>
<Stack.Screen name="Root" component={Home} /> {/* <Stack.Screen name="Root" component={Home} />
<Stack.Screen name="RegInfo" component={RegInfo} />
<Stack.Screen name="RouteInfo" component={RouteInfo} /> */}
{/* <Stack.Screen name="Login" component={Login} /> */}
<Stack.Screen name="RegInfo" component={RegInfo} /> <Stack.Screen name="RegInfo" component={RegInfo} />
<Stack.Screen name="RouteInfo" component={RouteInfo} /> <Stack.Screen name="RouteInfo" component={RouteInfo} />
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="DriverInfo" component={DriverInfo} />
<Stack.Screen name="Location" component={Location} />
<Stack.Screen name="GenerateSeatNo" component={GenerateSeatNo} />
<Stack.Screen name="PaymentQR" component={PaymentQR} />
<Stack.Screen name="ConfirmPayment" component={ConfirmPayment} />
<Stack.Screen name="PaymentStatus" component={PaymentStatus} />
</Stack.Navigator> </Stack.Navigator>
); );
} }
export default () => { export default () => {
return ( return (
<NavigationContainer independent> <NavigationContainer independent>
<App /> <App />
</NavigationContainer> </NavigationContainer>
) );
} };
import * as React from "react"
import { Dimensions, StyleSheet, Text, View } from "react-native"
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete"
import MapView, { Callout, Circle, Marker } from "react-native-maps" //library
import { Input, NativeBaseProvider, Button} from 'native-base';
import { useNavigation } from '@react-navigation/native';
function Location() {
const navigation = useNavigation();
const [ pin, setPin ] = React.useState({
latitude: 6.914879860168769, //curren loc
longitude: 79.97292303901023
})
const [ pin2, setPin2 ] = React.useState({
latitude: 6.935870750489668, // vehicle loc
longitude: 79.98420673859631
})
const [ region, setRegion ] = React.useState({
latitude: 6.914879860168769,
longitude: 79.97292303901023,
latitudeDelta: 0.0922, //map hight
longitudeDelta: 0.0421 // map width
})
return (
<View style={{ marginTop: 50, flex: 1 }}>
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={false}
returnKeyType={'search'} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
keyboardAppearance={'light'} // Can be left out for default keyboardAppearance https://facebook.github.io/react-native/docs/textinput.html#keyboardappearance
listViewDisplayed={false} // true/false/undefined
fetchDetails={true}
keyboardShouldPersistTaps='always'
GooglePlacesSearchQuery={{
rankby: "distance"
}}
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details)
setRegion({
latitude: details.geometry.location.lat,
longitude: details.geometry.location.lng,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421
})
}}
query={{
key: "KEY",
language: "en",
components: "country:us",
types: "establishment",
radius: 30000,
location: `${region.latitude}, ${region.longitude}`
}}
styles={{
container: { flex: 0, position: "absolute", width: "100%", zIndex: 1 },
listView: { backgroundColor: "white" }
}}
/>
<MapView
style={styles.map}
initialRegion={{
latitude: 6.914879860168769,
longitude: 79.97292303901023,
latitudeDelta: 0.00,
longitudeDelta: 0.04
}}
provider="google"
>
<Marker coordinate={{ latitude: region.latitude, longitude: region.longitude }} />
<Marker
coordinate={pin}
pinColor="red"
draggable={true}
onDragStart={(e) => {
console.log("Drag start", e.nativeEvent.coordinates)
}}
onDragEnd={(e) => {
setPin({
latitude: e.nativeEvent.coordinate.latitude,
longitude: e.nativeEvent.coordinate.longitude
})
}}
>
<Callout tooltip={true}>
<Text style={{fontSize: 20 , fontWeight:'bold', color:'red'}}>I'm here</Text>
</Callout>
</Marker>
<Circle center={pin} radius={500} />
<Marker
coordinate={pin2}
pinColor="green"
draggable={true}
onDragStart={(e) => {
console.log("Drag start", e.nativeEvent.coordinates)
}}
onDragEnd={(e) => {
setPin2({
latitude: e.nativeEvent.coordinate.latitude,
longitude: e.nativeEvent.coordinate.longitude
})
}}
>
<Callout>
<Text style={{fontSize: 20 , fontWeight:'bold', color:'green'}}>vehicle</Text>
</Callout>
</Marker>
<Circle center={pin2} radius={500} />
</MapView>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Login")}>
Logout
</Button>
</View>
</View>
)
}
export default () => {
return (
<NativeBaseProvider>
<Location />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
map: {
width: Dimensions.get("window").width,
height: Dimensions.get("window").height
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5 } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import SQLite from 'react-native-sqlite-storage';
function Login() {
const navigation = useNavigation();
seatNo= 9;
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
return (
<View style={styles.container}>
<View style={styles.TopView}>
<Image style={styles.imageStyle}
source={require('../assets/logo.jpg')}
alt="image"
/>
</View>
<View style={styles.Middle}>
<Text style={styles.LoginText}>Login</Text>
</View>
<View style={styles.text2}>
<Text>Don't have an account? </Text>
<TouchableOpacity onPress={() => navigation.navigate("Signup")} ><Text style={styles.signupText}> Sign up</Text></TouchableOpacity>
</View>
{/* Username or Email Input Field */}
<View style={styles.buttonStyle}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="user-secret" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
placeholder="Username or Email"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
/>
</View>
</View>
{/* Password Input Field */}
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="key" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
secureTextEntry={true}
placeholder="Password"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
/>
</View>
</View>
{/* Button */}
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
LOGIN
</Button>
</View>
<StatusBar style="auto" />
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<Login />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
LoginText: {
marginTop:100,
fontSize:30,
fontWeight:'bold',
},
Middle:{
alignItems:'center',
justifyContent:'center',
},
text2:{
flexDirection:'row',
justifyContent:'center',
paddingTop:5
},
signupText:{
fontWeight:'bold'
},
emailField:{
marginTop:30,
marginLeft:15
},
emailInput:{
marginTop:10,
marginRight:5
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
lineStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
alignItems:'center'
},
imageStyle:{
width:80,
height:80,
marginLeft:20,
},
boxStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
justifyContent:'space-around'
},
TopView:{
width:'100%',
height:'30%',
display:'flex',
justifyContent:'center',
alignItems:'center',
},
imageStyle:{
width:'60%',
resizeMode:'contain',
alignItems:'center',
top: 100,
},
});
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, Button } from 'react-native';
import React, { useEffect } from 'react';
import { BarCodeScanner } from 'expo-barcode-scanner';
import { useRoute } from '@react-navigation/native';
import { useNavigation } from '@react-navigation/native';
export default function PaymentQR () {
const navigation = useNavigation();
const [hasPermission, setHasPermission] = React.useState(false);
const [scanData, setScanData] = React.useState();
useEffect(() => {
(async() => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
if (!hasPermission) {
return (
<View style={styles.container}>
<Text>Please grant camera permissions to app.</Text>
</View>
);
}
const handleBarCodeScanned = ({type, data}) => {
setScanData(data);
navigation.navigate('ConfirmPayment', {
data,type
});
};
return (
<View style={styles.container}>
<BarCodeScanner
style={StyleSheet.absoluteFillObject}
onBarCodeScanned={scanData ? undefined : handleBarCodeScanned}
/>
{scanData && <Button title='Scan Again?' onPress={() => setScanData(undefined)} />}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { alignContent, flex, flexDirection, width } from 'styled-system';
import { colors } from '../util/index'
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors;
import { useRoute } from '@react-navigation/native';
function PaymentStatus() {
const navigation = useNavigation();
const route = useRoute();
seatNo= 9;
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
return (
<View style={styles.container}>
<View style={styles.main}>
<View style={styles.Info} >
<Image style={styles.Icon} source={require('../assets/successful.jpg')} alt="image" />
<Text style={{fontSize: 20 , marginTop: 20, color:'green'}}>Payment completed</Text>
<Text style={{fontSize: 12 , marginTop: 10, color:'#8e8e8e'}}>Ref# 837110243</Text>
<Text style={{fontSize: 20 , fontWeight:'bold', marginTop: 30, color:'green'}}>Paid Amount </Text>
<Text style={{fontSize: 45 , fontWeight:'bold', marginTop: 5, color:'#ff304f'}}>RS {route.params.amount}.00</Text>
<Text style={{fontSize: 12 , marginTop: 10, color:'#8e8e8e'}}>Account Number</Text>
<Text style={{fontSize: 20 , fontWeight:'bold', marginTop: 5, color:'#8e8e8e'}}>{route.params.accNo}</Text>
</View>
</View>
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
Home
</Button>
</View>
</View>
);
};
export default () => {
return (
<NativeBaseProvider>
<PaymentStatus />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
main: {
marginTop: 200,
justifyContent: 'center',
},
Icon: {
width: 100,
height: 100,
},
Info: {
alignItems: 'center',
},
textSecondary: {
fontSize: 15,
color: SECONDARY_COLOR,
fontWeight: '700',
margin: 7,
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
})
\ No newline at end of file
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import React from 'react'; import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native'; import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base'; import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons'; import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { colors } from '../util/index' import { alignContent, flex, flexDirection, width } from 'styled-system';
const { PRIMARY_COLOR, SECONDARY_COLOR, BORDER_COLOR } = colors
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors;
import { useRoute } from '@react-navigation/native';
import { colors } from '../util';
function RegInfo() {
function RegInfo() {
const navigation = useNavigation(); const navigation = useNavigation();
const route = useRoute();
seatNo= route.params.seatNo;
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.main}> <View style={styles.main}>
<View style={styles.Info} > <View style={styles.Info} >
<Image style={styles.Icon} source={require('../assets/successful.jpg')} alt="image" /> <Image style={styles.Icon} source={require('../assets/successful.jpg')} alt="image" />
<Text style={{ fontSize: 20, marginTop: 20, color: 'green' }}>Seat Reservation completed</Text> <Text style={{fontSize: 20 , marginTop: 20, color:'green'}}>Seat Reservation completed</Text>
<Text style={{ fontSize: 12, marginTop: 10, color: '#8e8e8e' }}>Ref# 837110243</Text> <Text style={{fontSize: 12 , marginTop: 10, color:'#8e8e8e'}}>Ref# 837110243</Text>
<Text style={{ fontSize: 20, fontWeight: 'bold', marginTop: 30, color: 'green' }}>Your Seat Number</Text> <Text style={{fontSize: 20 , fontWeight:'bold', marginTop: 30, color:'green'}}>Your Seat Number</Text>
<Text style={{ fontSize: 45, fontWeight: 'bold', marginTop: 5, color: '#ff304f' }}>25</Text> <Text style={{fontSize: 45 , fontWeight:'bold', marginTop: 5, color:'#ff304f'}}>{route.params.seatNo}</Text>
</View> </View>
</View> </View>
<View style={styles.weatherDetails}> <View style={styles.weatherDetails}>
...@@ -39,7 +48,7 @@ function RegInfo() { ...@@ -39,7 +48,7 @@ function RegInfo() {
<FontAwesome5 name="user-secret" size={25} color={PRIMARY_COLOR} /> <FontAwesome5 name="user-secret" size={25} color={PRIMARY_COLOR} />
<View style={styles.weatherDetailsItems}> <View style={styles.weatherDetailsItems}>
<Text>Driver name</Text> <Text>Driver name</Text>
<Text style={styles.textSecondary}>Anura Kumara</Text> <Text style={styles.textSecondary}>Gayan Peris</Text>
</View> </View>
</View> </View>
</View> </View>
...@@ -66,7 +75,7 @@ function RegInfo() { ...@@ -66,7 +75,7 @@ function RegInfo() {
</View> </View>
</View> </View>
<View style={styles.buttonStyle}> <View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Root")}> <Button style={styles.buttonDesign} onPress={saveSeatNo}>
Home Home
</Button> </Button>
</View> </View>
...@@ -75,24 +84,24 @@ function RegInfo() { ...@@ -75,24 +84,24 @@ function RegInfo() {
); );
} }
export default () => { export default () => {
return ( return (
<NativeBaseProvider> <NativeBaseProvider>
<RegInfo /> <RegInfo />
</NativeBaseProvider> </NativeBaseProvider>
) )
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#fff', backgroundColor: '#fff',
}, },
main: { main: {
marginTop: 10, marginTop: 200,
justifyContent: 'center', justifyContent: 'center',
}, },
...@@ -104,7 +113,7 @@ const styles = StyleSheet.create({ ...@@ -104,7 +113,7 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
}, },
weatherDetails: { weatherDetails: {
marginTop: 60, marginTop: 100,
margin: 15, margin: 15,
borderWidth: 1, borderWidth: 1,
borderColor: BORDER_COLOR, borderColor: BORDER_COLOR,
...@@ -129,17 +138,17 @@ const styles = StyleSheet.create({ ...@@ -129,17 +138,17 @@ const styles = StyleSheet.create({
fontWeight: '700', fontWeight: '700',
margin: 7, margin: 7,
}, },
buttonStyleX: { buttonStyleX:{
marginTop: 12, marginTop:12,
marginLeft: 15, marginLeft:15,
marginRight: 15 marginRight:15
}, },
buttonDesign: { buttonDesign:{
backgroundColor: '#026efd' backgroundColor:'#026efd'
}, },
buttonStyle: { buttonStyle:{
marginTop: 30, marginTop:30,
marginLeft: 15, marginLeft:15,
marginRight: 15 marginRight:15
}, },
}) })
\ No newline at end of file \ No newline at end of file
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react'; import React, {useState, useEffect} from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native'; import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base'; import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { colors } from '../util/index' import SelectBox from 'react-native-multi-selectbox';
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors import { xorBy } from 'lodash';
import RadioForm from 'react-native-radio-form';
const { PRIMARY_COLOR, SECONDARY_COLOR,BORDER_COLOR } = colors
import { useRoute } from '@react-navigation/native';
import { marginBottom } from 'styled-system';
import { collection, doc, setDoc, addDoc,getDocs,query ,where} from "firebase/firestore";
import {db} from './config';
import { colors } from '../util';
function RouteInfo() { function RouteInfo() {
const navigation = useNavigation(); const navigation = useNavigation();
seatNo= 9;
const saveSeatNo = () => {
navigation.navigate('Home', {
seatNo
});
};
const memberAttendance = [];
const sortData= [];
//connect to db
async function readData(){
const q = query(collection(db, "member_attendance"), where("name", "==", 'shashini'));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
memberAttendance.push(doc.data());
});
console.log(memberAttendance)
return memberAttendance;
}
data= readData()
console.log(data)
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.Head}> <View style={styles.Head}>
...@@ -109,7 +137,10 @@ return ( ...@@ -109,7 +137,10 @@ return (
</View> </View>
{/* Button */} {/* Button */}
<View style={styles.buttonStyle}> <View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPress={() => navigation.navigate("Root")}> <Button style={styles.buttonDesign} onPress={()=>navigation.navigate('PaymentQR')}>
Payment
</Button>
<Button style={styles.buttonDesign} onPress={saveSeatNo}>
Home Home
</Button> </Button>
</View> </View>
...@@ -137,12 +168,12 @@ const styles = StyleSheet.create({ ...@@ -137,12 +168,12 @@ const styles = StyleSheet.create({
backgroundColor: '#fff', backgroundColor: '#fff',
}, },
HeadText: { HeadText: {
marginTop:10, marginTop:80,
fontSize:30, fontSize:30,
fontWeight:'bold', fontWeight:'bold',
}, },
Head:{ Head:{
// alignItems:'left', alignItems:'left',
justifyContent:'center', justifyContent:'center',
marginLeft:15, marginLeft:15,
...@@ -155,8 +186,8 @@ const styles = StyleSheet.create({ ...@@ -155,8 +186,8 @@ const styles = StyleSheet.create({
alignItems:'center' alignItems:'center'
}, },
summeryDetails: { summeryDetails: {
marginTop: 15, marginTop: 20,
margin: 15, margin: 10,
borderWidth: 1, borderWidth: 1,
borderColor: BORDER_COLOR, borderColor: BORDER_COLOR,
borderRadius: 10, borderRadius: 10,
...@@ -190,10 +221,11 @@ const styles = StyleSheet.create({ ...@@ -190,10 +221,11 @@ const styles = StyleSheet.create({
marginRight:15 marginRight:15
}, },
buttonDesign:{ buttonDesign:{
backgroundColor:'#026efd' backgroundColor:'#026efd',
marginBottom: 12
}, },
buttonStyle:{ buttonStyle:{
marginTop:20, marginTop:30,
marginLeft:15, marginLeft:15,
marginRight:15 marginRight:15
}, },
......
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import SelectBox from 'react-native-multi-selectbox';
import { xorBy } from 'lodash';
import RadioForm from 'react-native-radio-form';
import { collection, doc, setDoc, addDoc } from "firebase/firestore";
import {db} from './config';
function Signup({}) {
const navigation = useNavigation();
const goGenerateSeatNo = () => {
navigation.navigate('GenerateSeatNo', {
username,email,age,selectedPickLoc,selectedDropLoc,selectedProfession,genderx
});
};
const [username, SetUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [age, setAge] = useState('');
const genderx= 'M';
const [selectedPickLoc, setSelectedPickLoc] = useState({});
const [selectedDropLoc, setSelectedDropLoc] = useState({});
const [selectedProfession, setSelectedProfession] = useState('');
const location = [
{id:'1', item:'Borella'},
{id:'2', item:'Rajagiriya'},
{id:'3', item:'Ethul Kotte'},
{id:'4', item:'Battaramulla'},
{id:'5', item:'Koswatta'},
{id:'6', item:'Malabe'},
{id:'7', item:'SLIIT'},
{id:'8', item:'Kaduwela'},
];
const profession= [
{id:'1', item:'IT Professional'},
{id:'2', item:'Lecture'},
{id:'3', item:'Banker'},
{id:'4', item:'Engineer'},
{id:'5', item:'Doctor'},
{id:'6', item:'Lawyer'},
{id:'7', item:'Other'},
];
const gender = [
{label: 'Male', value: 0 },
{label: 'Female', value: 1 }
];
//db save data
function saveData(){
addDoc(collection(db, "members"), {
username: username,
email: email,
password: password,
age: age,
gender: "male",
job: selectedProfession,
pickup: selectedPickLoc,
drop: selectedDropLoc,
}).then(() =>{
console.log('data submitted')
}).catch((error)=>{
console.log(error)
});;
}
return (
<View style={styles.container}>
<View style={styles.Middle}>
<Text style={styles.LoginText}>Signup</Text>
</View>
<View style={styles.text2}>
<Text>Already have account? </Text>
<TouchableOpacity onPress={() => navigation.navigate("Root")} ><Text style={styles.signupText}> Login </Text></TouchableOpacity>
</View>
{/* Username or Email Input Field */}
<View style={styles.buttonStyle}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="user-secret" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
placeholder="Username"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
onChangeText={(value) => SetUsername(value)}
/>
</View>
</View>
{/* Username or Email Input Field */}
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<MaterialCommunityIcons name="email" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
placeholder="Email"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
onChangeText={(value) => setEmail(value)}
/>
</View>
</View>
{/* Password Input Field */}
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="key" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
secureTextEntry={true}
placeholder="Password"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
onChangeText={(value) => setPassword(value)}
/>
</View>
</View>
{/* Password Input Field */}
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="key" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
secureTextEntry={true}
placeholder="Confirm Password"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
/>
</View>
</View>
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="key" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
secureTextEntry={false}
placeholder="Age"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
onChangeText={(value) => setAge(value)}
/>
</View>
</View>
<View style={styles.row}>
<View style={{ margin: 20}}>
<Text style={{fontSize: 12 , marginTop: 3, color:'#8e8e8e'}}>Gender</Text>
</View>
<View style={{ margin: 20, marginVertical: 10 }}>
<RadioForm
style={{ width: 200, color:'#8e8e8e', fontSize: 12, innerWidth:200 }}
dataSource={gender}
circleSize={12}
initial={1}
formHorizontal={true}
labelHorizontal={true}
onPress={(value) => {this.setState({value:value})}}
innerColor= '#8e8e8e'
outerColor= '#8e8e8e'
animation={true}
/>
</View>
</View>
<View style={{ marginTop: 10, marginLeft:20, marginRight:20}}>
<SelectBox
label="Profession"
options={profession}
value={selectedProfession}
onChange={onChangeProfession()}
hideInputFilter={false}
/>
</View>
<View style={styles.row}>
<View style={{ margin:20 , marginEnd:30}}>
<SelectBox width= '170%'
label="Pickup"
options={location}
value={selectedPickLoc}
onChange={onChangePick()}
hideInputFilter={false}
/>
</View>
<View style={{ margin: 20 , marginStart:70}}>
<SelectBox width= '170%'
label="Drop"
options={location}
value={selectedDropLoc}
onChange={onChangeDrop()}
hideInputFilter={false}
/>
</View>
</View>
{/* Button */}
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign} onPressIn= {() => { saveData(); }} onPress={goGenerateSeatNo}>
REGISTER NOW
</Button>
</View>
{/* Line */}
<View style={styles.lineStyle}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 80, textAlign: 'center'}}>Safe Drive</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
<StatusBar style="auto" />
</View>
);
function onChangePick() {
return (val) => setSelectedPickLoc(val)
}
function onChangeDrop() {
return (val) => setSelectedDropLoc(val)
}
function onChangeProfession() {
return (val) => setSelectedProfession(val)
}
}
export default () => {
return (
<NativeBaseProvider>
<Signup />
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
LoginText: {
marginTop:100,
fontSize:30,
fontWeight:'bold',
},
Middle:{
alignItems:'center',
justifyContent:'center',
},
text2:{
flexDirection:'row',
justifyContent:'center',
paddingTop:5
},
signupText:{
fontWeight:'bold'
},
emailField:{
marginTop:30,
marginLeft:15
},
emailInput:{
marginTop:10,
marginRight:5
},
buttonStyle:{
marginTop:30,
marginLeft:15,
marginRight:15
},
buttonStyleX:{
marginTop:12,
marginLeft:15,
marginRight:15
},
buttonDesign:{
backgroundColor:'#026efd'
},
lineStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
alignItems:'center'
},
imageStyle:{
width:80,
height:80,
marginLeft:20,
},
boxStyle:{
flexDirection:'row',
marginTop:30,
marginLeft:15,
marginRight:15,
justifyContent:'space-around'
},
row: {
flexDirection: "row",
paddingRight: 12,
},
});
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from "react";
import { FlatList, StyleSheet, TextInput, SectionList, Button, ActivityIndicator, View, Text, SafeAreaView } from 'react-native'; import {
import { AudioRecorder } from '../components/AudioRecorder'; FlatList,
import _ from 'lodash' StyleSheet,
TextInput,
SectionList,
import EditScreenInfo from '../components/EditScreenInfo'; Button,
ActivityIndicator,
View,
Text,
SafeAreaView,
TouchableOpacity,
} from "react-native";
import { AudioRecorder } from "../components/AudioRecorder";
import _ from "lodash";
import EditScreenInfo from "../components/EditScreenInfo";
// import { Text, View } from '../components/Themed'; // import { Text, View } from '../components/Themed';
import { RootTabScreenProps } from '../types'; import { RootTabScreenProps } from "../types";
import { addChats, create, getList, getOne } from '../api/api'; import { addChats, create, getList, getOne } from "../api/api";
import { BACKEND_ADDRESS } from '../api/constants'; import { BACKEND_ADDRESS } from "../api/constants";
import Ionicons from '@expo/vector-icons/Ionicons'; import Ionicons from "@expo/vector-icons/Ionicons";
import { CONVO_DEFAULT_ICON_COLOR, styles } from '../util/styles'; import { CONVO_DEFAULT_ICON_COLOR, styles } from "../util/styles";
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from "expo-status-bar";
import Slider from '@react-native-community/slider'; import Slider from "@react-native-community/slider";
import { PlayMessage } from '../components/PlayMessage'; import { PlayMessage } from "../components/PlayMessage";
import { Toast, Input } from 'native-base'; import { Toast, Input, ScrollView, Divider } from "native-base";
import { ERROR_TOAST_PROPS } from '../util/util'; import { ERROR_TOAST_PROPS } from "../util/util";
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from "@react-native-async-storage/async-storage";
export default function ChatScreen({ navigation }) { export default function ChatScreen({ navigation }) {
const currentTime = new Date();
const currentTime = new Date()
const QandAs = [
const defaultChatData = [{ id: 1, from_user: 2, to_user: 1, message: 'How many passengers?', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 1).valueOf() }, { Q: "Does the bus come today? ", A: "Yes" },
{ id: 2, from_user: 1, to_user: 2, message: 'Three', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 2).valueOf(), is_detected: true }, { Q: "What time the bus arrives? ", A: "10:30am" },
{ id: 3, from_user: 2, to_user: 1, message: 'Should i turn left or right here?', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 3).valueOf(), is_detected: false }, { Q: "Im not coming today ", A: "Okay" },
{ id: 4, from_user: 1, to_user: 2, message: 'Left', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 4).valueOf(), is_detected: true }, ];
{ id: 5, from_user: 1, to_user: 2, message: 'Please hurry', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 5).valueOf() },
{ id: 6, from_user: 2, to_user: 1, message: 'Ok', timestamp: currentTime.setMinutes(currentTime.getMinutes() - 6).valueOf() }, const defaultChatData = [
{
id: 1,
from_user: 2,
to_user: 1,
message: "How many passengers?",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 1).valueOf(),
},
{
id: 2,
from_user: 1,
to_user: 2,
message: "Three",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 2).valueOf(),
is_detected: true,
},
{
id: 3,
from_user: 2,
to_user: 1,
message: "Should i turn left or right here?",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 3).valueOf(),
is_detected: false,
},
{
id: 4,
from_user: 1,
to_user: 2,
message: "Left",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 4).valueOf(),
is_detected: true,
},
{
id: 5,
from_user: 1,
to_user: 2,
message: "Please hurry",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 5).valueOf(),
},
{
id: 6,
from_user: 2,
to_user: 1,
message: "Ok",
timestamp: currentTime.setMinutes(currentTime.getMinutes() - 6).valueOf(),
},
// { from_user: 1, to_user: 2, message: 'msg1', timestamp: currentTime.setDate(currentTime.getDate() - 1).valueOf() }, // { from_user: 1, to_user: 2, message: 'msg1', timestamp: currentTime.setDate(currentTime.getDate() - 1).valueOf() },
// { from_user: 1, to_user: 2, message: 'msg2', timestamp: currentTime.setDate(currentTime.getDate() - 2).valueOf() }, // { from_user: 1, to_user: 2, message: 'msg2', timestamp: currentTime.setDate(currentTime.getDate() - 2).valueOf() },
// { from_user: 2, to_user: 1, message: 'msg3', timestamp: currentTime.setDate(currentTime.getDate() - 3).valueOf() }, // { from_user: 2, to_user: 1, message: 'msg3', timestamp: currentTime.setDate(currentTime.getDate() - 3).valueOf() },
// { from_user: 1, to_user: 2, message: 'msg4', timestamp: currentTime.setDate(currentTime.getDate() - 4).valueOf() }, // { from_user: 1, to_user: 2, message: 'msg4', timestamp: currentTime.setDate(currentTime.getDate() - 4).valueOf() },
// { from_user: 2, to_user: 1, message: 'msg5', timestamp: currentTime.setDate(currentTime.getDate() - 5).valueOf() }, // { from_user: 2, to_user: 1, message: 'msg5', timestamp: currentTime.setDate(currentTime.getDate() - 5).valueOf() },
] ];
const [detectedText, setDetectedText] = useState("") const [detectedText, setDetectedText] = useState("");
const [playinId, setPlayingId] = useState(3) const [playinId, setPlayingId] = useState(3);
const [chatDetails, setChatDetails] = useState() const [chatDetails, setChatDetails] = useState(null);
const [chats, setChats] = useState([]) const [chats, setChats] = useState([]);
const [input, setInput] = useState('test') const [input, setInput] = useState("test");
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true);
const loadSampleChats = () => { const loadSampleChats = () => {
const chats_ = defaultChatData//res.results const chats_ = defaultChatData; //res.results
const sections = [...new Set(chats_.map(chat => new Date(chat.timestamp).setHours(0, 0, 0, 0)))]; const sections = [
const sectionChats = sections.map(section => { ...new Set(
console.log({ section }) chats_.map((chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0))
return ({ ),
title: section, data: chats_.filter(chat => { ];
console.log({ chat }) const sectionChats = sections.map((section) => {
return (new Date(chat.timestamp).setHours(0, 0, 0, 0).valueOf() == section) console.log({ section });
}).sort((a, b) => { return (a.timestamp - b.timestamp) }) return {
}) title: section,
data: chats_
.filter((chat) => {
console.log({ chat });
return (
new Date(chat.timestamp).setHours(0, 0, 0, 0).valueOf() == section
);
}) })
console.log({ chats_, sections, sectionChats }) .sort((a, b) => {
setChats(sectionChats) return a.timestamp - b.timestamp;
console.log({ chats }) }),
} };
});
console.log({ chats_, sections, sectionChats });
setChats(sectionChats);
useEffect(() => { if (chatDetails) { loadChats(); setLoading(false) } }, [chatDetails]) console.log({ chats });
};
useEffect(() => {
if (chatDetails) {
loadChats();
setLoading(false);
}
}, [chatDetails]);
// const ws = new WebSocket(`ws://${BACKEND_ADDRESS}/chatSocket/`) // const ws = new WebSocket(`ws://${BACKEND_ADDRESS}/chatSocket/`)
useEffect(() => { useEffect(() => {
loadChatDetails() loadChatDetails();
// startWebsocket() // startWebsocket()
// loadSampleChats() // loadSampleChats()
}, []) }, []);
// const startWebsocket = () => { // const startWebsocket = () => {
// ws.onopen = () => { // ws.onopen = () => {
...@@ -94,56 +162,125 @@ export default function ChatScreen({ navigation }) { ...@@ -94,56 +162,125 @@ export default function ChatScreen({ navigation }) {
// } // }
useEffect(() => {
const interval = setInterval(() => {
loadChats();
}, 2000);
return () => {
clearInterval(interval);
};
}, []);
const loadChatDetails = async () => { const loadChatDetails = async () => {
await getOne('conversations', 1).then(res => { await AsyncStorage.getItem("user_id").then((user_id) => {
return res.json() getOne("conversations", 1)
}).then(res => { .then((res) => {
console.log(res) return res.json();
AsyncStorage.getItem('user_id').then((user_id) => { })
console.log('chat details', user_id) .then((res) => {
console.log(res);
console.log("chat details", user_id);
//change from user and to user depending on the current user //change from user and to user depending on the current user
if (res.from_user == user_id) { if (res.from_user == user_id) {
setChatDetails(res) setChatDetails(res);
} else {
const n_res = {
...res,
from_user: res.to_user,
to_user: res.from_user,
};
setChatDetails(n_res);
} }
else { });
const n_res = { ...res, from_user: res.to_user, to_user: res.from_user } });
setChatDetails(n_res) };
}
})
const onDefaultMessagePressed = (item) => {
try {
addChats({
message: item.Q,
from_user: chatDetails.from_user,
to_user: chatDetails.to_user,
conversation: chatDetails.id,
}) })
.then((response) => {
// console.log(response)
})
.catch((e) => {
// console.log({e})
});
addChats({
message: item.A,
from_user: chatDetails.to_user,
to_user: chatDetails.from_user,
conversation: chatDetails.id,
})
.then((response) => {
// console.log(response)
})
.catch((e) => {
// console.log({e})
});
setLoading(true);
setInput("");
loadChats();
} catch (e) {
Toast.show({
title: "Error sending message. try again!",
...ERROR_TOAST_PROPS,
});
} }
};
const loadChats = async () => { const loadChats = () => {
await getList('chats').then(res => { getList("chats", { conversation: chatDetails?.id })
return res.json() .then((res) => {
}).then(res => { return res.json();
console.log("load chats")
const chats = res.results || []
const sections = [...new Set(chats.map(chat => new Date(chat.timestamp).setHours(0, 0, 0, 0)))];
const sectionChats = sections.map(section => ({ title: section, data: chats.filter(chat => new Date(chat.timestamp).setHours(0, 0, 0, 0) == section) }))
setChats(sectionChats)
}) })
.then((res) => {
setLoading(false) console.log("load chats");
} const chats = res.results || [];
const sections = [
...new Set(
chats.map((chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0))
),
];
const sectionChats = sections.map((section) => ({
title: section,
data: chats.filter(
(chat) => new Date(chat.timestamp).setHours(0, 0, 0, 0) == section
),
}));
setChats(sectionChats);
}).catch(e => {console.log(e)});
setLoading(false);
};
const onSendPress = () => { const onSendPress = () => {
try { try {
addChats({message: input, from_user: chatDetails.from_user, to_user: chatDetails.to_user, conversation: chatDetails.id }).then(response => { addChats({
message: input,
from_user: chatDetails.from_user,
to_user: chatDetails.to_user,
conversation: chatDetails.id,
}).then((response) => {
// console.log(response) // console.log(response)
}) });
setLoading(true) setLoading(true);
setInput('') setInput("");
loadChats() loadChats();
} } catch (e) {
catch (e) { Toast.show({
Toast.show({ title: 'Error sending message. try again!', ...ERROR_TOAST_PROPS }) title: "Error sending message. try again!",
} ...ERROR_TOAST_PROPS,
});
} }
};
return ( return (
<View style={styles.container}> <View style={styles.container}>
...@@ -153,71 +290,116 @@ export default function ChatScreen({ navigation }) { ...@@ -153,71 +290,116 @@ export default function ChatScreen({ navigation }) {
<EditScreenInfo path="/screens/TabOneScreen.tsx" /> */} <EditScreenInfo path="/screens/TabOneScreen.tsx" /> */}
<View style={{ flex: 1, width: '100%' }}> <View style={{ flex: 1, width: "100%", justifyContent: "space-between" }}>
<View style={{ display: 'flex', flex: 0.9, justifyContent: 'space-between' }}> <View
style={{
display: "flex",
flex: 1,
justifyContent: "space-between",
}}
>
<StatusBar /> <StatusBar />
{loading ? <ActivityIndicator /> : {loading ? (
<ActivityIndicator />
) : (
<SectionList <SectionList
// style={{ flex: 1 }}
refreshing={loading} refreshing={loading}
onRefresh={() => { onRefresh={() => {
// loadChatDetails() //remove // loadChatDetails() //remove
loadChats() loadChats();
}} }}
sections={chats} sections={chats}
keyExtractor={(item, index) => item + index} keyExtractor={(item, index) => item + index}
renderItem={({ item }) => { renderItem={({ item }) => {
// console.log({ item }) // console.log({ item })
const timeString = new Date(item.timestamp).toLocaleTimeString() const timeString = new Date(
const time = timeString.slice(-11, -6) + " " + timeString.slice(-2) item.timestamp
).toLocaleTimeString();
const time =
timeString.slice(-11, -6) + " " + timeString.slice(-2);
return ( return (
<View style={{ margin: 5, padding: 5 }}><Text <View style={{ margin: 5, padding: 5 }}>
style={[{ textAlign: chatDetails.from_user == item.from_user ? 'right' : 'left', backgroundColor: chatDetails.from_user == item.from_user ? 'lightgray' : '#FFDE03', borderRadius: 5, padding: 5 }, <Text
chatDetails.from_user == item.from_user ? { marginLeft: 'auto' } : { marginRight: 'auto' } style={[
{
textAlign:
chatDetails.from_user == item.from_user
? "right"
: "left",
backgroundColor:
chatDetails.from_user == item.from_user
? "lightgray"
: "#FFDE03",
borderRadius: 5,
padding: 5,
},
chatDetails.from_user == item.from_user
? { marginLeft: "auto" }
: { marginRight: "auto" },
]} ]}
key={item.timestamp}>{item.message}</Text> key={item.timestamp}
<View style={{ flex: 1, flexDirection: chatDetails.from_user == item.from_user ? 'row-reverse' : 'row', textAlign: chatDetails.from_user == item.from_user ? 'right' : 'left' }}> >
<Text style={{ textAlign: chatDetails.from_user == item.from_user ? 'right' : 'left', color: 'gray', fontSize: 11 }}>{time}</Text> {item.message}
{item.is_detected && <Ionicons name="mic" size={15} color={CONVO_DEFAULT_ICON_COLOR} />} </Text>
{/* {chatDetails.to_user == item.from_user && item.id != playinId && <Ionicons name="play" size={15} style={styles.chatIcon} />} <View
{chatDetails.to_user == item.from_user && item.id == playinId && <Ionicons name="pause" size={15} style={styles.chatIcon} />} */} style={{
{chatDetails.to_user == item.from_user && <PlayMessage message={item.message} />} flex: 1,
</View> flexDirection:
{/* {item.id == playinId ? chatDetails.from_user == item.from_user
<Slider ? "row-reverse"
style={{ width: 200, height: 40, FborderRadius: 5, padding: 0, margin: 0 }} : "row",
minimumValue={0} textAlign:
maximumValue={1} chatDetails.from_user == item.from_user
value={0.67} ? "right"
: "left",
}}
>
<Text
style={{
textAlign:
chatDetails.from_user == item.from_user
? "right"
: "left",
color: "gray",
fontSize: 11,
}}
>
{time}
</Text>
{item.is_detected && (
<Ionicons
name="mic"
size={15}
color={CONVO_DEFAULT_ICON_COLOR}
/>
)}
minimumTrackTintColor="black" {chatDetails.to_user == item.from_user && (
maximumTrackTintColor="grey" <PlayMessage message={item.message} />
/> : null )}
} */}
</View> </View>
) </View>
);
}} }}
invertStickyHeaders invertStickyHeaders
inverted inverted
contentContainerStyle={{ flexDirection: 'column-reverse' }} contentContainerStyle={{ flexDirection: "column-reverse" }}
renderSectionHeader={({ section: { title } }) => { renderSectionHeader={({ section: { title } }) => {
var date = "" var date = "";
if (new Date(title).toLocaleDateString() == new Date().toLocaleDateString()) { if (
date = "Today" new Date(title).toLocaleDateString() ==
} new Date().toLocaleDateString()
// else if (new Date(title).toLocaleDateString() == new Date().setDate(new Date().getDate() - 1).toLocaleDateString()){ ) {
// date = "Yesterday" date = "Today";
// } } else {
else { date = new Date(title).toLocaleDateString();
date = new Date(title).toLocaleDateString()
} }
return ( return <Text style={styles.header}>{date}</Text>;
<Text style={styles.header}>{date}</Text>
)
}} }}
/> />
} )}
{/* <FlatList {/* <FlatList
inverted={true} inverted={true}
style={{ alignContent: 'flex-end' }} style={{ alignContent: 'flex-end' }}
...@@ -234,31 +416,95 @@ export default function ChatScreen({ navigation }) { ...@@ -234,31 +416,95 @@ export default function ChatScreen({ navigation }) {
<Text style={{ textAlign: chatDetails.from == item.from ? 'right' : 'left', color: 'gray' }}>{new Date(item.time).toLocaleTimeString().slice(0, 5)}</Text></View> <Text style={{ textAlign: chatDetails.from == item.from ? 'right' : 'left', color: 'gray' }}>{new Date(item.time).toLocaleTimeString().slice(0, 5)}</Text></View>
) )
}} /> */} }} /> */}
</View>
<View>
<Divider />
<View
style={{
padding: 0,
backgroundColor: "white",
minHeight: 20,
justifyContent: "flex-end",
}}
>
<View style={{ flexDirection: "row", display: "flex" }}>
<ScrollView horizontal={true}>
{QandAs.map((item) => (
<TouchableOpacity
onPress={() => onDefaultMessagePressed(item)}
style={{
marginVertical: 5,
marginHorizontal: 5,
backgroundColor: "gray",
borderRadius: 5,
justifyContent: "center",
alignSelf: "center",
padding: 5,
}}
key={item.Q}
>
<Text
style={{ justifyContent: "center", alignSelf: "center" }}
>
{item.Q}
</Text>
</TouchableOpacity>
))}
</ScrollView>
</View>
</View> </View>
<View style={{ flex: 0.075, padding: 0, backgroundColor: 'white' }}> <Divider />
<View style={{ flexDirection: 'row', display: 'flex', height: '100%' }}> <View style={{ padding: 0, backgroundColor: "white", minHeight: 30 }}>
<SafeAreaView style={{ flex: 0.8, height: '100%', flexDirection: 'column-reverse' }}> <View style={{ flexDirection: "row", display: "flex" }}>
<SafeAreaView
style={{
flex: 0.8,
height: "100%",
flexDirection: "column-reverse",
}}
>
{/* <TextInput {/* <TextInput
style={{ borderWidth: 2, borderColor: 'gray', color: 'black', marginHorizontal: 5, paddingHorizontal: 10, borderRadius: 5 }} style={{ borderWidth: 2, borderColor: 'gray', color: 'black', marginHorizontal: 5, paddingHorizontal: 10, borderRadius: 5 }}
defaultValue={input} defaultValue={input}
onChange={(e) => setInput(e.target.value)}></TextInput> */} onChange={(e) => setInput(e.target.value)}></TextInput> */}
<Input style={{}} value={input} w="100%" onChangeText={setInput} placeholder="" /> <Input
style={{ height: 30 }}
value={input}
w="100%"
onChangeText={setInput}
placeholder=""
/>
</SafeAreaView> </SafeAreaView>
{input ? {input ? (
<View style={{ flex: 0.2, height: '100%', flexDirection: 'column-reverse' }}> <View
<Button style={{ width: '100%', height: '100%' }} title='Send' onPress={onSendPress} /> style={{
flex: 0.2,
// height: "100%",
flexDirection: "column-reverse",
}}
>
<Button
style={{ width: "100%" }}
title="Send"
onPress={onSendPress}
/>
</View>
) : (
<View
style={{
flex: 0.2,
height: "100%",
flexDirection: "column-reverse",
}}
>
<AudioRecorder setDetectedText={setInput} />
</View>
)}
</View> </View>
:
<View style={{ flex: 0.2, height: '100%', flexDirection: 'column-reverse' }}><AudioRecorder setDetectedText={setInput} /></View>
}
</View> </View>
</View> </View>
</View> </View>
</View> </View>
); );
} }
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import {getFirestore} from "firebase/firestore"
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyBclRBmE5oU1I4fcfFVySKR90tJ4Ddy29A",
authDomain: "safedrive-4fdc8.firebaseapp.com",
projectId: "safedrive-4fdc8",
storageBucket: "safedrive-4fdc8.appspot.com",
messagingSenderId: "577482229800",
appId: "1:577482229800:web:902b5a82915ee7c228cd1d",
measurementId: "G-HX3ZWKL2KQ"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
\ No newline at end of file
...@@ -13,6 +13,7 @@ export const styles = StyleSheet.create({ ...@@ -13,6 +13,7 @@ export const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: COLOR1, backgroundColor: COLOR1,
height: '100%'
}, },
loginContainer: { loginContainer: {
alignItems: 'center', alignItems: 'center',
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -31,7 +31,7 @@ class MyTokenObtainPairSerializer(TokenObtainPairSerializer): ...@@ -31,7 +31,7 @@ class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
class UserSerializer(serializers.HyperlinkedModelSerializer): class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ['url', 'username', 'email', 'groups'] fields = ['username', 'id']
class GroupSerializer(serializers.HyperlinkedModelSerializer): class GroupSerializer(serializers.HyperlinkedModelSerializer):
......
...@@ -32,11 +32,12 @@ from pydub import AudioSegment ...@@ -32,11 +32,12 @@ from pydub import AudioSegment
import numpy as np import numpy as np
#Custom Viewset to get auth token # Custom Viewset to get auth token
class ObtainTokenPairWithUserView(TokenObtainPairView): class ObtainTokenPairWithUserView(TokenObtainPairView):
permission_classes = (permissions.AllowAny,) permission_classes = (permissions.AllowAny,)
serializer_class = MyTokenObtainPairSerializer serializer_class = MyTokenObtainPairSerializer
class UserViewSet(viewsets.ModelViewSet): class UserViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows users to be viewed or edited. API endpoint that allows users to be viewed or edited.
...@@ -71,9 +72,9 @@ class MlModelViewSet(viewsets.ViewSet): ...@@ -71,9 +72,9 @@ class MlModelViewSet(viewsets.ViewSet):
permission_classes = [permissions.AllowAny] permission_classes = [permissions.AllowAny]
parser_classes = [MultiPartParser] parser_classes = [MultiPartParser]
#Custom api to add sample chats # Custom api to add sample chats
@action(detail=False) @action(detail=False)
def addChats(*args, **kwargs): def add_default_chats(*args, **kwargs):
admin = User.objects.get(username='admin') admin = User.objects.get(username='admin')
user2 = User.objects.get(username='user2') user2 = User.objects.get(username='user2')
...@@ -107,7 +108,7 @@ class MlModelViewSet(viewsets.ViewSet): ...@@ -107,7 +108,7 @@ class MlModelViewSet(viewsets.ViewSet):
conversation=convo, from_user_id=chat['from'], to_user_id=chat['to'], messsage=chat['message']) conversation=convo, from_user_id=chat['from'], to_user_id=chat['to'], messsage=chat['message'])
object.save() object.save()
#Custom api to train the model # Custom api to train the model
@action(detail=False) @action(detail=False)
def train(*args, **kwargs): def train(*args, **kwargs):
print('Function ran') print('Function ran')
...@@ -115,7 +116,7 @@ class MlModelViewSet(viewsets.ViewSet): ...@@ -115,7 +116,7 @@ class MlModelViewSet(viewsets.ViewSet):
print(results) print(results)
return Response({'success': True}) return Response({'success': True})
#Custom api to convert audio to text # Custom api to convert audio to text
@action(detail=False, methods=["POST"]) @action(detail=False, methods=["POST"])
def detect(self, request, *args, **kwargs): def detect(self, request, *args, **kwargs):
print('Function ran') print('Function ran')
...@@ -151,16 +152,18 @@ class MlModelViewSet(viewsets.ViewSet): ...@@ -151,16 +152,18 @@ class MlModelViewSet(viewsets.ViewSet):
print(results) print(results)
return Response({'success': True, 'result': results}) return Response({'success': True, 'result': results})
class ChatViewSet(viewsets.ModelViewSet): class ChatViewSet(viewsets.ModelViewSet):
queryset = Chat.objects.all().order_by('-timestamp') queryset = Chat.objects.all().order_by('-timestamp')
serializer_class = ChatSerializer serializer_class = ChatSerializer
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
#ovveride defualt list action to get chats of specific user conversation # ovveride defualt list action to get chats of specific user conversation
def list(self, request, pk=None): def list(self, request, pk=None):
conv_id = request.query_params.get("conversation")
if pk == None: if pk == None:
chats = Chat.objects \ chats = Chat.objects \
.filter(conversation_id=1) \ .filter(conversation_id=int(conv_id)) \
.filter(Q(from_user_id=request.user.id) | Q( .filter(Q(from_user_id=request.user.id) | Q(
to_user_id=request.user.id)) to_user_id=request.user.id))
else: else:
...@@ -193,15 +196,17 @@ class ChatViewSet(viewsets.ModelViewSet): ...@@ -193,15 +196,17 @@ class ChatViewSet(viewsets.ModelViewSet):
item = ChatSerializer(data=request.data) item = ChatSerializer(data=request.data)
# validating for already existing data # validating for already existing data
if Chat.objects.filter(**request.data).exists(): # if Chat.objects.filter(**request.data).exists():
raise serializers.ValidationError('This data already exists') # raise serializers.ValidationError('This data already exists')
print(item)
if item.is_valid(): if item.is_valid() or True:
item.save() item.save()
return Response(item.data) return Response(item.data)
else: else:
return Response(status=Status.HTTP_404_NOT_FOUND) return Response(status=Status.HTTP_404_NOT_FOUND)
class ConversationViewSet(viewsets.ModelViewSet): class ConversationViewSet(viewsets.ModelViewSet):
queryset = Conversation.objects.all().order_by('id') queryset = Conversation.objects.all().order_by('id')
serializer_class = ConversationSerializer serializer_class = ConversationSerializer
......
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment