forked from github/plane
Refactoring Phase 1 (#199)
* style: added cta at the bottom of sidebar, added missing icons as well, showing dynamic workspace member count on workspace dropdown * refractor: running parallel request, made create/edit label function to async function * fix: sidebar dropdown content going below kanban items outside click detection in need help dropdown * refractor: making parallel api calls fix: create state input comes at bottom, create state input gets on focus automatically, form is getting submitted on enter click * refactoring file structure and signin page * style: changed text and added spinner for signing in loading * refractor: removed unused type * fix: my issue cta in profile page sending to 404 page * fix: added new s3 bucket url in next.config.js file increased image modal height * packaging UI components * eslint config * eslint fixes * refactoring changes * build fixes * minor fixes * adding todo comments for reference * refactor: cleared unused imports and re ordered imports * refactor: removed unused imports * fix: added workspace argument to useissues hook * refactor: removed api-routes file, unnecessary constants * refactor: created helpers folder, removed unnecessary constants * refactor: new context for issue view * refactoring issues page * build fixes * refactoring * refactor: create issue modal * refactor: module ui * fix: sub-issues mutation * fix: create more option in create issue modal * description form debounce issue * refactor: global component for assignees list * fix: link module interface * fix: priority icons and sub-issues count added * fix: cycle mutation in issue details page * fix: remove issue from cycle mutation * fix: create issue modal in home page * fix: removed unnecessary props * fix: updated create issue form status * fix: settings auth breaking * refactor: issue details page Co-authored-by: Dakshesh Jain <dakshesh.jain14@gmail.com> Co-authored-by: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Co-authored-by: venkatesh-soulpage <venkatesh.marreboyina@soulpageit.com> Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com> Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia1001@gmail.com>
This commit is contained in:
committed by
GitHub
parent
9134b0c543
commit
9075f9441c
19
apps/app/hooks/use-debounce.tsx
Normal file
19
apps/app/hooks/use-debounce.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
const useDebounce = (value: any, milliSeconds: number) => {
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, milliSeconds);
|
||||
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [value, milliSeconds]);
|
||||
|
||||
return debouncedValue;
|
||||
};
|
||||
|
||||
export default useDebounce;
|
||||
96
apps/app/hooks/use-issue-properties.tsx
Normal file
96
apps/app/hooks/use-issue-properties.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import issueServices from "services/issues.service";
|
||||
// hooks
|
||||
import useUser from "hooks/use-user";
|
||||
// types
|
||||
import { IssuePriorities, Properties } from "types";
|
||||
|
||||
const initialValues: Properties = {
|
||||
key: true,
|
||||
state: true,
|
||||
assignee: true,
|
||||
priority: false,
|
||||
due_date: false,
|
||||
cycle: false,
|
||||
sub_issue_count: false,
|
||||
};
|
||||
|
||||
// TODO: CHECK THIS LOGIC
|
||||
const useIssuesProperties = (workspaceSlug?: string, projectId?: string) => {
|
||||
const [properties, setProperties] = useState<Properties>(initialValues);
|
||||
|
||||
const { user } = useUser();
|
||||
|
||||
const { data: issueProperties, mutate: mutateIssueProperties } = useSWR<IssuePriorities>(
|
||||
workspaceSlug && projectId
|
||||
? `/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/`
|
||||
: null,
|
||||
workspaceSlug && projectId
|
||||
? () => issueServices.getIssueProperties(workspaceSlug, projectId)
|
||||
: null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!issueProperties || !workspaceSlug || !projectId || !user) return;
|
||||
setProperties({ ...initialValues, ...issueProperties.properties });
|
||||
|
||||
if (Object.keys(issueProperties).length === 0)
|
||||
issueServices.createIssueProperties(workspaceSlug, projectId, {
|
||||
properties: { ...initialValues },
|
||||
user: user.id,
|
||||
});
|
||||
else if (Object.keys(issueProperties?.properties).length === 0)
|
||||
issueServices.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, {
|
||||
properties: { ...initialValues },
|
||||
user: user.id,
|
||||
});
|
||||
}, [issueProperties, workspaceSlug, projectId, user]);
|
||||
|
||||
const updateIssueProperties = useCallback(
|
||||
(key: keyof Properties) => {
|
||||
if (!workspaceSlug || !user) return;
|
||||
setProperties((prev) => ({ ...prev, [key]: !prev[key] }));
|
||||
if (issueProperties && projectId) {
|
||||
mutateIssueProperties(
|
||||
(prev) =>
|
||||
({
|
||||
...prev,
|
||||
properties: { ...prev?.properties, [key]: !prev?.properties?.[key] },
|
||||
} as IssuePriorities),
|
||||
false
|
||||
);
|
||||
if (Object.keys(issueProperties).length > 0) {
|
||||
issueServices.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, {
|
||||
properties: {
|
||||
...issueProperties.properties,
|
||||
[key]: !issueProperties.properties[key],
|
||||
},
|
||||
user: user.id,
|
||||
});
|
||||
} else {
|
||||
issueServices.createIssueProperties(workspaceSlug, projectId, {
|
||||
properties: { ...initialValues },
|
||||
user: user.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
[workspaceSlug, projectId, issueProperties, user, mutateIssueProperties]
|
||||
);
|
||||
|
||||
const newProperties: Properties = {
|
||||
key: properties.key,
|
||||
state: properties.state,
|
||||
assignee: properties.assignee,
|
||||
priority: properties.priority,
|
||||
due_date: properties.due_date,
|
||||
cycle: properties.cycle,
|
||||
sub_issue_count: properties.sub_issue_count,
|
||||
};
|
||||
|
||||
return [newProperties, updateIssueProperties] as const;
|
||||
};
|
||||
|
||||
export default useIssuesProperties;
|
||||
125
apps/app/hooks/use-issue-view.tsx
Normal file
125
apps/app/hooks/use-issue-view.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { useContext } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// services
|
||||
import stateService from "services/state.service";
|
||||
// contexts
|
||||
import { issueViewContext } from "contexts/issue-view.context";
|
||||
// helpers
|
||||
import { groupBy, orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { STATE_LIST } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { PRIORITIES } from "constants/";
|
||||
|
||||
const useIssueView = (projectIssues: IIssue[]) => {
|
||||
const {
|
||||
issueView,
|
||||
groupByProperty,
|
||||
setGroupByProperty,
|
||||
orderBy,
|
||||
setOrderBy,
|
||||
filterIssue,
|
||||
setFilterIssue,
|
||||
resetFilterToDefault,
|
||||
setNewFilterDefaultView,
|
||||
setIssueViewToKanban,
|
||||
setIssueViewToList,
|
||||
} = useContext(issueViewContext);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { data: states } = useSWR(
|
||||
workspaceSlug && projectId ? STATE_LIST(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
? () => stateService.getStates(workspaceSlug as string, projectId as string)
|
||||
: null
|
||||
);
|
||||
|
||||
let groupedByIssues: {
|
||||
[key: string]: IIssue[];
|
||||
} = {
|
||||
...(groupByProperty === "state_detail.name"
|
||||
? Object.fromEntries(
|
||||
states
|
||||
?.sort((a, b) => a.sequence - b.sequence)
|
||||
?.map((state) => [
|
||||
state.name,
|
||||
projectIssues.filter((issue) => issue.state === state.name) ?? [],
|
||||
]) ?? []
|
||||
)
|
||||
: groupByProperty === "priority"
|
||||
? Object.fromEntries(
|
||||
PRIORITIES.map((priority) => [
|
||||
priority,
|
||||
projectIssues.filter((issue) => issue.priority === priority) ?? [],
|
||||
])
|
||||
)
|
||||
: {}),
|
||||
...groupBy(projectIssues ?? [], groupByProperty ?? ""),
|
||||
};
|
||||
|
||||
if (orderBy) {
|
||||
groupedByIssues = Object.fromEntries(
|
||||
Object.entries(groupedByIssues).map(([key, value]) => [
|
||||
key,
|
||||
orderArrayBy(value, orderBy, "descending"),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (filterIssue !== null) {
|
||||
if (filterIssue === "activeIssue") {
|
||||
const filteredStates = states?.filter(
|
||||
(state) => state.group === "started" || state.group === "unstarted"
|
||||
);
|
||||
groupedByIssues = Object.fromEntries(
|
||||
filteredStates
|
||||
?.sort((a, b) => a.sequence - b.sequence)
|
||||
?.map((state) => [
|
||||
state.name,
|
||||
projectIssues.filter((issue) => issue.state === state.id) ?? [],
|
||||
]) ?? []
|
||||
);
|
||||
} else if (filterIssue === "backlogIssue") {
|
||||
const filteredStates = states?.filter(
|
||||
(state) => state.group === "backlog" || state.group === "cancelled"
|
||||
);
|
||||
groupedByIssues = Object.fromEntries(
|
||||
filteredStates
|
||||
?.sort((a, b) => a.sequence - b.sequence)
|
||||
?.map((state) => [
|
||||
state.name,
|
||||
projectIssues.filter((issue) => issue.state === state.id) ?? [],
|
||||
]) ?? []
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (groupByProperty === "priority" && orderBy === "priority") {
|
||||
setOrderBy(null);
|
||||
}
|
||||
|
||||
return {
|
||||
groupedByIssues,
|
||||
issueView,
|
||||
groupByProperty,
|
||||
setGroupByProperty,
|
||||
orderBy,
|
||||
setOrderBy,
|
||||
filterIssue,
|
||||
setFilterIssue,
|
||||
resetFilterToDefault,
|
||||
setNewFilterDefaultView,
|
||||
setIssueViewToKanban,
|
||||
setIssueViewToList,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export default useIssueView;
|
||||
22
apps/app/hooks/use-issues.tsx
Normal file
22
apps/app/hooks/use-issues.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import userService from "services/user.service";
|
||||
// types
|
||||
import type { IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { USER_ISSUE } from "constants/fetch-keys";
|
||||
|
||||
const useIssues = (workspaceSlug: string | undefined) => {
|
||||
// API Fetching
|
||||
const { data: myIssues, mutate: mutateMyIssues } = useSWR<IIssue[]>(
|
||||
workspaceSlug ? USER_ISSUE(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => userService.userIssues(workspaceSlug as string) : null
|
||||
);
|
||||
|
||||
return {
|
||||
myIssues: myIssues || [],
|
||||
mutateMyIssues,
|
||||
};
|
||||
};
|
||||
|
||||
export default useIssues;
|
||||
39
apps/app/hooks/use-local-storage.tsx
Normal file
39
apps/app/hooks/use-local-storage.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
|
||||
// TODO: No Use of this
|
||||
const useLocalStorage = <T,>(
|
||||
key: string,
|
||||
initialValue?: T extends Function ? never : T | (() => T)
|
||||
) => {
|
||||
const [value, setValue] = useState<T | string>("");
|
||||
|
||||
useEffect(() => {
|
||||
const data = window.localStorage.getItem(key);
|
||||
if (data !== null && data !== "undefined") setValue(JSON.parse(data));
|
||||
else setValue(typeof initialValue === "function" ? initialValue() : initialValue);
|
||||
}, [key, initialValue]);
|
||||
|
||||
const updateState = useCallback(
|
||||
(value: T) => {
|
||||
if (!value) window.localStorage.removeItem(key);
|
||||
else window.localStorage.setItem(key, JSON.stringify(value));
|
||||
setValue(value);
|
||||
window.dispatchEvent(new Event(`local-storage-change-${key}`));
|
||||
},
|
||||
[key]
|
||||
);
|
||||
|
||||
const reHydrateState = useCallback(() => {
|
||||
const data = window.localStorage.getItem(key);
|
||||
if (data !== null) setValue(JSON.parse(data));
|
||||
}, [key]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener(`local-storage-change-${key}`, reHydrateState);
|
||||
return () => window.removeEventListener(`local-storage-change-${key}`, reHydrateState);
|
||||
}, [reHydrateState, key]);
|
||||
|
||||
return [value, updateState];
|
||||
};
|
||||
|
||||
export default useLocalStorage;
|
||||
122
apps/app/hooks/use-my-issues-filter.tsx
Normal file
122
apps/app/hooks/use-my-issues-filter.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import stateService from "services/state.service";
|
||||
import userService from "services/user.service";
|
||||
// hooks
|
||||
import useUser from "hooks/use-user";
|
||||
// helpers
|
||||
import { groupBy } from "helpers/array.helper";
|
||||
// types
|
||||
import { Properties, NestedKeyOf, IIssue } from "types";
|
||||
// fetch-keys
|
||||
import { STATE_LIST } from "constants/fetch-keys";
|
||||
// constants
|
||||
import { PRIORITIES } from "constants/";
|
||||
|
||||
const initialValues: Properties = {
|
||||
key: true,
|
||||
state: true,
|
||||
assignee: true,
|
||||
priority: false,
|
||||
due_date: false,
|
||||
cycle: false,
|
||||
sub_issue_count: false,
|
||||
};
|
||||
|
||||
// TODO: Refactor this logic
|
||||
const useMyIssuesProperties = (issues?: IIssue[]) => {
|
||||
const [properties, setProperties] = useState<Properties>(initialValues);
|
||||
const [groupByProperty, setGroupByProperty] = useState<NestedKeyOf<IIssue> | null>(null);
|
||||
|
||||
// FIXME: where this hook is used we may not have project id in the url
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { user } = useUser();
|
||||
|
||||
const { data: states } = useSWR(
|
||||
workspaceSlug && projectId ? STATE_LIST(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
? () => stateService.getStates(workspaceSlug as string, projectId as string)
|
||||
: null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
setProperties({ ...initialValues, ...user.my_issues_prop?.properties });
|
||||
setGroupByProperty(user.my_issues_prop?.groupBy ?? null);
|
||||
}, [user]);
|
||||
|
||||
const groupedByIssues: {
|
||||
[key: string]: IIssue[];
|
||||
} = {
|
||||
...(groupByProperty === "state_detail.name"
|
||||
? Object.fromEntries(
|
||||
states
|
||||
?.sort((a, b) => a.sequence - b.sequence)
|
||||
?.map((state) => [
|
||||
state.name,
|
||||
issues?.filter((issue) => issue.state === state.name) ?? [],
|
||||
]) ?? []
|
||||
)
|
||||
: groupByProperty === "priority"
|
||||
? Object.fromEntries(
|
||||
PRIORITIES.map((priority) => [
|
||||
priority,
|
||||
issues?.filter((issue) => issue.priority === priority) ?? [],
|
||||
])
|
||||
)
|
||||
: {}),
|
||||
...groupBy(issues ?? [], groupByProperty ?? ""),
|
||||
};
|
||||
|
||||
const setMyIssueProperty = (key: keyof Properties) => {
|
||||
if (!user) return;
|
||||
userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } });
|
||||
setProperties((prevData) => ({
|
||||
...prevData,
|
||||
[key]: !prevData[key],
|
||||
}));
|
||||
localStorage.setItem(
|
||||
"my_issues_prop",
|
||||
JSON.stringify({
|
||||
properties: {
|
||||
...properties,
|
||||
[key]: !properties[key],
|
||||
},
|
||||
groupBy: groupByProperty,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const setMyIssueGroupByProperty = (groupByProperty: NestedKeyOf<IIssue> | null) => {
|
||||
if (!user) return;
|
||||
userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } });
|
||||
setGroupByProperty(groupByProperty);
|
||||
localStorage.setItem(
|
||||
"my_issues_prop",
|
||||
JSON.stringify({ properties, groupBy: groupByProperty })
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const viewProps = localStorage.getItem("my_issues_prop");
|
||||
if (viewProps) {
|
||||
const { properties, groupBy } = JSON.parse(viewProps);
|
||||
setProperties(properties);
|
||||
setGroupByProperty(groupBy);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
filteredIssues: groupedByIssues,
|
||||
groupByProperty,
|
||||
properties,
|
||||
setMyIssueProperty,
|
||||
setMyIssueGroupByProperty,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export default useMyIssuesProperties;
|
||||
19
apps/app/hooks/use-outside-click-detector.tsx
Normal file
19
apps/app/hooks/use-outside-click-detector.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
const useOutsideClickDetector = (ref: React.RefObject<HTMLElement>, callback: () => void) => {
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
if (ref.current && !ref.current.contains(event.target as Node)) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("click", handleClick);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("click", handleClick);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export default useOutsideClickDetector;
|
||||
33
apps/app/hooks/use-project-members.tsx
Normal file
33
apps/app/hooks/use-project-members.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
// fetch-keys
|
||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
// hooks
|
||||
import useUser from "./use-user";
|
||||
|
||||
const useProjectMembers = (workspaceSlug: string, projectId: string) => {
|
||||
const { user } = useUser();
|
||||
// fetching project members
|
||||
const { data: members } = useSWR(PROJECT_MEMBERS(projectId), () =>
|
||||
projectService.projectMembers(workspaceSlug, projectId)
|
||||
);
|
||||
|
||||
const isMember = members?.some((item: any) => item.member.id === (user as any)?.id);
|
||||
|
||||
const canEdit = members?.some(
|
||||
(item) => (item.member.id === (user as any)?.id && item.role === 20) || item.role === 15
|
||||
);
|
||||
const canDelete = members?.some(
|
||||
(item) => item.member.id === (user as any)?.id && item.role === 20
|
||||
);
|
||||
|
||||
return {
|
||||
members,
|
||||
isMember,
|
||||
canEdit,
|
||||
canDelete,
|
||||
};
|
||||
};
|
||||
|
||||
export default useProjectMembers;
|
||||
31
apps/app/hooks/use-projects.tsx
Normal file
31
apps/app/hooks/use-projects.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import useSWR from "swr";
|
||||
import { useRouter } from "next/router";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
// constants
|
||||
import { PROJECTS_LIST } from "constants/fetch-keys";
|
||||
|
||||
const useProjects = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// api fetching
|
||||
const { data: projects, mutate: mutateProjects } = useSWR<IProject[]>(
|
||||
workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => projectService.getProjects(workspaceSlug as string) : null
|
||||
);
|
||||
|
||||
const recentProjects = projects
|
||||
?.sort((a, b) => Date.parse(`${a.updated_at}`) - Date.parse(`${b.updated_at}`))
|
||||
.filter((_item, index) => index < 3);
|
||||
|
||||
return {
|
||||
projects: projects || [],
|
||||
recentProjects: recentProjects || [],
|
||||
mutateProjects,
|
||||
};
|
||||
};
|
||||
|
||||
export default useProjects;
|
||||
9
apps/app/hooks/use-theme.tsx
Normal file
9
apps/app/hooks/use-theme.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useContext } from "react";
|
||||
import { themeContext } from "contexts/theme.context";
|
||||
|
||||
const useTheme = () => {
|
||||
const themeContextData = useContext(themeContext);
|
||||
return themeContextData;
|
||||
};
|
||||
|
||||
export default useTheme;
|
||||
9
apps/app/hooks/use-toast.tsx
Normal file
9
apps/app/hooks/use-toast.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useContext } from "react";
|
||||
import { toastContext } from "contexts/toast.context";
|
||||
|
||||
const useToast = () => {
|
||||
const toastContextData = useContext(toastContext);
|
||||
return toastContextData;
|
||||
};
|
||||
|
||||
export default useToast;
|
||||
42
apps/app/hooks/use-user.tsx
Normal file
42
apps/app/hooks/use-user.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { useContext, useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
// context
|
||||
import { UserContext } from "contexts/user.context";
|
||||
|
||||
interface useUserOptions {
|
||||
redirectTo?: string;
|
||||
}
|
||||
|
||||
const useUser = (options: useUserOptions = {}) => {
|
||||
// props
|
||||
const { redirectTo = null } = options;
|
||||
// context
|
||||
const contextData = useContext(UserContext);
|
||||
// router
|
||||
const router = useRouter();
|
||||
|
||||
/**
|
||||
* Checks for redirect url and user details from the API.
|
||||
* if the user is not authenticated, user will be redirected
|
||||
* to the provided redirectTo route.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!contextData?.user || !redirectTo) return;
|
||||
|
||||
if (!contextData?.user) {
|
||||
if (redirectTo) {
|
||||
router?.pathname !== redirectTo && router.push(redirectTo);
|
||||
}
|
||||
router?.pathname !== "/signin" && router.push("/signin");
|
||||
}
|
||||
if (contextData?.user) {
|
||||
if (redirectTo) {
|
||||
router?.pathname !== redirectTo && router.push(redirectTo);
|
||||
}
|
||||
}
|
||||
}, [contextData?.user, redirectTo, router]);
|
||||
|
||||
return { ...contextData };
|
||||
};
|
||||
|
||||
export default useUser;
|
||||
37
apps/app/hooks/use-workspace-details.tsx
Normal file
37
apps/app/hooks/use-workspace-details.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import workspaceService from "services/workspace.service";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_DETAILS } from "constants/fetch-keys";
|
||||
|
||||
const useWorkspaceDetails = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// Fetching Workspace Details
|
||||
const {
|
||||
data: workspaceDetails,
|
||||
error: workspaceDetailsError,
|
||||
mutate: mutateWorkspaceDetails,
|
||||
} = useSWR(
|
||||
workspaceSlug ? WORKSPACE_DETAILS(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => workspaceService.getWorkspace(workspaceSlug as string) : null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (workspaceDetailsError?.status === 404) {
|
||||
router.push("/404");
|
||||
} else if (workspaceDetailsError) {
|
||||
router.push("/error");
|
||||
}
|
||||
}, [workspaceDetailsError, router]);
|
||||
|
||||
return {
|
||||
workspaceDetails,
|
||||
workspaceDetailsError,
|
||||
mutateWorkspaceDetails,
|
||||
};
|
||||
};
|
||||
|
||||
export default useWorkspaceDetails;
|
||||
31
apps/app/hooks/use-workspaces.tsx
Normal file
31
apps/app/hooks/use-workspaces.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import useSWR from "swr";
|
||||
import { useRouter } from "next/router";
|
||||
// types
|
||||
import { IWorkspace } from "types";
|
||||
// services
|
||||
import workspaceService from "services/workspace.service";
|
||||
// constants
|
||||
import { USER_WORKSPACES } from "constants/fetch-keys";
|
||||
|
||||
const useWorkspaces = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// API to fetch user information
|
||||
const {
|
||||
data = [],
|
||||
error,
|
||||
mutate,
|
||||
} = useSWR<IWorkspace[]>(USER_WORKSPACES, () => workspaceService.userWorkspaces());
|
||||
// active workspace
|
||||
const activeWorkspace = data?.find((w) => w.slug === workspaceSlug);
|
||||
|
||||
return {
|
||||
workspaces: data,
|
||||
error,
|
||||
activeWorkspace,
|
||||
mutateWorkspaces: mutate,
|
||||
};
|
||||
};
|
||||
|
||||
export default useWorkspaces;
|
||||
Reference in New Issue
Block a user