222 lines
5.9 KiB
TypeScript
222 lines
5.9 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { Alert, StyleSheet, AppState, Image, Platform } from 'react-native';
|
|
import { supabase } from '@/lib/supabase';
|
|
import { ThemedView, ThemedText, ThemedTextButton, ThemedTextInput } from '@/components/theme';
|
|
import AppleSignInButton from '@/components/auth/AppleSignIniOS';
|
|
import AzureSignIn from './AzureSignIn';
|
|
import { Colors } from '@/constants/Colors';
|
|
import { useColorScheme } from '@/hooks/useColorScheme';
|
|
|
|
// Tells Supabase Auth to continuously refresh the session automatically if
|
|
// the app is in the foreground. When this is added, you will continue to receive
|
|
// `onAuthStateChange` events with the `TOKEN_REFRESHED` or `SIGNED_OUT` event
|
|
// if the user's session is terminated. This should only be registered once.
|
|
if (Platform.OS !== 'web') {
|
|
AppState.addEventListener('change', (state) => {
|
|
if (state === 'active') {
|
|
supabase.auth.startAutoRefresh();
|
|
} else {
|
|
supabase.auth.stopAutoRefresh();
|
|
}
|
|
});
|
|
}
|
|
|
|
const Auth = () => {
|
|
const scheme = useColorScheme() ?? 'dark';
|
|
|
|
const [full_name, setFullName] = useState('');
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
// Set up auto-refreshing for web
|
|
useEffect(() => {
|
|
if (Platform.OS === 'web') {
|
|
supabase.auth.startAutoRefresh();
|
|
return () => {
|
|
supabase.auth.stopAutoRefresh();
|
|
};
|
|
}
|
|
}, []);
|
|
|
|
const signInWithEmail = async () => {
|
|
setLoading(true);
|
|
const { error } = await supabase.auth.signInWithPassword({
|
|
email: email,
|
|
password: password,
|
|
});
|
|
if (error) Alert.alert(error.message);
|
|
setLoading(false);
|
|
};
|
|
|
|
const signUpWithEmail = async () => {
|
|
setLoading(true);
|
|
const {
|
|
data: { session },
|
|
error,
|
|
} = await supabase.auth.signUp({
|
|
email,
|
|
password,
|
|
options: {
|
|
data: {
|
|
full_name,
|
|
provider: 'email',
|
|
}
|
|
}
|
|
});
|
|
if (error) Alert.alert(error.message);
|
|
else if (!session) Alert.alert('Please check your inbox for email verification!');
|
|
setLoading(false);
|
|
};
|
|
|
|
return (
|
|
<ThemedView style={styles.container}>
|
|
<ThemedView style={styles.titleContainer}>
|
|
<Image source={require('@/assets/images/tech_tracker_logo.png')} style={styles.reactLogo} />
|
|
<ThemedText type='title' style={styles.headerTitle}>
|
|
Tech Tracker
|
|
</ThemedText>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.verticallySpaced}>
|
|
<ThemedTextInput
|
|
height={60}
|
|
fontSize={24}
|
|
onChangeText={(text) => setFullName(text)}
|
|
value={full_name}
|
|
secureTextEntry={false}
|
|
autoCapitalize='words'
|
|
placeholder='Full Name'
|
|
/>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={[styles.verticallySpaced]}>
|
|
<ThemedTextInput
|
|
height={60}
|
|
fontSize={24}
|
|
onChangeText={(text) => setEmail(text)}
|
|
value={email}
|
|
secureTextEntry={false}
|
|
autoCapitalize='none'
|
|
placeholder='email@address.com'
|
|
/>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.verticallySpaced}>
|
|
<ThemedTextInput
|
|
height={60}
|
|
fontSize={24}
|
|
onChangeText={(text) => setPassword(text)}
|
|
value={password}
|
|
secureTextEntry={true}
|
|
placeholder='Password'
|
|
/>
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.verticallySpaced}>
|
|
<ThemedView style={styles.horizontallySpaced}>
|
|
<ThemedTextButton
|
|
text='Sign in'
|
|
disabled={loading}
|
|
onPress={() => signInWithEmail()}
|
|
fontSize={28}
|
|
fontWeight='semibold'
|
|
width='50%'
|
|
/>
|
|
<ThemedTextButton
|
|
text='Sign up'
|
|
disabled={loading}
|
|
onPress={() => signUpWithEmail()}
|
|
fontSize={28}
|
|
fontWeight='semibold'
|
|
width='50%'
|
|
/>
|
|
</ThemedView>
|
|
</ThemedView>
|
|
|
|
{ Platform.OS === 'ios' && (
|
|
<ThemedView style={styles.divider}>
|
|
<ThemedView style={[styles.dividerLine, { backgroundColor: Colors[scheme].text }]} />
|
|
<ThemedText type='subtitle' style={styles.dividerText}>or</ThemedText>
|
|
<ThemedView style={[styles.dividerLine, { backgroundColor: Colors[scheme].text }]} />
|
|
</ThemedView>
|
|
)}
|
|
|
|
<ThemedView style={styles.verticallySpaced}>
|
|
<AppleSignInButton />
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.divider}>
|
|
<ThemedView style={[styles.dividerLine, { backgroundColor: Colors[scheme].text }]} />
|
|
<ThemedText type='subtitle' style={styles.dividerText}>or</ThemedText>
|
|
<ThemedView style={[styles.dividerLine, { backgroundColor: Colors[scheme].text }]} />
|
|
</ThemedView>
|
|
|
|
<ThemedView style={styles.verticallySpaced}>
|
|
<AzureSignIn />
|
|
</ThemedView>
|
|
</ThemedView>
|
|
);
|
|
};
|
|
|
|
export default Auth;
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
padding: 12,
|
|
height: '100%',
|
|
},
|
|
verticallySpaced: {
|
|
paddingTop: 4,
|
|
paddingBottom: 4,
|
|
alignItems: 'center',
|
|
},
|
|
horizontallySpaced: {
|
|
flexDirection: 'row',
|
|
paddingLeft: 4,
|
|
paddingRight: 4,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
width: '90%',
|
|
},
|
|
mt20: {
|
|
marginTop: 20,
|
|
},
|
|
reactLogo: {
|
|
height: 70,
|
|
width: 72,
|
|
},
|
|
titleContainer: {
|
|
marginTop: 60,
|
|
marginBottom: 20,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 8,
|
|
},
|
|
headerTitle: {
|
|
textAlign: 'center',
|
|
fontSize: 48,
|
|
lineHeight: 64,
|
|
fontWeight: 'bold',
|
|
},
|
|
divider: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginVertical: 5,
|
|
width: '80%',
|
|
alignSelf: 'center',
|
|
},
|
|
dividerText: {
|
|
marginHorizontal: 15,
|
|
fontSize: 14,
|
|
opacity: 0.7,
|
|
},
|
|
dividerLine: {
|
|
flex: 1,
|
|
height: 1,
|
|
opacity: 0.3,
|
|
}
|
|
});
|