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

View File

@@ -13,7 +13,6 @@ import {
Divider
} from '@mui/material';
import { styled } from '@mui/material/styles';
import { keyframes } from '@mui/system';
import {
CheckCircle as CheckIcon,
WarningAmber as WarningIcon,
@@ -53,43 +52,64 @@ interface AnalyticsInsightsProps {
}
const ColumnCard = styled(Card)(({ theme }) => ({
background: 'linear-gradient(180deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.08) 100%)',
border: '1px solid rgba(255,255,255,0.16)',
backdropFilter: 'blur(18px)',
WebkitBackdropFilter: 'blur(18px)',
borderRadius: theme.spacing(2),
background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.8) 0%, rgba(30, 41, 59, 0.7) 100%)',
border: '1px solid rgba(148, 163, 184, 0.15)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
borderRadius: theme.spacing(3),
overflow: 'hidden',
boxShadow: '0 8px 20px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.22)',
transition: 'transform 0.3s ease, box-shadow 0.3s ease',
boxShadow: '0 20px 40px -12px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.05)',
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': {
transform: 'translateY(-3px)',
boxShadow: '0 12px 28px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.28)'
transform: 'translateY(-4px)',
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 }>(() => ({
width: 10,
height: 10,
borderRadius: 6,
}));
// Pill component removed as it's not used
const GradientHeader = styled(Box)<{ gradient: string }>(({ gradient }) => ({
background: gradient,
padding: '8px 12px',
padding: '12px 16px',
color: 'white',
display: 'flex',
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 }) => ({
background: 'rgba(255,255,255,0.15)',
border: '1px solid rgba(255,255,255,0.35)',
background: 'rgba(255,255,255,0.2)',
border: '1px solid rgba(255,255,255,0.4)',
color: 'white',
borderRadius: 999,
padding: '1px 6px',
borderRadius: 12,
padding: '4px 8px',
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 (
<Box sx={{ mt: 1, mb: 1.5 }}>
<Box sx={{ position: 'relative', overflow: 'hidden' }}>
<Typography
variant="h6"
sx={{
fontWeight: 800,
mb: 1.5,
fontSize: '1.1rem',
color: 'rgba(255,255,255,0.95)',
}}
>
Today's Analytics Insights
</Typography>
<Box sx={{
mt: 1.4,
mb: 1.4,
p: 2.1,
background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%)',
backdropFilter: 'blur(24px)',
border: '1px solid rgba(148, 163, 184, 0.1)',
borderRadius: 4,
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',
'&::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,
},
}}>
<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>
<Stack direction={{ xs: 'column', md: 'row' }} spacing={1}>
{columns.map((col) => {
const isHovered = hovered === col.key;
@@ -291,27 +420,60 @@ const AnalyticsInsights: React.FC<AnalyticsInsightsProps> = ({ data, onActionCli
<Badge>{col.items.length}</Badge>
</GradientHeader>
<CardContent sx={{ p: 1, '&:last-child': { pb: 1 } }}>
<Stack spacing={0.5}>
<CardContent sx={{ p: 1.4, '&:last-child': { pb: 1.4 } }}>
<Stack spacing={1.05}>
{visibleItems.map((insight) => (
<Box key={insight.id} sx={{
background: 'rgba(255,255,255,0.08)',
border: '1px solid rgba(255,255,255,0.18)',
borderRadius: 1.5,
p: 0.8
background: 'rgba(15, 23, 42, 0.4)',
border: '1px solid rgba(148, 163, 184, 0.1)',
borderRadius: 2,
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 }}>
<Typography variant="body2" sx={{ color: 'rgba(255,255,255,0.95)', fontWeight: 700, fontSize: '0.8rem' }}>
<Stack direction="row" spacing={0.7} alignItems="center" sx={{ mb: 0.7 }}>
<Typography variant="body2" sx={{
color: '#ffffff',
fontWeight: 700,
fontSize: '0.85rem',
textShadow: '0 1px 2px rgba(0,0,0,0.3)'
}}>
{insight.title}
</Typography>
<TrendChip trend={insight.trend} />
</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}
</Typography>
<Stack direction="row" spacing={0.5} sx={{ mt: 0.5 }}>
<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.platform} sx={{ color: 'rgba(255,255,255,0.85)', background: 'rgba(255,255,255,0.08)', fontSize: '0.65rem', height: 20 }} />
<Stack direction="row" spacing={0.7} sx={{ mt: 0.7 }}>
<Chip size="small" label={`${insight.metric}: ${insight.value}`} sx={{
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>
</Box>
))}

View File

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

View File

@@ -12,11 +12,11 @@ import { motion, AnimatePresence } from 'framer-motion';
import {
Search,
Filter,
Settings,
ChevronLeft,
ChevronRight,
Activity,
Zap
Zap,
Star
} from 'lucide-react';
// Shared components
@@ -38,6 +38,8 @@ interface CompactSidebarProps {
collapsed: boolean;
onToggleCollapse: () => void;
theme: any;
favorites?: string[];
onToolClick?: (tool: any) => void;
}
// Session control for animation
@@ -69,8 +71,18 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
onCategoryClick,
collapsed,
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 [rippleIndex, setRippleIndex] = useState(-1);
const [shouldAutoExpand, setShouldAutoExpand] = useState(false);
@@ -105,7 +117,7 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
setIsAnimating(true);
markAnimationShown();
}
}, []); // Empty dependency array - only run once on mount
}, [collapsed, userHasInteracted]); // Include dependencies to avoid warning
// Handle auto-expand animation
useEffect(() => {
@@ -157,6 +169,25 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
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
elevation={0}
@@ -164,24 +195,39 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
width: '100%',
height: 'fit-content',
minHeight: '400px',
background: 'linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%)',
backdropFilter: 'blur(10px)',
border: '1px solid rgba(255,255,255,0.1)',
borderRadius: 3,
background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%)',
backdropFilter: 'blur(24px)',
border: '1px solid rgba(148, 163, 184, 0.1)',
borderRadius: 4,
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 */}
<Box
sx={{
p: collapsed ? 1 : 2,
p: collapsed ? 1.5 : 2.5,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
borderBottom: '1px solid rgba(255,255,255,0.1)',
borderBottom: '1px solid rgba(148, 163, 184, 0.1)',
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',
'&::before': {
content: '""',
@@ -190,7 +236,7 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
left: 0,
right: 0,
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 */}
<Box sx={{
mb: 2,
p: 2,
backgroundColor: 'rgba(255,255,255,0.03)',
borderRadius: 2,
border: '1px solid rgba(255,255,255,0.05)',
p: 2.5,
backgroundColor: 'rgba(15, 23, 42, 0.4)',
borderRadius: 3,
border: '1px solid rgba(148, 163, 184, 0.1)',
position: 'relative',
backdropFilter: 'blur(8px)',
'&::before': {
content: '""',
position: 'absolute',
@@ -282,7 +329,11 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
left: 0,
right: 0,
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={{
@@ -311,172 +362,94 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
/>
</Box>
<Divider sx={{ my: 2, borderColor: 'rgba(255,255,255,0.1)' }} />
{/* Quick Stats */}
<Box sx={{
mb: 2,
p: 2,
backgroundColor: 'rgba(255,255,255,0.03)',
borderRadius: 2,
border: '1px solid rgba(255,255,255,0.05)',
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%)',
}
}}>
<Typography variant="subtitle2" sx={{
mb: 1,
color: 'rgba(255,255,255,0.9)',
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
gap: 1
}}>
<Activity size={16} color="rgba(255,255,255,0.7)" />
Quick Stats
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.7)' }}>
Total Tools
{/* Favorites Section */}
{favorites.length > 0 && (
<>
<Divider sx={{ my: 2, borderColor: 'rgba(255,255,255,0.1)' }} />
<Box sx={{
p: 2,
backgroundColor: 'rgba(15, 23, 42, 0.4)',
borderRadius: 3,
border: '1px solid rgba(148, 163, 184, 0.1)',
position: 'relative',
backdropFilter: 'blur(8px)',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(251, 191, 36, 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={{
mb: 1.5,
color: 'rgba(255,255,255,0.9)',
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
gap: 1
}}>
<Star size={16} color="#fbbf24" />
Favorite Tools
</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)' }} />
{/* Category Quick Access */}
<Box sx={{
p: 2,
backgroundColor: 'rgba(255,255,255,0.03)',
borderRadius: 2,
border: '1px solid rgba(255,255,255,0.05)',
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: '1px',
background: 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%)',
}
}}>
<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' }}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{favorites.slice(0, 5).map((favoriteTool, index) => (
<Box
key={index}
sx={{
p: 1.5,
borderRadius: 2,
backgroundColor: 'rgba(251, 191, 36, 0.05)',
border: '1px solid rgba(251, 191, 36, 0.1)',
cursor: 'pointer',
transition: 'all 0.2s ease-in-out',
'&:hover': {
backgroundColor: 'rgba(251, 191, 36, 0.1)',
border: '1px solid rgba(251, 191, 36, 0.2)',
transform: 'translateY(-1px)',
boxShadow: '0 4px 12px rgba(251, 191, 36, 0.2)',
}
}}
onClick={() => onToolClick && onToolClick({ name: favoriteTool })}
>
<Chip
label={`${categoryId} (${toolCount})`}
size="small"
onClick={() => {
setUserHasInteracted(true);
onCategoryClick(categoryId, category);
}}
sx={{
backgroundColor: selectedCategory === categoryId
? 'rgba(74, 222, 128, 0.2)'
: isRippling
? 'rgba(74, 222, 128, 0.15)'
: 'rgba(255,255,255,0.05)',
color: selectedCategory === categoryId || isRippling ? '#4ade80' : '#ffffff',
border: selectedCategory === categoryId
? '1px solid rgba(74, 222, 128, 0.3)'
: isRippling
? '1px solid rgba(74, 222, 128, 0.4)'
: '1px solid rgba(255,255,255,0.1)',
cursor: 'pointer',
transition: 'all 0.2s ease-in-out',
position: 'relative',
overflow: 'hidden',
'&::before': isRippling ? {
content: '""',
position: 'absolute',
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>
<Typography variant="body2" sx={{
color: 'rgba(255,255,255,0.9)',
fontSize: '13px',
fontWeight: 500,
display: 'flex',
alignItems: 'center',
gap: 1
}}>
<Star size={12} color="#fbbf24" />
{favoriteTool}
</Typography>
</Box>
))}
{favorites.length > 5 && (
<Typography variant="caption" sx={{
color: 'rgba(255,255,255,0.6)',
textAlign: 'center',
mt: 1,
fontStyle: 'italic'
}}>
+{favorites.length - 5} more favorites
</Typography>
)}
</Box>
</Box>
</>
)}
</>
) : (
/* Collapsed State - Enhanced Icons with Depth */
@@ -486,53 +459,109 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
whileHover={{ scale: 1.1, y: -2 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
onMouseEnter={() => {
setIsSearchExpanded(true);
setUserHasInteracted(true);
}}
onMouseLeave={() => {
setTimeout(() => setIsSearchExpanded(false), 1000);
}}
>
<IconButton
size="small"
sx={{
color: searchQuery ? '#4ade80' : 'rgba(255,255,255,0.8)',
backgroundColor: searchQuery
? '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',
<Box sx={{ position: 'relative' }}>
<IconButton
size="small"
sx={{
color: searchQuery ? '#4ade80' : 'rgba(255,255,255,0.8)',
backgroundColor: searchQuery
? 'rgba(74, 222, 128, 0.25)'
: 'rgba(255,255,255,0.15)',
? '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 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>
? '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
? '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>
</Tooltip>
@@ -591,6 +620,134 @@ const CompactSidebar: React.FC<CompactSidebarProps> = ({
</motion.div>
</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)' }} />
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>

View File

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

View File

@@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react';
import {
Box,
Typography,
Chip,
Tooltip
} from '@mui/material';
@@ -33,7 +32,7 @@ const EnhancedTodayChip: React.FC<EnhancedTodayChipProps> = ({
const [modalOpen, setModalOpen] = useState(false);
const [shouldShake, setShouldShake] = 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
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 }}
transition={{ duration: 0.6, ease: "easeOut" }}
>
{/* Backdrop Overlay - Only over pillars section */}
{/* Banner Overlay - Covers task workflow area with constrained width */}
<Box
sx={{
position: 'absolute',
@@ -49,23 +49,27 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.6)',
backdropFilter: 'blur(6px)',
zIndex: 10,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 2, // Match the parent container's border radius
px: 2, // Add horizontal padding to constrain width
}}
>
{/* Hero Content */}
{/* Hero Content - Full Coverage */}
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
maxWidth: isMobile ? '90%' : '500px',
px: 3,
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)',
borderRadius: 3,
border: '1px solid rgba(255,255,255,0.2)',
@@ -127,8 +131,29 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.8, delay: 0.2 }}
>
{/* Icon */}
<Box sx={{ mb: 2 }}>
{/* Main Heading with Rocket */}
<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
animate={{
rotate: [0, 5, -5, 0],
@@ -142,7 +167,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
>
<Rocket
sx={{
fontSize: isMobile ? 40 : 48,
fontSize: isMobile ? 32 : 40,
color: '#FF6B35',
filter: 'drop-shadow(0 4px 8px rgba(255,107,53,0.3))'
}}
@@ -150,38 +175,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
</motion.div>
</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 */}
<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 */}
<motion.div
@@ -251,7 +245,7 @@ const WorkflowHeroSection: React.FC<WorkflowHeroSectionProps> = ({
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
}}
>
{isLoading ? 'Starting...' : '🚀 Start Your Journey'}
{isLoading ? 'Starting...' : 'Start Today\'s Tasks'}
</Button>
</motion.div>