├── assets ├── images │ ├── icon.png │ ├── favicon.png │ ├── iconify.png │ ├── splash.png │ ├── weather.png │ ├── adaptive-icon.png │ └── map-background.png └── fonts │ └── SpaceMono-Regular.ttf ├── tsconfig.json ├── babel.config.js ├── components ├── StyledText.tsx ├── __tests__ │ └── StyledText-test.js ├── Icon │ └── index.tsx ├── Back.tsx ├── Themed.tsx ├── SearchBox │ └── index.tsx └── EditScreenInfo.tsx ├── constants ├── Layout.ts └── Colors.ts ├── .gitignore ├── .expo-shared └── assets.json ├── hooks ├── useColorScheme.ts └── useCachedResources.ts ├── App.tsx ├── screens ├── TabTwoScreen.tsx ├── NotFoundScreen.tsx ├── ModalScreen.tsx ├── SearchScreen.tsx └── HomeScreen.tsx ├── app.json ├── README.md ├── navigation ├── LinkingConfiguration.ts ├── index.tsx └── MainTabNavigator.tsx ├── headers ├── SearchScreenheader.tsx └── HomeScreenHeader.tsx ├── types.tsx └── package.json /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/iconify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/iconify.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/splash.png -------------------------------------------------------------------------------- /assets/images/weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/weather.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /assets/images/map-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/images/map-background.png -------------------------------------------------------------------------------- /assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbentil/weather-app-mobile/HEAD/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'] 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /components/StyledText.tsx: -------------------------------------------------------------------------------- 1 | import { Text, TextProps } from './Themed'; 2 | 3 | export function MonoText(props: TextProps) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /constants/Layout.ts: -------------------------------------------------------------------------------- 1 | import { Dimensions } from 'react-native'; 2 | 3 | const width = Dimensions.get('window').width; 4 | const height = Dimensions.get('window').height; 5 | 6 | export default { 7 | window: { 8 | width, 9 | height, 10 | }, 11 | isSmallDevice: width < 375, 12 | }; 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | <<<<<<< HEAD 16 | .env 17 | ======= 18 | 19 | # .env 20 | .env 21 | >>>>>>> 54f7f10e3277d57311e590f5da92a23785c0f037 22 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true, 3 | "af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true, 4 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 5 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 6 | } 7 | -------------------------------------------------------------------------------- /components/__tests__/StyledText-test.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | import { MonoText } from '../StyledText'; 5 | 6 | it(`renders correctly`, () => { 7 | const tree = renderer.create(Snapshot test!).toJSON(); 8 | 9 | expect(tree).toMatchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /hooks/useColorScheme.ts: -------------------------------------------------------------------------------- 1 | import { ColorSchemeName, useColorScheme as _useColorScheme } from 'react-native'; 2 | 3 | // The useColorScheme value is always either light or dark, but the built-in 4 | // type suggests that it can be null. This will not happen in practice, so this 5 | // makes it a bit easier to work with. 6 | export default function useColorScheme(): NonNullable { 7 | return _useColorScheme() as NonNullable; 8 | } 9 | -------------------------------------------------------------------------------- /constants/Colors.ts: -------------------------------------------------------------------------------- 1 | const tintColorLight = '#ffcc00'; 2 | const tintColorDark = '#fff'; 3 | 4 | export default { 5 | light: { 6 | text: '#000', 7 | background: '#fff', 8 | tint: tintColorLight, 9 | tabIconDefault: '#ccc', 10 | tabIconSelected: tintColorLight, 11 | }, 12 | dark: { 13 | text: '#fff', 14 | background: '#000', 15 | tint: tintColorDark, 16 | tabIconDefault: '#ccc', 17 | tabIconSelected: tintColorDark, 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /components/Icon/index.tsx: -------------------------------------------------------------------------------- 1 | import { Image, Text, View } from 'react-native' 2 | 3 | import React from 'react' 4 | 5 | const defIcon = require('../../assets/images/iconify.png') 6 | 7 | interface Props { 8 | style: any 9 | icon: any 10 | } 11 | const Icon: React.FC =({style='', icon = ''}) => { 12 | // let rIcon = icon == undefined? defIcon: icon 13 | let rIcon = {uri: `https://openweathermap.org/img/wn/${icon}.png`} 14 | return ( 15 | 16 | ) 17 | } 18 | 19 | 20 | export default Icon -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import Navigation from './navigation'; 2 | import { SafeAreaProvider } from 'react-native-safe-area-context'; 3 | import { StatusBar } from 'expo-status-bar'; 4 | import useCachedResources from './hooks/useCachedResources'; 5 | import useColorScheme from './hooks/useColorScheme'; 6 | // navigator.geolocation = require('@react-native-community/geolocation') 7 | 8 | export default function App() { 9 | const isLoadingComplete = useCachedResources(); 10 | const colorScheme = useColorScheme(); 11 | 12 | if (!isLoadingComplete) { 13 | return null; 14 | } else { 15 | return ( 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /screens/TabTwoScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import EditScreenInfo from '../components/EditScreenInfo'; 4 | import { Text, View } from '../components/Themed'; 5 | 6 | export default function TabTwoScreen() { 7 | return ( 8 | 9 | Tab Two 10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | const styles = StyleSheet.create({ 17 | container: { 18 | flex: 1, 19 | alignItems: 'center', 20 | justifyContent: 'center', 21 | }, 22 | title: { 23 | fontSize: 20, 24 | fontWeight: 'bold', 25 | }, 26 | separator: { 27 | marginVertical: 30, 28 | height: 1, 29 | width: '80%', 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "weather-app-mobile", 4 | "slug": "weather-app-mobile", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "scheme": "myapp", 9 | "userInterfaceStyle": "automatic", 10 | "splash": { 11 | "image": "./assets/images/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "updates": { 16 | "fallbackToCacheTimeout": 0 17 | }, 18 | "assetBundlePatterns": [ 19 | "**/*" 20 | ], 21 | "ios": { 22 | "supportsTablet": true 23 | }, 24 | "android": { 25 | "adaptiveIcon": { 26 | "foregroundImage": "./assets/images/adaptive-icon.png", 27 | "backgroundColor": "#ffffff" 28 | } 29 | }, 30 | "web": { 31 | "favicon": "./assets/images/favicon.png" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # weather-app-mobile 2 | A Complete Weather APP using React Native & Expo. 3 | 4 | 5 | # UI > HOME SCREEN 6 | 7 |
8 | 9 | 10 |
11 | 12 | # UI > SEARCH SCREEN 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | ## Technologies 21 | 1. React Native and Expo 22 | 2. TypeScript 23 | 3. Open Weather Map from Rapid API 24 | 4. Google Locations API 25 | 26 | 27 | -------------------------------------------------------------------------------- /navigation/LinkingConfiguration.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about deep linking with React Navigation 3 | * https://reactnavigation.org/docs/deep-linking 4 | * https://reactnavigation.org/docs/configuring-links 5 | */ 6 | 7 | import { LinkingOptions } from '@react-navigation/native'; 8 | import * as Linking from 'expo-linking'; 9 | 10 | import { RootStackParamList } from '../types'; 11 | 12 | const linking: LinkingOptions = { 13 | prefixes: [Linking.makeUrl('/')], 14 | config: { 15 | screens: { 16 | Root: { 17 | screens: { 18 | TabOne: { 19 | screens: { 20 | TabOneScreen: 'one', 21 | }, 22 | }, 23 | TabTwo: { 24 | screens: { 25 | TabTwoScreen: 'two', 26 | }, 27 | }, 28 | }, 29 | }, 30 | Modal: 'modal', 31 | NotFound: '*', 32 | }, 33 | }, 34 | }; 35 | 36 | export default linking; 37 | -------------------------------------------------------------------------------- /screens/NotFoundScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet, TouchableOpacity } from 'react-native'; 2 | 3 | import { Text, View } from '../components/Themed'; 4 | import { RootStackScreenProps } from '../types'; 5 | 6 | export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) { 7 | return ( 8 | 9 | This screen doesn't exist. 10 | navigation.replace('Root')} style={styles.link}> 11 | Go to home screen! 12 | 13 | 14 | ); 15 | } 16 | 17 | const styles = StyleSheet.create({ 18 | container: { 19 | flex: 1, 20 | alignItems: 'center', 21 | justifyContent: 'center', 22 | padding: 20, 23 | }, 24 | title: { 25 | fontSize: 20, 26 | fontWeight: 'bold', 27 | }, 28 | link: { 29 | marginTop: 15, 30 | paddingVertical: 15, 31 | }, 32 | linkText: { 33 | fontSize: 14, 34 | color: '#2e78b7', 35 | }, 36 | }); 37 | -------------------------------------------------------------------------------- /screens/ModalScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar'; 2 | import { Platform, StyleSheet } from 'react-native'; 3 | 4 | import EditScreenInfo from '../components/EditScreenInfo'; 5 | import { Text, View } from '../components/Themed'; 6 | 7 | export default function ModalScreen() { 8 | return ( 9 | 10 | Modal 11 | 12 | 13 | 14 | {/* Use a light status bar on iOS to account for the black space above the modal */} 15 | 16 | 17 | ); 18 | } 19 | 20 | const styles = StyleSheet.create({ 21 | container: { 22 | flex: 1, 23 | alignItems: 'center', 24 | justifyContent: 'center', 25 | }, 26 | title: { 27 | fontSize: 20, 28 | fontWeight: 'bold', 29 | }, 30 | separator: { 31 | marginVertical: 30, 32 | height: 1, 33 | width: '80%', 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /hooks/useCachedResources.ts: -------------------------------------------------------------------------------- 1 | import { FontAwesome } from '@expo/vector-icons'; 2 | import * as Font from 'expo-font'; 3 | import * as SplashScreen from 'expo-splash-screen'; 4 | import { useEffect, useState } from 'react'; 5 | 6 | export default function useCachedResources() { 7 | const [isLoadingComplete, setLoadingComplete] = useState(false); 8 | 9 | // Load any resources or data that we need prior to rendering the app 10 | useEffect(() => { 11 | async function loadResourcesAndDataAsync() { 12 | try { 13 | SplashScreen.preventAutoHideAsync(); 14 | 15 | // Load fonts 16 | await Font.loadAsync({ 17 | ...FontAwesome.font, 18 | 'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'), 19 | }); 20 | } catch (e) { 21 | // We might want to provide this error information to an error reporting service 22 | console.warn(e); 23 | } finally { 24 | setLoadingComplete(true); 25 | SplashScreen.hideAsync(); 26 | } 27 | } 28 | 29 | loadResourcesAndDataAsync(); 30 | }, []); 31 | 32 | return isLoadingComplete; 33 | } 34 | -------------------------------------------------------------------------------- /headers/SearchScreenheader.tsx: -------------------------------------------------------------------------------- 1 | import { Appearance, SafeAreaView, StyleSheet, TouchableOpacity, View } from 'react-native'; 2 | import { Entypo, FontAwesome5, Ionicons } from '@expo/vector-icons'; 3 | import { useEffect, useState } from 'react'; 4 | 5 | import Back from '../components/Back'; 6 | import Colors from '../constants/Colors'; 7 | import { Text } from '../components/Themed'; 8 | import tw from 'twrnc' 9 | import useColorScheme from '../hooks/useColorScheme'; 10 | 11 | export default function SearchScreenheader() { 12 | const colorScheme = useColorScheme(); 13 | 14 | return ( 15 | 16 | 17 | Search for City 18 | 19 | 20 | ); 21 | } 22 | 23 | const styles = StyleSheet.create({ 24 | container: { 25 | alignItems: 'center', 26 | justifyContent: 'center', 27 | }, 28 | title: { 29 | fontSize: 20, 30 | fontWeight: 'bold', 31 | }, 32 | separator: { 33 | marginVertical: 30, 34 | height: 1, 35 | width: '80%', 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /components/Back.tsx: -------------------------------------------------------------------------------- 1 | import Colors from "../constants/Colors" 2 | import { Ionicons } from "@expo/vector-icons" 3 | import React from "react" 4 | import { Text } from "./Themed" 5 | import { TouchableOpacity } from "react-native" 6 | import tw from 'twrnc' 7 | import { useNavigation } from "@react-navigation/native" 8 | 9 | interface Props{ 10 | showIcon: boolean, 11 | style: any, 12 | label: string 13 | } 14 | 15 | const Back: React.FC = ({showIcon, style, label}) => { 16 | 17 | const navigation = useNavigation() 18 | return ( 19 | navigation.goBack()} 22 | style={[tw`flex-row`, style]} 23 | > 24 | {showIcon && ( 25 | 31 | )} 32 | {label} 35 | 36 | ) 37 | } 38 | 39 | 40 | export default Back; -------------------------------------------------------------------------------- /types.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about using TypeScript with React Navigation: 3 | * https://reactnavigation.org/docs/typescript/ 4 | */ 5 | 6 | import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native'; 7 | 8 | import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'; 9 | import { NativeStackScreenProps } from '@react-navigation/native-stack'; 10 | 11 | declare global { 12 | namespace ReactNavigation { 13 | interface RootParamList extends RootStackParamList {} 14 | } 15 | } 16 | 17 | export type RootStackParamList = { 18 | Root: NavigatorScreenParams | undefined; 19 | Modal: undefined; 20 | NotFound: undefined; 21 | }; 22 | 23 | export type RootStackScreenProps = NativeStackScreenProps< 24 | RootStackParamList, 25 | Screen 26 | >; 27 | 28 | export type RootTabParamList = { 29 | Home: undefined; 30 | Search: undefined; 31 | Profile: undefined; 32 | Other: undefined; 33 | 34 | }; 35 | 36 | export type RootTabScreenProps = CompositeScreenProps< 37 | BottomTabScreenProps, 38 | NativeStackScreenProps 39 | >; 40 | 41 | export interface FetchWeatherProps { 42 | lon: string, 43 | lat: string 44 | } 45 | -------------------------------------------------------------------------------- /components/Themed.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about Light and Dark modes: 3 | * https://docs.expo.io/guides/color-schemes/ 4 | */ 5 | 6 | import { Text as DefaultText, View as DefaultView } from 'react-native'; 7 | 8 | import Colors from '../constants/Colors'; 9 | import useColorScheme from '../hooks/useColorScheme'; 10 | 11 | export function useThemeColor( 12 | props: { light?: string; dark?: string }, 13 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark 14 | ) { 15 | const theme = useColorScheme(); 16 | const colorFromProps = props[theme]; 17 | 18 | if (colorFromProps) { 19 | return colorFromProps; 20 | } else { 21 | return Colors[theme][colorName]; 22 | } 23 | } 24 | 25 | type ThemeProps = { 26 | lightColor?: string; 27 | darkColor?: string; 28 | }; 29 | 30 | export type TextProps = ThemeProps & DefaultText['props']; 31 | export type ViewProps = ThemeProps & DefaultView['props']; 32 | 33 | export function Text(props: TextProps) { 34 | const { style, lightColor, darkColor, ...otherProps } = props; 35 | const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); 36 | 37 | return ; 38 | } 39 | 40 | export function View(props: ViewProps) { 41 | const { style, lightColor, darkColor, ...otherProps } = props; 42 | const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); 43 | 44 | return ; 45 | } 46 | -------------------------------------------------------------------------------- /components/SearchBox/index.tsx: -------------------------------------------------------------------------------- 1 | import { EvilIcons, Ionicons } from '@expo/vector-icons'; 2 | import { KeyboardAvoidingView, StyleSheet, TextInput, TouchableOpacity } from 'react-native'; 3 | import { Text, View } from '../Themed'; 4 | 5 | import Colors from '../../constants/Colors'; 6 | import tw from 'twrnc' 7 | import useColorScheme from '../../hooks/useColorScheme'; 8 | import { useState } from 'react'; 9 | 10 | interface Props{ 11 | style: any, 12 | // search: any 13 | } 14 | const SearchBar: React.FC =({style, }) =>{ 15 | const colorScheme = useColorScheme(); 16 | const [val, setVal] = useState('') 17 | return ( 18 | 23 | 24 | setVal(text)} 29 | underlineColorAndroid="transparent" 30 | placeholderTextColor={Colors['light'].tabIconDefault} 31 | returnKeyType = {'search'} 32 | /> 33 | {/* */} 34 | setVal('')}> 35 | 36 | 37 | 38 | ); 39 | } 40 | 41 | export default SearchBar; 42 | 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather-app-mobile", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web", 10 | "eject": "expo eject", 11 | "test": "jest --watchAll" 12 | }, 13 | "jest": { 14 | "preset": "jest-expo" 15 | }, 16 | "dependencies": { 17 | "@expo/vector-icons": "^12.0.0", 18 | "@react-native-community/blur": "^3.6.0", 19 | "@react-native-community/geolocation": "^2.0.2", 20 | "@react-navigation/bottom-tabs": "^6.0.5", 21 | "@react-navigation/native": "^6.0.2", 22 | "@react-navigation/native-stack": "^6.1.0", 23 | "@react-navigation/stack": "^6.2.1", 24 | "axios": "^0.27.2", 25 | "expo": "~44.0.0", 26 | "expo-asset": "~8.4.4", 27 | "expo-blur": "~11.0.0", 28 | "expo-constants": "~13.0.0", 29 | "expo-font": "~10.0.4", 30 | "expo-linking": "~3.0.0", 31 | "expo-splash-screen": "~0.14.0", 32 | "expo-status-bar": "~1.2.0", 33 | "expo-web-browser": "~10.1.0", 34 | "moment": "^2.29.3", 35 | "react": "17.0.1", 36 | "react-dom": "17.0.1", 37 | "react-native": "0.64.3", 38 | "react-native-dotenv": "^3.3.1", 39 | "react-native-geolocation-service": "^5.3.0-beta.4", 40 | "react-native-safe-area-context": "3.3.2", 41 | "react-native-screens": "~3.10.1", 42 | "react-native-web": "0.17.1", 43 | "react-navigation": "^4.4.4", 44 | "twrnc": "^3.3.0" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.12.9", 48 | "@types/react": "~17.0.21", 49 | "@types/react-native": "~0.64.12", 50 | "jest": "^26.6.3", 51 | "jest-expo": "~44.0.1", 52 | "react-test-renderer": "17.0.1", 53 | "typescript": "~4.3.5" 54 | }, 55 | "private": true 56 | } 57 | -------------------------------------------------------------------------------- /navigation/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { ColorSchemeName, Pressable } from 'react-native'; 4 | import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native'; 5 | import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types'; 6 | 7 | import BottomTabNavigator from './MainTabNavigator'; 8 | import Colors from '../constants/Colors'; 9 | /** 10 | * If you are not familiar with React Navigation, refer to the "Fundamentals" guide: 11 | * https://reactnavigation.org/docs/getting-started 12 | * 13 | */ 14 | import { FontAwesome } from '@expo/vector-icons'; 15 | import LinkingConfiguration from './LinkingConfiguration'; 16 | import ModalScreen from '../screens/ModalScreen'; 17 | import NotFoundScreen from '../screens/NotFoundScreen'; 18 | import TabOneScreen from '../screens/HomeScreen'; 19 | import TabTwoScreen from '../screens/TabTwoScreen'; 20 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; 21 | import { createNativeStackNavigator } from '@react-navigation/native-stack'; 22 | import useColorScheme from '../hooks/useColorScheme'; 23 | 24 | export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) { 25 | return ( 26 | 29 | 30 | 31 | ); 32 | } 33 | 34 | /** 35 | * A root stack navigator is often used for displaying modals on top of all other content. 36 | * https://reactnavigation.org/docs/modal 37 | */ 38 | const Stack = createNativeStackNavigator(); 39 | 40 | function RootNavigator() { 41 | return ( 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ); 50 | } 51 | 52 | /** 53 | * A bottom tab navigator displays tab buttons on the bottom of the display to switch screens. 54 | * https://reactnavigation.org/docs/bottom-tab-navigator 55 | */ 56 | 57 | -------------------------------------------------------------------------------- /components/EditScreenInfo.tsx: -------------------------------------------------------------------------------- 1 | import * as WebBrowser from 'expo-web-browser'; 2 | import { StyleSheet, TouchableOpacity } from 'react-native'; 3 | 4 | import Colors from '../constants/Colors'; 5 | import { MonoText } from './StyledText'; 6 | import { Text, View } from './Themed'; 7 | 8 | export default function EditScreenInfo({ path }: { path: string }) { 9 | return ( 10 | 11 | 12 | 16 | Open up the code for this screen: 17 | 18 | 19 | 23 | {path} 24 | 25 | 26 | 30 | Change any of the text, save the file, and your app will automatically update. 31 | 32 | 33 | 34 | 35 | 36 | 37 | Tap here if your app doesn't automatically update after making changes 38 | 39 | 40 | 41 | 42 | ); 43 | } 44 | 45 | function handleHelpPress() { 46 | WebBrowser.openBrowserAsync( 47 | 'https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet' 48 | ); 49 | } 50 | 51 | const styles = StyleSheet.create({ 52 | getStartedContainer: { 53 | alignItems: 'center', 54 | marginHorizontal: 50, 55 | }, 56 | homeScreenFilename: { 57 | marginVertical: 7, 58 | }, 59 | codeHighlightContainer: { 60 | borderRadius: 3, 61 | paddingHorizontal: 4, 62 | }, 63 | getStartedText: { 64 | fontSize: 17, 65 | lineHeight: 24, 66 | textAlign: 'center', 67 | }, 68 | helpContainer: { 69 | marginTop: 15, 70 | marginHorizontal: 20, 71 | alignItems: 'center', 72 | }, 73 | helpLink: { 74 | paddingVertical: 15, 75 | }, 76 | helpLinkText: { 77 | textAlign: 'center', 78 | }, 79 | }); 80 | -------------------------------------------------------------------------------- /headers/HomeScreenHeader.tsx: -------------------------------------------------------------------------------- 1 | import { Appearance, SafeAreaView, StyleSheet, TouchableOpacity, View } from 'react-native'; 2 | import { Entypo, FontAwesome5, Ionicons } from '@expo/vector-icons'; 3 | import { useEffect, useState } from 'react'; 4 | 5 | import Colors from '../constants/Colors'; 6 | import { Text } from '../components/Themed'; 7 | import moment from 'moment'; 8 | import tw from 'twrnc' 9 | import useColorScheme from '../hooks/useColorScheme'; 10 | 11 | const HomeScreenHeader = () =>{ 12 | const colorScheme = useColorScheme(); 13 | // const [isEnabled, setIsEnabled] = useState(false); 14 | 15 | // const toggleSwitch = () => setIsEnabled(previousState => !previousState); 16 | 17 | // // add this 18 | // useEffect(()=>{ 19 | // const colorScheme = Appearance.getColorScheme(); 20 | // if (colorScheme === 'dark') { 21 | // setIsEnabled(true); // true means dark 22 | // }else{ 23 | // setIsEnabled(false); // false means light 24 | // } 25 | // },[]) 26 | 27 | return ( 28 | 29 | 30 | {'Feb 22, 2022'} 31 | 32 | 33 | {'Accra'}, 34 | {'GH'} 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ); 49 | } 50 | 51 | 52 | export default HomeScreenHeader -------------------------------------------------------------------------------- /navigation/MainTabNavigator.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { AntDesign, FontAwesome, Ionicons } from '@expo/vector-icons'; 4 | import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types'; 5 | import { Text, View } from '../components/Themed'; 6 | 7 | import Colors from '../constants/Colors'; 8 | import HomeScreen from '../screens/HomeScreen'; 9 | import { Pressable } from 'react-native'; 10 | import SearchScreen from '../screens/SearchScreen'; 11 | import TabTwoScreen from '../screens/TabTwoScreen'; 12 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; 13 | import { createStackNavigator } from '@react-navigation/stack'; 14 | import useColorScheme from '../hooks/useColorScheme'; 15 | 16 | const BottomTab = createBottomTabNavigator(); 17 | 18 | export default function BottomTabNavigator() { 19 | const colorScheme = useColorScheme(); 20 | 21 | return ( 22 | 29 | ) => ({ 34 | title: 'Home', 35 | tabBarIcon: ({ color }) => , 36 | })} 37 | /> 38 | , 44 | }} 45 | /> 46 | , 52 | }} 53 | /> 54 | , 60 | }} 61 | 62 | /> 63 | 64 | ); 65 | } 66 | 67 | /** 68 | * You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/ 69 | */ 70 | function TabBarIcon(props: { 71 | name: React.ComponentProps['name']; 72 | color: string; 73 | }) { 74 | return ; 75 | } 76 | 77 | // Each tab has its own navigation stack, you can read more about this pattern here: 78 | // https://reactnavigation.org/docs/tab-based-navigation#a-stack-navigator-for-each-tab 79 | const HomeStack = createStackNavigator(); 80 | const SearchStack= createStackNavigator(); 81 | const ProfileStack = createStackNavigator(); 82 | const StatusStack= createStackNavigator(); 83 | // const CallsStack = createStackNavigator(); 84 | -------------------------------------------------------------------------------- /screens/SearchScreen.tsx: -------------------------------------------------------------------------------- 1 | import { Feather, FontAwesome, FontAwesome5, MaterialCommunityIcons, MaterialIcons } from '@expo/vector-icons'; 2 | import { ImageBackground, SafeAreaView, StyleSheet, View } from 'react-native'; 3 | 4 | import Colors from '../constants/Colors'; 5 | import Icon from '../components/Icon'; 6 | import { RootTabScreenProps } from '../types'; 7 | import SearchBar from '../components/SearchBox'; 8 | import SearchScreenheader from '../headers/SearchScreenheader'; 9 | import { Text } from '../components/Themed'; 10 | import tw from 'twrnc' 11 | import useColorScheme from '../hooks/useColorScheme'; 12 | 13 | const image = {uri: "https://www.globe.gov/o/globe-gov-measurements-portlet/img/map-background.png"} 14 | export default function SearchScreen({ navigation }: RootTabScreenProps<'Search'>) { 15 | const colorScheme = useColorScheme(); 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | Temperature 24 | {/* */} 25 | 26 | 27 | 30 28 | Thunder 29 | 30 | 31 | 32 | Wind Speed 33 | 34 | 35 | 30 36 | m/s 37 | 38 | 39 | 40 | 41 | 42 | More cities 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Min Temperature 51 | 8 km/h 52 | 53 | 54 | Max Temperature 55 | 8 km/h 56 | 57 | 58 | 59 | 60 | 61 | Humidy 62 | 8 km/h 63 | 64 | 65 | Pressure 66 | 8 km/h 67 | 68 | 69 | 70 | 71 | ); 72 | } 73 | 74 | const styles = StyleSheet.create({ 75 | container: { 76 | flex: 1, 77 | justifyContent: 'center', 78 | }, 79 | title: { 80 | fontSize: 20, 81 | fontWeight: 'bold', 82 | }, 83 | separator: { 84 | marginVertical: 30, 85 | height: 1, 86 | width: '80%', 87 | }, 88 | }); 89 | -------------------------------------------------------------------------------- /screens/HomeScreen.tsx: -------------------------------------------------------------------------------- 1 | import { Feather, FontAwesome5 } from '@expo/vector-icons'; 2 | import { Image, ImageBackground, SafeAreaView, StyleSheet, View } from 'react-native'; 3 | 4 | import Colors from '../constants/Colors'; 5 | import HomeScreenHeader from '../headers/HomeScreenHeader'; 6 | import Icon from '../components/Icon'; 7 | import { RootTabScreenProps } from '../types'; 8 | import { Text } from '../components/Themed'; 9 | import tw from 'twrnc' 10 | import useColorScheme from '../hooks/useColorScheme'; 11 | import { useState } from 'react'; 12 | 13 | // import Geolocation from 'react-native-geolocation-service'; 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | // navigator.geolocation = require('@react-native-community/geolocation') 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | const image = {uri: "https://www.globe.gov/o/globe-gov-measurements-portlet/img/map-background.png"} 32 | export default function HomeScreen({ navigation }: RootTabScreenProps<'Home'>) { 33 | // const [currentLongitude, setCurrentLongitude] = useState('') 34 | // const [currentLatitude, setCurrentLatitude] = useState('') 35 | const colorScheme = useColorScheme(); 36 | 37 | // Geolocation.getCurrentPosition( 38 | // //Will give you the current location 39 | // (position) => { 40 | // //getting the Longitude from the location json 41 | // console.log(JSON.stringify(position.coords.longitude)); 42 | // setCurrentLongitude(JSON.stringify(position.coords.longitude)); 43 | 44 | 45 | // //getting the Latitude from the location json 46 | // console.log(JSON.stringify(position.coords.latitude)); 47 | // setCurrentLatitude(JSON.stringify(position.coords.latitude)) 48 | 49 | 50 | // }, (error) => alert(error.message), { 51 | // enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 52 | // } 53 | // ); 54 | 55 | // Geolocation.getCurrentPosition( 56 | // position => { 57 | // const initialPosition = JSON.stringify(position); 58 | // let region = { 59 | // latitude: position.coords.latitude, 60 | // longitude: position.coords.longitude, 61 | // latitudeDelta: 0.0922, 62 | // longitudeDelta: 0.0421, 63 | // } 64 | // // setState({initialPosition:region}); 65 | // console.log("lat "+position.coords.latitude+" longi "+position.coords.longitude) 66 | // console.log("initialPosition") 67 | // // console.log(this.state.initialPosition) 68 | // }, 69 | // error => console.log("Error "+ JSON.stringify(error)), 70 | // {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}, 71 | // ); 72 | // this.watchID = Geolocation.watchPosition(position => { 73 | // const lastPosition = JSON.stringify(position); 74 | // this.setState({lastPosition}); 75 | // }); 76 | 77 | 78 | return ( 79 | 80 | 81 | 82 | 83 | 84 | Thunder 85 | 13 86 | O 87 | 88 | 89 | 90 | 91 | 92 | Humidity 93 | 11 94 | 95 | 96 | 97 | 98 | Wind 99 | 11.6 100 | 101 | 102 | 103 | Pressure 104 | 2.78 105 | 106 | 107 | 108 | ); 109 | } 110 | 111 | const styles = StyleSheet.create({ 112 | container: { 113 | flex: 1, 114 | justifyContent: 'center', 115 | }, 116 | title: { 117 | fontSize: 20, 118 | fontWeight: 'bold', 119 | }, 120 | separator: { 121 | marginVertical: 30, 122 | height: 1, 123 | width: '80%', 124 | }, 125 | }); 126 | --------------------------------------------------------------------------------