Skip to content

Commit

Permalink
feat: intermediary profile options form required
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisCusihuaman committed Nov 9, 2023
1 parent 8f97839 commit 035f501
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 31 deletions.
57 changes: 46 additions & 11 deletions src/core/auth/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,52 @@ import { getToken, getUser, removeToken, setToken, setUser } from './utils';
interface AuthState {
token: TokenType | null;
user: UserType | undefined;
status: 'idle' | 'signOut' | 'signIn';
status: 'idle' | 'signOut' | 'signIn' | 'signInComplete';
signIn: (
data: TokenType,
userId: UserCredential['user']['uid'] | undefined
) => void;
signOut: () => void;
signInComplete: (user: UserType) => void;
hydrate: () => void;
}

const isUserComplete = (user: UserType): boolean => {
for (const key in user) {
if (user.hasOwnProperty(key)) {
const value = user[key as keyof UserType]; // Use type assertion here
if (value === null || value === '') {
return false;
}
}
}
return true;
};

const _useAuth = create<AuthState>((set, get) => ({
status: 'idle',
token: null,
user: undefined,
signIn: async (token, userId) => {
if (userId !== undefined) {
const response = await fetch(
`https://api-identity-socializer-luiscusihuaman.cloud.okteto.net/api/auth/users/${userId}`
);
const user: UserType = await response.json();
await setUser(user); // store user and user in phone storage
set({ user });
}

const response = await fetch(
`https://api-identity-socializer-luiscusihuaman.cloud.okteto.net/api/auth/users/${userId}`
);
const user: UserType = await response.json();
await setUser(user); // store user and user in phone storage
await setToken(token); // store token in phone storage
set({ status: 'signIn', token }); // store token in phone memory ram
const status = isUserComplete(user) ? 'signInComplete' : 'signIn';
set({ status, user, token }); // store token in phone memory ram
},
signOut: async () => {
await removeToken();
set({ status: 'signOut', token: null });
},
hydrate: () => {
console.log('HIDRATANDOO');
try {
const userToken = getToken();
const oldLoggedUser = getUser();
console.log('oldLoggedUser', oldLoggedUser);
if (userToken !== null) {
get().signIn(userToken, oldLoggedUser?.id);
} else {
Expand All @@ -52,6 +64,25 @@ const _useAuth = create<AuthState>((set, get) => ({
// Maybe sign_out user!
}
},
signInComplete: async (user) => {
const response = await fetch(
`https://api-identity-socializer-luiscusihuaman.cloud.okteto.net/api/auth/update_user`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(user),
}
);

if (response.status !== 200) {
console.log('error updating user, status code:', response.status);
return;
}
await setUser(user); // store user and user in phone storage
set({ user, status: 'signInComplete' });
},
}));

export const useAuth = createSelectors(_useAuth);
Expand All @@ -76,3 +107,7 @@ export const hydrateAuth = () => _useAuth.getState().hydrate();
export const getUserState = () => _useAuth.getState().user;

export const updateUserState = (user: UserType) => _useAuth.setState({ user });

export const signInComplete = (user: UserType) => {
_useAuth.getState().signInComplete(user);
};
16 changes: 15 additions & 1 deletion src/navigation/auth-navigator.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import * as React from 'react';

import { useAuth } from '@/core';
import { Login } from '@/screens';
import { Pressable, Text } from '@/ui';

export const GoToLogout = () => {
const status = useAuth.use.status();
if (status === 'signOut') {
return null;
}
const signOut = useAuth.use.signOut();
return (
<Pressable onPress={() => signOut()} className="p-2">
<Text className="text-red-600">Logout</Text>
</Pressable>
);
};

export type AuthStackParamList = {
Login: undefined;
};

const Stack = createNativeStackNavigator<AuthStackParamList>();

export const AuthNavigator = () => {
Expand Down
12 changes: 2 additions & 10 deletions src/navigation/feed-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import * as React from 'react';

import { useAuth } from '@/core';
import { AddSnap, Feed, Snap } from '@/screens';
import { Pressable, Text } from '@/ui';

import { GoToLogout } from './auth-navigator';

export type FeedStackParamList = {
Feed: undefined;
Snap: { id: number };
Expand All @@ -15,15 +16,6 @@ export type FeedStackParamList = {

const Stack = createNativeStackNavigator<FeedStackParamList>();

const GoToLogout = () => {
const signOut = useAuth.use.signOut();
return (
<Pressable onPress={() => signOut()} className="p-2">
<Text className="text-red-600">Logout</Text>
</Pressable>
);
};

const GoToAddSnap = () => {
const { navigate } = useNavigation();
return (
Expand Down
8 changes: 6 additions & 2 deletions src/navigation/root-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import React, { useEffect } from 'react';

import { useAuth } from '@/core';

import { AuthNavigator } from './auth-navigator';
import { AuthNavigator, GoToLogout } from './auth-navigator';
import { NavigationContainer } from './navigation-container';
import { SignInComplete } from './signin-complete';
import { TabNavigator } from './tab-navigator';

const Stack = createNativeStackNavigator();
Expand All @@ -21,6 +22,7 @@ export const Root = () => {
}
}, [hideSplash, status]);

console.log('status:', status);
return (
<Stack.Navigator
screenOptions={{
Expand All @@ -37,8 +39,10 @@ export const Root = () => {
component={AuthNavigator}
//options={{ headerTitle: (props) => <LogoTitle {...props} /> }}
/>
) : (
) : status === 'signInComplete' ? (
<Stack.Screen name="App" component={TabNavigator} />
) : (
<Stack.Screen name="signInComplete" component={SignInComplete} />
)}
</Stack.Group>
</Stack.Navigator>
Expand Down
117 changes: 117 additions & 0 deletions src/navigation/signin-complete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { zodResolver } from '@hookform/resolvers/zod';
import React from 'react';
import type { SubmitHandler } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import * as z from 'zod';

import { getUserState, signInComplete } from '@/core';
import type { UserType } from '@/core/auth/utils';
import { Button, ControlledInput, ScrollView, View } from '@/ui';

const schema = z.object({
first_name: z
.string()
.min(3, 'First Name must be at least 3 characters')
.max(50, 'First Name cannot exceed 50 characters'),
last_name: z
.string()
.min(3, 'Last Name must be at least 3 characters')
.max(50, 'Last Name cannot exceed 50 characters'),
username: z
.string()
.min(3, 'Username must be at least 4 characters')
.max(20, 'Username cannot exceed 20 characters'),
phone_number: z.string().regex(/^\d{10}$/, 'Invalid phone number format'), // Assuming 10-digit phone number
bio_msg: z.string().max(500, 'Bio Message cannot exceed 500 characters'),
profile_photo_id: z
.string()
.max(200, 'Profile Photo ID cannot exceed 100 characters'),
});

export type FormType = z.infer<typeof schema>;

export type SignUpFormProps = {
onSignUpSubmit?: SubmitHandler<FormType>;
};

const whenSignInComplete: SignUpFormProps['onSignUpSubmit'] = (data) => {
const getCurrentUser = getUserState();
console.log('current user data:', getCurrentUser);
if (getCurrentUser) {
const updatedUser: UserType = {
...getCurrentUser,
...data,
};
signInComplete(updatedUser);
} else {
console.error('Error: Current user data is undefined');
// Handle the case where user data is undefined, such as showing an error message or redirecting the user.
}
};
export const SignInComplete = () => {
return <FormForSignInComplete onSignUpSubmit={whenSignInComplete} />;
};

export const FormForSignInComplete = ({
onSignUpSubmit = () => {},
}: SignUpFormProps) => {
const { handleSubmit, control } = useForm<FormType>({
resolver: zodResolver(schema),
});

return (
<View className="flex-1 p-4">
<ScrollView className="flex-1 p-4">
<ControlledInput
testID="first-name-input"
control={control}
name="first_name"
label="First Name"
/>

<ControlledInput
testID="last-name-input"
control={control}
name="last_name"
label="Last Name"
/>

<ControlledInput
testID="username-input"
control={control}
name="username"
label="Username"
/>

<ControlledInput
testID="phone-number-input"
control={control}
name="phone_number"
label="Phone Number"
keyboardType="numeric"
/>

<ControlledInput
testID="bio-input"
control={control}
name="bio_msg"
label="Bio Message"
/>

<ControlledInput
testID="photo-id-input"
control={control}
name="profile_photo_id"
label="Profile Photo ID"
/>
</ScrollView>

<Button
testID="sign-up-button"
label="Complete Sign Up"
onPress={handleSubmit(onSignUpSubmit)}
variant="secondary"
/>
</View>
);
};
7 changes: 0 additions & 7 deletions src/screens/login/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,6 @@ export const LoginForm = ({
Welcome
</Text>

<ControlledInput
testID="name"
control={control}
name="name"
label="Name"
/>

<ControlledInput
testID="email-input"
control={control}
Expand Down

0 comments on commit 035f501

Please sign in to comment.