Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
/node_modules
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# Temporary files
/tmp
14 changes: 14 additions & 0 deletions dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Wokay Assignment</title>
<script type="module" crossorigin src="/assets/index-qbwFwaaX.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B4kJOju9.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
57 changes: 53 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"framer-motion": "^12.23.0",
"lucide-react": "^0.344.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
8 changes: 4 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import TaskCharts from "./components/TaskCharts";

function App() {
return (
<div className="min-h-screen bg-gray-50">
<div className="h-screen bg-gray-50 flex flex-col">
<Header />

<div className="flex">
<div className="flex flex-1 overflow-hidden">
<Sidebar />

<div className="flex-1">
<div className="flex-1 flex flex-col overflow-hidden">
<SecondaryHeader />
<DashboardControls />

<main className="p-6 space-y-6">
<main className="flex-1 overflow-y-auto p-6 space-y-6">
<div className="grid grid-cols-2 gap-6">
<div className="h-full flex flex-col">
<AIExecutiveSummary />
Expand Down
184 changes: 166 additions & 18 deletions src/components/AIExecutiveSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,192 @@
import { Sparkles, Expand, RefreshCw } from "lucide-react";
import { useState, useEffect } from "react";
import { Sparkles, Expand, RefreshCw, TrendingUp, AlertTriangle, CheckCircle } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";

const AIExecutiveSummary = () => {
const [isGenerating, setIsGenerating] = useState(false);
const [currentInsight, setCurrentInsight] = useState(0);
const [isExpanded, setIsExpanded] = useState(false);

const insights = [
{
title: "Team Productivity Surge",
content: "Your team has completed 73% more tasks this week compared to last week. The Development team is leading with 18 completed tasks.",
type: "positive",
icon: TrendingUp,
color: "text-green-600",
bgColor: "bg-green-50",
borderColor: "border-green-200"
},
{
title: "Bottleneck Alert",
content: "The Review process is experiencing delays with 8 pending tasks. Consider allocating additional reviewers to maintain workflow.",
type: "warning",
icon: AlertTriangle,
color: "text-amber-600",
bgColor: "bg-amber-50",
borderColor: "border-amber-200"
},
{
title: "Sprint Goal Achievement",
content: "You're on track to exceed your sprint goal by 15%. Current completion rate suggests finishing 2 days ahead of schedule.",
type: "success",
icon: CheckCircle,
color: "text-blue-600",
bgColor: "bg-blue-50",
borderColor: "border-blue-200"
}
];

const recommendations = [
"Consider redistributing 3 tasks from Design to Development team",
"Schedule additional code review sessions for Thursday",
"Celebrate team achievements to maintain momentum"
];

const handleRefresh = () => {
setIsGenerating(true);
setTimeout(() => {
setIsGenerating(false);
setCurrentInsight((prev) => (prev + 1) % insights.length);
}, 2000);
};

useEffect(() => {
const interval = setInterval(() => {
setCurrentInsight((prev) => (prev + 1) % insights.length);
}, 8000);
return () => clearInterval(interval);
}, [insights.length]);

const currentData = insights[currentInsight];
const IconComponent = currentData.icon;

return (
<div className="bg-white flex-grow rounded-lg border border-gray-200 p-6">
<div className={`bg-white flex-grow rounded-lg border border-gray-200 p-6 transition-all duration-300 hover:shadow-sm ${
isExpanded ? 'row-span-2' : ''
}`}>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
<div className="w-8 h-8 bg-gradient-to-br from-purple-500 to-pink-500 rounded-lg flex items-center justify-center">
<Sparkles className="w-5 h-5 text-white" />
<div className="relative">
<div className="w-8 h-8 bg-purple-600 rounded-lg flex items-center justify-center">
<Sparkles className="w-5 h-5 text-white" />
</div>
{isGenerating && (
<motion.div
className="absolute inset-0 rounded-lg bg-purple-400 opacity-30"
animate={{ scale: [1, 1.1, 1] }}
transition={{ duration: 1, repeat: Infinity }}
/>
)}
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900">
AI Executive Summary
</h3>
<p className="text-sm text-gray-500">Refreshed 3 mins ago</p>
<p className="text-sm text-gray-500">
{isGenerating ? "Generating insights..." : "Updated just now"}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
<button
onClick={() => setIsExpanded(!isExpanded)}
className="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded transition-colors"
>
<Expand className="w-4 h-4" />
</button>
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
<RefreshCw className="w-4 h-4" />
<button
onClick={handleRefresh}
disabled={isGenerating}
className="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded transition-colors disabled:opacity-50"
>
<RefreshCw className={`w-4 h-4 ${isGenerating ? 'animate-spin text-purple-600' : ''}`} />
</button>
</div>
</div>

<div className="space-y-4">
<div>
<h4 className="font-medium text-gray-900 mb-2">Executive Summary</h4>
<p className="text-gray-600">
No tasks were updated in the last week.
</p>
</div>
{/* Main Insight Card */}
<AnimatePresence mode="wait">
<motion.div
key={currentInsight}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
className={`${currentData.bgColor} ${currentData.borderColor} border rounded-lg p-4 mb-4`}
>
<div className="flex items-start space-x-3">
<div className={`p-2 rounded-lg bg-white shadow-sm`}>
<IconComponent className={`w-5 h-5 ${currentData.color}`} />
</div>
<div className="flex-1">
<h4 className={`font-medium ${currentData.color} mb-2`}>
{currentData.title}
</h4>
<p className="text-gray-700 text-sm leading-relaxed">
{currentData.content}
</p>
</div>
</div>
</motion.div>
</AnimatePresence>

{/* Insight Indicators */}
<div className="flex justify-center space-x-2 mb-4">
{insights.map((_, index) => (
<button
key={index}
onClick={() => setCurrentInsight(index)}
className={`w-2 h-2 rounded-full transition-all duration-200 ${
index === currentInsight ? 'bg-purple-600 w-4' : 'bg-gray-300 hover:bg-gray-400'
}`}
/>
))}
</div>

{/* Recommendations Section */}
<div className="space-y-4">
<div>
<h4 className="font-medium text-gray-900 mb-2">
Key Efforts & Initiatives
<h4 className="font-medium text-gray-900 mb-3 flex items-center">
<span className="w-2 h-2 bg-purple-600 rounded-full mr-3"></span>
AI Recommendations
</h4>
<p className="text-gray-600">There are no active tasks.</p>
<div className="space-y-2">
{recommendations.map((rec, index) => (
<motion.div
key={index}
whileHover={{ x: 4 }}
className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
>
<div className="w-5 h-5 rounded-full bg-purple-100 flex items-center justify-center mt-0.5">
<span className="text-xs font-medium text-purple-600">{index + 1}</span>
</div>
<p className="text-sm text-gray-700 leading-relaxed">{rec}</p>
</motion.div>
))}
</div>
</div>

{isExpanded && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
className="mt-6 pt-4 border-t border-gray-200"
>
<h4 className="font-medium text-gray-900 mb-3">Detailed Analytics</h4>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg">
<div className="text-xl font-bold text-blue-600">92%</div>
<div className="text-xs text-gray-600">Team Efficiency</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg">
<div className="text-xl font-bold text-green-600">+18%</div>
<div className="text-xs text-gray-600">Week over Week</div>
</div>
</div>
</motion.div>
)}
</div>
</div>
);
Expand Down
Loading