import { useCallback, useMemo } from "react"; // types import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, IssuePaginationOptions, TIssue, TIssueKanbanFilters, TIssuesResponse, TLoader, TProfileViews, } from "@plane/types"; import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; import { useAppRouter, useIssues } from "./store"; interface IssueActions { fetchIssues: ( loadType: TLoader, options: IssuePaginationOptions, viewId?: string ) => Promise; fetchNextIssues: (groupId?: string, subGroupId?: string) => Promise; removeIssue: (projectId: string | undefined | null, issueId: string) => Promise; createIssue?: (projectId: string | undefined | null, data: Partial) => Promise; quickAddIssue?: (projectId: string | undefined | null, data: TIssue) => Promise; updateIssue?: (projectId: string | undefined | null, issueId: string, data: Partial) => Promise; removeIssueFromView?: (projectId: string | undefined | null, issueId: string) => Promise; archiveIssue?: (projectId: string | undefined | null, issueId: string) => Promise; restoreIssue?: (projectId: string | undefined | null, issueId: string) => Promise; updateFilters: ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => Promise; } export const useIssuesActions = (storeType: EIssuesStoreType): IssueActions => { const projectIssueActions = useProjectIssueActions(); const cycleIssueActions = useCycleIssueActions(); const moduleIssueActions = useModuleIssueActions(); const projectViewIssueActions = useProjectViewIssueActions(); const globalIssueActions = useGlobalIssueActions(); const profileIssueActions = useProfileIssueActions(); const draftIssueActions = useDraftIssueActions(); const archivedIssueActions = useArchivedIssueActions(); switch (storeType) { case EIssuesStoreType.PROJECT_VIEW: return projectViewIssueActions; case EIssuesStoreType.PROFILE: return profileIssueActions; case EIssuesStoreType.ARCHIVED: return archivedIssueActions; case EIssuesStoreType.DRAFT: return draftIssueActions; case EIssuesStoreType.CYCLE: return cycleIssueActions; case EIssuesStoreType.MODULE: return moduleIssueActions; case EIssuesStoreType.GLOBAL: return globalIssueActions; case EIssuesStoreType.PROJECT: default: return projectIssueActions; } }; const useProjectIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.PROJECT); const { workspaceSlug, projectId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions) => { if (!workspaceSlug || !projectId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId) return; return issues.fetchNextIssues(workspaceSlug.toString(), projectId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, projectId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data); }, [issues.createIssue, workspaceSlug] ); const quickAddIssue = useCallback( async (projectId: string | undefined | null, data: TIssue) => { if (!workspaceSlug || !projectId) return; return await issues.quickAddIssue(workspaceSlug, projectId, data); }, [issues.quickAddIssue, workspaceSlug] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const archiveIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.archiveIssue(workspaceSlug, projectId, issueId); }, [issues.archiveIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters); }, [issuesFilter.updateFilters, workspaceSlug] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, archiveIssue, updateFilters, }), [fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, archiveIssue, updateFilters] ); }; const useCycleIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.CYCLE); const { workspaceSlug, projectId, cycleId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions, cycleId?: string) => { if (!workspaceSlug || !projectId || !cycleId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options, cycleId.toString()); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId || !cycleId) return; return issues.fetchNextIssues( workspaceSlug.toString(), projectId.toString(), cycleId.toString(), groupId, subGroupId ); }, [issues.fetchIssues, workspaceSlug, projectId, cycleId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!cycleId || !workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data, cycleId); }, [issues.createIssue, cycleId, workspaceSlug] ); const quickAddIssue = useCallback( async (projectId: string | undefined | null, data: TIssue) => { if (!cycleId || !workspaceSlug || !projectId) return; return await issues.quickAddIssue(workspaceSlug, projectId, data, cycleId); }, [issues.quickAddIssue, workspaceSlug, cycleId] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const removeIssueFromView = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!cycleId || !workspaceSlug || !projectId) return; return await issues.removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId); }, [issues.removeIssueFromCycle, cycleId, workspaceSlug] ); const archiveIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.archiveIssue(workspaceSlug, projectId, issueId); }, [issues.archiveIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!cycleId || !workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters, cycleId); }, [issuesFilter.updateFilters, cycleId, workspaceSlug] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, removeIssueFromView, archiveIssue, updateFilters, }), [ fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, removeIssueFromView, archiveIssue, updateFilters, ] ); }; const useModuleIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.MODULE); const { workspaceSlug, projectId, moduleId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions, moduleId?: string) => { if (!workspaceSlug || !projectId || !moduleId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options, moduleId.toString()); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId || !moduleId) return; return issues.fetchNextIssues( workspaceSlug.toString(), projectId.toString(), moduleId.toString(), groupId, subGroupId ); }, [issues.fetchIssues, workspaceSlug, projectId, moduleId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!moduleId || !workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data, moduleId); }, [issues.createIssue, moduleId, workspaceSlug] ); const quickAddIssue = useCallback( async (projectId: string | undefined | null, data: TIssue) => { if (!moduleId || !workspaceSlug || !projectId) return; return await issues.quickAddIssue(workspaceSlug, projectId, data, moduleId); }, [issues.quickAddIssue, workspaceSlug, moduleId] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const removeIssueFromView = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!moduleId || !workspaceSlug || !projectId) return; return await issues.removeIssuesFromModule(workspaceSlug, projectId, moduleId, [issueId]); }, [issues.removeIssuesFromModule, moduleId, workspaceSlug] ); const archiveIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.archiveIssue(workspaceSlug, projectId, issueId); }, [issues.archiveIssue, moduleId, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!moduleId || !workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters, moduleId); }, [issuesFilter.updateFilters, moduleId] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, removeIssueFromView, archiveIssue, updateFilters, }), [fetchIssues, createIssue, updateIssue, removeIssue, removeIssueFromView, archiveIssue, updateFilters] ); }; const useProfileIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.PROFILE); const { workspaceSlug, userId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions, viewId?: string) => { if (!workspaceSlug || !userId || !viewId) return; return issues.fetchIssues( workspaceSlug.toString(), userId.toString(), loadType, options, viewId as TProfileViews ); }, [issues.fetchIssues, workspaceSlug, userId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !userId) return; return issues.fetchNextIssues(workspaceSlug.toString(), userId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, userId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data); }, [issues.createIssue, workspaceSlug] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const archiveIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.archiveIssue(workspaceSlug, projectId, issueId); }, [issues.archiveIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!userId || !workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters, userId); }, [issuesFilter.updateFilters, userId, workspaceSlug] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, updateIssue, removeIssue, archiveIssue, updateFilters, }), [fetchIssues, createIssue, updateIssue, removeIssue, archiveIssue, updateFilters] ); }; const useProjectViewIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.PROJECT_VIEW); const { workspaceSlug, projectId, viewId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions) => { if (!workspaceSlug || !projectId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId) return; return issues.fetchNextIssues(workspaceSlug.toString(), projectId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, projectId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data); }, [issues.createIssue, workspaceSlug] ); const quickAddIssue = useCallback( async (projectId: string | undefined | null, data: TIssue) => { if (!workspaceSlug || !projectId) return; return await issues.quickAddIssue(workspaceSlug, projectId, data); }, [issues.quickAddIssue, workspaceSlug] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const archiveIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.archiveIssue(workspaceSlug, projectId, issueId); }, [issues.archiveIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!viewId || !workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters, viewId); }, [issuesFilter.updateFilters, viewId, workspaceSlug] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, archiveIssue, updateFilters, }), [fetchIssues, fetchNextIssues, createIssue, quickAddIssue, updateIssue, removeIssue, archiveIssue, updateFilters] ); }; const useDraftIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.DRAFT); const { workspaceSlug, projectId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions) => { if (!workspaceSlug || !projectId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId) return; return issues.fetchNextIssues(workspaceSlug.toString(), projectId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, projectId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data); }, [issues.createIssue, workspaceSlug] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters); }, [issuesFilter.updateFilters] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, updateIssue, removeIssue, updateFilters, }), [fetchIssues, createIssue, updateIssue, removeIssue, updateFilters] ); }; const useArchivedIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.ARCHIVED); const { workspaceSlug, projectId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions) => { if (!workspaceSlug || !projectId) return; return issues.fetchIssues(workspaceSlug.toString(), projectId.toString(), loadType, options); }, [issues.fetchIssues, workspaceSlug, projectId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !projectId) return; return issues.fetchNextIssues(workspaceSlug.toString(), projectId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, projectId] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue] ); const restoreIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.restoreIssue(workspaceSlug, projectId, issueId); }, [issues.restoreIssue] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters); }, [issuesFilter.updateFilters] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, removeIssue, restoreIssue, updateFilters, }), [fetchIssues, fetchNextIssues, removeIssue, restoreIssue, updateFilters] ); }; const useGlobalIssueActions = () => { const { issues, issuesFilter } = useIssues(EIssuesStoreType.GLOBAL); const { workspaceSlug, globalViewId } = useAppRouter(); const fetchIssues = useCallback( async (loadType: TLoader, options: IssuePaginationOptions) => { if (!workspaceSlug || !globalViewId) return; return issues.fetchIssues(workspaceSlug.toString(), globalViewId.toString(), loadType, options); }, [issues.fetchIssues, workspaceSlug, globalViewId] ); const fetchNextIssues = useCallback( async (groupId?: string, subGroupId?: string) => { if (!workspaceSlug || !globalViewId) return; return issues.fetchNextIssues(workspaceSlug.toString(), globalViewId.toString(), groupId, subGroupId); }, [issues.fetchIssues, workspaceSlug, globalViewId] ); const createIssue = useCallback( async (projectId: string | undefined | null, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.createIssue(workspaceSlug, projectId, data); }, [issues.createIssue, workspaceSlug] ); const updateIssue = useCallback( async (projectId: string | undefined | null, issueId: string, data: Partial) => { if (!workspaceSlug || !projectId) return; return await issues.updateIssue(workspaceSlug, projectId, issueId, data); }, [issues.updateIssue, workspaceSlug] ); const removeIssue = useCallback( async (projectId: string | undefined | null, issueId: string) => { if (!workspaceSlug || !projectId) return; return await issues.removeIssue(workspaceSlug, projectId, issueId); }, [issues.removeIssue, workspaceSlug] ); const updateFilters = useCallback( async ( projectId: string, filterType: EIssueFilterType, filters: IIssueFilterOptions | IIssueDisplayFilterOptions | IIssueDisplayProperties | TIssueKanbanFilters ) => { if (!globalViewId || !workspaceSlug) return; return await issuesFilter.updateFilters(workspaceSlug, projectId, filterType, filters, globalViewId); }, [issuesFilter.updateFilters, globalViewId, workspaceSlug] ); return useMemo( () => ({ fetchIssues, fetchNextIssues, createIssue, updateIssue, removeIssue, updateFilters, }), [createIssue, updateIssue, removeIssue, updateFilters] ); };