feat(KB-125): add planning mode checkbox to new task flow

- Add planning mode checkbox to NewTaskModal with onPlanGenerated callback
- Wire up planning mode flow in App.tsx to open modal after task creation
- Add initialPlan prop to PlanningModeModal with auto-start logic
- Add comprehensive tests for planning mode checkbox flow in both modals
- Include changeset for the planning mode checkbox fix
This commit is contained in:
gsxdsm
2026-03-30 07:57:53 -07:00
parent ea5a34f7cf
commit 3c9901b2cf
6 changed files with 255 additions and 8 deletions

View File

@@ -14,6 +14,7 @@ interface PlanningModeModalProps {
onClose: () => void;
onTaskCreated: (task: Task) => void;
tasks: Task[];
initialPlan?: string;
}
interface QuestionResponse {
@@ -33,12 +34,13 @@ const EXAMPLE_PLANS = [
"Refactor the task card component for better performance",
];
export function PlanningModeModal({ isOpen, onClose, onTaskCreated, tasks }: PlanningModeModalProps) {
export function PlanningModeModal({ isOpen, onClose, onTaskCreated, tasks, initialPlan: initialPlanProp }: PlanningModeModalProps) {
const [initialPlan, setInitialPlan] = useState("");
const [view, setView] = useState<ViewState>({ type: "initial" });
const [error, setError] = useState<string | null>(null);
const [responseHistory, setResponseHistory] = useState<QuestionResponse[]>([]);
const [editedSummary, setEditedSummary] = useState<PlanningSummary | null>(null);
const [hasAutoStarted, setHasAutoStarted] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Focus textarea when opening
@@ -48,6 +50,26 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, tasks }: Pla
}
}, [isOpen, view.type]);
// Auto-start planning when initialPlan prop is provided
useEffect(() => {
if (isOpen && initialPlanProp && !hasAutoStarted && view.type === "initial") {
setInitialPlan(initialPlanProp);
setHasAutoStarted(true);
// Use a small timeout to allow state update to propagate before starting
const timer = setTimeout(() => {
handleStartPlanningWithPlan(initialPlanProp);
}, 0);
return () => clearTimeout(timer);
}
}, [isOpen, initialPlanProp, hasAutoStarted, view.type]);
// Reset hasAutoStarted when modal closes
useEffect(() => {
if (!isOpen) {
setHasAutoStarted(false);
}
}, [isOpen]);
// Handle browser unload during active session
useEffect(() => {
if (!isOpen) return;
@@ -104,6 +126,28 @@ export function PlanningModeModal({ isOpen, onClose, onTaskCreated, tasks }: Pla
}
}, [initialPlan]);
// Helper for auto-start with a specific plan (from prop)
const handleStartPlanningWithPlan = useCallback(async (plan: string) => {
if (!plan.trim()) return;
setError(null);
setView({ type: "loading" });
try {
const session = await startPlanning(plan.trim());
if (session.currentQuestion) {
setView({ type: "question", session });
} else if (session.summary) {
setView({ type: "summary", session, summary: session.summary });
setEditedSummary(session.summary);
}
setResponseHistory([]);
} catch (err: any) {
setError(err.message || "Failed to start planning session");
setView({ type: "initial" });
}
}, []);
const handleSubmitResponse = useCallback(
async (responses: QuestionResponse) => {
if (view.type !== "question") return;