-
- {hasSteps && }
-
-
-
- {t('Home')}
-
-
-
- {displayName}
-
-
- {hasSteps && (
-
- {validation.stepsRemaining > 0 && (
-
- )}
-
-
- )}
-
-
+
);
};
-const MobileSidebar = ({ instanceId }: { instanceId: string }) => {
+const MobileSidebarWithProfile = ({
+ instanceId,
+ slug,
+}: {
+ instanceId: string;
+ slug?: string;
+}) => {
+ const { data: decisionProfile } = trpc.decision.getDecisionBySlug.useQuery(
+ { slug: slug! },
+ { enabled: !!slug },
+ );
+ return (
+
+ );
+};
+
+const MobileSidebar = ({
+ instanceId,
+ decisionProfileId,
+}: {
+ instanceId: string;
+ decisionProfileId?: string;
+}) => {
const t = useTranslations();
const rubricBuilderEnabled = useFeatureFlag('rubric_builder');
const navigationConfig = useNavigationConfig(instanceId);
- const { visibleSteps, currentStep, setStep } =
+ const { visibleSections, currentSection, setSection } =
useProcessNavigation(navigationConfig);
- const hasSteps = visibleSteps.length > 0;
const { setOpen } = useSidebar();
- const handleSelectionChange = (key: Key) => {
- setStep(String(key));
+ const storePhases = useProcessBuilderStore((s) =>
+ decisionProfileId ? s.instances[decisionProfileId]?.phases : undefined,
+ );
+
+ const { data: instance } = trpc.decision.getInstance.useQuery(
+ { instanceId },
+ { enabled: !!instanceId },
+ );
+
+ const phases = useMemo(() => {
+ // Prefer Zustand store phases (updated immediately on edit) over API data
+ if (storePhases?.length) {
+ return storePhases
+ .map((p) => ({ id: p.phaseId, name: p.name ?? '' }))
+ .filter((p) => p.name);
+ }
+ const instancePhases = instance?.instanceData?.phases;
+ if (instancePhases?.length) {
+ return instancePhases
+ .map((p) => ({ id: p.phaseId, name: p.name ?? '' }))
+ .filter((p) => p.name);
+ }
+ const templatePhases = instance?.process?.processSchema?.phases;
+ if (templatePhases?.length) {
+ return templatePhases.map((p) => ({ id: p.id, name: p.name }));
+ }
+ return [];
+ }, [storePhases, instance]);
+
+ const handleSectionClick = (sectionId: string) => {
+ setSection(sectionId);
setOpen(false);
};
- if (!hasSteps) {
+ if (visibleSections.length === 0) {
return null;
}
+
return (
-
- );
-};
-
-const ComingSoonIndicator = () => {
- const t = useTranslations();
- return (
-
- {t('Coming soon')}
-
- );
-};
-
-const StepsRemainingPopover = ({
- validation,
-}: {
- validation: ValidationSummary;
-}) => {
- const t = useTranslations();
-
- return (
-
-
-
-
- {t('Complete these steps to launch')}
-
-
- {validation.checklist.map((item) => (
- -
- {item.isValid ? (
-
- ) : (
-
- )}
-
- {t(item.labelKey)}
-
-
- ))}
-
-
+
+
);
};
diff --git a/apps/app/src/components/decisions/ProcessBuilder/ProcessBuilderSectionNav.tsx b/apps/app/src/components/decisions/ProcessBuilder/ProcessBuilderSectionNav.tsx
index dc896ce0b..55f41eaed 100644
--- a/apps/app/src/components/decisions/ProcessBuilder/ProcessBuilderSectionNav.tsx
+++ b/apps/app/src/components/decisions/ProcessBuilder/ProcessBuilderSectionNav.tsx
@@ -1,57 +1,97 @@
'use client';
-import { Key } from '@op/ui/RAC';
-import { Tab, TabList, Tabs } from '@op/ui/Tabs';
+import { trpc } from '@op/api/client';
+import { useMemo } from 'react';
+import { LuCornerDownRight } from 'react-icons/lu';
import { useTranslations } from '@/lib/i18n';
+import { useProcessBuilderStore } from './stores/useProcessBuilderStore';
import { useNavigationConfig } from './useNavigationConfig';
import { useProcessNavigation } from './useProcessNavigation';
export const ProcessBuilderSidebar = ({
instanceId,
+ decisionProfileId,
}: {
instanceId: string;
+ decisionProfileId?: string;
}) => {
const t = useTranslations();
const navigationConfig = useNavigationConfig(instanceId);
- const { visibleSections, currentSection, currentStep, setSection } =
+ const { visibleSections, currentSection, setSection } =
useProcessNavigation(navigationConfig);
- const handleSelectionChange = (key: Key) => {
- setSection(String(key));
- };
+ const storePhases = useProcessBuilderStore((s) =>
+ decisionProfileId ? s.instances[decisionProfileId]?.phases : undefined,
+ );
+
+ const { data: instance } = trpc.decision.getInstance.useQuery(
+ { instanceId },
+ { enabled: !!instanceId },
+ );
- // Don't render sidebar for single-section steps
- // These steps manage their own layout (e.g., template step with form builder)
- if (visibleSections.length <= 1) {
- return null;
- }
+ const phases = useMemo(() => {
+ // Prefer Zustand store phases (updated immediately on edit) over API data
+ if (storePhases?.length) {
+ return storePhases
+ .map((p) => ({ id: p.phaseId, name: p.name ?? '' }))
+ .filter((p) => p.name);
+ }
+ const instancePhases = instance?.instanceData?.phases;
+ if (instancePhases?.length) {
+ return instancePhases
+ .map((p) => ({ id: p.phaseId, name: p.name ?? '' }))
+ .filter((p) => p.name);
+ }
+ const templatePhases = instance?.process?.processSchema?.phases;
+ if (templatePhases?.length) {
+ return templatePhases.map((p) => ({ id: p.id, name: p.name }));
+ }
+ return [];
+ }, [storePhases, instance]);
return (
-