diff --git a/TaskTerriers/App.tsx b/TaskTerriers/App.tsx index a2dcedc..0f0606e 100644 --- a/TaskTerriers/App.tsx +++ b/TaskTerriers/App.tsx @@ -3,8 +3,10 @@ import { StatusBar } from 'expo-status-bar' import { Col, Span } from './src/StyleToProps' import * as SplashScreen from 'expo-splash-screen' import useFonts from './hooks/useFonts' -import { BottomTabs } from './navigation/BottomTabNavigator' +import { BottomTabNavigation } from './src/navigation/BottomTabNavigator' import { NavigationContainer } from '@react-navigation/native' +import RootStack from './src/navigation/RootStack' +import { TaskTerriersNavigationRef } from './src/navigation/NavigationModule' export default function App() { const [IsReady, SetIsReady] = useState(false) @@ -50,8 +52,8 @@ export default function App() { return ( - - + + ) diff --git a/TaskTerriers/navigation/BottomTabNavigator.tsx b/TaskTerriers/navigation/BottomTabNavigator.tsx deleted file mode 100644 index 62ea832..0000000 --- a/TaskTerriers/navigation/BottomTabNavigator.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' -import RequestsTab from '../src/Screens/RequestsTab' -import ServicesTab from '../src/Screens/ServicesTab' -import MessagesTab from '../src/Screens/MessagesTab' -import SettingsTab from '../src/Screens/SettingsTab' -import { Col, Row, Span } from '../src/StyleToProps' -import { Ionicons } from '@expo/vector-icons' -import { BUColor, NeutralColor } from '../src/Libs/Colors' -import { TouchableOpacity } from 'react-native' -import { toStyle } from '../src/StyleToProps/withStyleProps' -import { Style } from '../src/StyleToProps/styleProps' -import { deviceInfo } from '../src/utilities/deviceInfo' - -const Tab = createBottomTabNavigator() - -export const BottomTabs = () => { - return ( - } - screenOptions={() => { - return { - tabBarShowIcon: true, - tabBarShowLabel: false, - headerShown: false, - } - }}> - {/* */} - - - - - ) -} - -const CustomTabBarContent = ({ state, descriptors, navigation }) => { - return ( - - {state.routes.map((route, index) => { - const isFocused = state.index === index - const { options } = descriptors[route.key] - const onPress = () => { - const event = navigation.emit({ - type: 'tabPress', - target: route.key, - canPreventDefault: true, - }) - - if (!isFocused && !event.defaultPrevented) { - navigation.navigate(route.name, route.params) - } - } - return ( - )}> - - - - {route.name} - - - - ) - })} - - ) -} - -const LocalTabBarIcon = (props: { focused: boolean; name: React.ComponentProps['name'] }) => { - switch (props.name) { - case 'Requests': - if (props.focused) return - else return - case 'Services': - if (props.focused) return - else return - case 'Messages': - if (props.focused) return - else return - case 'Settings': - if (props.focused) return - else return - default: - return null - } -} diff --git a/TaskTerriers/package.json b/TaskTerriers/package.json index 2f62e32..0717014 100644 --- a/TaskTerriers/package.json +++ b/TaskTerriers/package.json @@ -15,10 +15,12 @@ "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/core": "^6.4.10", "@react-navigation/native": "^6.1.9", + "@react-navigation/stack": "^6.3.20", "@types/react": "~18.2.14", "eslint-config-prettier": "^9.0.0", "expo": "~49.0.15", "expo-image": "^1.5.1", + "expo-navigation-bar": "^2.5.0", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", "prettier": "^3.1.0", diff --git a/TaskTerriers/src/Screens/ServiceDetailScreen.tsx b/TaskTerriers/src/Screens/ServiceDetailScreen.tsx new file mode 100644 index 0000000..1e1a60e --- /dev/null +++ b/TaskTerriers/src/Screens/ServiceDetailScreen.tsx @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from 'react' +import { SafeAreaView, View, StyleSheet, Text, TouchableOpacity } from 'react-native' +import NavigationBar from '../components/NavigationBar' +import { IconNames } from '../components/types' +import { TaskTerriersNavigationModule } from '../navigation/NavigationModule' + +interface Props { } + + +const ServiceDetailScreen = ({ navigation, route }) => { + + /********* + * recoil + *********/ + + /************************** + * props, navigation prams + **************************/ + + /************* + * state, ref + *************/ + + const [isRendering, setIsRendering] = useState(true) + + /************** + * life cycles + **************/ + + useEffect(() => { + // ComponentDidMount + + // setIsRendering(false) + return () => { + // ComponentWillUnmount + } + }, []) + + /************ + * functions + ************/ + + const onPressReturn = () => { + TaskTerriersNavigationModule.goBack() + } + + /********* + * render + *********/ + + const renderNavBar = () => { + return + } + + /*********** + * render() + ***********/ + + return ( + + {renderNavBar()} + + ) + +} + +export default ServiceDetailScreen diff --git a/TaskTerriers/src/Screens/ServicesTab.tsx b/TaskTerriers/src/Screens/ServicesTab.tsx index adced86..968fbda 100644 --- a/TaskTerriers/src/Screens/ServicesTab.tsx +++ b/TaskTerriers/src/Screens/ServicesTab.tsx @@ -5,10 +5,13 @@ import { Col } from '../StyleToProps/Col' import { Span } from '../StyleToProps' import NavigationBar from '../components/NavigationBar' import { IconNames } from '../components/types' +import { UniversalButton } from '../components/Buttons' +import { TaskTerriersNavigationModule } from '../navigation/NavigationModule' +import { Root } from '../navigation/type' -interface Props {} +interface Props { } -const ServicesTab = ({ navigation, route }) => { +const ServicesTab = ({ route }) => { /********* * recoil *********/ @@ -40,24 +43,36 @@ const ServicesTab = ({ navigation, route }) => { * functions ************/ + const onPressButton = () => { + return ( + TaskTerriersNavigationModule.navigate('ServiceDetailScreen') + ) + } + /********* * render *********/ - // if (isRendering === true) { - // return null - // } + const renderNavigationBar = () => { + return + } + + const renderButton = () => { + console.log('Clicked button') + return + } /*********** * render() ***********/ return ( - - - - this is the ServicesTab + + {renderNavigationBar()} + + {renderButton()} + ) } diff --git a/TaskTerriers/src/Views/TaskTerriersSafeAreaView.tsx b/TaskTerriers/src/Views/TaskTerriersSafeAreaView.tsx index 3397b54..5b9f26d 100644 --- a/TaskTerriers/src/Views/TaskTerriersSafeAreaView.tsx +++ b/TaskTerriers/src/Views/TaskTerriersSafeAreaView.tsx @@ -63,7 +63,7 @@ const TaskTerriersSafeAreaView: React.FC = (props: Props) => { style={[ { flex: 1, - backgroundColor: props?.backgroundColor || NeutralColor['neutral-100'], + backgroundColor: props?.backgroundColor || NeutralColor['neutral-80'], paddingBottom: props.hasBottomSpace ? bottom : undefined, }, props.style, diff --git a/TaskTerriers/src/components/Divider/Divider.tsx b/TaskTerriers/src/components/Divider/Divider.tsx index 049b418..c4cc207 100644 --- a/TaskTerriers/src/components/Divider/Divider.tsx +++ b/TaskTerriers/src/components/Divider/Divider.tsx @@ -14,7 +14,7 @@ const Divider: React.FC = ({ color, margin }) => { return { marginLeft: 16, marginRight: 16 } } - return + return } export { Divider } diff --git a/TaskTerriers/src/components/NavigationBar.tsx b/TaskTerriers/src/components/NavigationBar.tsx index 2294339..4d130f2 100644 --- a/TaskTerriers/src/components/NavigationBar.tsx +++ b/TaskTerriers/src/components/NavigationBar.tsx @@ -10,10 +10,11 @@ interface NavigationBarProps { title: TypographyType.Value hasDivider?: boolean iconName?: IconName.Value + iconAction?: () => void backgroundColor?: UniversalColorType.Value } -const NavigationBar: React.FC = ({ title, hasDivider, iconName, backgroundColor }) => { +const NavigationBar: React.FC = ({ title, hasDivider, iconName, backgroundColor, iconAction }) => { /************************** * props, navigation prams **************************/ @@ -44,6 +45,9 @@ const NavigationBar: React.FC = ({ title, hasDivider, iconNa if (backgroundColor) return backgroundColor return '#ffffff' } + const getHeight = () => { + return 54 + } /********* * render @@ -51,7 +55,16 @@ const NavigationBar: React.FC = ({ title, hasDivider, iconNa const renderIcon = () => { if (!iconName) return null - return + if (iconAction) { + return ( + + + + ) + + } else { + return + } } const renderTitle = () => { @@ -62,8 +75,8 @@ const NavigationBar: React.FC = ({ title, hasDivider, iconNa ) } - const getHeight = () => { - return 54 + const renderDivider = () => { + if (hasDivider) return } /*********** @@ -71,10 +84,13 @@ const NavigationBar: React.FC = ({ title, hasDivider, iconNa ***********/ return ( - - {renderIcon()} - {renderTitle()} - + <> + + {renderIcon()} + {renderTitle()} + + {renderDivider()} + ) } diff --git a/TaskTerriers/src/components/types.tsx b/TaskTerriers/src/components/types.tsx index 7943cef..40b7c3b 100644 --- a/TaskTerriers/src/components/types.tsx +++ b/TaskTerriers/src/components/types.tsx @@ -24,6 +24,7 @@ export const IconNames = { MessageOutline: 'chatbox-ellipses-outline', Setting: 'settings-sharp', SettingOutline: 'settings-outline', + Return: 'chevron-back' } as const declare namespace IconName { @@ -149,7 +150,7 @@ const ListItemPaddingVerticalMap: Record = { xxlarge: 0, xxxlarge: 0, } as const -declare namespace ListItemType {} +declare namespace ListItemType { } declare namespace TabBarType { type Value = Attr | string diff --git a/TaskTerriers/src/navigation/AuthStack.tsx b/TaskTerriers/src/navigation/AuthStack.tsx new file mode 100644 index 0000000..e69de29 diff --git a/TaskTerriers/src/navigation/BottomTabNavigator.tsx b/TaskTerriers/src/navigation/BottomTabNavigator.tsx new file mode 100644 index 0000000..22058d1 --- /dev/null +++ b/TaskTerriers/src/navigation/BottomTabNavigator.tsx @@ -0,0 +1,90 @@ +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' +import RequestsTab from '../Screens/RequestsTab' +import ServicesTab from '../Screens/ServicesTab' +import MessagesTab from '../Screens/MessagesTab' +import SettingsTab from '../Screens/SettingsTab' +import { Col, Row, Span } from '../StyleToProps' +import { Ionicons } from '@expo/vector-icons' +import { BUColor, NeutralColor } from '../Libs/Colors' +import { TouchableOpacity } from 'react-native' +import { toStyle } from '../StyleToProps/withStyleProps' +import { Style } from '../StyleToProps/styleProps' +import { deviceInfo } from '../utilities/deviceInfo' + +const Tab = createBottomTabNavigator() + +export const BottomTabNavigation = () => { + return ( + } + screenOptions={() => { + return { + tabBarShowIcon: true, + tabBarShowLabel: false, + headerShown: false, + } + }}> + {/* */} + + + + + ) +} + +const CustomTabBarContent = ({ state, descriptors, navigation }) => { + return ( + + {state.routes.map((route, index) => { + const isFocused = state.index === index + const { options } = descriptors[route.key] + const onPress = () => { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }) + + if (!isFocused && !event.defaultPrevented) { + navigation.navigate(route.name, route.params) + } + } + return ( + )}> + + + + {route.name} + + + + ) + })} + + ) +} + +const LocalTabBarIcon = (props: { focused: boolean; name: React.ComponentProps['name'] }) => { + switch (props.name) { + case 'Requests': + if (props.focused) return + else return + case 'Services': + if (props.focused) return + else return + case 'Messages': + if (props.focused) return + else return + case 'Settings': + if (props.focused) return + else return + default: + return null + } +} diff --git a/TaskTerriers/src/navigation/NavigationModule.ts b/TaskTerriers/src/navigation/NavigationModule.ts new file mode 100644 index 0000000..6132fc7 --- /dev/null +++ b/TaskTerriers/src/navigation/NavigationModule.ts @@ -0,0 +1,55 @@ +import React from 'react' + +import { NavigationContainerRef, StackActions } from '@react-navigation/native' +import { NavigationState, PartialState } from '@react-navigation/native' +import { RootStackParamList } from './type' + +export const TaskTerriersNavigationRef: React.RefObject> | undefined = React.createRef() + +export function navigate(screenName: string, params?: any) { + console.log(' TaskTerriersNavigationRef: ', TaskTerriersNavigationRef) + // @ts-ignore + TaskTerriersNavigationRef.current?.navigate(screenName, params) +} + +export function push(screenName: string, params?: any) { + TaskTerriersNavigationRef.current.dispatch(StackActions.push(screenName, params)) +} + +export function pop() { + TaskTerriersNavigationRef.current.dispatch(StackActions.pop()) +} + +export function goBack() { + TaskTerriersNavigationRef.current?.goBack() +} + +export function popToTop() { + const targetScreen = TaskTerriersNavigationRef.current.getRootState?.()?.routes?.[0]?.name + if (!targetScreen) return + // @ts-ignore + TaskTerriersNavigationRef.current.navigate(targetScreen) +} + +export function replace(screenName: string, params?: any) { + TaskTerriersNavigationRef.current.dispatch(StackActions.replace(screenName, params)) +} + +export async function reset(state: PartialState | NavigationState) { + TaskTerriersNavigationRef.current?.reset(state) +} + +export function getCurrentScreenName() { + return TaskTerriersNavigationRef.current?.getCurrentRoute()?.name || '' +} + +export const TaskTerriersNavigationModule = { + navigate, + push, + pop, + goBack, + popToTop, + replace, + reset, + getCurrentScreenName, +} diff --git a/TaskTerriers/src/navigation/RootStack.tsx b/TaskTerriers/src/navigation/RootStack.tsx new file mode 100644 index 0000000..5e6ff9d --- /dev/null +++ b/TaskTerriers/src/navigation/RootStack.tsx @@ -0,0 +1,26 @@ +import React from 'react' +import { createStackNavigator } from '@react-navigation/stack'; +import { RootStackParamList } from './type'; +import NavigationBar from '../components/NavigationBar'; +import { BottomTabNavigation } from './BottomTabNavigator'; +import StackGroup from './StackGroup'; + +const Stack = createStackNavigator() + +const RootStack = () => { + return ( + + + {StackGroup()} + + + ) +} +export default RootStack \ No newline at end of file diff --git a/TaskTerriers/src/navigation/StackGroup.tsx b/TaskTerriers/src/navigation/StackGroup.tsx new file mode 100644 index 0000000..5d1466e --- /dev/null +++ b/TaskTerriers/src/navigation/StackGroup.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import { RootStackParamList } from './type' +import 'react-native-gesture-handler'; +import { createStackNavigator } from '@react-navigation/stack'; +import ServiceDetailScreen from '../Screens/ServiceDetailScreen'; + + +const Stack = createStackNavigator() +const StackGroup = () => { + return ( + + {/* Services Tab */} + + + ) +} + +export default StackGroup diff --git a/TaskTerriers/src/navigation/type.ts b/TaskTerriers/src/navigation/type.ts new file mode 100644 index 0000000..9a54aaf --- /dev/null +++ b/TaskTerriers/src/navigation/type.ts @@ -0,0 +1,19 @@ +type ValueType = string | number | boolean + +export type Union> = T extends ReadonlyArray + ? T[number] + : T extends { [key: string]: infer U } + ? U + : never + +export const Root = { + BottomTabNavigation: 'BottomTabNavigation', + ServiceDetailScreen: 'ServiceDetailScreen', +} as const + +export type Root = Union + +export type RootStackParamList = { + [Root.BottomTabNavigation]: object + [Root.ServiceDetailScreen]: object +} diff --git a/TaskTerriers/yarn.lock b/TaskTerriers/yarn.lock index e23c603..b22cab7 100644 --- a/TaskTerriers/yarn.lock +++ b/TaskTerriers/yarn.lock @@ -1915,6 +1915,15 @@ dependencies: nanoid "^3.1.23" +"@react-navigation/stack@^6.3.20": + version "6.3.20" + resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.3.20.tgz#8eec944888f317bb1ba1ff30e7f513806bea16c2" + integrity sha512-vE6mgZzOgoa5Uy7ayT97Cj+ZIK7DK+JBYVuKUViILlWZy6IWK7HFDuqoChSbZ1ajTIfAxj/acVGg1jkbAKsToA== + dependencies: + "@react-navigation/elements" "^1.3.21" + color "^4.2.3" + warn-once "^0.1.0" + "@segment/loosely-validate-event@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681" @@ -3243,6 +3252,14 @@ expo-modules-core@1.5.11: compare-versions "^3.4.0" invariant "^2.2.4" +expo-navigation-bar@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/expo-navigation-bar/-/expo-navigation-bar-2.5.0.tgz#4573eeae5a17afa0fca85fa17d4873af096257c0" + integrity sha512-cKwBNh692qBuly7fKeM+XBQSvsOf53CGmmyUNRTuQN7YWOEv9HSFzacPncr/Ne1jR2odML3jGgMO5fA+LnRGGw== + dependencies: + "@react-native/normalize-color" "^2.0.0" + debug "^4.3.2" + expo-splash-screen@~0.20.5: version "0.20.5" resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.20.5.tgz#ebeba3e3977606830f74f506ab2cc25042bb7efd"