chore: handled lint errors in use accounts

This commit is contained in:
gurusainath 2024-05-02 16:04:14 +05:30
parent 4239dc0daf
commit 9ea5caed1b
18 changed files with 211 additions and 197 deletions

View File

@ -26,7 +26,7 @@ const inputRules = {
export const CustomThemeSelector: React.FC = observer(() => {
const {
profile: { data: userProfile },
userProfile: { data: userProfile },
} = useUser();
const userTheme: any = userProfile?.theme;

View File

@ -15,7 +15,7 @@ import { useUser } from "@/hooks/store";
export const WorkspaceActiveCyclesUpgrade = observer(() => {
// store hooks
const {
profile: { data: userProfile },
userProfile: { data: userProfile },
} = useUser();
const isDarkMode = userProfile?.theme.theme === "dark";

View File

@ -27,8 +27,7 @@ export * from "./use-issue-detail";
// project inbox
export * from "./use-project-inbox";
export * from "./use-inbox-issues";
export * from "./use-user-profile";
export * from "./use-user";
export * from "./user";
export * from "./use-instance";
export * from "./use-app-theme";
export * from "./use-command-palette";

View File

@ -1,11 +0,0 @@
import { useContext } from "react";
// mobx store
import { StoreContext } from "@/lib/store-context";
// types
import { IUserSettingsStore } from "@/store/user/user-setting.store";
export const useCurrentUserSettings = (): IUserSettingsStore => {
const context = useContext(StoreContext);
if (context === undefined) throw new Error("useCurrentUserSettings must be used within StoreProvider");
return context.user.currentUserSettings;
};

View File

@ -1,11 +0,0 @@
import { useContext } from "react";
// mobx store
import { StoreContext } from "@/lib/store-context";
// types
import { IProfileStore } from "store/user/profile.store";
export const useUserProfile = (): IProfileStore => {
const context = useContext(StoreContext);
if (context === undefined) throw new Error("useUser must be used within StoreProvider");
return context.user.profile;
};

View File

@ -0,0 +1,3 @@
export * from "./user-user";
export * from "./user-user-profile";
export * from "./user-user-settings";

View File

@ -0,0 +1,11 @@
import { useContext } from "react";
// mobx store
import { StoreContext } from "@/lib/store-context";
// types
import { IUserProfileStore } from "@/store/user/profile.store";
export const useUserProfile = (): IUserProfileStore => {
const context = useContext(StoreContext);
if (context === undefined) throw new Error("useUserProfile must be used within StoreProvider");
return context.user.userProfile;
};

View File

@ -0,0 +1,11 @@
import { useContext } from "react";
// mobx store
import { StoreContext } from "@/lib/store-context";
// types
import { IUserSettingsStore } from "@/store/user/settings.store";
export const useUserSettings = (): IUserSettingsStore => {
const context = useContext(StoreContext);
if (context === undefined) throw new Error("useUserSettings must be used within StoreProvider");
return context.user.userSettings;
};

View File

@ -8,7 +8,6 @@ import { Spinner } from "@plane/ui";
// hooks
import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys";
import { useUser, useUserProfile, useWorkspace } from "@/hooks/store";
import { useCurrentUserSettings } from "@/hooks/store/use-current-user-settings";
export interface IUserAuthWrapper {
children: ReactNode;
@ -19,7 +18,6 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = observer((props) => {
// store hooks
const { fetchCurrentUser, data: currentUser, error: currentUserError } = useUser();
const { fetchUserProfile } = useUserProfile();
const { fetchCurrentUserSettings } = useCurrentUserSettings();
const { fetchWorkspaces } = useWorkspace();
// router
const router = useRouter();
@ -30,10 +28,6 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = observer((props) => {
useSWR("CURRENT_USER_PROFILE_DETAILS", () => fetchUserProfile(), {
shouldRetryOnError: false,
});
//fetching user settings
const { isLoading: userSettingsLoader } = useSWR("CURRENT_USER_SETTINGS", () => fetchCurrentUserSettings(), {
shouldRetryOnError: false,
});
// fetching all workspaces
const { isLoading: workspaceLoader } = useSWR(USER_WORKSPACES_LIST, () => fetchWorkspaces(), {
shouldRetryOnError: false,

View File

@ -6,7 +6,7 @@ import { Spinner } from "@plane/ui";
// helpers
import { EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useUser, useWorkspace } from "@/hooks/store";
import { useUser, useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store";
type TPageType = EPageTypes;
@ -26,13 +26,13 @@ export const AuthenticationWrapper: FC<TAuthenticationWrapper> = observer((props
// props
const { children, pageType = EPageTypes.AUTHENTICATED } = props;
// hooks
const { isLoading: isUserLoading, data: currentUser, fetchCurrentUser } = useUser();
const { isLoading: currentUserProfileLoader, data: currentUserProfile, fetchUserProfile } = useUserProfile();
const {
isLoading: isUserLoading,
data: currentUser,
currentUserSettings: { isLoading: currentUserSettingsLoader, data: currentUserSettings, fetchCurrentUserSettings },
profile: { isLoading: currentUserProfileLoader, data: currentUserProfile, fetchUserProfile },
fetchCurrentUser,
} = useUser();
isLoading: currentUserSettingsLoader,
data: currentUserSettings,
fetchCurrentUserSettings,
} = useUserSettings();
const { loader: workspaceLoader, workspaces, fetchWorkspaces } = useWorkspace();
useSWR("USER_INFORMATION", async () => await fetchCurrentUser(), {
@ -75,19 +75,13 @@ export const AuthenticationWrapper: FC<TAuthenticationWrapper> = observer((props
return redirectionRoute;
};
if (isUserLoading || currentUserSettingsLoader || currentUserProfileLoader || workspaceLoader)
if (isUserLoading || currentUserProfileLoader || currentUserSettingsLoader || workspaceLoader)
return (
<div className="relative flex h-screen w-full items-center justify-center">
<Spinner />
</div>
);
console.log("---");
console.log("currentUser", currentUser?.id);
console.log("currentUserProfile", currentUserProfile?.id);
console.log("currentUserSettings", currentUserSettings?.id);
console.log("---");
if (pageType === EPageTypes.PUBLIC) return <>{children}</>;
if (pageType === EPageTypes.NON_AUTHENTICATED) {

View File

@ -21,7 +21,7 @@ const StoreWrapper: FC<TStoreWrapper> = observer((props) => {
const { setQuery } = useAppRouter();
const { sidebarCollapsed, toggleSidebar } = useAppTheme();
const {
profile: { data: userProfile },
userProfile: { data: userProfile },
} = useUser();
// states
const [dom, setDom] = useState<undefined | HTMLElement>();

View File

@ -23,7 +23,7 @@ const ProfilePreferencesThemePage: NextPageWithLayout = observer(() => {
// store hooks
const {
data: currentUser,
profile: { data: userProfile },
userProfile: { data: userProfile },
} = useUser();
// computed
const userTheme = userProfile?.theme;

View File

@ -76,7 +76,7 @@ export class RootStore {
this.theme = new ThemeStore(this);
}
resetOnSignout() {
resetOnSignOut() {
this.workspaceRoot = new WorkspaceRootStore(this);
this.projectRoot = new ProjectRootStore(this);
this.memberRoot = new MemberRootStore(this);

View File

@ -1,11 +1,10 @@
import { action, makeObservable, observable, runInAction } from "mobx";
import set from "lodash/set";
// stores
import { RootStore } from "store/root.store";
// services
import { UserService } from "services/user.service";
// types
import { makeObservable, observable } from "mobx";
import { IUserAccount } from "@plane/types";
// services
import { UserService } from "@/services/user.service";
// stores
import { RootStore } from "@/store/root.store";
export interface IAccountStore {
// observables
@ -24,7 +23,10 @@ export class AccountStore implements IAccountStore {
provider: string | undefined = undefined;
// service
userService: UserService;
constructor(private store: RootStore, private _account: IUserAccount) {
constructor(
private store: RootStore,
private _account: IUserAccount
) {
makeObservable(this, {
// observables
isLoading: observable.ref,

View File

@ -1,6 +1,7 @@
import set from "lodash/set";
import { action, makeObservable, observable, runInAction } from "mobx";
// types
import { IUser, IUserAccount } from "@plane/types";
import { IUser } from "@plane/types";
// helpers
import { API_BASE_URL } from "@/helpers/common.helper";
// services
@ -8,54 +9,43 @@ import { AuthService } from "@/services/auth.service";
import { UserService } from "@/services/user.service";
// stores
import { RootStore } from "@/store/root.store";
import { IAccountStore, AccountStore } from "@/store/user/account.store";
import { ProfileStore, IProfileStore } from "@/store/user/profile.store";
import { IAccountStore } from "@/store/user/account.store";
import { ProfileStore, IUserProfileStore } from "@/store/user/profile.store";
import { IUserMembershipStore, UserMembershipStore } from "@/store/user/user-membership.store";
import { IUserSettingsStore, UserSettingsStore } from "./user-setting.store";
import { IUserSettingsStore, UserSettingsStore } from "./settings.store";
type TUserErrorStatus = {
status: string;
message: string;
};
export interface IUserStore {
// observables
isAuthenticated: boolean;
isLoading: boolean;
error: any | undefined;
// model observables
error: TUserErrorStatus | undefined;
data: IUser | undefined;
currentUserSettings: IUserSettingsStore;
profile: IProfileStore;
// store observables
userProfile: IUserProfileStore;
userSettings: IUserSettingsStore;
accounts: Record<string, IAccountStore>;
membership: IUserMembershipStore;
// actions
fetchCurrentUser: () => Promise<IUser>;
updateCurrentUser: (data: Partial<IUser>) => Promise<IUser>;
fetchUserAccounts: () => Promise<void>;
fetchCurrentUser: () => Promise<IUser | undefined>;
updateCurrentUser: (data: Partial<IUser>) => Promise<IUser | undefined>;
deactivateAccount: () => Promise<void>;
signOut: () => Promise<void>;
}
export class UserStore implements IUserStore {
// observables flags
// observables
isAuthenticated: boolean = false;
isLoading: boolean = true;
error: any | undefined = undefined;
isLoading: boolean = false;
error: TUserErrorStatus | undefined = undefined;
data: IUser | undefined = undefined;
// model observables
avatar: string | undefined = undefined;
cover_image: string | null = null;
date_joined: string | undefined = undefined;
display_name: string | undefined = undefined;
email: string | undefined = undefined;
first_name: string | undefined = undefined;
id: string | undefined = undefined;
is_active: boolean = false;
is_bot: boolean = false;
is_email_verified: boolean = false;
is_password_autoset: boolean = false;
last_name: string | undefined = undefined;
username: string | undefined = undefined;
user_timezone: string | undefined = undefined;
// relational observables
profile: IProfileStore;
currentUserSettings: IUserSettingsStore;
// store observables
userProfile: IUserProfileStore;
userSettings: IUserSettingsStore;
accounts: Record<string, IAccountStore> = {};
membership: IUserMembershipStore;
// service
@ -67,8 +57,8 @@ export class UserStore implements IUserStore {
constructor(rootStore: RootStore) {
// stores
this.rootStore = rootStore;
this.profile = new ProfileStore();
this.currentUserSettings = new UserSettingsStore();
this.userProfile = new ProfileStore();
this.userSettings = new UserSettingsStore();
this.membership = new UserMembershipStore(rootStore);
// service
this.userService = new UserService();
@ -81,86 +71,100 @@ export class UserStore implements IUserStore {
error: observable,
// model observables
data: observable,
profile: observable,
currentUserSettings: observable,
userProfile: observable,
userSettings: observable,
accounts: observable,
membership: observable,
// actions
fetchCurrentUser: action,
fetchUserAccounts: action,
updateCurrentUser: action,
deactivateAccount: action,
signOut: action,
});
}
/**
* Fetches the current user
* @returns Promise<IUser>
* @description fetches the current user
* @returns {Promise<IUser>}
*/
fetchCurrentUser = async () => {
try {
runInAction(() => {
this.isLoading = true;
this.error = undefined;
});
const user = await this.userService.currentUser();
runInAction(() => {
this.data = user;
this.isLoading = false;
this.isAuthenticated = true;
});
if (user && user.id) {
await this.userProfile.fetchUserProfile();
await this.userSettings.fetchCurrentUserSettings();
runInAction(() => {
this.data = user;
this.isLoading = false;
this.isAuthenticated = true;
});
}
return user;
} catch (error) {
runInAction(() => {
this.isLoading = false;
this.isAuthenticated = false;
this.error = error;
this.error = {
status: "user-fetch-error",
message: "Failed to fetch current user",
};
});
throw error;
}
};
/**
* Updates the current user
* @description updates the current user
* @param data
* @returns Promise<IUser>
* @returns {Promise<IUser>}
*/
updateCurrentUser = async (data: Partial<IUser>) => {
const currentUserData = this.data;
try {
if (currentUserData) {
Object.keys(data).forEach((key: string) => {
const userKey: keyof IUser = key as keyof IUser;
if (this.data) set(this.data, userKey, data[userKey]);
});
}
const user = await this.userService.updateUser(data);
runInAction(() => {
this.data = user;
});
return user;
} catch (error) {
if (currentUserData) {
Object.keys(currentUserData).forEach((key: string) => {
const userKey: keyof IUser = key as keyof IUser;
if (this.data) set(this.data, userKey, currentUserData[userKey]);
});
}
runInAction(() => {
this.error = {
status: "user-update-error",
message: "Failed to update current user",
};
});
throw error;
}
};
/**
* Deactivates the current user
* @returns Promise<void>
* @description deactivates the current user
* @returns {Promise<void>}
*/
deactivateAccount = async () => {
await this.userService.deactivateAccount();
this.rootStore.resetOnSignout();
this.rootStore.resetOnSignOut();
};
/**
* Signs out the current user
* @returns Promise<void>
* @description signs out the current user
* @returns {Promise<void>}
*/
signOut = async () => {
await this.authService.signOut(API_BASE_URL);
this.rootStore.resetOnSignout();
};
/**
* Fetches the user accounts
*/
fetchUserAccounts = async () => {
const userAccounts = await this.userService.getCurrentUserAccounts();
runInAction(() => {
userAccounts.forEach((account: IUserAccount) => {
this.accounts[account.provider_account_id] = new AccountStore(this.rootStore, account);
});
});
this.rootStore.resetOnSignOut();
};
}

View File

@ -1,3 +1,4 @@
import set from "lodash/set";
import { action, makeObservable, observable, runInAction } from "mobx";
// services
import { UserService } from "services/user.service";
@ -9,20 +10,21 @@ type TError = {
message: string;
};
export interface IProfileStore {
export interface IUserProfileStore {
// observables
isLoading: boolean;
data: TUserProfile;
error: TError | undefined;
data: TUserProfile;
// actions
fetchUserProfile: () => Promise<TUserProfile | undefined>;
updateUserProfile: (data: Partial<TUserProfile>) => Promise<void>;
updateUserOnBoard: () => Promise<void>;
updateTourCompleted: () => Promise<void>;
updateUserProfile: (data: Partial<TUserProfile>) => Promise<TUserProfile | undefined>;
updateUserOnBoard: () => Promise<TUserProfile | undefined>;
updateTourCompleted: () => Promise<TUserProfile | undefined>;
}
export class ProfileStore implements IProfileStore {
isLoading: boolean = true;
export class ProfileStore implements IUserProfileStore {
isLoading: boolean = false;
error: TError | undefined = undefined;
data: TUserProfile = {
id: undefined,
user: undefined,
@ -53,7 +55,7 @@ export class ProfileStore implements IProfileStore {
created_at: "",
updated_at: "",
};
error: TError | undefined = undefined;
// services
userService: UserService;
@ -61,8 +63,8 @@ export class ProfileStore implements IProfileStore {
makeObservable(this, {
// observables
isLoading: observable.ref,
data: observable,
error: observable,
data: observable,
// actions
fetchUserProfile: action,
updateUserProfile: action,
@ -74,6 +76,10 @@ export class ProfileStore implements IProfileStore {
}
// actions
/**
* @description fetches user profile information
* @returns {Promise<TUserProfile | undefined>}
*/
fetchUserProfile = async () => {
try {
runInAction(() => {
@ -85,81 +91,91 @@ export class ProfileStore implements IProfileStore {
this.isLoading = false;
this.data = userProfile;
});
return userProfile;
} catch (error) {
runInAction(() => {
this.isLoading = false;
this.error = {
status: "error",
message: "Failed to fetch instance info",
};
});
}
};
updateUserProfile = async (data: Partial<TUserProfile>) => {
try {
runInAction(() => {
this.isLoading = true;
this.error = undefined;
});
const userProfile = await this.userService.updateCurrentUserProfile(data);
runInAction(() => {
this.isLoading = false;
this.data = userProfile;
});
} catch (error) {
console.log("Failed to fetch profile details");
runInAction(() => {
this.isLoading = true;
this.error = {
status: "error",
message: "Failed to fetch instance info",
status: "user-profile-fetch-error",
message: "Failed to fetch user profile",
};
});
}
};
/**
* Updates the user onboarding status
* @returns Promise<void>
* @description updated the user profile information
* @param {Partial<TUserProfile>} data
* @returns {Promise<TUserProfile | undefined>}
*/
updateUserProfile = async (data: Partial<TUserProfile>) => {
const currentUserProfileData = this.data;
try {
if (currentUserProfileData) {
Object.keys(data).forEach((key: string) => {
const userKey: keyof TUserProfile = key as keyof TUserProfile;
if (this.data) set(this.data, userKey, data[userKey]);
});
}
const userProfile = await this.userService.updateCurrentUserProfile(data);
return userProfile;
} catch (error) {
if (currentUserProfileData) {
Object.keys(currentUserProfileData).forEach((key: string) => {
const userKey: keyof TUserProfile = key as keyof TUserProfile;
if (this.data) set(this.data, userKey, currentUserProfileData[userKey]);
});
}
runInAction(() => {
this.error = {
status: "user-profile-update-error",
message: "Failed to update user profile",
};
});
}
};
/**
* @description updates the user onboarding status
* @returns @returns {Promise<TUserProfile | undefined>}
*/
updateUserOnBoard = async () => {
const isUserProfileOnboard = this.data.is_onboarded || false;
try {
runInAction(() => {
this.data = {
...this.data,
is_onboarded: true,
} as TUserProfile;
});
const user = this.data ?? undefined;
if (!user) return;
await this.userService.updateUserOnBoard();
runInAction(() => set(this.data, ["is_onboarded"], true));
const userProfile = await this.userService.updateUserOnBoard();
return userProfile;
} catch (error) {
this.fetchUserProfile();
runInAction(() => {
set(this.data, ["is_onboarded"], isUserProfileOnboard);
this.error = {
status: "user-profile-onboard-error",
message: "Failed to update user profile is_onboarded",
};
});
throw error;
}
};
/**
* Updates the user tour completed status
* @returns Promise<void>
* @description updates the user tour completed status
* @returns @returns {Promise<TUserProfile | undefined>}
*/
updateTourCompleted = async () => {
const isUserProfileTourCompleted = this.data.is_tour_completed || false;
try {
if (this.data) {
runInAction(() => {
this.data = {
...this.data,
is_tour_completed: true,
} as TUserProfile;
});
const response = await this.userService.updateUserTourCompleted();
return response;
}
runInAction(() => set(this.data, ["is_tour_completed"], true));
const userProfile = await this.userService.updateUserTourCompleted();
return userProfile;
} catch (error) {
this.fetchUserProfile();
runInAction(() => {
set(this.data, ["is_tour_completed"], isUserProfileTourCompleted);
this.error = {
status: "user-profile-tour-complete-error",
message: "Failed to update user profile is_tour_completed",
};
});
throw error;
}
};

View File

@ -1,8 +1,7 @@
import { action, makeObservable, observable, runInAction } from "mobx";
// services
import { UserService } from "services/user.service";
// types
import { IUserSettings } from "@plane/types";
// services
import { UserService } from "@/services/user.service";
type TError = {
status: string;
@ -12,14 +11,16 @@ type TError = {
export interface IUserSettingsStore {
// observables
isLoading: boolean;
data: IUserSettings;
error: TError | undefined;
data: IUserSettings;
// actions
fetchCurrentUserSettings: () => Promise<IUserSettings | undefined>;
}
export class UserSettingsStore implements IUserSettingsStore {
isLoading: boolean = true;
// observables
isLoading: boolean = false;
error: TError | undefined = undefined;
data: IUserSettings = {
id: undefined,
email: undefined,
@ -31,7 +32,6 @@ export class UserSettingsStore implements IUserSettingsStore {
invites: undefined,
},
};
error: TError | undefined = undefined;
// services
userService: UserService;
@ -39,8 +39,8 @@ export class UserSettingsStore implements IUserSettingsStore {
makeObservable(this, {
// observables
isLoading: observable.ref,
data: observable,
error: observable,
data: observable,
// actions
fetchCurrentUserSettings: action,
});
@ -49,26 +49,28 @@ export class UserSettingsStore implements IUserSettingsStore {
}
// actions
/**
* @description fetches user profile information
* @returns {Promise<IUserSettings | undefined>}
*/
fetchCurrentUserSettings = async () => {
try {
runInAction(() => {
this.isLoading = true;
this.error = undefined;
});
const currentUserSettings = await this.userService.currentUserSettings();
const userSettings = await this.userService.currentUserSettings();
runInAction(() => {
this.isLoading = false;
this.data = currentUserSettings;
this.data = userSettings;
});
return currentUserSettings;
return userSettings;
} catch (error) {
console.log("Failed to fetch profile details");
runInAction(() => {
this.isLoading = false;
this.error = {
status: "error",
message: "Failed to fetch instance info",
message: "Failed to fetch user settings",
};
});
}