Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 5 additions & 15 deletions Client/watchout/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import '@expo/metro-runtime';
import { StatusBar } from 'expo-status-bar';
import { GEOCODING_API_KEY } from '@env';

import { ActivityIndicator, Icon, PaperProvider } from 'react-native-paper';
import { Text } from 'components/Base/Text';
import { PaperProvider } from 'react-native-paper';
import { DefaultTheme, NavigationContainer } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -23,11 +22,11 @@ import { useEffect } from 'react';
import { useCustomFonts } from 'utils/useCustomFonts';
import { theme } from 'utils/theme';
import { AppNavigator } from 'components/Layout/AppNavigator';
import { DevToolsBubble } from 'react-native-react-query-devtools';
import { SnackbarProvider } from 'utils/useSnackbar';
import { View } from 'react-native';
import Reactotron, { openInEditor } from 'reactotron-react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { DevToolsBubble } from "react-native-react-query-devtools";
Comment thread
t-shotgnu marked this conversation as resolved.
import { LoadingScreen } from 'components/Common/LoadingScreen';

Reactotron.setAsyncStorageHandler(AsyncStorage)
.configure({ name: 'WatchOut' })
Expand All @@ -54,6 +53,7 @@ export default function App() {
const { loaded } = useCustomFonts();

useEffect(() => {
console.info('Initializing Geocoding with API Key:', GEOCODING_API_KEY.substring(0, 5) + '****' + ' (truncated for security)');
Comment thread
t-shotgnu marked this conversation as resolved.
Geocoding.init(GEOCODING_API_KEY);
}, []);

Expand All @@ -63,17 +63,7 @@ export default function App() {
};

if (!loaded) {
return (
<>
<View style={{ justifyContent: 'center', alignItems: 'center', marginBottom: 24 }}>
<Icon source={require('assets/watchout.png')} size={250} />
<Text variant="h4" style={{ marginTop: 16 }}>
Ładowanie...
</Text>
<ActivityIndicator size="large" style={{ marginTop: 16 }} />
</View>
</>
);
return <LoadingScreen />;
}

return (
Expand Down
30 changes: 30 additions & 0 deletions Client/watchout/components/Base/CustomChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CustomSurface } from 'components/Layout/CustomSurface';
import { ViewStyle } from 'react-native';
import { Icon } from 'react-native-paper';

type CustomChipProps = {
icon: string;
iconColor: string;
style: ViewStyle;
children?: React.ReactNode;
};

export const CustomChip = ({ icon, iconColor, style, children }: CustomChipProps) => {
return (
<CustomSurface
style={[
{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
paddingBlock: 6,
paddingInline: 10,
gap: 4,
},
style,
]}>
<Icon source={icon} size={16} color={iconColor} />
{children}
</CustomSurface>
);
};
15 changes: 15 additions & 0 deletions Client/watchout/components/Common/LoadingScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ActivityIndicator, View } from 'react-native';
import { Icon } from 'react-native-paper';
import { Text } from 'components/Base/Text';

export const LoadingScreen = () => {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', marginBottom: 24 }}>
<Icon source={require('assets/watchout.png')} size={250} />
<Text variant="h4" style={{ marginTop: 16 }}>
Ładowanie...
</Text>
<ActivityIndicator size="large" style={{ marginTop: 16 }} />
</View>
);
};
22 changes: 13 additions & 9 deletions Client/watchout/components/Layout/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import { getFocusedRouteNameFromRoute, RouteProp } from '@react-navigation/nativ
import { navigationTheme } from 'components/Base/navigationTheme';
import { AlertsNavigator } from 'features/outages/AlertsNavigator';
import { useBottomSheetModal } from '@gorhom/bottom-sheet';
import { LoadingScreen } from 'components/Common/LoadingScreen';

const NavDrawer = createDrawerNavigator();
const LoginStack = createDrawerNavigator();

