Commit c998912e authored by Malsha Rathnasiri's avatar Malsha Rathnasiri

Merge branch 'IT18094664'

parents 8f472708 51dc3b18
......@@ -5,3 +5,4 @@ ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffmpeg.exe
ngrok.exe
ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffplay.exe
ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffprobe.exe
backend/db.sqlite3
{
"e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true,
"af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true,
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
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://4c61-2401-dd00-10-20-7542-a875-30e7-8931.ap.ngrok.io"
export const BACKEND_URL = `${BACKEND_ADDRESS}`
{
"expo": {
"name": "MobileApp",
"slug": "MobileApp",
"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": "^12.0.0",
"@react-native-async-storage/async-storage": "~1.15.0",
"@react-native-community/slider": "4.1.12",
"@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": "~44.0.0",
"expo-asset": "~8.4.4",
"expo-av": "~10.2.0",
"expo-constants": "~13.0.0",
"expo-file-system": "~13.1.4",
"expo-font": "~10.0.4",
"expo-linking": "~3.0.0",
"expo-media-library": "~14.0.0",
"expo-speech": "~10.1.0",
"expo-splash-screen": "~0.14.0",
"expo-status-bar": "~1.2.0",
"expo-web-browser": "~10.1.0",
"jwt-decode": "^3.1.2",
"native-base": "^3.4.11",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-multi-selectbox": "^1.5.0",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.10.1",
"react-native-svg": "12.1.1",
"react-native-web": "0.17.1",
"styled-system": "^5.1.5"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@types/react": "~17.0.21",
"@types/react-native": "~0.64.12",
"jest": "^26.6.3",
"jest-expo": "~44.0.1",
"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 from "react";
import { View, Button, Text } from 'react-native'
import { styles } from "../util/styles";
export const SignupScreen = ({ navigation }) => {
return (
<View style={styles.container}><Text style={{
padding: 10,
textAlign: 'center',
// fontWeight: 'bold',
fontSize: 40
}}>Sign up</Text>
<View style={{ flexDirection: 'row', padding: 10, justifyContent: 'center' }}>
<Text style={{ textAlign: 'center' }}>Already have an account? </Text>
<Text style={{ fontWeight: 'bold', textAlign: 'center', }} onPress={() => navigation.replace('Root')}>Login</Text>
</View>
<SignupForm />
</View>
)
}
const SignupForm = () => {
return(
<View>
</View>
)
}
\ No newline at end of file
This diff is collapsed.
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' }}>
<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 diff is collapsed.
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