mirror of
https://github.com/urosran/cally.git
synced 2025-07-10 15:17:17 +00:00
340 lines
10 KiB
TypeScript
340 lines
10 KiB
TypeScript
import React, { useEffect, useRef, useState } from "react";
|
|
import {
|
|
Button,
|
|
ButtonSize,
|
|
Checkbox,
|
|
Colors,
|
|
KeyboardAwareScrollView,
|
|
LoaderScreen,
|
|
Text,
|
|
TextField,
|
|
TextFieldRef,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native-ui-lib";
|
|
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
|
import {
|
|
Dimensions,
|
|
KeyboardAvoidingView,
|
|
Platform,
|
|
StyleSheet,
|
|
} from "react-native";
|
|
import { AntDesign } from "@expo/vector-icons";
|
|
import KeyboardManager from "react-native-keyboard-manager";
|
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
import { useRouter } from "expo-router";
|
|
import * as Device from "expo-device";
|
|
import { DeviceType } from "expo-device";
|
|
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
|
|
|
|
if (Platform.OS === "ios") KeyboardManager.setEnableAutoToolbar(true);
|
|
|
|
const SignUpPage = () => {
|
|
const [email, setEmail] = useState<string>("");
|
|
const [firstName, setFirstName] = useState<string>("");
|
|
const [lastName, setLastName] = useState<string>("");
|
|
const [password, setPassword] = useState<string>("");
|
|
|
|
const [isPasswordVisible, setIsPasswordVisible] = useState<boolean>(false);
|
|
const [allowFaceID, setAllowFaceID] = useState<boolean>(false);
|
|
const [acceptTerms, setAcceptTerms] = useState<boolean>(false);
|
|
const { mutateAsync: signUp, isLoading } = useSignUp();
|
|
const {profileData} = useAuthContext();
|
|
|
|
const lnameRef = useRef<TextFieldRef>(null);
|
|
const emailRef = useRef<TextFieldRef>(null);
|
|
const passwordRef = useRef<TextFieldRef>(null);
|
|
|
|
const isTablet: boolean = Device.deviceType === DeviceType.TABLET;
|
|
const [isPortrait, setIsPortrait] = useState(() => {
|
|
const dim = Dimensions.get("screen");
|
|
return dim.height >= dim.width;
|
|
});
|
|
|
|
useEffect(() => {
|
|
const subscription = Dimensions.addEventListener("change", ({ screen }) => {
|
|
setIsPortrait(screen.height >= screen.width);
|
|
});
|
|
|
|
return () => subscription.remove();
|
|
}, []);
|
|
|
|
const getTopPadding = () => {
|
|
if (Device.deviceType === DeviceType.TABLET) {
|
|
return isPortrait ? "50%" : "15%";
|
|
}
|
|
return "20%"; // non-tablet case, regardless of orientation
|
|
};
|
|
|
|
const router = useRouter();
|
|
|
|
const handleSignUp = async () => {
|
|
await signUp({ email, password, firstName, lastName });
|
|
|
|
if (profileData?.userType === ProfileType.FAMILY_DEVICE) {
|
|
router.replace("/(auth)/calendar");
|
|
} else {
|
|
router.replace("/(unauth)/cal_sync");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<SafeAreaView
|
|
style={{
|
|
flex: 1,
|
|
}}
|
|
>
|
|
<KeyboardAwareScrollView
|
|
contentContainerStyle={{ flexGrow: 1,
|
|
alignItems: isTablet ? "center" : undefined,
|
|
width: '100%' }}
|
|
enableOnAndroid
|
|
>
|
|
<View
|
|
style={{
|
|
flex: 1,
|
|
padding: 21,
|
|
paddingBottom: 45,
|
|
paddingTop: isLoading ? "20%" : getTopPadding(),
|
|
width: isLoading ? undefined : (isTablet ? 629 : undefined),
|
|
}}
|
|
>
|
|
<View gap-13 width={"100%"} marginB-20>
|
|
<Text style={{ fontSize: 40, fontFamily: "Manrope_600SemiBold" }}>
|
|
Get started with Cally
|
|
</Text>
|
|
<Text color={"#919191"} style={{ fontSize: 20 }}>
|
|
Please enter your details.
|
|
</Text>
|
|
</View>
|
|
|
|
<KeyboardAvoidingView style={{ width: "100%" }}>
|
|
<TextField
|
|
marginT-30
|
|
autoFocus
|
|
placeholder="First name"
|
|
value={firstName}
|
|
onChangeText={setFirstName}
|
|
style={styles.textfield}
|
|
onSubmitEditing={() => {
|
|
lnameRef.current?.focus();
|
|
}}
|
|
blurOnSubmit={false}
|
|
accessibilityLabel="First name input"
|
|
accessibilityHint="Enter your first name"
|
|
accessible
|
|
returnKeyType="next"
|
|
textContentType="givenName"
|
|
importantForAccessibility="yes"
|
|
/>
|
|
<TextField
|
|
ref={lnameRef}
|
|
placeholder="Last name"
|
|
value={lastName}
|
|
onChangeText={setLastName}
|
|
style={styles.textfield}
|
|
onSubmitEditing={() => {
|
|
emailRef.current?.focus();
|
|
}}
|
|
blurOnSubmit={false}
|
|
accessibilityLabel="Last name input"
|
|
accessibilityHint="Enter your last name"
|
|
accessible
|
|
returnKeyType="next"
|
|
textContentType="familyName"
|
|
importantForAccessibility="yes"
|
|
/>
|
|
<TextField
|
|
placeholder="Email"
|
|
keyboardType={"email-address"}
|
|
returnKeyType={"next"}
|
|
textContentType={"emailAddress"}
|
|
defaultValue={email}
|
|
onChangeText={setEmail}
|
|
style={styles.textfield}
|
|
autoComplete={"email"}
|
|
autoCorrect={false}
|
|
ref={emailRef}
|
|
onSubmitEditing={() => {
|
|
passwordRef.current?.focus();
|
|
}}
|
|
/>
|
|
|
|
<View
|
|
centerV
|
|
style={[styles.textfield, { padding: 0, paddingHorizontal: 30 }]}
|
|
>
|
|
<TextField
|
|
ref={passwordRef}
|
|
placeholder="Password"
|
|
style={styles.jakartaLight}
|
|
value={password}
|
|
onChangeText={setPassword}
|
|
secureTextEntry={!isPasswordVisible}
|
|
trailingAccessory={
|
|
<TouchableOpacity
|
|
onPress={() => setIsPasswordVisible(!isPasswordVisible)}
|
|
>
|
|
<AntDesign
|
|
name={isPasswordVisible ? "eye" : "eyeo"}
|
|
size={24}
|
|
color="gray"
|
|
/>
|
|
</TouchableOpacity>
|
|
}
|
|
/>
|
|
</View>
|
|
</KeyboardAvoidingView>
|
|
|
|
<View gap-5 marginT-15>
|
|
<View row centerV>
|
|
<Checkbox
|
|
style={[
|
|
styles.check,
|
|
{ borderRadius: 3, width: 18, height: 18 },
|
|
]}
|
|
color="#919191"
|
|
size={18}
|
|
borderRadius={3}
|
|
value={allowFaceID}
|
|
containerStyle={{ borderRadius: 3, width: 18, height: 18 }}
|
|
onValueChange={(value) => {
|
|
setAllowFaceID(value);
|
|
}}
|
|
/>
|
|
<Text style={styles.jakartaLight} marginL-10>
|
|
Allow FaceID for login in future
|
|
</Text>
|
|
</View>
|
|
<View row centerV>
|
|
<Checkbox
|
|
style={[
|
|
styles.check,
|
|
{ borderRadius: 3, width: 18, height: 18 },
|
|
]}
|
|
color="#919191"
|
|
size={18}
|
|
containerStyle={{ borderRadius: 3, width: 18, height: 18 }}
|
|
borderRadius={3}
|
|
value={acceptTerms}
|
|
onValueChange={(value) => setAcceptTerms(value)}
|
|
/>
|
|
<View row style={{ flexWrap: "wrap", marginLeft: 10 }}>
|
|
<Text style={styles.jakartaLight}>I accept the</Text>
|
|
<TouchableOpacity>
|
|
<Text text90 style={styles.jakartaMedium}>
|
|
{" "}
|
|
terms and conditions
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<Text style={styles.jakartaLight}> and </Text>
|
|
<TouchableOpacity>
|
|
<Text text90 style={styles.jakartaMedium}>
|
|
{" "}
|
|
privacy policy
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{isTablet ? (
|
|
<View height={50} />
|
|
) : (
|
|
<View flexG style={{ minHeight: 50 }} />
|
|
)}
|
|
|
|
<View>
|
|
<Button
|
|
label="Register"
|
|
disabled={!acceptTerms}
|
|
labelStyle={{
|
|
fontFamily: "PlusJakartaSans_600SemiBold",
|
|
fontSize: 16,
|
|
}}
|
|
onPress={handleSignUp}
|
|
backgroundColor={"#fd1775"}
|
|
style={{ marginBottom: 0, height: 50 }}
|
|
/>
|
|
<View row centerH marginT-10 marginB-2 gap-5>
|
|
<Text
|
|
style={[
|
|
styles.jakartaLight,
|
|
{ fontSize: 16, color: "#484848" },
|
|
]}
|
|
center
|
|
>
|
|
Already have an account?
|
|
</Text>
|
|
|
|
<Button
|
|
label="Log in"
|
|
labelStyle={[
|
|
styles.jakartaMedium,
|
|
{
|
|
fontSize: 16,
|
|
textDecorationLine: "none",
|
|
color: "#fd1775",
|
|
},
|
|
]}
|
|
flexS
|
|
margin-0
|
|
link
|
|
color="#fd1775"
|
|
size={ButtonSize.small}
|
|
text70
|
|
onPress={() => router.replace("/(unauth)/sign_in")}
|
|
/>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</KeyboardAwareScrollView>
|
|
|
|
{isLoading && (
|
|
<LoaderScreen
|
|
overlay
|
|
message={"Signing up..."}
|
|
backgroundColor={Colors.white}
|
|
color={Colors.grey40}
|
|
/>
|
|
)}
|
|
</SafeAreaView>
|
|
);
|
|
};
|
|
|
|
export default SignUpPage;
|
|
|
|
const styles = StyleSheet.create({
|
|
textfield: {
|
|
backgroundColor: "white",
|
|
marginVertical: 8,
|
|
padding: 30,
|
|
height: 44,
|
|
borderRadius: 50,
|
|
fontFamily: "PlusJakartaSans_300Light",
|
|
fontSize: 13,
|
|
color: "#919191",
|
|
},
|
|
jakartaLight: {
|
|
fontFamily: "PlusJakartaSans_300Light",
|
|
fontSize: 13,
|
|
color: "#919191",
|
|
},
|
|
jakartaMedium: {
|
|
fontFamily: "PlusJakartaSans_500Medium",
|
|
fontSize: 13,
|
|
color: "#919191",
|
|
textDecorationLine: "underline",
|
|
},
|
|
title: { fontFamily: "Manrope_600SemiBold", fontSize: 34, marginTop: 50 },
|
|
subtitle: { fontFamily: "PlusJakartaSans_400Regular", fontSize: 16 },
|
|
check: {
|
|
borderRadius: 3,
|
|
aspectRatio: 1,
|
|
width: 18,
|
|
color: "#919191",
|
|
borderColor: "#919191",
|
|
borderWidth: 1,
|
|
},
|
|
});
|