Add routes and core views

This commit is contained in:
Paul Frazee 2022-06-09 16:32:03 -05:00
parent d6942bffab
commit fc3b2952bb
16 changed files with 293 additions and 118 deletions

View file

@ -1,52 +1,6 @@
import React, {useState, useEffect} from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import {NavigationContainer} from '@react-navigation/native'
import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack'
import {RootStore, setupState, RootStoreProvider} from './state'
type RootStackParamList = {
Home: undefined
Profile: {name: string}
}
const Stack = createNativeStackNavigator()
const HomeScreen = ({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Native</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
const ProfileScreen = ({
route,
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}
import * as Routes from './routes'
function App() {
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@ -63,16 +17,7 @@ function App() {
return (
<RootStoreProvider value={rootStore}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{title: 'Welcome'}}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
<Routes.Root />
</RootStoreProvider>
)
}

View file

@ -1,52 +1,6 @@
import React, {useState, useEffect} from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import {NavigationContainer} from '@react-navigation/native'
import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack'
import {RootStore, setupState, RootStoreProvider} from './state'
type RootStackParamList = {
Home: undefined
Profile: {name: string}
}
const Stack = createNativeStackNavigator()
const HomeScreen = ({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Web</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
const ProfileScreen = ({
route,
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}
import * as Routes from './routes'
function App() {
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@ -63,16 +17,7 @@ function App() {
return (
<RootStoreProvider value={rootStore}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{title: 'Welcome'}}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
<Routes.Root />
</RootStoreProvider>
)
}

72
src/routes/index.tsx Normal file
View file

@ -0,0 +1,72 @@
import React from 'react'
import {Text} from 'react-native'
import {
NavigationContainer,
LinkingOptions,
RouteProp,
ParamListBase,
} from '@react-navigation/native'
import {createNativeStackNavigator} from '@react-navigation/native-stack'
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import type {RootStackParamList} from './types'
import {Home} from '../screens/Home'
import {Search} from '../screens/Search'
import {Notifications} from '../screens/Notifications'
import {Menu} from '../screens/Menu'
import {Profile} from '../screens/Profile'
import {NotFound} from '../screens/NotFound'
const linking: LinkingOptions<RootStackParamList> = {
prefixes: [
'http://localhost:3000', // local dev
],
config: {
screens: {
Primary: {
screens: {
Home: '',
Search: 'search',
Notifications: 'notifications',
Menu: 'menu',
},
},
Profile: 'profile/:name',
NotFound: '*',
},
},
}
export const RootStack = createNativeStackNavigator()
export const PrimaryTab = createBottomTabNavigator()
const tabBarScreenOptions = ({
route,
}: {
route: RouteProp<ParamListBase, string>
}) => ({
tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => {
// TODO: icons
return <Text>{route.name.at(0)}</Text>
},
})
const Primary = () => (
<PrimaryTab.Navigator
screenOptions={tabBarScreenOptions}
initialRouteName="Home">
<PrimaryTab.Screen name="Home" component={Home} />
<PrimaryTab.Screen name="Search" component={Search} />
<PrimaryTab.Screen name="Notifications" component={Notifications} />
<PrimaryTab.Screen name="Menu" component={Menu} />
</PrimaryTab.Navigator>
)
export const Root = () => (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
<RootStack.Navigator initialRouteName="Primary">
<RootStack.Screen name="Primary" component={Primary} />
<RootStack.Screen name="Profile" component={Profile} />
<RootStack.Screen name="NotFound" component={NotFound} />
</RootStack.Navigator>
</NavigationContainer>
)

24
src/routes/types.ts Normal file
View file

@ -0,0 +1,24 @@
import type {NavigatorScreenParams} from '@react-navigation/native'
import type {CompositeScreenProps} from '@react-navigation/native'
import type {StackScreenProps} from '@react-navigation/stack'
import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs'
export type RootStackParamList = {
Primary: undefined
Profile: {name: string}
NotFound: undefined
}
export type RootStackScreenProps<T extends keyof RootStackParamList> =
StackScreenProps<RootStackParamList, T>
export type PrimaryTabParamList = {
Home: NavigatorScreenParams<RootStackParamList>
Search: undefined
Notifications: undefined
Menu: undefined
}
export type PrimaryTabScreenProps<T extends keyof PrimaryTabParamList> =
CompositeScreenProps<
BottomTabScreenProps<PrimaryTabParamList, T>,
RootStackScreenProps<keyof RootStackParamList>
>

17
src/screens/Home.tsx Normal file
View file

@ -0,0 +1,17 @@
import React from 'react'
import {Text, Button, View, SafeAreaView} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => {
return (
<SafeAreaView style={{flex: 1}}>
<View style={{flex: 1}}>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</SafeAreaView>
)
}

19
src/screens/Menu.tsx Normal file
View file

@ -0,0 +1,19 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Menu = ({navigation}: PrimaryTabScreenProps<'Menu'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}

27
src/screens/NotFound.tsx Normal file
View file

@ -0,0 +1,27 @@
import React from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import type {RootStackScreenProps} from '../routes/types'
export const NotFound = ({navigation}: RootStackScreenProps<'NotFound'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Page not found</Text>
<Button title="Home" onPress={() => navigation.navigate('Primary')} />
</View>
</ScrollView>
</SafeAreaView>
)
}

View file

@ -0,0 +1,21 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Notifications = ({
navigation,
}: PrimaryTabScreenProps<'Notifications'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}

7
src/screens/Profile.tsx Normal file
View file

@ -0,0 +1,7 @@
import React from 'react'
import {Text} from 'react-native'
import type {RootStackScreenProps} from '../routes/types'
export const Profile = ({route}: RootStackScreenProps<'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}

19
src/screens/Search.tsx Normal file
View file

@ -0,0 +1,19 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Search = ({navigation}: PrimaryTabScreenProps<'Search'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}