add tab bar to separate profile and home screens

This commit is contained in:
Joseph D'Souza 2026-02-08 04:19:49 +01:00
parent 012d84b369
commit e51b284181
5 changed files with 130 additions and 30 deletions

View File

@ -1,14 +1,16 @@
{
"name": "casadoc-mobile",
"version": "1.0.0",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "casadoc-mobile",
"version": "1.0.0",
"version": "0.0.1",
"dependencies": {
"@expo/vector-icons": "^15.0.3",
"@react-native-async-storage/async-storage": "2.2.0",
"@react-navigation/bottom-tabs": "^7.12.0",
"@react-navigation/native": "^7.1.28",
"@react-navigation/native-stack": "^7.12.0",
"babel-preset-expo": "^54.0.10",
@ -1858,6 +1860,17 @@
"integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
"license": "MIT"
},
"node_modules/@expo/vector-icons": {
"version": "15.0.3",
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz",
"integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==",
"license": "MIT",
"peerDependencies": {
"expo-font": ">=14.0.4",
"react": "*",
"react-native": "*"
}
},
"node_modules/@expo/ws-tunnel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz",
@ -2404,6 +2417,24 @@
"integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==",
"license": "MIT"
},
"node_modules/@react-navigation/bottom-tabs": {
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-7.12.0.tgz",
"integrity": "sha512-/GtOfVWRligHG0mvX39I1FGdUWeWl0GVF2okEziQSQj0bOTrLIt7y44C3r/aCLkEpTVltCPGM3swqGTH3UfRCw==",
"license": "MIT",
"dependencies": {
"@react-navigation/elements": "^2.9.5",
"color": "^4.2.3",
"sf-symbols-typescript": "^2.1.0"
},
"peerDependencies": {
"@react-navigation/native": "^7.1.28",
"react": ">= 18.2.0",
"react-native": "*",
"react-native-safe-area-context": ">= 4.0.0",
"react-native-screens": ">= 4.0.0"
}
},
"node_modules/@react-navigation/core": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.14.0.tgz",
@ -3911,6 +3942,20 @@
"expo": "*"
}
},
"node_modules/expo-font": {
"version": "14.0.11",
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
"integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
"license": "MIT",
"dependencies": {
"fontfaceobserver": "^2.1.0"
},
"peerDependencies": {
"expo": "*",
"react": "*",
"react-native": "*"
}
},
"node_modules/expo-linking": {
"version": "8.0.11",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.11.tgz",
@ -4156,17 +4201,6 @@
}
}
},
"node_modules/expo/node_modules/@expo/vector-icons": {
"version": "15.0.3",
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz",
"integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==",
"license": "MIT",
"peerDependencies": {
"expo-font": ">=14.0.4",
"react": "*",
"react-native": "*"
}
},
"node_modules/expo/node_modules/ci-info": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
@ -4221,20 +4255,6 @@
"react-native": "*"
}
},
"node_modules/expo/node_modules/expo-font": {
"version": "14.0.11",
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
"integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
"license": "MIT",
"dependencies": {
"fontfaceobserver": "^2.1.0"
},
"peerDependencies": {
"expo": "*",
"react": "*",
"react-native": "*"
}
},
"node_modules/expo/node_modules/expo-keep-awake": {
"version": "15.0.8",
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.8.tgz",

View File

@ -11,7 +11,9 @@
"web": "expo start --web"
},
"dependencies": {
"@expo/vector-icons": "^15.0.3",
"@react-native-async-storage/async-storage": "2.2.0",
"@react-navigation/bottom-tabs": "^7.12.0",
"@react-navigation/native": "^7.1.28",
"@react-navigation/native-stack": "^7.12.0",
"babel-preset-expo": "^54.0.10",

View File

@ -3,14 +3,15 @@ import { View, ActivityIndicator } from 'react-native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import AuthScreen from '../screens/AuthScreen';
import HomeScreen from '../screens/HomeScreen';
import TabNavigator from './TabNavigator';
import ForgotPasswordScreen from '../screens/ForgotPasswordScreen';
import { useAuthStore } from '../store/useAuthStore';
// Define the types for your stack
export type RootStackParamList = {
Auth: undefined;
ForgotPassword: undefined;
Home: undefined;
Home: undefined; // This is now a nested navigator
Main: undefined; // The tab navigator 'Main'
};
const Stack = createNativeStackNavigator<RootStackParamList>();
@ -31,7 +32,7 @@ export default function AppNavigator() {
<Stack.Navigator screenOptions={{ headerShown: false }}>
{user ? (
// Screens for logged-in users
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Main" component={TabNavigator} options={{ headerShown: false }} />
) : (
// Screens for logged-out users
<Stack.Group>

View File

@ -0,0 +1,59 @@
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { useColorScheme } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import HomeScreen from '../screens/HomeScreen';
import ProfileScreen from '../screens/ProfileScreen';
import { COLORS } from '../theme/colors';
const Tab = createBottomTabNavigator();
export default function TabNavigator() {
const colorScheme = useColorScheme();
const isDark = colorScheme === 'dark';
const themeColors = isDark ? COLORS.DARK : COLORS.LIGHT;
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return <Ionicons name={iconName as any} size={20} color={color} />;
},
tabBarActiveTintColor: themeColors.brand,
tabBarInactiveTintColor: isDark ? '#a0aec0' : 'gray',
tabBarStyle: {
backgroundColor: themeColors.card,
borderTopColor: isDark ? '#2d3748' : '#e2e8f0',
height: 60
},
headerStyle: {
backgroundColor: themeColors.card,
},
headerTitleStyle: {
color: themeColors.text,
fontSize: 17,
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{
tabBarItemStyle: {
borderLeftWidth: 1.5,
borderLeftColor: isDark ? '#4A5568' : '#E2E8F0',
}
}}
/>
</Tab.Navigator>
);
}

View File

@ -0,0 +1,18 @@
import React from 'react';
import { View, Text, useColorScheme } from 'react-native';
import { getThemeStyles, commonStyles } from '../theme/styles';
export default function ProfileScreen() {
const colorScheme = useColorScheme();
const isDark = colorScheme === 'dark';
const themeStyles = getThemeStyles(isDark);
return (
<View style={themeStyles.container}>
<View style={commonStyles.centered}>
<Text style={themeStyles.headerTitle}>Profile Screen</Text>
<Text style={themeStyles.subtitle}>User profile details will go here.</Text>
</View>
</View>
);
}