Skip to content
Open
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
2 changes: 1 addition & 1 deletion frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const App = () => {
return (
<BrowserRouter>
<Navbar />
<main className="app-bg min-h-screen pt-15 flex flex-col">
<main className="pp-bg min-h-screen pt-15 flex flex-col bg-white text-black transition-colors duration-300 dark:bg-gray-900 dark:text-white">
<Routes>
<Route path="/" element={<PublicRoute><AuthLayout><Login /></AuthLayout></PublicRoute>} />
<Route path="/login" element={<PublicRoute><AuthLayout><Login /></AuthLayout></PublicRoute>} />
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/Dashboard/DashboardTasks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export default function DashboardTasks({ tasks, updateTask }) {
<p
className={`text-sm font-medium transition-colors ${
task.status === "Completed"
? "line-through text-muted"
: "text-main"
? "line-through text-muted dark:text-gray-300"
: "text-main dark:text-white"
}`}
>
{task.title}
Expand All @@ -94,20 +94,20 @@ export default function DashboardTasks({ tasks, updateTask }) {
</span>

{task.status === "Completed" && (
<span className="text-[11px] text-muted">Completed</span>
<span className="text-[11px] text-muted dark:text-gray-300">Completed</span>
)}
</div>
</div>

{/* Hover affordance */}
<span className="absolute right-4 top-1/2 -translate-y-1/2 text-xs text-muted opacity-0 group-hover:opacity-100 transition">
<span className="absolute right-4 top-1/2 -translate-y-1/2 text-xs text-muted dark:text-gray-300 opacity-0 group-hover:opacity-100 transition">
</span>
</div>
))}
</div>
) : (
<div className="text-sm text-muted text-center py-6 flex flex-col ">
<div className="text-sm text-muted dark:text-gray-300 text-center py-6 flex flex-col">
No tasks for today.

<button
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/Dashboard/TaskPreview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function TaskPreview({ tasks , updateTask}) {
return (
<div
key={task._id}
className={`flex items-center gap-4 border-l-4 rounded-xl p-4 transition
className={`flex items-center gap-4 border-l-4 rounded-xl p-4 transition-all duration-200 shadow-sm hover:shadow-md
${priorityBorder[task.priority]}
bg-white/80 hover:bg-white dark:bg-slate-800/80 dark:hover:bg-slate-800 shadow-sm`}
>
Expand All @@ -76,8 +76,8 @@ export default function TaskPreview({ tasks , updateTask}) {
<p
className={`text-sm font-medium ${
task.status === "Completed"
? "line-through decoration-2 decoration-muted text-muted"
: "text-main"
? "line-through decoration-2 decoration-muted text-muted dark:text-gray-300"
: "text-main dark:text-white"
}`}
>
{task.title}
Expand All @@ -93,7 +93,7 @@ export default function TaskPreview({ tasks , updateTask}) {
</span>

{task.dueDate && (
<span className="text-[11px] text-muted">
<span className="text-[11px] text-muted dark:text-gray-300">
{new Date(task.dueDate).toLocaleDateString("en-US", {
weekday: "short",
})}
Expand All @@ -115,15 +115,15 @@ export default function TaskPreview({ tasks , updateTask}) {
) })}
</div>
) : (
<p className="text-sm text-muted text-center py-6">
<p className="text-sm text-muted dark:text-gray-300 text-center py-6">
No upcoming tasks.
</p>
)}

<div className="mt-4 text-sm text-primary">
<button
onClick={() => navigate("/tasks")}
className="group mt-3 flex gap-2 self-center px-4 py-2 rounded-lg bg-(--primary) text-white text-sm font-medium hover:opacity-90 active:scale-95 transition-all duration-150 cursor-pointer"
className="group mt-3 flex gap-2 self-center px-4 py-2 rounded-lg bg-(--primary) text-white text-sm font-medium hover:opacity-80 active:scale-95 transition-all duration-150 cursor-pointer"
>
View All Tasks <ArrowRight className="transition-transform duration-150 group-hover:translate-x-1" />
</button>
Expand Down
3 changes: 0 additions & 3 deletions frontend/src/components/EmptyState.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,3 @@ export default function EmptyState({ type = "tasks", onAction }) {
</div>
);
}



151 changes: 89 additions & 62 deletions frontend/src/components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ThemeContext } from "../context/ThemeContext";
import gsap from "gsap";
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import ThemeToggle from "./ThemeToggle";

// Utility for merging tailwind classes safely
function cn(...inputs) {
Expand Down Expand Up @@ -261,7 +262,7 @@ const Navbar = () => {
"px-4 py-2 rounded-xl text-sm font-medium transition-all duration-200 flex items-center gap-2",
isActive
? "bg-[#d0f6e3] text-[#3b8ea0] shadow-sm"
: "text-[#4eb7b3] hover:bg-[#d0f6e3]/50 hover:text-[#3b8ea0]"
: "text-[#4eb7b3] hover:bg-[#d0f6e3]/50 hover:text-[#3b8ea0] dark:text-gray-300 dark:hover:bg-gray-800"
)
}
>
Expand Down Expand Up @@ -293,7 +294,7 @@ const Navbar = () => {
<>
<Link
to="/login"
className="text-sm font-medium text-[#4eb7b3] hover:text-[#3b8ea0] transition-colors px-4 py-2 rounded-xl hover:bg-[#d0f6e3]/50"
className="text-sm font-medium text-[#4eb7b3] hover:text-[#3b8ea0] dark:hover:text-white dark:hover:bg-gray-800 transition-colors px-4 py-2 rounded-xl hover:bg-[#d0f6e3]/50"
>
Login
</Link>
Expand All @@ -315,74 +316,100 @@ const Navbar = () => {
)}
</div>

{/* Mobile Menu Toggle Button */}
<div className="md:hidden flex items-center gap-2">
<ThemeToggle />

<button
onClick={() => setIsOpen(!isOpen)}
className="p-2 rounded-xl text-[#3b8ea0] dark:text-white hover:bg-[#d0f6e3] dark:hover:bg-gray-800 transition-colors focus:outline-none"
aria-label="Toggle menu"
aria-expanded={isOpen}
aria-controls="mobile-navigation-menu"
>
<AnimatePresence mode="wait">
<motion.div
key={isOpen ? "close" : "open"}
initial={{ opacity: 0, rotate: -90 }}
animate={{ opacity: 1, rotate: 0 }}
exit={{ opacity: 0, rotate: 90 }}
transition={{ duration: 0.15 }}
>
{isOpen ? <X size={24} /> : <Menu size={24} />}
</motion.div>
</AnimatePresence>
</button>
</div>
</div>
</div>

{/* Mobile Navigation Dropdown */}
<AnimatePresence>
{isOpen && (
<motion.div
id="mobile-navigation-menu"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
className="md:hidden border-b border-soft bg-white/95 dark:bg-slate-900/95 backdrop-blur-xl overflow-hidden"
>
<div className="px-4 pt-2 pb-6 space-y-1">
{user && navLinks.map((link) => (
<NavLink
key={link.name}
to={link.path}
onClick={() => setIsOpen(false)}
className={({ isActive }) =>
cn(
"px-4 py-3 rounded-xl text-base font-medium transition-colors flex items-center gap-3 w-full",
isActive
? "bg-[#d0f6e3] text-[#3b8ea0]"
: "text-[#4eb7b3] dark:text-gray-300 hover:bg-[#d0f6e3]/50 dark:hover:bg-gray-800 hover:text-[#3b8ea0]"
)
}
>
<link.icon size={18} />
{link.name}
</NavLink>
))}

<div className={cn("flex flex-col gap-2", user ? "pt-4 mt-2 border-t border-[#98e1d7]/30" : "pt-2")}>

{/* Mobile Navigation Dropdown */}
<AnimatePresence>
{isOpen && (
<motion.div
id="mobile-navigation-menu"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
className="md:hidden border-b border-soft bg-white/95 dark:bg-slate-900/95 backdrop-blur-xl overflow-hidden"
>
<div className="px-4 pt-2 pb-6 space-y-1">
{user && navLinks.map((link) => (
<NavLink
key={link.name}
to={link.path}
onClick={() => setIsOpen(false)}
className={({ isActive }) =>
cn(
"px-4 py-3 rounded-xl text-base font-medium transition-colors flex items-center gap-3 w-full",
isActive
? "bg-[#d0f6e3] text-[#3b8ea0]"
: "text-[#4eb7b3] hover:bg-[#d0f6e3]/50 hover:text-[#3b8ea0]"
)
}
>
<link.icon size={18} />
{link.name}
</NavLink>
))}
{!user ? (
<>
<Link
to="/login"
onClick={() => setIsOpen(false)}
className="w-full flex items-center justify-center gap-2 px-4 py-3 rounded-xl text-[#3b8ea0] dark:text-gray-300 font-medium hover:bg-[#d0f6e3] dark:hover:bg-gray-800 dark:hover:text-white transition-colors"
>
<LogIn size={18} />
Login
</Link>

<div className={cn("flex flex-col gap-2", user ? "pt-4 mt-2 border-t border-[#98e1d7]/30" : "pt-2")}>
{!user ? (
<>
<Link
to="/login"
onClick={() => setIsOpen(false)}
className="w-full flex items-center justify-center gap-2 px-4 py-3 rounded-xl text-[#3b8ea0] font-medium hover:bg-[#d0f6e3] transition-colors"
>
<LogIn size={18} />
Login
</Link>
<Link
to="/signup"
onClick={() => setIsOpen(false)}
className="w-full flex items-center justify-center gap-2 btn btn-primary py-3"
>
<User size={18} />
Signup
</Link>
</>
) : (
<button
onClick={handleLogoutClick}
<Link
to="/signup"
onClick={() => setIsOpen(false)}
className="w-full flex items-center justify-center gap-2 btn btn-primary py-3"
>
<LogOut size={18} />
Logout
</button>
)}
</div>
<User size={18} />
Signup
</Link>
</>
) : (
<button
onClick={handleLogoutClick}
className="w-full flex items-center justify-center gap-2 btn btn-primary py-3"
>
<LogOut size={18} />
Logout
</button>
)}
</div>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</AnimatePresence>
</motion.nav>
</>
);
Expand Down
8 changes: 3 additions & 5 deletions frontend/src/components/Routine/TaskLibrary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ function DraggableTask({ task }) {
style={style}
{...listeners}
{...attributes}
className="group flex items-center gap-3 rounded-xl border border-soft/50 bg-[#f8fafc]/30 dark:bg-slate-800/40 p-3
cursor-grab active:cursor-grabbing
hover:bg-white dark:hover:bg-slate-850 hover:shadow-md transition duration-200 hover-lift"
className="group flex items-center gap-3 rounded-xl border border-soft/50 dark:border-gray-700/60 bg-[#f8fafc]/30 dark:bg-slate-800/80 p-3 cursor-grab active:cursor-grabbing hover:bg-white dark:hover:bg-slate-850 hover:shadow-md transition duration-200 hover-lift"
role="button"
tabIndex={0}
aria-label={`${task.title} - Drag to schedule or use arrow keys`}
Expand All @@ -50,7 +48,7 @@ function DraggableTask({ task }) {
/>

{/* Title */}
<p className="flex-1 text-sm font-medium text-main truncate">
<p className="flex-1 text-sm font-medium text-main dark:text-white truncate">
{task.title}
</p>
</div>
Expand Down Expand Up @@ -87,7 +85,7 @@ export default function TaskLibrary({ tasks, onAddTask }) {
placeholder="Search tasks…"
value={query}
onChange={(e) => setQuery(e.target.value)}
className="mb-4 rounded-xl border border-soft/80 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#4eb7b3] bg-transparent text-main placeholder:text-muted"
className="mb-4 rounded-xl border border-soft/80 px-3 py-2 text-sm bg-transparent text-main placeholder:text-muted dark:bg-slate-800 dark:text-white dark:border-gray-700 dark:placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-[#4eb7b3]"
/>

{/* Task List */}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ScrollToTop.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const ScrollToTop = () => {
{shouldShow && (
<button
onClick={scrollToTop}
className="p-3 rounded-full bg-[var(--text-main)] text-white shadow-lg hover:bg-[var(--primary)] transition-all duration-300 transform hover:scale-110 flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-[var(--primary)] focus:ring-offset-2"
className="p-3 rounded-full bg-[var(--primary)] text-white shadow-lg border border-white/10 dark:border-slate-700 hover:bg-[var(--primary-hover)] transition-all duration-300 transform hover:scale-110 flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-[var(--primary)] focus:ring-offset-2 dark:focus:ring-offset-slate-900"
aria-label="Scroll to top"
>
<ArrowUp size={24} />
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/Task/TaskFormModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export default function TaskFormModal({
disabled={isSubmitting}
className="w-full mt-1 p-2 border border-soft rounded-lg
focus:ring-(--primary) focus:border-(--primary)
bg-transparent text-main"
bg-transparent text-main dark:bg-slate-800"
placeholder="Task title"
maxLength={TITLE_MAX_LENGTH}
required
Expand Down Expand Up @@ -251,7 +251,7 @@ export default function TaskFormModal({
disabled={isSubmitting}
className="w-full mt-1 p-2 border border-soft rounded-lg
focus:ring-(--primary) focus:border-(--primary)
bg-transparent text-main"
bg-transparent text-main dark:bg-slate-800"
placeholder="Optional task description"
rows={3}
maxLength={DESCRIPTION_MAX_LENGTH}
Expand Down Expand Up @@ -301,7 +301,7 @@ export default function TaskFormModal({
value={customTagInput}
onChange={(e) => setCustomTagInput(e.target.value)}
disabled={isSubmitting}
className="flex-1 p-2 border border-soft rounded-lg bg-transparent text-main"
className="flex-1 p-2 border border-soft rounded-lg bg-transparent text-main dark:bg-slate-800"
placeholder="Enter custom tag (e.g., 'Essay')"
/>
<button
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/Task/TaskItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function TaskItem({ task, onToggleComplete, onDelete, onUpdate, i
w-full rounded-xl border-l-4
${priorityStyles[task.priority]}
${isCompleted ? "opacity-70" : ""}
shadow-sm hover:shadow-md transition
shadow-sm hover:shadow-md transition dark:border-gray-700 dark:text-white
`}
>
<div className="flex items-center gap-6 px-6 py-6">
Expand All @@ -44,7 +44,7 @@ export default function TaskItem({ task, onToggleComplete, onDelete, onUpdate, i
w-8 h-8 rounded-md flex items-center justify-center
border-soft shrink-0 cursor-pointer
transition-transform duration-150
${isCompleted ? "bg-(--primary) text-white" : "bg-white dark:bg-slate-800"}
${isCompleted ? "bg-(--primary) text-white" : "bg-white dark:bg-slate-800 dark:text-white"}
`}
>
{isCompleted && <Check size={18} />}
Expand All @@ -54,7 +54,7 @@ export default function TaskItem({ task, onToggleComplete, onDelete, onUpdate, i
<div className="flex-1">
<p
className={`text-lg font-semibold ${
isCompleted ? "line-through text-muted" : "text-main"
isCompleted ? "line-through text-muted dark:text-gray-300" : "text-main"
}`}
>
{task.title}
Expand Down Expand Up @@ -102,15 +102,15 @@ export default function TaskItem({ task, onToggleComplete, onDelete, onUpdate, i
{/* Edit Button */}
<button
onClick={() => setIsEditModalOpen(true)}
className="p-2 rounded-lg hover:bg-white dark:hover:bg-slate-700 transition cursor-pointer"
className="p-2 rounded-lg hover:bg-white/80 dark:hover:bg-slate-700 transition cursor-pointer"
>
<Pencil size={18} className="text-main" />
</button>

{/* Delete Button - Fix : Ensure onDelete uses task._id*/}
<button
onClick={()=> onDelete(task._id)}
className="p-2 rounded-lg hover:bg-red-100 transition cursor-pointer"
className="p-2 rounded-lg hover:bg-red-100 dark:hover:bg-red-900/20 transition cursor-pointer"
>
<Trash2 size={18} className="text-red-500" />
</button>
Expand Down
Loading
Loading