Added beta testing for user_id=1 for all requests
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
))}
|
||||
|
||||
@@ -22,7 +22,6 @@ const AnalyzePillarChips: React.FC<AnalyzePillarChipsProps> = ({
|
||||
isHovered,
|
||||
pillarColor
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Today's tasks for Analyze pillar
|
||||
|
||||
@@ -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 }}>
|
||||
|
||||
@@ -23,7 +23,6 @@ const EngagePillarChips: React.FC<EngagePillarChipsProps> = ({
|
||||
isHovered,
|
||||
pillarColor
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Today's tasks for Engage pillar
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user