undefined / index.html
Yash-js's picture
Create a full-stack developer portfolio website. like a hacker. use modern components or ui library for this
4040819 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YearEndQuest Tracker</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: ["class"],
theme: {
extend: {
colors: {
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
},
secondary: {
50: '#faf7ff',
100: '#f2e9ff',
200: '#e4d4ff',
300: '#d0b4ff',
400: '#b990ff',
500: '#a855f7',
600: '#9333ea',
700: '#7c3aed',
800: '#6b21a8',
900: '#581c87',
}
}
}
}
}
</script>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/framer-motion@10.16.4/dist/framer-motion.js"></script>
<script src="https://unpkg.com/recharts/umd/Recharts.js"></script>
<script src="https://unpkg.com/lucide-react@0.263.1/dist/umd/lucide-react.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
* {
font-family: 'Inter', sans-serif;
}
.shadcn-button {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 0.375rem;
font-weight: 500;
transition: all 0.2s;
outline: none;
}
.shadcn-button:focus-visible {
outline: 2px solid rgb(14 165 233);
outline-offset: 2px;
}
.shadcn-button-primary {
background-color: rgb(14 165 233);
color: white;
}
.shadcn-button-primary:hover {
background-color: rgb(3 105 161);
}
.shadcn-button-secondary {
background-color: rgb(168 85 247);
color: white;
}
.shadcn-button-secondary:hover {
background-color: rgb(126 58 237);
}
.shadcn-input {
display: flex;
height: 2.5rem;
width: 100%;
border-radius: 0.375rem;
border: 1px solid rgb(229 231 235);
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
transition: border-color 0.2s;
}
.shadcn-input:focus {
outline: none;
border-color: rgb(14 165 233);
}
.shadcn-card {
border-radius: 0.5rem;
border: 1px solid rgb(229 231 235);
background-color: white;
padding: 1.5rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
}
.dark .shadcn-card {
background-color: rgb(31 41 55);
border-color: rgb(55 65 81);
}
.dark .shadcn-input {
background-color: rgb(31 41 55);
border-color: rgb(55 65 81);
color: white;
}
.grid-square {
width: 1.25rem;
height: 1.25rem;
border-radius: 0.25rem;
margin: 0.125rem;
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.scale-up {
animation: scaleUp 0.3s ease-out;
}
@keyframes scaleUp {
from { transform: scale(0.8); }
to { transform: scale(1); }
}
.progress-bar {
transition: width 0.5s ease-in-out;
}
.streak-badge {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(14, 165, 233, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(14, 165, 233, 0); }
100% { box-shadow: 0 0 0 0 rgba(14, 165, 233, 0); }
}
.completed-task {
text-decoration: line-through;
opacity: 0.7;
transition: all 0.3s ease;
}
</style>
</head>
<body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useRef } = React;
const { motion, AnimatePresence } = FramerMotion;
const { LineChart, Line, BarChart, Bar, PieChart, Pie, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Cell } = Recharts;
const { Check, Plus, X, Calendar, Target, BarChart3, Sun, Moon, Trophy, Flame } = LucideReact;
// Custom hook for localStorage
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = (value) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
// Utility functions
const utils = {
getDaysRemaining: () => {
const now = new Date();
const endOfYear = new Date(now.getFullYear(), 11, 31, 23, 59, 59);
const diff = endOfYear - now;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return { days, hours, minutes, seconds, totalSeconds: diff / 1000 };
},
getYearProgress: () => {
const now = new Date();
const startOfYear = new Date(now.getFullYear(), 0, 1);
const endOfYear = new Date(now.getFullYear(), 11, 31, 23, 59, 59);
const total = endOfYear - startOfYear;
const elapsed = now - startOfYear;
return (elapsed / total) * 100;
},
getDaysInYear: () => {
const now = new Date();
const startOfYear = new Date(now.getFullYear(), 0, 1);
const endOfYear = new Date(now.getFullYear(), 11, 31, 23, 59, 59);
return Math.ceil((endOfYear - startOfYear) / (1000 * 60 * 60 * 24));
},
getDayOfYear: () => {
const now = new Date();
const start = new Date(now.getFullYear(), 0, 0);
const diff = now - start;
const oneDay = 1000 * 60 * 60 * 24;
return Math.floor(diff / oneDay);
},
formatDate: (date) => {
return date.toLocaleDateString('en-US', {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric'
});
}
};
// Countdown component
function Countdown() {
const [timeLeft, setTimeLeft] = useState(utils.getDaysRemaining());
useEffect(() => {
const timer = setInterval(() => {
setTimeLeft(utils.getDaysRemaining());
}, 1000);
return () => clearInterval(timer);
}, []);
return (
<div className="text-center mb-8">
<h2 className="text-2xl font-bold mb-4">Time Until New Year</h2>
<div className="flex justify-center space-x-4">
<div className="bg-primary-100 dark:bg-primary-900 rounded-lg p-4 min-w-[80px]">
<div className="text-3xl font-bold">{timeLeft.days}</div>
<div className="text-sm">Days</div>
</div>
<div className="bg-primary-100 dark:bg-primary-900 rounded-lg p-4 min-w-[80px]">
<div className="text-3xl font-bold">{timeLeft.hours}</div>
<div className="text-sm">Hours</div>
</div>
<div className="bg-primary-100 dark:bg-primary-900 rounded-lg p-4 min-w-[80px]">
<div className="text-3xl font-bold">{timeLeft.minutes}</div>
<div className="text-sm">Minutes</div>
</div>
<div className="bg-primary-100 dark:bg-primary-900 rounded-lg p-4 min-w-[80px]">
<div className="text-3xl font-bold">{timeLeft.seconds}</div>
<div className="text-sm">Seconds</div>
</div>
</div>
</div>
);
}
// GitHub-style grid visualization
function YearGrid({ dailyTasks }) {
const daysInYear = utils.getDaysInYear();
const dayOfYear = utils.getDayOfYear();
const daysRemaining = daysInYear - dayOfYear;
const grid = [];
for (let i = 1; i <= daysInYear; i++) {
const isFuture = i > dayOfYear;
const isCompleted = dailyTasks.some(task =>
task.completed && new Date(task.date).getDate() === new Date().getDate() &&
new Date(task.date).getMonth() === new Date().getMonth() &&
new Date(task.date).getFullYear() === new Date().getFullYear()
);
grid.push(
<motion.div
key={i}
className={`grid-square ${isFuture ? 'bg-primary-300' : isCompleted ? 'bg-primary-600' : 'bg-gray-300 dark:bg-gray-600'}`}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: i * 0.002 }}
title={`Day ${i}`}
/>
);
}
return (
<div className="mb-8">
<h2 className="text-2xl font-bold mb-4">Year Progress</h2>
<div className="flex flex-wrap justify-center max-w-3xl mx-auto">
{grid}
</div>
</div>
);
}
// Progress bar component
function ProgressBar() {
const [progress, setProgress] = useState(0);
useEffect(() => {
setProgress(utils.getYearProgress());
}, []);
return (
<div className="w-full bg-gray-200 rounded-full h-4 mb-8 dark:bg-gray-700">
<motion.div
className="progress-bar h-4 rounded-full bg-primary-500"
initial={{ width: 0 }}
animate={{ width: `${progress}%` }}
transition={{ duration: 1, ease: "easeOut" }}
/>
<div className="text-xs mt-1 text-right">{progress.toFixed(1)}% of year completed</div>
</div>
);
}
// Task management components
function TaskManager() {
const [dailyTasks, setDailyTasks] = useLocalStorage('dailyTasks', []);
const [yearlyGoals, setYearlyGoals] = useLocalStorage('yearlyGoals', []);
const [showAddDaily, setShowAddDaily] = useState(false);
const [showAddYearly, setShowAddYearly] = useState(false);
const [newDailyTask, setNewDailyTask] = useState('');
const [newYearlyGoal, setNewYearlyGoal] = useState('');
const addDailyTask = () => {
if (newDailyTask.trim()) {
setDailyTasks([...dailyTasks, {
id: Date.now(),
text: newDailyTask,
completed: false,
date: new Date().toISOString(),
streak: 0
}]);
setNewDailyTask('');
setShowAddDaily(false);
}
};
const addYearlyGoal = () => {
if (newYearlyGoal.trim()) {
setYearlyGoals([...yearlyGoals, {
id: Date.now(),
text: newYearlyGoal,
completed: false
}]);
setNewYearlyGoal('');
setShowAddYearly(false);
}
};
const toggleDailyTask = (id) => {
setDailyTasks(dailyTasks.map(task =>
task.id === id ? { ...task, completed: !task.completed } : task
));
};
const toggleYearlyGoal = (id) => {
setYearlyGoals(yearlyGoals.map(goal =>
goal.id === id ? { ...goal, completed: !goal.completed } : goal
));
};
const deleteDailyTask = (id) => {
setDailyTasks(dailyTasks.filter(task => task.id !== id));
};
const deleteYearlyGoal = (id) => {
setYearlyGoals(yearlyGoals.filter(goal => goal.id !== id));
};
// Calculate streak
const streak = dailyTasks.filter(task => {
const taskDate = new Date(task.date);
const today = new Date();
return task.completed && taskDate.toDateString() === today.toDateString();
}).length > 0 ? (parseInt(localStorage.getItem('streak') || 0)) : 0;
useEffect(() => {
// Check if we need to reset tasks for a new day
const lastReset = localStorage.getItem('lastReset');
const today = new Date().toDateString();
if (lastReset !== today) {
// Reset daily tasks completion status
setDailyTasks(prev => prev.map(task => ({ ...task, completed: false })));
localStorage.setItem('lastReset', today);
// Update streak
const completedYesterday = dailyTasks.some(task => {
const taskDate = new Date(task.date);
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
return task.completed && taskDate.toDateString() === yesterday.toDateString();
});
if (completedYesterday) {
const newStreak = streak + 1;
localStorage.setItem('streak', newStreak);
} else {
localStorage.setItem('streak', 0);
}
}
}, [dailyTasks, setDailyTasks, streak]);
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
{/* Daily Tasks */}
<div className="shadcn-card">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold flex items-center">
<Calendar className="mr-2" size={20} />
Daily Goals
{streak > 0 && (
<span className="streak-badge ml-2 bg-primary-100 text-primary-800 text-xs font-medium px-2.5 py-0.5 rounded-full dark:bg-primary-900 dark:text-primary-300 flex items-center">
<Flame size={12} className="mr-1" /> {streak} day streak
</span>
)}
</h2>
<button
className="shadcn-button shadcn-button-primary p-2"
onClick={() => setShowAddDaily(true)}
>
<Plus size={16} />
</button>
</div>
{showAddDaily && (
<motion.div
className="mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
>
<input
type="text"
className="shadcn-input mb-2"
placeholder="Enter daily task"
value={newDailyTask}
onChange={(e) => setNewDailyTask(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && addDailyTask()}
/>
<div className="flex space-x-2">
<button
className="shadcn-button shadcn-button-primary flex-1"
onClick={addDailyTask}
>
Add Task
</button>
<button
className="shadcn-button bg-gray-300 dark:bg-gray-600 flex-1"
onClick={() => setShowAddDaily(false)}
>
Cancel
</button>
</div>
</motion.div>
)}
<AnimatePresence>
{dailyTasks.filter(task => !task.completed).map((task) => (
<motion.div
key={task.id}
className="flex items-center justify-between p-3 mb-2 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<div className="flex items-center">
<button
className="w-5 h-5 rounded border border-gray-300 dark:border-gray-600 mr-3 flex items-center justify-center hover:bg-primary-50 dark:hover:bg-primary-900"
onClick={() => toggleDailyTask(task.id)}
>
{task.completed && <Check size={14} className="text-primary-600" />}
</button>
<span>{task.text}</span>
</div>
<button
className="text-gray-400 hover:text-red-500"
onClick={() => deleteDailyTask(task.id)}
>
<X size={16} />
</button>
</motion.div>
))}
</AnimatePresence>
{dailyTasks.filter(task => task.completed).length > 0 && (
<div className="mt-4">
<h3 className="text-sm font-medium mb-2 text-gray-500 dark:text-gray-400">Completed Today</h3>
<AnimatePresence>
{dailyTasks.filter(task => task.completed).map((task) => (
<motion.div
key={task.id}
className="flex items-center justify-between p-3 mb-2 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-200 dark:border-green-800"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3 }}
>
<div className="flex items-center">
<Check size={16} className="text-green-600 mr-3" />
<span className="completed-task">{task.text}</span>
</div>
<button
className="text-gray-400 hover:text-red-500"
onClick={() => deleteDailyTask(task.id)}
>
<X size={16} />
</button>
</motion.div>
))}
</AnimatePresence>
</div>
)}
</div>
{/* Yearly Goals */}
<div className="shadcn-card">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold flex items-center">
<Target className="mr-2" size={20} />
End-of-Year Goals
</h2>
<button
className="shadcn-button shadcn-button-secondary p-2"
onClick={() => setShowAddYearly(true)}
>
<Plus size={16} />
</button>
</div>
{showAddYearly && (
<motion.div
className="mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
>
<input
type="text"
className="shadcn-input mb-2"
placeholder="Enter yearly goal"
value={newYearlyGoal}
onChange={(e) => setNewYearlyGoal(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && addYearlyGoal()}
/>
<div className="flex space-x-2">
<button
className="shadcn-button shadcn-button-secondary flex-1"
onClick={addYearlyGoal}
>
Add Goal
</button>
<button
className="shadcn-button bg-gray-300 dark:bg-gray-600 flex-1"
onClick={() => setShowAddYearly(false)}
>
Cancel
</button>
</div>
</motion.div>
)}
<AnimatePresence>
{yearlyGoals.filter(goal => !goal.completed).map((goal) => (
<motion.div
key={goal.id}
className="flex items-center justify-between p-3 mb-2 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<div className="flex items-center">
<button
className="w-5 h-5 rounded border border-gray-300 dark:border-gray-600 mr-3 flex items-center justify-center hover:bg-primary-50 dark:hover:bg-primary-900"
onClick={() => toggleYearlyGoal(goal.id)}
>
{goal.completed && <Check size={14} className="text-primary-600" />}
</button>
<span>{goal.text}</span>
</div>
<button
className="text-gray-400 hover:text-red-500"
onClick={() => deleteYearlyGoal(goal.id)}
>
<X size={16} />
</button>
</motion.div>
))}
</AnimatePresence>
{yearlyGoals.filter(goal => goal.completed).length > 0 && (
<div className="mt-4">
<h3 className="text-sm font-medium mb-2 text-gray-500 dark:text-gray-400 flex items-center">
<Trophy className="mr-1" size={16} /> Completed Goals
</h3>
<AnimatePresence>
{yearlyGoals.filter(goal => goal.completed).map((goal) => (
<motion.div
key={goal.id}
className="flex items-center justify-between p-3 mb-2 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg border border-yellow-200 dark:border-yellow-800"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3 }}
>
<div className="flex items-center">
<Check size={16} className="text-yellow-600 mr-3" />
<span className="completed-task">{goal.text}</span>
</div>
<button
className="text-gray-400 hover:text-red-500"
onClick={() => deleteYearlyGoal(goal.id)}
>
<X size={16} />
</button>
</motion.div>
))}
</AnimatePresence>
</div>
)}
</div>
</div>
);
}
// Analytics component
function Analytics({ dailyTasks, yearlyGoals }) {
const completedYearly = yearlyGoals.filter(g => g.completed).length;
const totalYearly = yearlyGoals.length;
const yearlyPercentage = totalYearly > 0 ? (completedYearly / totalYearly) * 100 : 0;
// Last 7 days completion rate
const last7Days = Array.from({ length: 7 }, (_, i) => {
const date = new Date();
date.setDate(date.getDate() - i);
return date.toDateString();
});
const weeklyData = last7Days.map(date => {
const completed = dailyTasks.filter(task =>
new Date(task.date).toDateString() === date && task.completed
).length;
const total = dailyTasks.filter(task =>
new Date(task.date).toDateString() === date
).length;
return {
date: date.slice(0, 3),
completionRate: total > 0 ? (completed / total) * 100 : 0,
completed,
total
};
}).reverse();
const motivationalMessages = [
"You're on a roll! Keep it up!",
"Consistency is key - great job!",
"Every task completed brings you closer to your goals!",
"You're making amazing progress!",
"Just a few more tasks to complete your day!",
"Your dedication is inspiring!",
"Small steps lead to big achievements!"
];
const randomMessage = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
return (
<div className="shadcn-card mb-8">
<h2 className="text-xl font-bold mb-4 flex items-center">
<BarChart3 className="mr-2" size={20} />
Progress Analytics
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
{/* Yearly Goals Progress */}
<div>
<h3 className="text-lg font-semibold mb-2">Yearly Goals</h3>
<div className="w-full bg-gray-200 rounded-full h-4 dark:bg-gray-700 mb-2">
<div
className="h-4 rounded-full bg-primary-500 transition-all duration-500"
style={{ width: `${yearlyPercentage}%` }}
/>
</div>
<p className="text-sm text-gray-600 dark:text-gray-400">
{completedYearly} of {totalYearly} goals completed ({yearlyPercentage.toFixed(1)}%)
</p>
</div>
{/* Weekly Completion */}
<div>
<h3 className="text-lg font-semibold mb-2">Weekly Performance</h3>
<ResponsiveContainer width="100%" height={100}>
<BarChart data={weeklyData}>
<Bar dataKey="completionRate" fill="#0ea5e9" radius={[4, 4, 0, 0]} />
<XAxis dataKey="date" />
<YAxis domain={[0, 100]} />
</BarChart>
</ResponsiveContainer>
</div>
</div>
{/* Motivational Message */}
<div className="bg-primary-50 dark:bg-primary-900/30 p-4 rounded-lg border border-primary-200 dark:border-primary-800">
<p className="text-primary-800 dark:text-primary-200 text-center italic">
{randomMessage}
</p>
</div>
</div>
);
}
// Theme Toggle
function ThemeToggle() {
const [isDark, setIsDark] = useState(() => {
return localStorage.getItem('theme') === 'dark' ||
(window.matchMedia('(prefers-color-scheme: dark)').matches && !localStorage.getItem('theme'));
});
useEffect(() => {
if (isDark) {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
}
}, [isDark]);
return (
<button
className="fixed top-4 right-4 p-2 rounded-lg bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow-lg"
onClick={() => setIsDark(!isDark)}
>
{isDark ? <Sun size={20} /> : <Moon size={20} />}
</button>
);
}
// Main App Component
function App() {
const [dailyTasks] = useLocalStorage('dailyTasks', []);
const [yearlyGoals] = useLocalStorage('yearlyGoals', []);
return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors duration-200">
<div className="container mx-auto px-4 py-8 max-w-6xl">
<motion.header
className="text-center mb-8"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
<h1 className="text-4xl font-bold mb-2 bg-gradient-to-r from-primary-600 to-secondary-600 bg-clip-text text-transparent">
YearEndQuest Tracker
</h1>
<p className="text-gray-600 dark:text-gray-400 mb-4">
Make the most of the remaining days this year
</p>
<div className="flex justify-center space-x-4">
<a href="portfolio.html" className="shadcn-button shadcn-button-primary px-6 py-3">
View Portfolio
</a>
</motion.header>
<Countdown />
<ProgressBar />
<YearGrid dailyTasks={dailyTasks} />
<TaskManager />
<Analytics dailyTasks={dailyTasks} yearlyGoals={yearlyGoals} />
<ThemeToggle />
</div>
</div>
);
}
// Render the app
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
// Initialize feather icons
feather.replace();
</script>
</body>
</html>
</body>
</html>