mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-10-02 23:53:18 +00:00
161 lines
4.9 KiB
TypeScript
161 lines
4.9 KiB
TypeScript
|
|
import React from 'react';
|
||
|
|
import { ActivityIndicator, View, StyleSheet } from 'react-native';
|
||
|
|
import { NavigationContainer } from '@react-navigation/native';
|
||
|
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||
|
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||
|
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||
|
|
import { useSelector } from 'react-redux';
|
||
|
|
import {
|
||
|
|
selectIsAuthenticated,
|
||
|
|
selectAuthLoading,
|
||
|
|
selectUser,
|
||
|
|
} from '../store/slices/authSlice';
|
||
|
|
import type {
|
||
|
|
RootStackParamList,
|
||
|
|
MainTabParamList,
|
||
|
|
ProposalsStackParamList,
|
||
|
|
} from './types';
|
||
|
|
|
||
|
|
import { LoginScreen } from '../screens/auth/LoginScreen';
|
||
|
|
import { DashboardScreen } from '../screens/dispatcher/DashboardScreen';
|
||
|
|
import { AdminDashboardScreen } from '../screens/admin/AdminDashboardScreen';
|
||
|
|
import { NewProposalScreen } from '../screens/dispatcher/NewProposalScreen';
|
||
|
|
import { ProposalDetailScreen } from '../screens/dispatcher/ProposalDetailScreen';
|
||
|
|
import { ProposalQueueScreen } from '../screens/admin/ProposalQueueScreen';
|
||
|
|
import { ProposalWorkspaceScreen } from '../screens/admin/ProposalWorkspaceScreen';
|
||
|
|
import { LineItemEditScreen } from '../screens/admin/LineItemEditScreen';
|
||
|
|
import { SettingsScreen } from '../screens/SettingsScreen';
|
||
|
|
|
||
|
|
const RootStack = createNativeStackNavigator<RootStackParamList>();
|
||
|
|
const Tab = createBottomTabNavigator<MainTabParamList>();
|
||
|
|
const ProposalsStack = createNativeStackNavigator<ProposalsStackParamList>();
|
||
|
|
|
||
|
|
function ProposalsNavigator() {
|
||
|
|
const user = useSelector(selectUser);
|
||
|
|
const isAdmin = user?.role === 'Admin' || user?.role === 'SysAdmin';
|
||
|
|
|
||
|
|
return (
|
||
|
|
<ProposalsStack.Navigator screenOptions={{ headerShown: true }}>
|
||
|
|
{isAdmin ? (
|
||
|
|
<>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="ProposalList"
|
||
|
|
component={ProposalQueueScreen}
|
||
|
|
options={{ title: 'Proposal Queue' }}
|
||
|
|
/>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="ProposalWorkspace"
|
||
|
|
component={ProposalWorkspaceScreen}
|
||
|
|
options={{ title: 'Proposal' }}
|
||
|
|
/>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="LineItemEdit"
|
||
|
|
component={LineItemEditScreen}
|
||
|
|
options={{ title: 'Edit Line Item' }}
|
||
|
|
/>
|
||
|
|
</>
|
||
|
|
) : (
|
||
|
|
<>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="ProposalList"
|
||
|
|
component={ProposalQueueScreen}
|
||
|
|
options={{ title: 'My Proposals' }}
|
||
|
|
/>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="NewProposal"
|
||
|
|
component={NewProposalScreen}
|
||
|
|
options={{ title: 'New Proposal' }}
|
||
|
|
/>
|
||
|
|
<ProposalsStack.Screen
|
||
|
|
name="ProposalDetail"
|
||
|
|
component={ProposalDetailScreen}
|
||
|
|
options={{ title: 'Proposal' }}
|
||
|
|
/>
|
||
|
|
</>
|
||
|
|
)}
|
||
|
|
</ProposalsStack.Navigator>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function DashboardRouter() {
|
||
|
|
const user = useSelector(selectUser);
|
||
|
|
const isAdmin = user?.role === 'Admin' || user?.role === 'SysAdmin';
|
||
|
|
return isAdmin ? <AdminDashboardScreen /> : <DashboardScreen />;
|
||
|
|
}
|
||
|
|
|
||
|
|
function MainTabs() {
|
||
|
|
return (
|
||
|
|
<Tab.Navigator
|
||
|
|
screenOptions={({ route }) => ({
|
||
|
|
headerShown: route.name === 'DashboardTab',
|
||
|
|
tabBarIcon: ({ color, size }) => {
|
||
|
|
const icons: Record<string, string> = {
|
||
|
|
DashboardTab: 'view-dashboard',
|
||
|
|
ProposalsTab: 'file-document-outline',
|
||
|
|
SettingsTab: 'cog-outline',
|
||
|
|
};
|
||
|
|
return (
|
||
|
|
<Icon
|
||
|
|
name={icons[route.name] || 'circle'}
|
||
|
|
size={size}
|
||
|
|
color={color}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
},
|
||
|
|
tabBarActiveTintColor: '#1565C0',
|
||
|
|
tabBarInactiveTintColor: '#757575',
|
||
|
|
})}
|
||
|
|
>
|
||
|
|
<Tab.Screen
|
||
|
|
name="DashboardTab"
|
||
|
|
component={DashboardRouter}
|
||
|
|
options={{ title: 'Dashboard' }}
|
||
|
|
/>
|
||
|
|
<Tab.Screen
|
||
|
|
name="ProposalsTab"
|
||
|
|
component={ProposalsNavigator}
|
||
|
|
options={{ headerShown: false, title: 'Proposals' }}
|
||
|
|
/>
|
||
|
|
<Tab.Screen
|
||
|
|
name="SettingsTab"
|
||
|
|
component={SettingsScreen}
|
||
|
|
options={{ title: 'Settings' }}
|
||
|
|
/>
|
||
|
|
</Tab.Navigator>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function RootNavigator() {
|
||
|
|
const isAuthenticated = useSelector(selectIsAuthenticated);
|
||
|
|
const loading = useSelector(selectAuthLoading);
|
||
|
|
|
||
|
|
if (loading) {
|
||
|
|
return (
|
||
|
|
<View style={styles.loading}>
|
||
|
|
<ActivityIndicator size="large" color="#1565C0" />
|
||
|
|
</View>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<NavigationContainer>
|
||
|
|
<RootStack.Navigator screenOptions={{ headerShown: false }}>
|
||
|
|
{isAuthenticated ? (
|
||
|
|
<RootStack.Screen name="Main" component={MainTabs} />
|
||
|
|
) : (
|
||
|
|
<RootStack.Screen name="Auth" component={LoginScreen} />
|
||
|
|
)}
|
||
|
|
</RootStack.Navigator>
|
||
|
|
</NavigationContainer>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const styles = StyleSheet.create({
|
||
|
|
loading: {
|
||
|
|
flex: 1,
|
||
|
|
justifyContent: 'center',
|
||
|
|
alignItems: 'center',
|
||
|
|
backgroundColor: '#FAFAFA',
|
||
|
|
},
|
||
|
|
});
|