mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-09-30 15:53:15 +00:00
Keychain token storage, Axios client with async token injection, Cognito PKCE auth via react-native-app-auth, Redux auth slice, TanStack Query config, offline draft queue with NetInfo auto-submit, and SHOC theme.
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { Provider as ReduxProvider, useDispatch } from 'react-redux';
|
|
import { PaperProvider } from 'react-native-paper';
|
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
import NetInfo from '@react-native-community/netinfo';
|
|
import { Alert } from 'react-native';
|
|
|
|
import { store } from './store';
|
|
import { theme } from './theme';
|
|
import { queryClient } from './lib/queryClient';
|
|
import { RootNavigator } from './navigation/RootNavigator';
|
|
import { tokenStorage, userStorage } from './lib/storage';
|
|
import { setUser, setLoading } from './store/slices/authSlice';
|
|
import { processOfflineQueue } from './hooks/useOfflineDraft';
|
|
import { proposalsApi, CreateProposalRequest } from './lib/api/proposals';
|
|
|
|
function AuthBootstrap({ children }: { children: React.ReactNode }) {
|
|
const dispatch = useDispatch();
|
|
|
|
useEffect(() => {
|
|
(async () => {
|
|
try {
|
|
const tokens = await tokenStorage.get();
|
|
const user = await userStorage.get();
|
|
|
|
if (tokens && user && new Date(tokens.expiresAt) > new Date()) {
|
|
dispatch(setUser(user));
|
|
} else {
|
|
if (tokens) await tokenStorage.clear();
|
|
dispatch(setLoading(false));
|
|
}
|
|
} catch {
|
|
dispatch(setLoading(false));
|
|
}
|
|
})();
|
|
}, [dispatch]);
|
|
|
|
useEffect(() => {
|
|
const unsubscribe = NetInfo.addEventListener((state) => {
|
|
if (state.isConnected) {
|
|
processOfflineQueue((data) =>
|
|
proposalsApi.create(data as CreateProposalRequest),
|
|
).then((count) => {
|
|
if (count > 0) {
|
|
Alert.alert(
|
|
'Synced',
|
|
`${count} offline proposal${count > 1 ? 's' : ''} submitted.`,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
return unsubscribe;
|
|
}, []);
|
|
|
|
return <>{children}</>;
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<ReduxProvider store={store}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<PaperProvider theme={theme}>
|
|
<SafeAreaProvider>
|
|
<AuthBootstrap>
|
|
<RootNavigator />
|
|
</AuthBootstrap>
|
|
</SafeAreaProvider>
|
|
</PaperProvider>
|
|
</QueryClientProvider>
|
|
</ReduxProvider>
|
|
);
|
|
}
|