feat(cortex): Epic 4 - Nudge MVP (Layer 3) complete
Proactive suggestions after successful actions - proof of concept. E4.S1 - Protocol Rules (lib/cortex/nudge.ts) - ProtocolRule and ProtocolCondition types - Condition operators: equals, contains, matches, exists - 2 hardcoded rules: wondzorg-controle, medicatie-controle E4.S2 - evaluateNudge Function - evaluateNudge(input) returns NudgeSuggestion[] - checkCondition() helper for rule matching - Priority sorting (high → medium → low) E4.S3 - NudgeToast Component - Countdown progress bar with auto-dismiss (5 min) - Priority-based styling (low/medium/high) - Accept and dismiss buttons - Framer Motion animations E4.S4 - Integration - NudgeToast rendered in CommandCenter (fixed position) - Trigger added in DagnotatieBlock after successful save - Accept opens corresponding artifact with prefilled data Demo flow: 1. Create dagnotitie with "wond" in content 2. Save → NudgeToast appears 3. Click "Ja, inplannen" → Appointment artifact opens 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,16 +17,28 @@
|
||||
*/
|
||||
|
||||
import { useEffect, useCallback, useRef } from 'react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { useCortexStore } from '@/stores/cortex-store';
|
||||
import { ContextBar } from './context-bar';
|
||||
import { OfflineBanner } from './offline-banner';
|
||||
import { NudgeToast } from './nudge-toast';
|
||||
import { ChatPanel } from '../chat/chat-panel';
|
||||
import { ArtifactArea } from '../artifacts/artifact-area';
|
||||
import { getArtifactTitle } from '../artifacts/artifact-container';
|
||||
import { routeIntentToArtifact } from '@/lib/cortex/action-parser';
|
||||
|
||||
export function CommandCenter() {
|
||||
const { closeAllArtifacts, openArtifacts, openArtifact, pendingAction, setPendingAction } = useCortexStore();
|
||||
const {
|
||||
closeAllArtifacts,
|
||||
openArtifacts,
|
||||
openArtifact,
|
||||
pendingAction,
|
||||
setPendingAction,
|
||||
// Nudge state (E4)
|
||||
suggestions,
|
||||
acceptSuggestion,
|
||||
dismissSuggestion,
|
||||
} = useCortexStore();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// Global keyboard shortcuts
|
||||
@@ -118,6 +130,43 @@ export function CommandCenter() {
|
||||
<ArtifactArea />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Nudge Toast - E4 (fixed position, bottom-left above chat) */}
|
||||
<AnimatePresence mode="wait">
|
||||
{suggestions.length > 0 && (
|
||||
<div className="fixed bottom-20 left-4 right-4 lg:left-4 lg:right-auto lg:w-[38%] z-50">
|
||||
<NudgeToast
|
||||
key={suggestions[0].id}
|
||||
suggestion={suggestions[0]}
|
||||
onAccept={(id) => {
|
||||
const suggestion = suggestions.find((s) => s.id === id);
|
||||
if (suggestion) {
|
||||
// Route the suggested intent to an artifact
|
||||
const artifact = routeIntentToArtifact(
|
||||
suggestion.suggestion.intent,
|
||||
suggestion.suggestion.entities,
|
||||
1.0 // High confidence since user explicitly accepted
|
||||
);
|
||||
|
||||
if (artifact) {
|
||||
console.log('[CommandCenter] Opening artifact from nudge:', artifact.type);
|
||||
openArtifact({
|
||||
type: artifact.type,
|
||||
prefill: artifact.prefill,
|
||||
title: artifact.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
acceptSuggestion(id);
|
||||
}}
|
||||
onDismiss={(id) => {
|
||||
dismissSuggestion(id);
|
||||
console.log('[CommandCenter] Nudge dismissed:', id);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user