Added beta testing for user_id=1 for all requests

This commit is contained in:
ajaysi
2025-09-14 18:56:30 +05:30
parent 380bb19673
commit 9f13daf443
7 changed files with 631 additions and 330 deletions

View File

@@ -2,11 +2,9 @@ import React, { useState } from 'react';
import { import {
Box, Box,
Container, Container,
Grid,
Alert, Alert,
Snackbar, Snackbar,
useTheme, useTheme
useMediaQuery
} from '@mui/material'; } from '@mui/material';
import { motion, AnimatePresence } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -15,12 +13,8 @@ import AskAlwrityIcon from '../../assets/images/AskAlwrity-min.ico';
// Shared components // Shared components
import DashboardHeader from '../shared/DashboardHeader'; import DashboardHeader from '../shared/DashboardHeader';
import SystemStatusIndicator from '../ContentPlanningDashboard/components/SystemStatusIndicator'; import SystemStatusIndicator from '../ContentPlanningDashboard/components/SystemStatusIndicator';
import SearchFilter from '../shared/SearchFilter';
import ToolCard from '../shared/ToolCard';
import CategoryHeader from '../shared/CategoryHeader';
import LoadingSkeleton from '../shared/LoadingSkeleton'; import LoadingSkeleton from '../shared/LoadingSkeleton';
import ErrorDisplay from '../shared/ErrorDisplay'; import ErrorDisplay from '../shared/ErrorDisplay';
import EmptyState from '../shared/EmptyState';
import ContentLifecyclePillars from './ContentLifecyclePillars'; import ContentLifecyclePillars from './ContentLifecyclePillars';
import AnalyticsInsights from './components/AnalyticsInsights'; import AnalyticsInsights from './components/AnalyticsInsights';
import ToolsModal from './components/ToolsModal'; import ToolsModal from './components/ToolsModal';
@@ -61,7 +55,6 @@ const MainDashboard: React.FC = () => {
setSelectedSubCategory, setSelectedSubCategory,
showSnackbar, showSnackbar,
hideSnackbar, hideSnackbar,
clearFilters,
} = useDashboardStore(); } = useDashboardStore();
// Workflow store hooks // Workflow store hooks
@@ -219,7 +212,7 @@ const MainDashboard: React.FC = () => {
// Close modal if search query is too short // Close modal if search query is too short
setToolsModalOpen(false); setToolsModalOpen(false);
} }
}, [searchQuery, toolCategories]); }, [searchQuery]);
// Close modal and clear search // Close modal and clear search
const handleCloseModal = () => { const handleCloseModal = () => {
@@ -232,11 +225,7 @@ const MainDashboard: React.FC = () => {
} }
}; };
const filteredCategories = getFilteredCategories( // Note: filteredCategories removed as it's not used in the current implementation
toolCategories,
selectedCategory,
searchQuery
);
if (loading) { if (loading) {
return <LoadingSkeleton />; return <LoadingSkeleton />;
@@ -334,6 +323,8 @@ const MainDashboard: React.FC = () => {
collapsed={sidebarCollapsed} collapsed={sidebarCollapsed}
onToggleCollapse={() => setSidebarCollapsed(!sidebarCollapsed)} onToggleCollapse={() => setSidebarCollapsed(!sidebarCollapsed)}
theme={theme} theme={theme}
favorites={favorites}
onToolClick={handleToolClick}
/> />
</Box> </Box>

View File

@@ -13,7 +13,6 @@ import {
Divider Divider
} from '@mui/material'; } from '@mui/material';
import { styled } from '@mui/material/styles'; import { styled } from '@mui/material/styles';
import { keyframes } from '@mui/system';
import { import {
CheckCircle as CheckIcon, CheckCircle as CheckIcon,
WarningAmber as WarningIcon, WarningAmber as WarningIcon,
@@ -53,43 +52,64 @@ interface AnalyticsInsightsProps {
} }
const ColumnCard = styled(Card)(({ theme }) => ({ const ColumnCard = styled(Card)(({ theme }) => ({
background: 'linear-gradient(180deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.08) 100%)', background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.8) 0%, rgba(30, 41, 59, 0.7) 100%)',
border: '1px solid rgba(255,255,255,0.16)', border: '1px solid rgba(148, 163, 184, 0.15)',
backdropFilter: 'blur(18px)', backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(18px)', WebkitBackdropFilter: 'blur(20px)',
borderRadius: theme.spacing(2), borderRadius: theme.spacing(3),
overflow: 'hidden', overflow: 'hidden',
boxShadow: '0 8px 20px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.22)', boxShadow: '0 20px 40px -12px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.05)',
transition: 'transform 0.3s ease, box-shadow 0.3s ease', transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, rgba(59, 130, 246, 0.02) 0%, rgba(147, 51, 234, 0.01) 100%)',
zIndex: -1,
},
'&:hover': { '&:hover': {
transform: 'translateY(-3px)', transform: 'translateY(-4px)',
boxShadow: '0 12px 28px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.28)' boxShadow: '0 32px 64px -12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08)',
border: '1px solid rgba(148, 163, 184, 0.25)',
} }
})); }));
const Pill = styled('div')<{ color: string }>(() => ({ // Pill component removed as it's not used
width: 10,
height: 10,
borderRadius: 6,
}));
const GradientHeader = styled(Box)<{ gradient: string }>(({ gradient }) => ({ const GradientHeader = styled(Box)<{ gradient: string }>(({ gradient }) => ({
background: gradient, background: gradient,
padding: '8px 12px', padding: '12px 16px',
color: 'white', color: 'white',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: 6, gap: 8,
position: 'relative',
'&::after': {
content: '""',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%)',
}
})); }));
const Badge = styled('span')(({ theme }) => ({ const Badge = styled('span')(({ theme }) => ({
background: 'rgba(255,255,255,0.15)', background: 'rgba(255,255,255,0.2)',
border: '1px solid rgba(255,255,255,0.35)', border: '1px solid rgba(255,255,255,0.4)',
color: 'white', color: 'white',
borderRadius: 999, borderRadius: 12,
padding: '1px 6px', padding: '4px 8px',
fontWeight: 700, fontWeight: 700,
fontSize: '0.65rem' fontSize: '0.7rem',
backdropFilter: 'blur(8px)',
boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
textShadow: '0 1px 2px rgba(0,0,0,0.3)'
})); }));
@@ -263,20 +283,129 @@ const AnalyticsInsights: React.FC<AnalyticsInsightsProps> = ({ data, onActionCli
}; };
return ( return (
<Box sx={{ mt: 1, mb: 1.5 }}> <Box sx={{
<Box sx={{ position: 'relative', overflow: 'hidden' }}> mt: 1.4,
<Typography mb: 1.4,
variant="h6" p: 2.1,
sx={{ background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%)',
fontWeight: 800, backdropFilter: 'blur(24px)',
mb: 1.5, border: '1px solid rgba(148, 163, 184, 0.1)',
fontSize: '1.1rem', borderRadius: 4,
color: 'rgba(255,255,255,0.95)', boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.05)',
}} position: 'relative',
> overflow: 'hidden',
Today's Analytics Insights '&::before': {
</Typography> content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, rgba(59, 130, 246, 0.03) 0%, rgba(147, 51, 234, 0.02) 100%)',
zIndex: -1,
},
}}>
<Box sx={{
position: 'relative',
overflow: 'hidden',
mb: 2.1,
pb: 1.4,
borderBottom: '1px solid rgba(148, 163, 184, 0.1)',
'&::after': {
content: '""',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(59, 130, 246, 0.3) 50%, transparent 100%)',
}
}}>
<Box sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
width: '100%'
}}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<TrendingUpIcon sx={{ color: '#3b82f6', fontSize: '1.5rem' }} />
<Typography
variant="h5"
sx={{
fontWeight: 800,
fontSize: '1.4rem',
color: '#ffffff',
textShadow: '0 2px 4px rgba(0,0,0,0.3)',
background: 'linear-gradient(135deg, #ffffff 0%, #e2e8f0 100%)',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
Today's Analytics Insights
</Typography>
</Box>
{/* Chat with Analytics Pro Button - Inline */}
<Button
disabled
variant="contained"
sx={{
background: 'linear-gradient(135deg, rgba(148, 163, 184, 0.1) 0%, rgba(100, 116, 139, 0.1) 100%)',
border: '1px solid rgba(148, 163, 184, 0.2)',
borderRadius: 2,
px: 2,
py: 0.8,
color: 'rgba(148, 163, 184, 0.6)',
fontSize: '0.8rem',
fontWeight: 600,
textTransform: 'none',
backdropFilter: 'blur(8px)',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
position: 'relative',
overflow: 'hidden',
minWidth: 'auto',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, rgba(148, 163, 184, 0.05) 0%, rgba(100, 116, 139, 0.05) 100%)',
zIndex: -1,
},
'&:hover': {
background: 'linear-gradient(135deg, rgba(148, 163, 184, 0.1) 0%, rgba(100, 116, 139, 0.1) 100%)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
},
'&.Mui-disabled': {
background: 'linear-gradient(135deg, rgba(148, 163, 184, 0.1) 0%, rgba(100, 116, 139, 0.1) 100%)',
color: 'rgba(148, 163, 184, 0.6)',
border: '1px solid rgba(148, 163, 184, 0.2)',
}
}}
>
💬 Chat
<Chip
label="Pro"
size="small"
sx={{
ml: 1,
background: 'linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%)',
color: 'white',
fontSize: '0.6rem',
fontWeight: 700,
height: 18,
'& .MuiChip-label': {
px: 0.8,
}
}}
/>
</Button>
</Box>
</Box> </Box>
<Stack direction={{ xs: 'column', md: 'row' }} spacing={1}> <Stack direction={{ xs: 'column', md: 'row' }} spacing={1}>
{columns.map((col) => { {columns.map((col) => {
const isHovered = hovered === col.key; const isHovered = hovered === col.key;
@@ -291,27 +420,60 @@ const AnalyticsInsights: React.FC<AnalyticsInsightsProps> = ({ data, onActionCli
<Badge>{col.items.length}</Badge> <Badge>{col.items.length}</Badge>
</GradientHeader> </GradientHeader>
<CardContent sx={{ p: 1, '&:last-child': { pb: 1 } }}> <CardContent sx={{ p: 1.4, '&:last-child': { pb: 1.4 } }}>
<Stack spacing={0.5}> <Stack spacing={1.05}>
{visibleItems.map((insight) => ( {visibleItems.map((insight) => (
<Box key={insight.id} sx={{ <Box key={insight.id} sx={{
background: 'rgba(255,255,255,0.08)', background: 'rgba(15, 23, 42, 0.4)',
border: '1px solid rgba(255,255,255,0.18)', border: '1px solid rgba(148, 163, 184, 0.1)',
borderRadius: 1.5, borderRadius: 2,
p: 0.8 p: 1.05,
backdropFilter: 'blur(8px)',
transition: 'all 0.2s ease-in-out',
'&:hover': {
background: 'rgba(15, 23, 42, 0.6)',
border: '1px solid rgba(148, 163, 184, 0.2)',
transform: 'translateY(-1px)',
boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
}
}}> }}>
<Stack direction="row" spacing={0.5} alignItems="center" sx={{ mb: 0.1 }}> <Stack direction="row" spacing={0.7} alignItems="center" sx={{ mb: 0.7 }}>
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.95)', fontWeight: 700, fontSize: '0.8rem' }}> <Typography variant="body2" sx={{
color: '#ffffff',
fontWeight: 700,
fontSize: '0.85rem',
textShadow: '0 1px 2px rgba(0,0,0,0.3)'
}}>
{insight.title} {insight.title}
</Typography> </Typography>
<TrendChip trend={insight.trend} /> <TrendChip trend={insight.trend} />
</Stack> </Stack>
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.8)', fontSize: '0.7rem', lineHeight: 1.2 }}> <Typography variant="body2" sx={{
color: 'rgba(255,255,255,0.8)',
fontSize: '0.75rem',
lineHeight: 1.4,
mb: 0.7
}}>
{insight.description} {insight.description}
</Typography> </Typography>
<Stack direction="row" spacing={0.5} sx={{ mt: 0.5 }}> <Stack direction="row" spacing={0.7} sx={{ mt: 0.7 }}>
<Chip size="small" label={`${insight.metric}: ${insight.value}`} sx={{ color: 'rgba(255,255,255,0.95)', background: 'rgba(255,255,255,0.12)', border: '1px solid rgba(255,255,255,0.24)', fontWeight: 700, fontSize: '0.65rem', height: 20 }} /> <Chip size="small" label={`${insight.metric}: ${insight.value}`} sx={{
<Chip size="small" label={insight.platform} sx={{ color: 'rgba(255,255,255,0.85)', background: 'rgba(255,255,255,0.08)', fontSize: '0.65rem', height: 20 }} /> color: '#ffffff',
background: 'rgba(59, 130, 246, 0.2)',
border: '1px solid rgba(59, 130, 246, 0.3)',
fontWeight: 700,
fontSize: '0.7rem',
height: 24,
backdropFilter: 'blur(8px)'
}} />
<Chip size="small" label={insight.platform} sx={{
color: 'rgba(255,255,255,0.9)',
background: 'rgba(148, 163, 184, 0.15)',
border: '1px solid rgba(148, 163, 184, 0.2)',
fontSize: '0.7rem',
height: 24,
backdropFilter: 'blur(8px)'
}} />
</Stack> </Stack>
</Box> </Box>
))} ))}

View File

@@ -22,7 +22,6 @@ const AnalyzePillarChips: React.FC<AnalyzePillarChipsProps> = ({
isHovered, isHovered,
pillarColor pillarColor
}) => { }) => {
const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
// Today's tasks for Analyze pillar // Today's tasks for Analyze pillar

View File

@@ -12,11 +12,11 @@ import { motion, AnimatePresence } from 'framer-motion';
import { import {
Search, Search,
Filter, Filter,
Settings,
ChevronLeft, ChevronLeft,
ChevronRight, ChevronRight,
Activity, Activity,
Zap Zap,
Star
} from 'lucide-react'; } from 'lucide-react';
// Shared components // Shared components
@@ -38,6 +38,8 @@ interface CompactSidebarProps {
collapsed: boolean; collapsed: boolean;
onToggleCollapse: () => void; onToggleCollapse: () => void;
theme: any; theme: any;
favorites?: string[];
onToolClick?: (tool: any) => void;
} }
// Session control for animation // Session control for animation
@@ -69,8 +71,18 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
onCategoryClick, onCategoryClick,
collapsed, collapsed,
onToggleCollapse, onToggleCollapse,
theme theme,
favorites = [],
onToolClick
}) => { }) => {
// State for search expansion on hover
const [isSearchExpanded, setIsSearchExpanded] = useState(false);
// State for sidebar hover expansion
const [isSidebarHovered, setIsSidebarHovered] = useState(false);
// State for favorites expansion on hover
const [isFavoritesExpanded, setIsFavoritesExpanded] = useState(false);
// Track original collapsed state for hover behavior
const [wasOriginallyCollapsed, setWasOriginallyCollapsed] = useState(false);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
const [rippleIndex, setRippleIndex] = useState(-1); const [rippleIndex, setRippleIndex] = useState(-1);
const [shouldAutoExpand, setShouldAutoExpand] = useState(false); const [shouldAutoExpand, setShouldAutoExpand] = useState(false);
@@ -105,7 +117,7 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
setIsAnimating(true); setIsAnimating(true);
markAnimationShown(); markAnimationShown();
} }
}, []); // Empty dependency array - only run once on mount }, [collapsed, userHasInteracted]); // Include dependencies to avoid warning
// Handle auto-expand animation // Handle auto-expand animation
useEffect(() => { useEffect(() => {
@@ -157,6 +169,25 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
boxShadow: { duration: 2, ease: 'easeInOut' } boxShadow: { duration: 2, ease: 'easeInOut' }
}) })
}} }}
onMouseEnter={() => {
setIsSidebarHovered(true);
if (collapsed) {
setUserHasInteracted(true);
setWasOriginallyCollapsed(true);
// Temporarily expand the sidebar on hover
onToggleCollapse();
}
}}
onMouseLeave={() => {
setIsSidebarHovered(false);
setIsSearchExpanded(false);
setIsFavoritesExpanded(false);
// Collapse back if it was originally collapsed
if (wasOriginallyCollapsed) {
onToggleCollapse();
setWasOriginallyCollapsed(false);
}
}}
> >
<Paper <Paper
elevation={0} elevation={0}
@@ -164,24 +195,39 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
width: '100%', width: '100%',
height: 'fit-content', height: 'fit-content',
minHeight: '400px', minHeight: '400px',
background: 'linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%)', background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%)',
backdropFilter: 'blur(10px)', backdropFilter: 'blur(24px)',
border: '1px solid rgba(255,255,255,0.1)', border: '1px solid rgba(148, 163, 184, 0.1)',
borderRadius: 3, borderRadius: 4,
overflow: 'hidden', overflow: 'hidden',
boxShadow: '0 8px 32px rgba(0,0,0,0.1)', boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.05)',
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, rgba(59, 130, 246, 0.03) 0%, rgba(147, 51, 234, 0.02) 100%)',
zIndex: -1,
},
'&:hover': {
border: '1px solid rgba(148, 163, 184, 0.2)',
boxShadow: '0 32px 64px -12px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.08)',
},
}} }}
> >
{/* Header */} {/* Header */}
<Box <Box
sx={{ sx={{
p: collapsed ? 1 : 2, p: collapsed ? 1.5 : 2.5,
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
borderBottom: '1px solid rgba(255,255,255,0.1)', borderBottom: '1px solid rgba(148, 163, 184, 0.1)',
minHeight: 56, minHeight: 56,
background: 'linear-gradient(90deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)', background: 'linear-gradient(90deg, rgba(59, 130, 246, 0.05) 0%, rgba(147, 51, 234, 0.03) 100%)',
position: 'relative', position: 'relative',
'&::before': { '&::before': {
content: '""', content: '""',
@@ -190,7 +236,7 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
left: 0, left: 0,
right: 0, right: 0,
height: '1px', height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.2) 50%, transparent 100%)', background: 'linear-gradient(90deg, transparent 0%, rgba(59, 130, 246, 0.3) 50%, transparent 100%)',
} }
}} }}
> >
@@ -270,11 +316,12 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
{/* Search Section */} {/* Search Section */}
<Box sx={{ <Box sx={{
mb: 2, mb: 2,
p: 2, p: 2.5,
backgroundColor: 'rgba(255,255,255,0.03)', backgroundColor: 'rgba(15, 23, 42, 0.4)',
borderRadius: 2, borderRadius: 3,
border: '1px solid rgba(255,255,255,0.05)', border: '1px solid rgba(148, 163, 184, 0.1)',
position: 'relative', position: 'relative',
backdropFilter: 'blur(8px)',
'&::before': { '&::before': {
content: '""', content: '""',
position: 'absolute', position: 'absolute',
@@ -282,7 +329,11 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
left: 0, left: 0,
right: 0, right: 0,
height: '1px', height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%)', background: 'linear-gradient(90deg, transparent 0%, rgba(59, 130, 246, 0.3) 50%, transparent 100%)',
},
'&:hover': {
border: '1px solid rgba(148, 163, 184, 0.2)',
backgroundColor: 'rgba(15, 23, 42, 0.6)',
} }
}}> }}>
<Typography variant="subtitle2" sx={{ <Typography variant="subtitle2" sx={{
@@ -311,172 +362,94 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
/> />
</Box> </Box>
<Divider sx={{ my: 2, borderColor: 'rgba(255,255,255,0.1)' }} />
{/* Quick Stats */}
<Box sx={{ {/* Favorites Section */}
mb: 2, {favorites.length > 0 && (
p: 2, <>
backgroundColor: 'rgba(255,255,255,0.03)', <Divider sx={{ my: 2, borderColor: 'rgba(255,255,255,0.1)' }} />
borderRadius: 2,
border: '1px solid rgba(255,255,255,0.05)', <Box sx={{
position: 'relative', p: 2,
'&::before': { backgroundColor: 'rgba(15, 23, 42, 0.4)',
content: '""', borderRadius: 3,
position: 'absolute', border: '1px solid rgba(148, 163, 184, 0.1)',
top: 0, position: 'relative',
left: 0, backdropFilter: 'blur(8px)',
right: 0, '&::before': {
height: '1px', content: '""',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%)', position: 'absolute',
} top: 0,
}}> left: 0,
<Typography variant="subtitle2" sx={{ right: 0,
mb: 1, height: '1px',
color: 'rgba(255,255,255,0.9)', background: 'linear-gradient(90deg, transparent 0%, rgba(251, 191, 36, 0.3) 50%, transparent 100%)',
fontWeight: 'bold', },
display: 'flex', '&:hover': {
alignItems: 'center', border: '1px solid rgba(148, 163, 184, 0.2)',
gap: 1 backgroundColor: 'rgba(15, 23, 42, 0.6)',
}}> }
<Activity size={16} color="rgba(255,255,255,0.7)" /> }}>
Quick Stats <Typography variant="subtitle2" sx={{
</Typography> mb: 1.5,
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}> color: 'rgba(255,255,255,0.9)',
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> fontWeight: 'bold',
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.7)' }}> display: 'flex',
Total Tools alignItems: 'center',
gap: 1
}}>
<Star size={16} color="#fbbf24" />
Favorite Tools
</Typography> </Typography>
<Chip
label={totalTools}
size="small"
sx={{
backgroundColor: 'rgba(74, 222, 128, 0.2)',
color: '#4ade80',
border: '1px solid rgba(74, 222, 128, 0.3)'
}}
/>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.7)' }}>
Categories
</Typography>
<Chip
label={Object.keys(toolCategories).length}
size="small"
sx={{
backgroundColor: 'rgba(59, 130, 246, 0.2)',
color: '#3b82f6',
border: '1px solid rgba(59, 130, 246, 0.3)'
}}
/>
</Box>
</Box>
</Box>
<Divider sx={{ my: 2, borderColor: 'rgba(255,255,255,0.1)' }} /> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{favorites.slice(0, 5).map((favoriteTool, index) => (
{/* Category Quick Access */} <Box
<Box sx={{ key={index}
p: 2, sx={{
backgroundColor: 'rgba(255,255,255,0.03)', p: 1.5,
borderRadius: 2, borderRadius: 2,
border: '1px solid rgba(255,255,255,0.05)', backgroundColor: 'rgba(251, 191, 36, 0.05)',
position: 'relative', border: '1px solid rgba(251, 191, 36, 0.1)',
'&::before': { cursor: 'pointer',
content: '""', transition: 'all 0.2s ease-in-out',
position: 'absolute', '&:hover': {
top: 0, backgroundColor: 'rgba(251, 191, 36, 0.1)',
left: 0, border: '1px solid rgba(251, 191, 36, 0.2)',
right: 0, transform: 'translateY(-1px)',
height: '1px', boxShadow: '0 4px 12px rgba(251, 191, 36, 0.2)',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%)', }
} }}
}}> onClick={() => onToolClick && onToolClick({ name: favoriteTool })}
<Typography variant="subtitle2" sx={{
mb: 1,
color: 'rgba(255,255,255,0.9)',
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
gap: 1
}}>
<Zap size={16} color="rgba(255,255,255,0.7)" />
Quick Access
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{Object.entries(toolCategories).slice(0, 5).map(([categoryId, category], index) => {
const toolCount = 'tools' in category
? category.tools.length
: Object.values(category.subCategories).reduce((sum, subCat) => sum + subCat.tools.length, 0);
const isRippling = rippleIndex === index;
return (
<Tooltip key={categoryId} title={`${categoryId} (${toolCount} tools)`}>
<motion.div
animate={isRippling ? {
scale: [1, 1.05, 1],
boxShadow: [
'0 0 0 rgba(74, 222, 128, 0)',
'0 0 20px rgba(74, 222, 128, 0.6)',
'0 0 0 rgba(74, 222, 128, 0)'
]
} : {}}
transition={{ duration: 1, ease: 'easeInOut' }}
> >
<Chip <Typography variant="body2" sx={{
label={`${categoryId} (${toolCount})`} color: 'rgba(255,255,255,0.9)',
size="small" fontSize: '13px',
onClick={() => { fontWeight: 500,
setUserHasInteracted(true); display: 'flex',
onCategoryClick(categoryId, category); alignItems: 'center',
}} gap: 1
sx={{ }}>
backgroundColor: selectedCategory === categoryId <Star size={12} color="#fbbf24" />
? 'rgba(74, 222, 128, 0.2)' {favoriteTool}
: isRippling </Typography>
? 'rgba(74, 222, 128, 0.15)' </Box>
: 'rgba(255,255,255,0.05)', ))}
color: selectedCategory === categoryId || isRippling ? '#4ade80' : '#ffffff',
border: selectedCategory === categoryId {favorites.length > 5 && (
? '1px solid rgba(74, 222, 128, 0.3)' <Typography variant="caption" sx={{
: isRippling color: 'rgba(255,255,255,0.6)',
? '1px solid rgba(74, 222, 128, 0.4)' textAlign: 'center',
: '1px solid rgba(255,255,255,0.1)', mt: 1,
cursor: 'pointer', fontStyle: 'italic'
transition: 'all 0.2s ease-in-out', }}>
position: 'relative', +{favorites.length - 5} more favorites
overflow: 'hidden', </Typography>
'&::before': isRippling ? { )}
content: '""', </Box>
position: 'absolute', </Box>
top: 0, </>
left: '-100%', )}
width: '100%',
height: '100%',
background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)',
animation: 'shimmer 1s ease-in-out',
'@keyframes shimmer': {
'0%': { left: '-100%' },
'100%': { left: '100%' }
}
} : {},
'&:hover': {
backgroundColor: selectedCategory === categoryId
? 'rgba(74, 222, 128, 0.3)'
: 'rgba(255,255,255,0.15)',
transform: 'translateY(-1px)',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
}
}}
/>
</motion.div>
</Tooltip>
);
})}
</Box>
</Box>
</> </>
) : ( ) : (
/* Collapsed State - Enhanced Icons with Depth */ /* Collapsed State - Enhanced Icons with Depth */
@@ -486,53 +459,109 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
whileHover={{ scale: 1.1, y: -2 }} whileHover={{ scale: 1.1, y: -2 }}
whileTap={{ scale: 0.95 }} whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 300, damping: 20 }} transition={{ type: "spring", stiffness: 300, damping: 20 }}
onMouseEnter={() => {
setIsSearchExpanded(true);
setUserHasInteracted(true);
}}
onMouseLeave={() => {
setTimeout(() => setIsSearchExpanded(false), 1000);
}}
> >
<IconButton <Box sx={{ position: 'relative' }}>
size="small" <IconButton
sx={{ size="small"
color: searchQuery ? '#4ade80' : 'rgba(255,255,255,0.8)', sx={{
backgroundColor: searchQuery color: searchQuery ? '#4ade80' : 'rgba(255,255,255,0.8)',
? 'rgba(74, 222, 128, 0.15)'
: 'rgba(255,255,255,0.08)',
border: searchQuery
? '2px solid rgba(74, 222, 128, 0.4)'
: '2px solid rgba(255,255,255,0.15)',
borderRadius: '12px',
width: 40,
height: 40,
boxShadow: searchQuery
? '0 8px 25px rgba(74, 222, 128, 0.3), 0 0 20px rgba(74, 222, 128, 0.2), inset 0 1px 0 rgba(255,255,255,0.2)'
: '0 6px 20px rgba(0,0,0,0.15), 0 0 15px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.1)',
backdropFilter: 'blur(10px)',
position: 'relative',
overflow: 'hidden',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: searchQuery
? 'linear-gradient(135deg, rgba(74, 222, 128, 0.1) 0%, rgba(34, 197, 94, 0.1) 100%)'
: 'linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)',
borderRadius: '10px',
zIndex: -1
},
'&:hover': {
color: '#ffffff',
backgroundColor: searchQuery backgroundColor: searchQuery
? 'rgba(74, 222, 128, 0.25)' ? 'rgba(74, 222, 128, 0.15)'
: 'rgba(255,255,255,0.15)', : 'rgba(255,255,255,0.08)',
border: searchQuery
? '2px solid rgba(74, 222, 128, 0.4)'
: '2px solid rgba(255,255,255,0.15)',
borderRadius: '12px',
width: 40,
height: 40,
boxShadow: searchQuery boxShadow: searchQuery
? '0 12px 35px rgba(74, 222, 128, 0.4), 0 0 30px rgba(74, 222, 128, 0.3), inset 0 1px 0 rgba(255,255,255,0.3)' ? '0 8px 25px rgba(74, 222, 128, 0.3), 0 0 20px rgba(74, 222, 128, 0.2), inset 0 1px 0 rgba(255,255,255,0.2)'
: '0 10px 30px rgba(0,0,0,0.2), 0 0 25px rgba(255,255,255,0.15), inset 0 1px 0 rgba(255,255,255,0.2)', : '0 6px 20px rgba(0,0,0,0.15), 0 0 15px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.1)',
transform: 'translateY(-2px)' backdropFilter: 'blur(10px)',
} position: 'relative',
}} overflow: 'hidden',
> '&::before': {
<Search size={18} /> content: '""',
</IconButton> position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: searchQuery
? 'linear-gradient(135deg, rgba(74, 222, 128, 0.1) 0%, rgba(34, 197, 94, 0.1) 100%)'
: 'linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)',
borderRadius: '10px',
zIndex: -1
},
'&:hover': {
color: '#ffffff',
backgroundColor: searchQuery
? 'rgba(74, 222, 128, 0.25)'
: 'rgba(255,255,255,0.15)',
boxShadow: searchQuery
? '0 12px 35px rgba(74, 222, 128, 0.4), 0 0 30px rgba(74, 222, 128, 0.3), inset 0 1px 0 rgba(255,255,255,0.3)'
: '0 10px 30px rgba(0,0,0,0.2), 0 0 25px rgba(255,255,255,0.15), inset 0 1px 0 rgba(255,255,255,0.2)',
transform: 'translateY(-2px)'
}
}}
>
<Search size={18} />
</IconButton>
{/* Expanded Search Input */}
<AnimatePresence>
{isSearchExpanded && (
<motion.div
initial={{ opacity: 0, x: -20, scale: 0.8 }}
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: -20, scale: 0.8 }}
transition={{ duration: 0.3, ease: "easeOut" }}
style={{
position: 'absolute',
left: 50,
top: 0,
zIndex: 1000,
}}
>
<Box
sx={{
backgroundColor: 'rgba(0, 0, 0, 0.9)',
backdropFilter: 'blur(20px)',
borderRadius: 2,
p: 1,
border: '1px solid rgba(255,255,255,0.2)',
boxShadow: '0 8px 32px rgba(0,0,0,0.3)',
minWidth: 200,
}}
>
<input
type="text"
placeholder="Search tools..."
value={searchQuery}
onChange={(e) => onSearchChange(e.target.value)}
style={{
background: 'transparent',
border: 'none',
outline: 'none',
color: 'white',
fontSize: '14px',
width: '100%',
padding: '8px 12px',
}}
autoFocus
/>
</Box>
</motion.div>
)}
</AnimatePresence>
</Box>
</motion.div> </motion.div>
</Tooltip> </Tooltip>
@@ -591,6 +620,134 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
</motion.div> </motion.div>
</Tooltip> </Tooltip>
{/* Favorites Star Icon */}
<Tooltip title="Favorite Tools">
<motion.div
whileHover={{ scale: 1.1, y: -2 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
onMouseEnter={() => {
setIsFavoritesExpanded(true);
setUserHasInteracted(true);
}}
onMouseLeave={() => {
setTimeout(() => setIsFavoritesExpanded(false), 1000);
}}
>
<Box sx={{ position: 'relative' }}>
<IconButton
size="small"
sx={{
color: favorites.length > 0 ? '#fbbf24' : 'rgba(255,255,255,0.8)',
backgroundColor: favorites.length > 0
? 'rgba(251, 191, 36, 0.15)'
: 'rgba(255,255,255,0.08)',
border: favorites.length > 0
? '2px solid rgba(251, 191, 36, 0.4)'
: '2px solid rgba(255,255,255,0.15)',
borderRadius: '12px',
width: 40,
height: 40,
boxShadow: favorites.length > 0
? '0 8px 25px rgba(251, 191, 36, 0.3), 0 0 20px rgba(251, 191, 36, 0.2), inset 0 1px 0 rgba(255,255,255,0.2)'
: '0 6px 20px rgba(0,0,0,0.15), 0 0 15px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.1)',
backdropFilter: 'blur(10px)',
position: 'relative',
overflow: 'hidden',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: favorites.length > 0
? 'linear-gradient(135deg, rgba(251, 191, 36, 0.1) 0%, rgba(245, 158, 11, 0.1) 100%)'
: 'linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)',
borderRadius: '10px',
zIndex: -1
},
'&:hover': {
color: '#ffffff',
backgroundColor: favorites.length > 0
? 'rgba(251, 191, 36, 0.25)'
: 'rgba(255,255,255,0.15)',
boxShadow: favorites.length > 0
? '0 12px 35px rgba(251, 191, 36, 0.4), 0 0 30px rgba(251, 191, 36, 0.3), inset 0 1px 0 rgba(255,255,255,0.3)'
: '0 10px 30px rgba(0,0,0,0.2), 0 0 25px rgba(255,255,255,0.15), inset 0 1px 0 rgba(255,255,255,0.2)',
transform: 'translateY(-2px)'
}
}}
>
<Star size={18} />
</IconButton>
{/* Expanded Favorites List */}
<AnimatePresence>
{isFavoritesExpanded && favorites.length > 0 && (
<motion.div
initial={{ opacity: 0, x: -20, scale: 0.8 }}
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: -20, scale: 0.8 }}
transition={{ duration: 0.3, ease: "easeOut" }}
style={{
position: 'absolute',
left: 50,
top: 0,
zIndex: 1000,
}}
>
<Box
sx={{
backgroundColor: 'rgba(0, 0, 0, 0.9)',
backdropFilter: 'blur(20px)',
borderRadius: 2,
p: 1,
border: '1px solid rgba(255,255,255,0.2)',
boxShadow: '0 8px 32px rgba(0,0,0,0.3)',
minWidth: 200,
maxHeight: 300,
overflowY: 'auto',
}}
>
<Typography variant="subtitle2" sx={{
color: '#fbbf24',
mb: 1,
px: 1,
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
gap: 1
}}>
<Star size={16} />
Favorite Tools
</Typography>
{favorites.map((favoriteTool, index) => (
<Box
key={index}
sx={{
p: 1,
borderRadius: 1,
cursor: 'pointer',
'&:hover': {
backgroundColor: 'rgba(255,255,255,0.1)',
}
}}
onClick={() => onToolClick && onToolClick({ name: favoriteTool })}
>
<Typography variant="body2" sx={{ color: 'white', fontSize: '12px' }}>
{favoriteTool}
</Typography>
</Box>
))}
</Box>
</motion.div>
)}
</AnimatePresence>
</Box>
</motion.div>
</Tooltip>
<Divider sx={{ width: '100%', borderColor: 'rgba(255,255,255,0.1)' }} /> <Divider sx={{ width: '100%', borderColor: 'rgba(255,255,255,0.1)' }} />
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>

