From 74abe909bd77c99bb46f2bdef65b33670bae7f48 Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Sun, 5 Jul 2026 17:41:53 +0300 Subject: [PATCH] Stabilize SEO project stage navigation --- seo_mode/seo_mode/app/src/App.tsx | 75 ++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/seo_mode/seo_mode/app/src/App.tsx b/seo_mode/seo_mode/app/src/App.tsx index 3de4f50..f5228ea 100644 --- a/seo_mode/seo_mode/app/src/App.tsx +++ b/seo_mode/seo_mode/app/src/App.tsx @@ -5706,8 +5706,8 @@ function getPipelineStageAccess( const marketReady = Boolean(input.marketEnrichment && input.marketEnrichment.state !== "not_ready"); const keywordReady = Boolean(input.keywordMap && input.keywordMap.readiness.mappedItemCount > 0); const strategyReady = Boolean(input.seoStrategy && input.seoStrategy.state !== "blocked"); - const synthesisReady = input.strategySynthesis?.state === "ready"; - const qualityReady = input.strategyQualityReview?.state === "ready"; + const synthesisReady = strategyReady && input.strategySynthesis?.state === "ready"; + const qualityReady = synthesisReady && input.strategyQualityReview?.state === "ready"; if (stageIndex === 0) { return { reason: "Импортируй сайт или выбери уже созданный проект.", status: "open", unlocked: true }; @@ -5784,6 +5784,18 @@ function getPipelineStageAccess( }; } +function getPreferredProjectStageIndex(input: Parameters[1]) { + const stageAccess = pipeline.map((_, stageIndex) => getPipelineStageAccess(stageIndex, input)); + + if (stageAccess[7]?.unlocked) return 7; + if (stageAccess[6]?.unlocked) return 6; + if (stageAccess[5]?.unlocked) return 5; + if (stageAccess[4]?.unlocked) return 4; + if (stageAccess[3]?.unlocked) return 3; + if (stageAccess[2]?.unlocked) return 2; + return 1; +} + function getAuditIssueCounts(issues: AuditIssue[]) { return issues.reduce( (counts, issue) => { @@ -14481,6 +14493,14 @@ export function App() { const activeSeoStrategy = activeProject ? (seoStrategies[activeProject.id] ?? null) : null; const activeStrategySynthesis = activeProject ? (strategySyntheses[activeProject.id] ?? null) : null; const activeStrategyQualityReview = activeProject ? (strategyQualityReviews[activeProject.id] ?? null) : null; + const activeLiveSemanticAnalysis = activeProject ? (semanticAnalyses[activeProject.id] ?? null) : null; + const activeLiveContextReviewRaw = activeProject ? (contextReviews[activeProject.id] ?? null) : null; + const activeLiveContextReview = + activeLiveSemanticAnalysis && activeLiveContextReviewRaw?.semanticRunId === activeLiveSemanticAnalysis.runId + ? activeLiveContextReviewRaw + : null; + const activeLiveMarketEnrichment = activeProject ? (marketEnrichments[activeProject.id] ?? null) : null; + const activeLiveKeywordMap = activeProject ? (keywordMaps[activeProject.id] ?? null) : null; const activeProjectScanScopeCounts = activeProjectScanSummary ? getScanScopeCounts(activeProjectScanSummary) : null; const activeProjectSelectedWorkspaceScopeItems = activeProjectScanSummary ? getSelectedWorkspaceScopeItems(activeProjectScanSummary) @@ -14562,12 +14582,12 @@ export function App() { const visibleProjects = activeStageIndex === 0 ? projects : activeProject ? [activeProject] : []; const stageAccessList = pipeline.map((_, stageIndex) => getPipelineStageAccess(stageIndex, { - contextReview: activeContextReview, + contextReview: activeLiveContextReview, hasProject: Boolean(activeProject), - keywordMap: activeKeywordMap, - marketEnrichment: activeMarketEnrichment, + keywordMap: activeLiveKeywordMap, + marketEnrichment: activeLiveMarketEnrichment, scan: activeProjectScanSummary, - semanticAnalysis: activeSemanticAnalysis, + semanticAnalysis: activeLiveSemanticAnalysis, seoStrategy: activeSeoStrategy, strategyQualityReview: activeStrategyQualityReview, strategySynthesis: activeStrategySynthesis @@ -14966,6 +14986,7 @@ export function App() { disabled={isSavingActiveKeywordContextSnapshot} menuClassName="keyword-context-profile-menu" onChange={(snapshotId) => { + clearProjectActionFeedback(); setActiveKeywordContextSnapshotIds((currentIds) => ({ ...currentIds, [activeProject.id]: snapshotId @@ -15221,11 +15242,41 @@ export function App() { ) : null; + function clearProjectActionFeedback() { + setProjectActionProjectId(null); + setProjectActionError(null); + setProjectActionMessage(null); + } + + function getProjectPipelineAccessInput(projectId: string): Parameters[1] { + const semanticAnalysis = semanticAnalyses[projectId] ?? null; + const contextReviewRaw = contextReviews[projectId] ?? null; + const contextReview = + semanticAnalysis && contextReviewRaw?.semanticRunId === semanticAnalysis.runId ? contextReviewRaw : null; + + return { + contextReview, + hasProject: true, + keywordMap: keywordMaps[projectId] ?? null, + marketEnrichment: marketEnrichments[projectId] ?? null, + scan: scanSummaries[projectId], + semanticAnalysis, + seoStrategy: seoStrategies[projectId] ?? null, + strategyQualityReview: strategyQualityReviews[projectId] ?? null, + strategySynthesis: strategySyntheses[projectId] ?? null + }; + } + + function getPreferredStageIndexForProject(projectId: string) { + return getPreferredProjectStageIndex(getProjectPipelineAccessInput(projectId)); + } + function openProjectScanStage(project: ProjectSummary) { if (editingProjectId === project.id || pendingDeleteProjectId === project.id) { return; } + clearProjectActionFeedback(); setActiveProjectId(project.id); setActiveStageIndex(1); setIsProjectMenuOpen(false); @@ -15239,17 +15290,20 @@ export function App() { } function openProjectFromMenu(project: ProjectSummary) { - const nextStageIndex = activeProjectId === project.id ? activeStageIndex : 1; + const nextStageIndex = + activeProjectId === project.id && isWorkPanelOpen ? activeStageIndex : getPreferredStageIndexForProject(project.id); + clearProjectActionFeedback(); setActiveProjectId(project.id); setActiveStageIndex(nextStageIndex); setIsProjectMenuOpen(false); setIsStageRailOpen(true); - setIsWorkPanelOpen(false); + setIsWorkPanelOpen(true); setIsWorkPanelFullscreen(false); } function closeActiveProject() { + clearProjectActionFeedback(); setActiveProjectId(null); setActiveStageIndex(0); setIsProjectMenuOpen(false); @@ -15279,10 +15333,7 @@ export function App() { return; } - if (!projectActionProjectId) { - setProjectActionError(null); - setProjectActionMessage(null); - } + clearProjectActionFeedback(); setActiveStageIndex(stageIndex); setIsStageRailOpen(true);