Spaces:
Running
Running
| import React, { useState, useEffect } from 'react'; | |
| import { useLocation } from 'react-router-dom'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { Sparkles, X, ChevronRight, BookOpen, Lightbulb, HelpCircle, MessageSquare } from 'lucide-react'; | |
| import { useUserStore } from '@/store/userStore'; | |
| const helpContent: Record<string, any> = { | |
| '/dashboard': { | |
| title: 'Autonomous Dashboard', | |
| description: 'This is your central command center. AI generates these widgets automatically based on your connected data.', | |
| tips: [ | |
| 'Click on any chart to expand it for a deeper analysis.', | |
| 'Use the filter panel on the right to drill down into specific timeframes.', | |
| 'The AI insights at the top update in real-time as new data flows in.' | |
| ], | |
| action: 'Ask AI about these metrics' | |
| }, | |
| '/data-hub': { | |
| title: 'Data Hub', | |
| description: 'Manage all your datasets here. You can upload CSV, Excel, or PDF files, or connect directly to Google Sheets.', | |
| tips: [ | |
| 'Try the "Synthetic Data Generator" if you need realistic test data.', | |
| 'You can train ML models directly from your uploaded files.', | |
| 'Click the trash icon to delete files you no longer need.' | |
| ], | |
| action: 'How to structure my data?' | |
| }, | |
| '/ml-predictions': { | |
| title: 'ML Predictions', | |
| description: 'Explore automated machine learning models trained on your data to forecast trends and detect patterns.', | |
| tips: [ | |
| 'Toggle between Regression (numbers) and Classification (categories) models.', | |
| 'Hover over the prediction charts to see confidence intervals.', | |
| 'Use the "Deploy Model" button to create an API endpoint.' | |
| ], | |
| action: 'Explain these ML metrics' | |
| }, | |
| '/chat': { | |
| title: 'AI Analyst Chat', | |
| description: 'Your personal data scientist. Ask questions in plain English and it will query your datasets, generate charts, and provide insights.', | |
| tips: [ | |
| 'Try asking for specific aggregations, e.g., "Show total revenue by month".', | |
| 'The AI remembers past conversations for continuous context.', | |
| 'You can attach files directly in the chat to analyze them on the fly.' | |
| ], | |
| action: 'Show me example questions' | |
| }, | |
| '/anomalies': { | |
| title: 'Anomaly Monitor', | |
| description: 'Real-time detection of outliers and unusual patterns in your live data streams.', | |
| tips: [ | |
| 'Red dots indicate critical anomalies that require immediate attention.', | |
| 'Adjust the sensitivity slider to reduce false positives.', | |
| 'Set up webhook alerts in Settings to get notified instantly.' | |
| ], | |
| action: 'What causes these anomalies?' | |
| }, | |
| '/decisions': { | |
| title: 'Decision Intelligence', | |
| description: 'Actionable business recommendations generated by AI based on deep pattern recognition across your data.', | |
| tips: [ | |
| 'Review the confidence score before approving an automated action.', | |
| 'Click "Approve & Execute" to trigger the associated API workflow.', | |
| 'Dismissed recommendations help train the AI to better understand your preferences.' | |
| ], | |
| action: 'How are these generated?' | |
| } | |
| }; | |
| const defaultHelp = { | |
| title: 'Need Help?', | |
| description: 'Navigate to different pages in the application to see contextual tips and AI guidance specific to that feature.', | |
| tips: [ | |
| 'Use the left sidebar to navigate between modules.', | |
| 'Press Ctrl+K (or Cmd+K) to open the quick search palette.', | |
| 'Check Settings to customize your theme and preferences.' | |
| ], | |
| action: 'Go to Help Center' | |
| }; | |
| export const ContextualHelp: React.FC = () => { | |
| const [isOpen, setIsOpen] = useState(false); | |
| const [hasPulse, setHasPulse] = useState(true); | |
| const location = useLocation(); | |
| const { isDark } = useUserStore(); | |
| // Get content based on current path | |
| const currentPath = Object.keys(helpContent).find(path => location.pathname.startsWith(path)); | |
| const content = currentPath ? helpContent[currentPath] : defaultHelp; | |
| useEffect(() => { | |
| // Pulse animation triggers when route changes to draw attention | |
| setHasPulse(true); | |
| const timer = setTimeout(() => setHasPulse(false), 5000); | |
| return () => clearTimeout(timer); | |
| }, [location.pathname]); | |
| return ( | |
| <> | |
| {/* Floating Action Button */} | |
| <motion.button | |
| initial={{ scale: 0 }} | |
| animate={{ scale: 1 }} | |
| whileHover={{ scale: 1.05 }} | |
| whileTap={{ scale: 0.95 }} | |
| onClick={() => { | |
| setIsOpen(true); | |
| setHasPulse(false); | |
| }} | |
| className={`fixed bottom-6 right-6 z-50 p-4 rounded-full shadow-2xl flex items-center justify-center transition-colors ${ | |
| isDark ? 'bg-indigo-600 hover:bg-indigo-500 text-white shadow-indigo-900/50' : 'bg-indigo-600 hover:bg-indigo-500 text-white shadow-indigo-500/30' | |
| }`} | |
| > | |
| <div className="relative"> | |
| <HelpCircle className="w-6 h-6" /> | |
| {hasPulse && ( | |
| <span className="absolute top-0 right-0 w-3 h-3 bg-rose-500 border-2 border-indigo-600 rounded-full animate-pulse"></span> | |
| )} | |
| </div> | |
| </motion.button> | |
| {/* Slide-out Panel */} | |
| <AnimatePresence> | |
| {isOpen && ( | |
| <motion.div | |
| initial={{ opacity: 0, x: 400 }} | |
| animate={{ opacity: 1, x: 0 }} | |
| exit={{ opacity: 0, x: 400 }} | |
| transition={{ type: 'spring', damping: 25, stiffness: 200 }} | |
| className={`fixed bottom-24 right-6 w-80 sm:w-96 z-50 rounded-3xl border shadow-2xl overflow-hidden ${ | |
| isDark ? 'bg-zinc-900/90 border-white/10 backdrop-blur-xl shadow-black/50' : 'bg-white/95 border-gray-200 backdrop-blur-xl shadow-gray-300/50' | |
| }`} | |
| > | |
| {/* Header */} | |
| <div className={`p-5 border-b flex justify-between items-center ${isDark ? 'border-white/10' : 'border-gray-100'}`}> | |
| <div className="flex items-center gap-2 text-indigo-500"> | |
| <Sparkles className="w-5 h-5" /> | |
| <h3 className="font-bold text-lg">AI Assistant</h3> | |
| </div> | |
| <button | |
| onClick={() => setIsOpen(false)} | |
| className={`p-1.5 rounded-full transition-colors ${isDark ? 'hover:bg-white/10 text-gray-400' : 'hover:bg-gray-100 text-gray-500'}`} | |
| > | |
| <X className="w-5 h-5" /> | |
| </button> | |
| </div> | |
| {/* Body */} | |
| <div className="p-6 space-y-6"> | |
| <div> | |
| <h4 className="text-xl font-bold mb-2" style={{ color: isDark ? 'white' : 'black' }}> | |
| {content.title} | |
| </h4> | |
| <p className="text-sm leading-relaxed" style={{ color: isDark ? '#a1a1aa' : '#52525b' }}> | |
| {content.description} | |
| </p> | |
| </div> | |
| <div className="space-y-3"> | |
| <h5 className="text-xs font-bold uppercase tracking-wider flex items-center gap-2" style={{ color: isDark ? '#71717a' : '#a1a1aa' }}> | |
| <Lightbulb className="w-3.5 h-3.5" /> Pro Tips | |
| </h5> | |
| <ul className="space-y-3"> | |
| {content.tips.map((tip: string, idx: number) => ( | |
| <li key={idx} className="flex items-start gap-3 text-sm"> | |
| <div className="mt-0.5 w-1.5 h-1.5 rounded-full bg-indigo-500 shrink-0"></div> | |
| <span style={{ color: isDark ? '#d4d4d8' : '#3f3f46' }}>{tip}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| </div> | |
| {/* Footer Action */} | |
| <div className={`p-4 border-t ${isDark ? 'bg-black/20 border-white/5' : 'bg-gray-50/50 border-gray-100'}`}> | |
| <button className="w-full py-3 px-4 rounded-xl font-semibold text-sm bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white shadow-lg shadow-indigo-500/25 flex items-center justify-center gap-2 transition-all"> | |
| <MessageSquare className="w-4 h-4" /> | |
| {content.action} | |
| </button> | |
| </div> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </> | |
| ); | |
| }; | |