View File

@@ -23,7 +23,6 @@ const EngagePillarChips: React.FC<EngagePillarChipsProps> = ({
isHovered, isHovered,
pillarColor pillarColor
}) => { }) => {
const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
// Today's tasks for Engage pillar // Today's tasks for Engage pillar

View File

@@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { import {
Box, Box,
Typography,
Chip, Chip,
Tooltip Tooltip
} from '@mui/material'; } from '@mui/material';
@@ -33,7 +32,7 @@ const EnhancedTodayChip: React.FC<EnhancedTodayChipProps> = ({
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [shouldShake, setShouldShake] = useState(false); const [shouldShake, setShouldShake] = useState(false);
const [userManuallyClosed, setUserManuallyClosed] = useState(false); const [userManuallyClosed, setUserManuallyClosed] = useState(false);
const { workflowProgress, navigationState, currentWorkflow } = useWorkflowStore(); const { currentWorkflow } = useWorkflowStore();
// Prefer live workflow tasks (to reflect updated statuses), fallback to props // Prefer live workflow tasks (to reflect updated statuses), fallback to props
const liveTasks = currentWorkflow?.tasks && Array.isArray(currentWorkflow.tasks) && currentWorkflow.tasks.length > 0 const liveTasks = currentWorkflow?.tasks && Array.isArray(currentWorkflow.tasks) && currentWorkflow.tasks.length > 0

View File

@@ -41,7 +41,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
exit={{ opacity: 0, y: -20 }} exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.6, ease: "easeOut" }} transition={{ duration: 0.6, ease: "easeOut" }}
> >
{/* Backdrop Overlay - Only over pillars section */} {/* Banner Overlay - Covers task workflow area with constrained width */}
<Box <Box
sx={{ sx={{
position: 'absolute', position: 'absolute',
@@ -49,23 +49,27 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
left: 0, left: 0,
right: 0, right: 0,
bottom: 0, bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.6)',
backdropFilter: 'blur(6px)',
zIndex: 10, zIndex: 10,
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
borderRadius: 2, // Match the parent container's border radius borderRadius: 2, // Match the parent container's border radius
px: 2, // Add horizontal padding to constrain width
}} }}
> >
{/* Hero Content */} {/* Hero Content - Full Coverage */}
<Box <Box
sx={{ sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center', textAlign: 'center',
maxWidth: isMobile ? '90%' : '500px',
px: 3, px: 3,
py: 4, py: 4,
background: 'linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%)', background: 'linear-gradient(135deg, rgba(255,255,255,0.036) 0%, rgba(255,255,255,0.018) 100%)',
backdropFilter: 'blur(20px)', backdropFilter: 'blur(20px)',
borderRadius: 3, borderRadius: 3,
border: '1px solid rgba(255,255,255,0.2)', border: '1px solid rgba(255,255,255,0.2)',
@@ -127,8 +131,29 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
animate={{ opacity: 1, scale: 1 }} animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.8, delay: 0.2 }} transition={{ duration: 0.8, delay: 0.2 }}
> >
{/* Icon */} {/* Main Heading with Rocket */}
<Box sx={{ mb: 2 }}> <Box sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 2,
mb: 2
}}>
<Typography
variant={isMobile ? "h5" : "h4"}
sx={{
fontWeight: 800,
color: '#ffffff',
textShadow: '0 4px 8px rgba(0,0,0,0.3)',
background: 'linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%)',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
Grow Your Business Now
</Typography>
<motion.div <motion.div
animate={{ animate={{
rotate: [0, 5, -5, 0], rotate: [0, 5, -5, 0],
@@ -142,7 +167,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
> >
<Rocket <Rocket
sx={{ sx={{
fontSize: isMobile ? 40 : 48, fontSize: isMobile ? 32 : 40,
color: '#FF6B35', color: '#FF6B35',
filter: 'drop-shadow(0 4px 8px rgba(255,107,53,0.3))' filter: 'drop-shadow(0 4px 8px rgba(255,107,53,0.3))'
}} }}
@@ -150,38 +175,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
</motion.div> </motion.div>
</Box> </Box>
{/* Main Heading */}
<Typography
variant={isMobile ? "h5" : "h4"}
sx={{
fontWeight: 800,
color: '#ffffff',
mb: 1.5,
textShadow: '0 4px 8px rgba(0,0,0,0.3)',
background: 'linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%)',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
Grow Your Business Now
</Typography>
{/* Supporting Text */} {/* Supporting Text */}
<Typography
variant={isMobile ? "body2" : "body1"}
sx={{
color: 'rgba(255,255,255,0.9)',
mb: 3,
lineHeight: 1.5,
maxWidth: '400px',
mx: 'auto',
textShadow: '0 2px 4px rgba(0,0,0,0.3)',
}}
>
Start your personalized content workflow and watch your digital marketing transform.
Our AI-powered system will guide you through every step of your content journey.
</Typography>
{/* CTA Button */} {/* CTA Button */}
<motion.div <motion.div
@@ -251,7 +245,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
}} }}
> >
{isLoading ? 'Starting...' : '🚀 Start Your Journey'} {isLoading ? 'Starting...' : 'Start Today\'s Tasks'}
</Button> </Button>
</motion.div> </motion.div>