const routes = [
{
name: 'WatchOut',
name: 'Map',
component: Map,
label: 'Mapa',
icon: 'map',
Expand Down Expand Up @@ -55,16 +57,18 @@ export const AppNavigator = () => {
const { user, loading } = useAuth();
const { dismissAll } = useBottomSheetModal();

if (loading) return null;
if (loading) {
return <LoadingScreen />;
}
const isUserLoggedIn = user != null && user.isEmailVerified;

if (!user) {
if (!isUserLoggedIn) {
return (
<NavDrawer.Navigator
screenOptions={{ headerShown: false }}
drawerContent={(props) => <SafeAreaView style={{ flex: 1 }} />}>
<NavDrawer.Screen name="Login" component={LoginScreen} />
<NavDrawer.Screen name="SignUp" component={SignUpScreen} />
</NavDrawer.Navigator>
<LoginStack.Navigator
screenOptions={{ headerShown: false }}>
<LoginStack.Screen name="Login" component={LoginScreen} />
<LoginStack.Screen name="SignUp" component={SignUpScreen} />
</LoginStack.Navigator>
);
}

Expand Down
2 changes: 1 addition & 1 deletion Client/watchout/components/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Appbar } from "react-native-paper";
import { Text } from "components/Base/Text";
import { Button, getHeaderTitle } from '@react-navigation/elements';
import { getHeaderTitle } from '@react-navigation/elements';

export const NavigationBar = ({ route, options }: any) => {
const title = getHeaderTitle(options, route.name);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState, useEffect } from "react";
import { PermissionsAndroid, Platform } from "react-native";
import { useState, useEffect, createContext, ReactNode, useContext } from 'react';
import { PermissionsAndroid, Platform } from 'react-native';
import Geolocation from '@react-native-community/geolocation';
import { Coordinates } from 'utils/types';

const isUserLocationGranted = async () => {
try {
Expand All @@ -12,7 +13,7 @@ const isUserLocationGranted = async () => {
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
}
);
return granted === PermissionsAndroid.RESULTS.GRANTED;
} catch (error) {
Expand All @@ -21,16 +22,38 @@ const isUserLocationGranted = async () => {
}
};

type UserLocationContextType = {
location: Coordinates | null;
isLoading: boolean;
hasPermission: boolean;
error: string | null;
};

export const UserLocationContext = createContext<UserLocationContextType>({
location: null,
isLoading: false,
hasPermission: false,
error: null,
});

export const useUserLocation = () => {
const context = useContext(UserLocationContext);
return context;
}

export const UserLocationProvider = ({ children }: { children: ReactNode }) => {
const [hasPermission, setHasPermission] = useState(false);
const [location, setLocation] = useState<{ latitude: number; longitude: number } | null>(null);
const [error, setError] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const checkAndRequest = async () => {
let permissionGranted = false;
if (Platform.OS === 'android') {
const checkResult = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
const checkResult = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
);
if (checkResult) {
permissionGranted = true;
} else {
Expand All @@ -51,9 +74,14 @@ export const useUserLocation = () => {
}
);
}
setIsLoading(false);
};
checkAndRequest();
}, []);

return { hasPermission, location, error };
};
return (
<UserLocationContext.Provider value={{ hasPermission, location, error, isLoading }}>
{children}
</UserLocationContext.Provider>
);
};
37 changes: 29 additions & 8 deletions Client/watchout/features/auth/LoginScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { Button, Icon } from 'react-native-paper';
import { GoogleSignInButton } from 'features/auth/GoogleSignInButton';
import { signInWithEmail, resetPassword } from './auth';
import { AuthLayout } from 'components/Layout/AuthLayout';
import { AuthError } from 'utils/AuthError';
import { firebaseAuthErrorMessages } from 'utils/dictionaries';

