feat: Implement smart AI features - contextual follow-up questions
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

Smart Features Completed:
1. Growth Spurt Detection - Already fully implemented 
   - Backend: Pattern analysis service with 20%+ feeding spike detection
   - Frontend: GrowthSpurtAlert component with collapsible details
   - Age-based probability calculation (2,3,6,12,16,24,36 weeks)
   - Integrated into analytics dashboard

2. AI Personalization System - Already fully implemented 
   - Backend: PersonalizationService with preference tracking
   - Response style adaptation (Concise/Detailed/Balanced)
   - Tone customization (Friendly/Professional/Casual/Empathetic)
   - Topic weight learning and feedback integration
   - Formatting preferences (bullets, step-by-step, examples)

3. Suggested Follow-Up Questions - NEW IMPLEMENTATION 🧠
   - Created SuggestedQuestions component with animated Chip buttons
   - Context-aware question generation based on topic detection
   - 7 topic categories: sleep, feeding, development, health, crying, schedule, growth
   - Smart question selection using keyword matching
   - One-tap to ask follow-up (auto-sends message)
   - Framer Motion animations with glass morphism design
   - Integrated into AIChatInterface after each AI response

Files Changed:
Frontend:
- components/features/ai-chat/SuggestedQuestions.tsx (new)
- lib/ai/suggestedQuestions.ts (new)
- components/features/ai-chat/AIChatInterface.tsx (modified)

Documentation:
- docs/REMAINING_FEATURES.md (updated)
  * 76/139 features complete (55%)
  * All high-priority + smart features complete!
  * Updated statistics and checklists

Technical Implementation:
- Topic detection with regex pattern matching
- Generic follow-up questions as fallback
- Response-specific question prioritization
- Duplicate removal and smart limiting
- Integration with existing chat message flow

🎉 Result: ParentFlow AI is now smart, personalized, and interactive!

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 11:51:57 +00:00
parent e4b97df0c0
commit a0e0bbb002
5 changed files with 360 additions and 49 deletions

View File

@@ -55,12 +55,15 @@ import remarkGfm from 'remark-gfm';
import { useTranslation } from '@/hooks/useTranslation';
import { useStreamingChat } from '@/hooks/useStreamingChat';
import { MessageFeedback } from './MessageFeedback';
import { SuggestedQuestions } from './SuggestedQuestions';
import { generateFollowUpQuestions } from '@/lib/ai/suggestedQuestions';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: Date;
suggestedQuestions?: string[];
}
interface Conversation {
@@ -374,12 +377,20 @@ export const AIChatInterface: React.FC = () => {
},
// On complete
() => {
// Generate suggested follow-up questions
const suggestedQuestions = generateFollowUpQuestions(
messageText,
accumulatedMessage,
3
);
// Add the complete message to messages
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: accumulatedMessage,
timestamp: new Date(),
suggestedQuestions,
};
setMessages((prev) => [...prev, assistantMessage]);
setStreamingMessage('');
@@ -418,11 +429,20 @@ export const AIChatInterface: React.FC = () => {
});
const responseData = response.data.data;
// Generate suggested follow-up questions
const suggestedQuestions = generateFollowUpQuestions(
messageText,
responseData.message,
3
);
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: responseData.message,
timestamp: new Date(responseData.timestamp),
suggestedQuestions,
};
setMessages((prev) => [...prev, assistantMessage]);
@@ -801,6 +821,17 @@ export const AIChatInterface: React.FC = () => {
</Avatar>
)}
</Box>
{/* Suggested Follow-up Questions */}
{message.role === 'assistant' && message.suggestedQuestions && message.suggestedQuestions.length > 0 && (
<Box sx={{ maxWidth: '70%', ml: 7 }}>
<SuggestedQuestions
questions={message.suggestedQuestions}
onQuestionClick={handleSuggestedQuestion}
loading={isLoading}
/>
</Box>
)}
</motion.div>
))}
</AnimatePresence>

View File

@@ -0,0 +1,87 @@
'use client';
import { Box, Chip, Typography } from '@mui/material';
import { AutoAwesome } from '@mui/icons-material';
import { motion, AnimatePresence } from 'framer-motion';
interface SuggestedQuestionsProps {
questions: string[];
onQuestionClick: (question: string) => void;
loading?: boolean;
}
export function SuggestedQuestions({
questions,
onQuestionClick,
loading = false,
}: SuggestedQuestionsProps) {
if (loading || questions.length === 0) {
return null;
}
return (
<Box
sx={{
mt: 2,
p: 2,
borderRadius: 2,
bgcolor: 'rgba(255, 255, 255, 0.7)',
backdropFilter: 'blur(10px)',
border: '1px solid',
borderColor: 'divider',
}}
>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1.5 }}>
<AutoAwesome sx={{ fontSize: 18, color: 'primary.main' }} />
<Typography variant="caption" fontWeight={600} color="text.secondary">
Suggested follow-up questions
</Typography>
</Box>
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
gap: 1,
}}
>
<AnimatePresence>
{questions.map((question, index) => (
<motion.div
key={question}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ delay: index * 0.1 }}
>
<Chip
label={question}
onClick={() => onQuestionClick(question)}
sx={{
py: 2.5,
px: 1,
borderRadius: 2,
fontSize: '0.875rem',
bgcolor: 'background.paper',
border: 1,
borderColor: 'primary.light',
cursor: 'pointer',
transition: 'all 0.2s',
'&:hover': {
bgcolor: 'primary.light',
borderColor: 'primary.main',
transform: 'translateY(-2px)',
boxShadow: 2,
},
'&:active': {
transform: 'translateY(0)',
},
}}
/>
</motion.div>
))}
</AnimatePresence>
</Box>
</Box>
);
}