refactor(renderer): dismantle useAppController 47-prop god-hook
Sections now subscribe directly to the Zustand store via useSectionContext
(shared data derivation) and useAppStore fine-grained selectors. Delete
useAppController, useExecutionController, useOrganizationController, and
useCommunicationController; the three domain forwarders held no logic
beyond re-exporting store slices.
SectionContentView becomes a 50-line layout dispatcher taking only
{section, error, pageTransition}; cross-domain run actions (startRun /
cancelRun) move into App.tsx and are exposed to sections through a new
AppActionsContext alongside refresh / setError / openPathWithFeedback.
App.tsx now calls useUIController + useCompanyController directly and
composes palette + navigation plumbing itself.
This commit is contained in:
1 parent
de77f5f38e
commit
e2253b92fa
12 files changed
+339
-897
No files matched your search
@@ -1,19 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { NEW_ENTITY_ID } from "../../lib/constants";
|
||||
import type {
|
||||
AgentRecord,
|
||||
ApprovalRecord,
|
||||
CompanyRecord,
|
||||
CostRecord,
|
||||
DocumentRecord,
|
||||
GoalRecord,
|
||||
ProjectRecord,
|
||||
RunRecord,
|
||||
SectionId,
|
||||
TaskRecord,
|
||||
WorkspaceRecord,
|
||||
ProfileSnapshot,
|
||||
} from "@shared/types";
|
||||
import type { SectionId } from "@shared/types";
|
||||
import {
|
||||
Kanban,
|
||||
ListChecks,
|
||||
@@ -43,88 +30,52 @@ import {
|
||||
} from "../../components/organization";
|
||||
import { ActionButton, ListFrame, ListRow, Modal, Panel, StatusPill } from "../../components/ui";
|
||||
import { unwrap } from "../../lib/desktop";
|
||||
import { useAppStore } from "../../state/store";
|
||||
import { useSectionContext } from "../../hooks/useSectionContext";
|
||||
import { useAppActions } from "../../hooks/useAppActions";
|
||||
|
||||
interface ExecutionSectionsProps {
|
||||
section: SectionId;
|
||||
snapshot: ProfileSnapshot;
|
||||
currentCompany: CompanyRecord | null;
|
||||
tasks: TaskRecord[];
|
||||
runs: RunRecord[];
|
||||
approvals: ApprovalRecord[];
|
||||
pendingApprovals: ApprovalRecord[];
|
||||
companyAgents: AgentRecord[];
|
||||
companyGoals: GoalRecord[];
|
||||
companyProjects: ProjectRecord[];
|
||||
companyWorkspaces: WorkspaceRecord[];
|
||||
companyCosts: CostRecord[];
|
||||
companyDocuments: DocumentRecord[];
|
||||
filteredActivity: ReturnType<ProfileSnapshot["activity"]["filter"]>;
|
||||
selectedRunId: string | null;
|
||||
selectedTask: TaskRecord | null;
|
||||
selectedTaskId: string | null;
|
||||
setSelectedTaskId: (id: string | null) => void;
|
||||
selectedConnector: ProfileSnapshot["connectors"][number] | null;
|
||||
setSelectedConnectorId: (id: string | null) => void;
|
||||
selectedApproval: ApprovalRecord | null;
|
||||
selectedApprovalId: string | null;
|
||||
setSelectedApprovalId: (id: string | null) => void;
|
||||
selectedGoalId: string | null;
|
||||
setSelectedGoalId: (id: string | null) => void;
|
||||
taskViewMode: "list" | "kanban";
|
||||
setTaskViewMode: (mode: "list" | "kanban") => void;
|
||||
setSection: (section: SectionId) => void;
|
||||
setConsoleOpen: (value: boolean) => void;
|
||||
setSelectedRunId: (id: string | null) => void;
|
||||
setSelectedCommunicationEntityId: (id: string | null) => void;
|
||||
refresh: () => Promise<void>;
|
||||
startRun: (taskId: string) => Promise<void>;
|
||||
cancelRun: (runId: string) => Promise<void>;
|
||||
openPathWithFeedback: (path: string) => Promise<void>;
|
||||
setError: (error: string | null) => void;
|
||||
}
|
||||
|
||||
export function ExecutionSections({
|
||||
section,
|
||||
snapshot,
|
||||
currentCompany,
|
||||
tasks,
|
||||
runs,
|
||||
approvals: _approvals,
|
||||
pendingApprovals,
|
||||
companyAgents,
|
||||
companyGoals,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
companyCosts,
|
||||
companyDocuments,
|
||||
filteredActivity,
|
||||
selectedRunId,
|
||||
selectedTask,
|
||||
selectedTaskId,
|
||||
setSelectedTaskId,
|
||||
selectedConnector,
|
||||
setSelectedConnectorId,
|
||||
selectedApproval,
|
||||
selectedApprovalId: _selectedApprovalId,
|
||||
setSelectedApprovalId,
|
||||
selectedGoalId,
|
||||
setSelectedGoalId,
|
||||
taskViewMode,
|
||||
setTaskViewMode,
|
||||
setSection,
|
||||
setConsoleOpen,
|
||||
setSelectedRunId,
|
||||
setSelectedCommunicationEntityId,
|
||||
refresh,
|
||||
startRun,
|
||||
cancelRun,
|
||||
openPathWithFeedback,
|
||||
setError: _setError,
|
||||
}: ExecutionSectionsProps) {
|
||||
const [costsTab, setCostsTab] = useState<"costs" | "policies" | "incidents">("costs");
|
||||
const selectedGoal = companyGoals.find((g) => g.id === selectedGoalId) ?? null;
|
||||
export function ExecutionSections({ section }: ExecutionSectionsProps) {
|
||||
const {
|
||||
snapshot,
|
||||
currentCompany,
|
||||
tasks,
|
||||
runs,
|
||||
pendingApprovals,
|
||||
companyAgents,
|
||||
companyGoals,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
companyCosts,
|
||||
companyDocuments,
|
||||
filteredActivity,
|
||||
selectedTask,
|
||||
selectedConnector,
|
||||
selectedApproval,
|
||||
selectedGoal,
|
||||
} = useSectionContext();
|
||||
const { refresh, startRun, cancelRun, openPathWithFeedback } = useAppActions();
|
||||
|
||||
if (!currentCompany) return null;
|
||||
const selectedRunId = useAppStore((s) => s.selectedRunId);
|
||||
const setSelectedRunId = useAppStore((s) => s.setSelectedRunId);
|
||||
const selectedTaskId = useAppStore((s) => s.selectedTaskId);
|
||||
const setSelectedTaskId = useAppStore((s) => s.setSelectedTaskId);
|
||||
const setSelectedConnectorId = useAppStore((s) => s.setSelectedConnectorId);
|
||||
const setSelectedApprovalId = useAppStore((s) => s.setSelectedApprovalId);
|
||||
const selectedGoalId = useAppStore((s) => s.selectedGoalId);
|
||||
const setSelectedGoalId = useAppStore((s) => s.setSelectedGoalId);
|
||||
const taskViewMode = useAppStore((s) => s.taskViewMode);
|
||||
const setTaskViewMode = useAppStore((s) => s.setTaskViewMode);
|
||||
const setSection = useAppStore((s) => s.setSection);
|
||||
const setConsoleOpen = useAppStore((s) => s.setConsoleOpen);
|
||||
const setSelectedCommunicationEntityId = useAppStore((s) => s.setSelectedCommunicationEntityId);
|
||||
|
||||
const [costsTab, setCostsTab] = useState<"costs" | "policies" | "incidents">("costs");
|
||||
|
||||
if (!snapshot || !currentCompany) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,23 +1,4 @@
|
||||
import type {
|
||||
AgentRecord,
|
||||
BrowserActionRecord,
|
||||
CompanyRecord,
|
||||
DocumentRecord,
|
||||
InboxItem,
|
||||
CompanyMetrics,
|
||||
KnowledgeEntryRecord,
|
||||
MeetingRecord,
|
||||
ProjectRecord,
|
||||
RunRecord,
|
||||
SectionId,
|
||||
SocialAccountRecord,
|
||||
SprintRecord,
|
||||
StandupReport,
|
||||
TaskRecord,
|
||||
WorkspaceRecord,
|
||||
ProfileSnapshot,
|
||||
} from "@shared/types";
|
||||
import type { AppLocale } from "@shared/locale";
|
||||
import type { SectionId } from "@shared/types";
|
||||
import { Inbox, StandupView, PerformanceView } from "../../components/inbox";
|
||||
import { Dashboard } from "../../components/dashboard";
|
||||
import { EntityWorkspace } from "../../components/EntityWorkspace";
|
||||
@@ -35,78 +16,51 @@ import { SkillsSection } from "../../components/skills";
|
||||
import { DocumentCenter, KnowledgeBaseManager, MeetingsManager, SprintManager } from "../../components/company-operations";
|
||||
import { Panel } from "../../components/ui";
|
||||
import { unwrap } from "../../lib/desktop";
|
||||
import { useAppStore } from "../../state/store";
|
||||
import { useSectionContext } from "../../hooks/useSectionContext";
|
||||
import { useAppActions } from "../../hooks/useAppActions";
|
||||
|
||||
interface OperationsSectionsProps {
|
||||
section: SectionId;
|
||||
snapshot: ProfileSnapshot;
|
||||
currentCompany: CompanyRecord | null;
|
||||
locale: AppLocale;
|
||||
tasks: TaskRecord[];
|
||||
runs: RunRecord[];
|
||||
companyAgents: AgentRecord[];
|
||||
companyProjects: ProjectRecord[];
|
||||
companyWorkspaces: WorkspaceRecord[];
|
||||
companyDocuments: DocumentRecord[];
|
||||
companyKnowledge: KnowledgeEntryRecord[];
|
||||
companyMeetings: MeetingRecord[];
|
||||
companySprints: SprintRecord[];
|
||||
socialAccounts: SocialAccountRecord[];
|
||||
browserActions: BrowserActionRecord[];
|
||||
inboxItems: InboxItem[];
|
||||
companyMetrics: CompanyMetrics | null;
|
||||
standupReport: StandupReport | null;
|
||||
companySecrets: ProfileSnapshot["secrets"];
|
||||
selectedWorkspace: WorkspaceRecord | null;
|
||||
setSelectedWorkspaceId: (id: string | null) => void;
|
||||
selectedCommunicationEntityId: string | null;
|
||||
setSelectedCommunicationEntityId: (id: string | null) => void;
|
||||
setSelectedTaskId: (id: string | null) => void;
|
||||
setSelectedApprovalId: (id: string | null) => void;
|
||||
setSection: (section: SectionId) => void;
|
||||
navigateTo: (section: SectionId, entityId?: string) => void;
|
||||
refresh: () => Promise<void>;
|
||||
openPathWithFeedback: (path: string) => Promise<void>;
|
||||
setError: (error: string | null) => void;
|
||||
filteredActivity: ReturnType<ProfileSnapshot["activity"]["filter"]>;
|
||||
companyCosts: ReturnType<ProfileSnapshot["costs"]["filter"]>;
|
||||
companyGoals: ReturnType<NonNullable<ProfileSnapshot["goals"]>["filter"]>;
|
||||
}
|
||||
|
||||
export function OperationsSections({
|
||||
section,
|
||||
snapshot,
|
||||
currentCompany,
|
||||
locale,
|
||||
tasks,
|
||||
runs,
|
||||
companyAgents,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
companyDocuments,
|
||||
companyKnowledge,
|
||||
companyMeetings,
|
||||
companySprints,
|
||||
socialAccounts,
|
||||
browserActions,
|
||||
inboxItems,
|
||||
companyMetrics,
|
||||
standupReport,
|
||||
companySecrets,
|
||||
selectedWorkspace,
|
||||
setSelectedWorkspaceId,
|
||||
selectedCommunicationEntityId,
|
||||
setSelectedCommunicationEntityId,
|
||||
setSelectedTaskId,
|
||||
setSelectedApprovalId,
|
||||
setSection,
|
||||
navigateTo,
|
||||
refresh,
|
||||
openPathWithFeedback,
|
||||
setError,
|
||||
filteredActivity,
|
||||
companyCosts,
|
||||
companyGoals,
|
||||
}: OperationsSectionsProps) {
|
||||
export function OperationsSections({ section }: OperationsSectionsProps) {
|
||||
const {
|
||||
snapshot,
|
||||
currentCompany,
|
||||
tasks,
|
||||
runs,
|
||||
companyAgents,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
companyDocuments,
|
||||
companyKnowledge,
|
||||
companyMeetings,
|
||||
companySprints,
|
||||
companyCosts,
|
||||
companyGoals,
|
||||
companySecrets,
|
||||
filteredActivity,
|
||||
selectedWorkspace,
|
||||
} = useSectionContext();
|
||||
const { refresh, openPathWithFeedback, setError } = useAppActions();
|
||||
|
||||
const locale = useAppStore((s) => s.locale);
|
||||
const inboxItems = useAppStore((s) => s.inboxItems);
|
||||
const companyMetrics = useAppStore((s) => s.companyMetrics);
|
||||
const standupReport = useAppStore((s) => s.standupReport);
|
||||
const socialAccounts = useAppStore((s) => s.socialAccounts);
|
||||
const browserActions = useAppStore((s) => s.browserActions);
|
||||
const selectedCommunicationEntityId = useAppStore((s) => s.selectedCommunicationEntityId);
|
||||
const setSelectedCommunicationEntityId = useAppStore((s) => s.setSelectedCommunicationEntityId);
|
||||
const setSelectedWorkspaceId = useAppStore((s) => s.setSelectedWorkspaceId);
|
||||
const setSelectedTaskId = useAppStore((s) => s.setSelectedTaskId);
|
||||
const setSelectedApprovalId = useAppStore((s) => s.setSelectedApprovalId);
|
||||
const setSection = useAppStore((s) => s.setSection);
|
||||
const navigateTo = useAppStore((s) => s.navigateTo);
|
||||
|
||||
if (!snapshot) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{section === "overview" ? (
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
import type {
|
||||
AgentRecord,
|
||||
CompanyRecord,
|
||||
GoalRecord,
|
||||
ProjectRecord,
|
||||
WorkspaceRecord,
|
||||
ProfileSnapshot,
|
||||
SectionId,
|
||||
} from "@shared/types";
|
||||
import type { SectionId } from "@shared/types";
|
||||
import { NEW_ENTITY_ID } from "../../lib/constants";
|
||||
import {
|
||||
Target,
|
||||
@@ -28,48 +20,38 @@ import {
|
||||
import { HiringPipeline } from "../../components/hiring";
|
||||
import { ActionButton, Modal, Panel } from "../../components/ui";
|
||||
import { useT } from "../../i18n";
|
||||
import { useAppStore } from "../../state/store";
|
||||
import { useSectionContext } from "../../hooks/useSectionContext";
|
||||
import { useAppActions } from "../../hooks/useAppActions";
|
||||
|
||||
interface OrganizationSectionsProps {
|
||||
section: SectionId;
|
||||
snapshot: ProfileSnapshot;
|
||||
currentCompany: CompanyRecord | null;
|
||||
companyAgents: AgentRecord[];
|
||||
companyGoals: GoalRecord[];
|
||||
companyProjects: ProjectRecord[];
|
||||
companyWorkspaces: WorkspaceRecord[];
|
||||
selectedAgentId: string | null;
|
||||
setSelectedAgentId: (id: string | null) => void;
|
||||
selectedGoalId: string | null;
|
||||
setSelectedGoalId: (id: string | null) => void;
|
||||
selectedProjectId: string | null;
|
||||
setSelectedProjectId: (id: string | null) => void;
|
||||
setSection: (section: SectionId) => void;
|
||||
refresh: () => Promise<void>;
|
||||
}
|
||||
|
||||
export function OrganizationSections({
|
||||
section,
|
||||
snapshot,
|
||||
currentCompany,
|
||||
companyAgents,
|
||||
companyGoals,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
selectedAgentId,
|
||||
setSelectedAgentId,
|
||||
selectedGoalId,
|
||||
setSelectedGoalId,
|
||||
selectedProjectId,
|
||||
setSelectedProjectId,
|
||||
setSection,
|
||||
refresh,
|
||||
}: OrganizationSectionsProps) {
|
||||
export function OrganizationSections({ section }: OrganizationSectionsProps) {
|
||||
const t = useT();
|
||||
const selectedAgent = companyAgents.find((a) => a.id === selectedAgentId) ?? null;
|
||||
const selectedGoal = companyGoals.find((g) => g.id === selectedGoalId) ?? null;
|
||||
const selectedProject = companyProjects.find((p) => p.id === selectedProjectId) ?? null;
|
||||
const {
|
||||
snapshot,
|
||||
currentCompany,
|
||||
companyAgents,
|
||||
companyGoals,
|
||||
companyProjects,
|
||||
companyWorkspaces,
|
||||
selectedAgent,
|
||||
selectedGoal,
|
||||
selectedProject,
|
||||
} = useSectionContext();
|
||||
const { refresh } = useAppActions();
|
||||
|
||||
if (!currentCompany) return null;
|
||||
const selectedAgentId = useAppStore((s) => s.selectedAgentId);
|
||||
const setSelectedAgentId = useAppStore((s) => s.setSelectedAgentId);
|
||||
const selectedGoalId = useAppStore((s) => s.selectedGoalId);
|
||||
const setSelectedGoalId = useAppStore((s) => s.setSelectedGoalId);
|
||||
const selectedProjectId = useAppStore((s) => s.selectedProjectId);
|
||||
const setSelectedProjectId = useAppStore((s) => s.setSelectedProjectId);
|
||||
const setSection = useAppStore((s) => s.setSection);
|
||||
|
||||
if (!snapshot || !currentCompany) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in new issue
Block a user