Story 31: View Upcoming Stories
Add GET /workflow/upcoming endpoint that reads .story_kit/stories/upcoming/ and returns story IDs with names parsed from frontmatter. Add UpcomingPanel component wired into Chat view with loading, error, empty, and list states. 12 new tests (3 backend, 9 frontend) all passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,13 @@ import Markdown from "react-markdown";
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||
import { api, ChatWebSocket } from "../api/client";
|
||||
import type { ReviewStory } from "../api/workflow";
|
||||
import type { ReviewStory, UpcomingStory } from "../api/workflow";
|
||||
import { workflowApi } from "../api/workflow";
|
||||
import type { Message, ProviderConfig, ToolCall } from "../types";
|
||||
import { ChatHeader } from "./ChatHeader";
|
||||
import { GatePanel } from "./GatePanel";
|
||||
import { ReviewPanel } from "./ReviewPanel";
|
||||
import { UpcomingPanel } from "./UpcomingPanel";
|
||||
|
||||
const { useCallback, useEffect, useRef, useState } = React;
|
||||
|
||||
@@ -61,6 +62,12 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
const [lastGateRefresh, setLastGateRefresh] = useState<Date | null>(null);
|
||||
const [isCollectingCoverage, setIsCollectingCoverage] = useState(false);
|
||||
const [coverageError, setCoverageError] = useState<string | null>(null);
|
||||
const [upcomingStories, setUpcomingStories] = useState<UpcomingStory[]>([]);
|
||||
const [upcomingError, setUpcomingError] = useState<string | null>(null);
|
||||
const [isUpcomingLoading, setIsUpcomingLoading] = useState(false);
|
||||
const [lastUpcomingRefresh, setLastUpcomingRefresh] = useState<Date | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const storyId = "26_establish_tdd_workflow_and_gates";
|
||||
const gateStatusColor = isGateLoading
|
||||
@@ -306,6 +313,58 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
setIsUpcomingLoading(true);
|
||||
setUpcomingError(null);
|
||||
|
||||
workflowApi
|
||||
.getUpcomingStories()
|
||||
.then((response) => {
|
||||
if (!active) return;
|
||||
setUpcomingStories(response.stories);
|
||||
setLastUpcomingRefresh(new Date());
|
||||
})
|
||||
.catch((error) => {
|
||||
if (!active) return;
|
||||
const message =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Failed to load upcoming stories.";
|
||||
setUpcomingError(message);
|
||||
setUpcomingStories([]);
|
||||
})
|
||||
.finally(() => {
|
||||
if (active) {
|
||||
setIsUpcomingLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const refreshUpcomingStories = async () => {
|
||||
setIsUpcomingLoading(true);
|
||||
setUpcomingError(null);
|
||||
|
||||
try {
|
||||
const response = await workflowApi.getUpcomingStories();
|
||||
setUpcomingStories(response.stories);
|
||||
setLastUpcomingRefresh(new Date());
|
||||
} catch (error) {
|
||||
const message =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Failed to load upcoming stories.";
|
||||
setUpcomingError(message);
|
||||
setUpcomingStories([]);
|
||||
} finally {
|
||||
setIsUpcomingLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshReviewQueue = async () => {
|
||||
setIsReviewLoading(true);
|
||||
setReviewError(null);
|
||||
@@ -593,6 +652,14 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
onCollectCoverage={handleCollectCoverage}
|
||||
isCollectingCoverage={isCollectingCoverage}
|
||||
/>
|
||||
|
||||
<UpcomingPanel
|
||||
stories={upcomingStories}
|
||||
isLoading={isUpcomingLoading}
|
||||
error={upcomingError}
|
||||
lastRefresh={lastUpcomingRefresh}
|
||||
onRefresh={refreshUpcomingStories}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user