Skip to content

Commit

Permalink
✨ feat: Extend AppWriteProvider with user refresh and update function…
Browse files Browse the repository at this point in the history
…ality

feat: Extend AppWriteProvider with user refresh and update functionality

Refactor sign-in, sign-up, and sign-out to use new helper functions
```

The AppWriteProvider and associated authentication module have been extended to include user refresh and user update functionalities. The `signOut` method now explicitly sets the user state to undefined and authentication status to false upon user sign-out. The `signUp`, `signIn`, and `signOut` methods have been refactored to use new internal helper functions that handle user data refresh post-sign-in/sign-up and ensure the user state is appropriately updated. Additional state variables have been introduced to track the refreshing status of user data. The type definition for the AppWrite configuration object has been updated for consistent capitalization.
  • Loading branch information
Gincioks committed May 5, 2024
1 parent 4b78ebc commit d2dbf62
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 18 deletions.
61 changes: 46 additions & 15 deletions src/lib/AppWriteProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type Models } from '../index';
import { createContext, type FC, useContext, useEffect, useMemo, useState } from 'react';
import { appWriteAuth } from './app-write-auth';

export type AppwriteConfigType = {
export type AppWriteConfigType = {
readonly endpoint: string;
readonly platform: string;
readonly projectId: string;
Expand All @@ -13,16 +13,19 @@ export type AppwriteConfigType = {

export type AppWriteProviderProps = {
readonly children: React.ReactNode;
readonly config: AppwriteConfigType;
readonly config: AppWriteConfigType;
};

export type AppWriteContextType = {
signUp: (email: string, password: string, username: string) => Promise<Models.Document>;
signIn: (email: string, password: string) => Promise<Models.Session>;
signOut: () => Promise<{}>;
signOut: () => Promise<void>;
userRefresh: () => Promise<void>;
updateUser: (newUser: Models.Document) => Promise<void>;
isAuthenticated: boolean;
user: Models.Document | undefined;
isAuthenticationLoading: boolean;
isUserDataRefreshing: boolean;
};

const AppWriteContext = createContext<AppWriteContextType>({
Expand All @@ -35,49 +38,77 @@ const AppWriteContext = createContext<AppWriteContextType>({
signOut: async () => {
throw new Error('AppWriteProvider not found');
},
userRefresh: async () => {
throw new Error('AppWriteProvider not found');
},
updateUser: async () => {
throw new Error('AppWriteProvider not found');
},
isAuthenticated: false,
user: undefined,
isAuthenticationLoading: true,
isUserDataRefreshing: false,
});

export const useAppWrite = () => useContext(AppWriteContext);

export const AppWriteProvider: FC<AppWriteProviderProps> = ({ children, config }) => {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const [user, setUser] = useState<Models.Document | undefined>(undefined);
const [isAuthenticationLoading, setIsAuthenticationLoading] = useState<boolean>(true);
const [isAuthenticationLoading, setIsAuthenticationLoading] = useState<boolean>(true); // for initial navigation guards
const [isUserDataRefreshing, setIsUserDataRefresh] = useState<boolean>(false);

const { signUp, signIn, signOut, getCurrentUser } = appWriteAuth(config);

const fetchUserData = async () => {
setIsAuthenticationLoading(true);
setIsUserDataRefresh(true);
const userData = await getCurrentUser();
if (userData) {
setIsAuthenticated(true);
setUser(userData);
} else {
setIsAuthenticated(false);
setUser(undefined);
}
setIsAuthenticated(userData !== undefined);
setUser(userData);
setIsAuthenticationLoading(false);
setIsUserDataRefresh(false);
};

const handleSignUp = async (email: string, password: string, username: string) => {
const newUser = await signUp(email, password, username);
await fetchUserData(); // Refresh user data post-sign-up
return newUser;
}

const handleSignIn = async (email: string, password: string) => {
const session = await signIn(email, password);
await fetchUserData(); // Refresh user data post-sign-in
return session;
};

const handleSignOut = async () => {
await signOut();
setIsAuthenticated(false);
setUser(undefined);
}

const handleUserRefresh = async () => {
await fetchUserData();
}

// Placeholder for future functionality
const handleUpdateUser = async (newUser: Models.Document) => {
setUser(newUser);
}

const contextValue = useMemo(
() => ({
signUp,
signUp: handleSignUp,
signIn: handleSignIn,
signOut,
signOut: handleSignOut,
userRefresh: handleUserRefresh,
updateUser: handleUpdateUser,
isAuthenticated,
user,
isAuthenticationLoading,
isUserDataRefreshing,
}),
[isAuthenticated, user, isAuthenticationLoading]
[isAuthenticated, user, isAuthenticationLoading, isUserDataRefreshing]
);

useEffect(() => {
Expand Down
6 changes: 3 additions & 3 deletions src/lib/app-write-auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Client } from 'client';
import { type AppwriteConfigType } from './AppWriteProvider';
import { type AppWriteConfigType } from './AppWriteProvider';
import { Account } from 'services/account';
import { Avatars } from 'services/avatars';
import { Databases } from 'services/databases';
Expand All @@ -13,7 +13,7 @@ function handleApiError(error: unknown): Error {
return new Error('An unexpected error occurred');
}

export const appWriteAuth = (config: AppwriteConfigType) => {
export const appWriteAuth = (config: AppWriteConfigType) => {
const client = new Client();

client.setEndpoint(config.endpoint).setProject(config.projectId).setPlatform(config.platform);
Expand Down Expand Up @@ -96,7 +96,7 @@ export const appWriteAuth = (config: AppwriteConfigType) => {
return currentUser.documents[0];
} catch (error) {
console.log(error);
return null;
return undefined;
}
};

Expand Down

0 comments on commit d2dbf62

Please sign in to comment.