export const LoginScreen = () => {
const navigation = useNavigation();
const { navigate } = useNavigation();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

Expand All @@ -19,8 +21,16 @@ export const LoginScreen = () => {
const handleLogin = async () => {
try {
await signInWithEmail(email, password);
navigate('Map' as never);
} catch (err: any) {
Alert.alert('Login failed', err.message || 'Nie udało się zalogować');
if (err.code && err.code in firebaseAuthErrorMessages) {
Alert.alert('Ups! Coś poszło nie tak', firebaseAuthErrorMessages[err.code]);
return;
}
Alert.alert(
'Ups! Coś poszło nie tak',
'Nie udało się zalogować. Spróbuj ponownie później. Przepraszamy za utrudnienia.'
);
}
};

Expand All @@ -35,13 +45,22 @@ export const LoginScreen = () => {
setResetVisible(false);
setResetEmail('');
} catch (err: any) {
Alert.alert('Błąd', err.message || 'Nie udało się wysłać maila');
if (err.code && err.code in firebaseAuthErrorMessages) {
Alert.alert('Ups! Coś poszło nie tak', firebaseAuthErrorMessages[err.code]);
return;
}
if (err instanceof AuthError) {
Alert.alert('Ups! Coś poszło nie tak', err.message);
return;
}
Alert.alert(
'Ups! Coś poszło nie tak',
'Nie udało się zarejestrować. Spróbuj ponownie później. Przepraszamy za utrudnienia.'
);
}
};

const header = (
<Icon source={require('assets/watchout.png')} size={150} />
);
const header = <Icon source={require('assets/watchout.png')} size={150} />;

const footer = (
<>
Expand Down Expand Up @@ -87,7 +106,7 @@ export const LoginScreen = () => {
Zaloguj się
</Button>

<TouchableOpacity onPress={() => navigation.navigate('SignUp' as never)}>
<TouchableOpacity onPress={() => navigate('SignUp' as never)}>
<Text style={styles.registerText}>Nie masz konta? Zarejestruj się</Text>
</TouchableOpacity>
</AuthLayout>
Expand All @@ -110,7 +129,9 @@ export const LoginScreen = () => {
</Button>

<TouchableOpacity onPress={() => setResetVisible(false)} style={{ marginTop: 12 }}>
<Text align="center" style={{ color: 'red' }}>Zamknij</Text>
<Text align="center" style={{ color: 'red' }}>
Zamknij
</Text>
</TouchableOpacity>
</View>
</View>
Expand Down
20 changes: 15 additions & 5 deletions Client/watchout/features/auth/SignUpScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@ import { Button, Icon } from 'react-native-paper';
import { GoogleSignInButton } from 'features/auth/GoogleSignInButton';
import { signUpEmail } from './auth';
import { AuthLayout } from 'components//Layout/AuthLayout';
import { AuthError } from 'utils/AuthError';
import { firebaseAuthErrorMessages } from 'utils/dictionaries';

export const SignUpScreen = () => {
const navigation = useNavigation();
const { navigate } = useNavigation();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [displayName, setDisplayName] = useState('');

const handleSignup = async () => {
try {
await signUpEmail(email, password, displayName);
Alert.alert('Sukces', 'Konto zostało utworzone');
navigation.navigate('Login' as never);
Alert.alert('Udało się!', 'Konto zostało utworzone. Zapraszamy do korzystania z aplikacji!');
navigate('Map' as never);
} catch (err: any) {
Alert.alert('Rejestracja nie powiodła się', err.message || 'Błąd');
let message = err.message || '';
Comment thread
t-shotgnu marked this conversation as resolved.
if (err.code && err.code in firebaseAuthErrorMessages) {
message = firebaseAuthErrorMessages[err.code];
} else if (err instanceof AuthError) {
message = err.message;
} else {
message = 'Nie udało się zarejestrować. Spróbuj ponownie później. Przepraszamy za utrudnienia.';
}
Alert.alert('Ups! Coś poszło nie tak', message);
}
};

Expand Down Expand Up @@ -71,7 +81,7 @@ export const SignUpScreen = () => {
Zarejestruj się
</Button>

<TouchableOpacity onPress={() => navigation.navigate('Login' as never)}>
<TouchableOpacity onPress={() => navigate('Login' as never)}>
<Text style={styles.registerText}>Masz już konto? Zaloguj się</Text>
</TouchableOpacity>
</AuthLayout>
Expand Down
Loading