Skip to content

Commit c044f91

Browse files
authored
Merge pull request #57 from Shreyanshi210205/dark_mode
feat(theme): implement dark mode support across the application
2 parents f05bc8e + 77521f4 commit c044f91

File tree

11 files changed

+94
-41
lines changed

11 files changed

+94
-41
lines changed

frontend/src/components/Home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const Hero: React.FC = () => {
3232
{/* Left Content */}
3333
<div className="space-y-6 text-center lg:text-left">
3434

35-
<h1 className="text-5xl md:text-6xl lg:text-7xl font-extrabold text-gray-800 leading-tight tracking-tighter ml-2">
35+
<h1 className="text-5xl md:text-6xl lg:text-7xl font-extrabold text-gray-800 leading-tight tracking-tighter ml-2 dark:text-gray-200">
3636
UniLoot - Your<br />
3737
<span className="text-blue-800">Campus Marketplace,</span><br />
3838
Simplified!

frontend/src/components/Navbar.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
1-
import React, { useState } from "react";
1+
import React, { useState, useEffect } from "react";
22
import { Link, useNavigate, useLocation } from "react-router-dom";
33
import { Button } from "@/components/ui/button";
4-
import { Menu, X } from "lucide-react";
4+
import { Menu, X, Moon, Sun } from "lucide-react";
55

66
const Navbar: React.FC = () => {
77
const [isOpen, setIsOpen] = useState(false);
8+
9+
const getInitialTheme = () =>
10+
typeof document !== "undefined" && document.documentElement.classList.contains("dark")
11+
? ("dark" as const)
12+
: ("light" as const);
13+
14+
const [theme, setTheme] = useState<"light" | "dark">(getInitialTheme);
815
const navigate = useNavigate();
916
const location = useLocation();
1017

18+
useEffect(() => {
19+
const root = window.document.documentElement;
20+
if (theme === "dark") root.classList.add("dark");
21+
else root.classList.remove("dark");
22+
try {
23+
localStorage.setItem("theme", theme);
24+
} catch (err) {
25+
// ignore (e.g. storage not available)
26+
}
27+
}, [theme]);
28+
29+
const toggleTheme = () => setTheme((prev) => (prev === "dark" ? "light" : "dark"));
30+
1131
const handleNavClick = (path: string) => {
1232
navigate(path);
1333
setIsOpen(false);
@@ -20,11 +40,11 @@ const Navbar: React.FC = () => {
2040
];
2141

2242
return (
23-
<nav className="w-full bg-white/80 backdrop-blur-md shadow-sm fixed top-0 left-0 z-50">
43+
<nav className="w-full bg-white/80 dark:bg-gray-800/80 backdrop-blur-md shadow-sm fixed top-0 left-0 z-50 transition-colors">
2444
<div className="container mx-auto px-6 py-3 flex items-center justify-between">
2545
<Link
2646
to="/"
27-
className="text-2xl font-extrabold text-blue-800 tracking-tight hover:opacity-80 transition"
47+
className="text-2xl font-extrabold text-blue-800 tracking-tight hover:opacity-80 transition dark:text-blue-300"
2848
>
2949
UniLoot
3050
</Link>
@@ -36,8 +56,8 @@ const Navbar: React.FC = () => {
3656
onClick={() => handleNavClick(link.path)}
3757
className={`text-base font-semibold transition-colors duration-300 ${
3858
location.pathname === link.path
39-
? "text-blue-800"
40-
: "text-gray-700 hover:text-blue-800"
59+
? "text-blue-800 dark:text-blue-300"
60+
: "text-gray-700 dark:text-gray-300 hover:text-blue-800 dark:hover:text-blue-300"
4161
}`}
4262
>
4363
{link.name}
@@ -46,9 +66,20 @@ const Navbar: React.FC = () => {
4666
</div>
4767

4868
<div className="hidden md:flex items-center gap-3">
69+
<button
70+
onClick={toggleTheme}
71+
className="p-2 rounded-full border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-all duration-300"
72+
>
73+
{theme === "light" ? (
74+
<Sun size={20} className="transition-transform duration-300 rotate-0 text-gray-700 dark:text-gray-200" />
75+
) : (
76+
<Moon size={20} className="transition-transform duration-300 rotate-0 text-gray-700 dark:text-gray-200" />
77+
)}
78+
</button>
79+
4980
<Button
5081
variant="outline"
51-
className="border-2 border-blue-800 text-blue-800 hover:bg-blue-800 hover:text-white transition"
82+
className="border-2 border-blue-800 text-blue-800 hover:bg-blue-800 hover:text-white transition dark:text-blue-300"
5283
onClick={() => handleNavClick("/signin")}
5384
>
5485
Sign In
@@ -63,28 +94,36 @@ const Navbar: React.FC = () => {
6394

6495
<button
6596
onClick={() => setIsOpen(!isOpen)}
66-
className="md:hidden text-blue-800 focus:outline-none"
97+
className="md:hidden text-blue-800 dark:text-blue-300 focus:outline-none"
6798
>
6899
{isOpen ? <X size={28} /> : <Menu size={28} />}
69100
</button>
70101
</div>
71102

72103
{isOpen && (
73-
<div className="md:hidden bg-white border-t border-gray-200 shadow-md">
104+
<div className="md:hidden bg-white dark:bg-slate-900 border-t border-gray-200 dark:border-slate-700 shadow-md">
74105
<div className="flex flex-col items-center py-4 space-y-4">
75106
{navLinks.map((link) => (
76107
<button
77108
key={link.name}
78109
onClick={() => handleNavClick(link.path)}
79110
className={`text-lg font-semibold ${
80111
location.pathname === link.path
81-
? "text-blue-800"
82-
: "text-gray-700 hover:text-blue-800"
112+
? "text-blue-800 dark:text-blue-300"
113+
: "text-gray-700 dark:text-gray-300 hover:text-blue-800 dark:hover:text-blue-300"
83114
}`}
84115
>
85116
{link.name}
86117
</button>
87118
))}
119+
120+
<button
121+
onClick={toggleTheme}
122+
className="p-2 rounded-full border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-all duration-300"
123+
>
124+
{theme === "light" ? <Sun size={22} /> : <Moon size={22} />}
125+
</button>
126+
88127
<div className="flex flex-col gap-2 pt-3 w-4/5">
89128
<Button
90129
variant="outline"

frontend/src/index.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
@import "tailwindcss";
22

3+
html,body {
4+
@apply bg-white text-gray-900 duration-300;
5+
}
6+
.dark body{
7+
@apply bg-gray-950 text-gray-100 duration-300;
8+
}
9+
@custom-variant dark (&:where(.dark, .dark *));

frontend/src/main.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ import { createRoot } from "react-dom/client";
22
import App from "./App.tsx";
33
import "./index.css";
44

5+
if (localStorage.getItem("theme") === "dark") {
6+
document.documentElement.classList.add("dark");
7+
}
58
createRoot(document.getElementById("root")!).render(<App />);

frontend/src/pages/Browse.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ const Browse = () => {
172172
});
173173

174174
return (
175-
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 px-4 py-8">
175+
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 px-4 py-8 dark:bg-gradient-to-br dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
176176
<div className="absolute inset-0 -z-10">
177177
<div className="absolute -top-32 -left-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob"></div>
178178
<div className="absolute top-0 -right-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob animation-delay-2000"></div>
@@ -182,10 +182,10 @@ const Browse = () => {
182182
<div className="container mx-auto max-w-7xl">
183183
{/* Header */}
184184
<div className="mb-8 text-center">
185-
<h1 className="text-4xl md:text-5xl font-extrabold text-blue-800 mb-4">
185+
<h1 className="text-4xl md:text-5xl font-extrabold text-blue-800 mb-4 dark:text-blue-300">
186186
Browse Products
187187
</h1>
188-
<p className="text-lg text-gray-600">
188+
<p className="text-lg text-gray-600 dark:text-gray-300">
189189
Find what you need from fellow students
190190
</p>
191191
</div>

frontend/src/pages/Cart.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const Cart = () => {
6161
};
6262

6363
return (
64-
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 py-8 px-4 sm:px-6 lg:px-8">
64+
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 py-8 px-4 sm:px-6 lg:px-8 dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
6565
{/* Header */}
6666
<motion.div
6767
className="max-w-6xl mx-auto text-center mb-8"

frontend/src/pages/Dashboard.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,50 +36,50 @@ const handleBuyClick = () => {
3636
};
3737

3838
return (
39-
<section className="w-full min-h-[calc(100vh-80px)] bg-blue-50 py-12 px-6 text-black">
39+
<section className="w-full min-h-[calc(100vh-80px)] bg-blue-50 dark:bg-slate-900 py-12 px-6 text-gray-900 dark:text-gray-200 transition-colors">
4040
<div className="container mx-auto space-y-12">
41-
<h1 className="text-4xl font-extrabold text-gray-800 mb-6">
41+
<h1 className="text-4xl font-extrabold text-gray-800 dark:text-gray-100 mb-6">
4242
Welcome Back, Student!
4343
</h1>
4444

45-
<div className="bg-white rounded-2xl shadow-lg p-6">
45+
<div className="bg-white rounded-2xl shadow-lg p-6 dark:bg-slate-800 dark:border dark:border-slate-700">
4646
<div className="flex items-center gap-3 mb-4">
47-
<ShoppingCart className="w-6 h-6 text-blue-800" />
48-
<h2 className="text-2xl font-semibold text-gray-800">Bought Items</h2>
47+
<ShoppingCart className="w-6 h-6 text-blue-800 dark:text-blue-300" />
48+
<h2 className="text-2xl font-semibold text-gray-800 dark:text-gray-100">Bought Items</h2>
4949
</div>
5050
<ul className="space-y-2">
5151
{boughtItems.map(item => (
52-
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 hover:bg-blue-100 transition">
52+
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 dark:bg-slate-700 dark:hover:bg-slate-600 hover:bg-blue-100 transition">
5353
<span>{item.name}</span>
5454
<span className="font-semibold">{item.price}</span>
5555
</li>
5656
))}
5757
</ul>
5858
</div>
5959

60-
<div className="bg-white rounded-2xl shadow-lg p-6">
60+
<div className="bg-white rounded-2xl shadow-lg p-6 dark:bg-slate-800 dark:border dark:border-slate-700">
6161
<div className="flex items-center gap-3 mb-4">
62-
<Tag className="w-6 h-6 text-blue-800" />
63-
<h2 className="text-2xl font-semibold text-gray-800">Sold Items</h2>
62+
<Tag className="w-6 h-6 text-blue-800 dark:text-blue-300" />
63+
<h2 className="text-2xl font-semibold text-gray-800 dark:text-gray-100">Sold Items</h2>
6464
</div>
6565
<ul className="space-y-2">
6666
{soldItems.map(item => (
67-
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 hover:bg-blue-100 transition">
67+
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 dark:bg-slate-700 dark:hover:bg-slate-600 hover:bg-blue-100 transition">
6868
<span>{item.name}</span>
6969
<span className="font-semibold">{item.price}</span>
7070
</li>
7171
))}
7272
</ul>
7373
</div>
7474

75-
<div className="bg-white rounded-2xl shadow-lg p-6">
75+
<div className="bg-white rounded-2xl shadow-lg p-6 dark:bg-slate-800 dark:border dark:border-slate-700">
7676
<div className="flex items-center gap-3 mb-4">
77-
<Clock className="w-6 h-6 text-blue-800" />
78-
<h2 className="text-2xl font-semibold text-gray-800">Current Bids</h2>
77+
<Clock className="w-6 h-6 text-blue-800 dark:text-blue-300" />
78+
<h2 className="text-2xl font-semibold text-gray-800 dark:text-gray-100">Current Bids</h2>
7979
</div>
8080
<ul className="space-y-2">
8181
{currentBids.map(item => (
82-
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 hover:bg-blue-100 transition">
82+
<li key={item.id} className="flex justify-between p-3 rounded-lg bg-blue-50 dark:bg-slate-700 dark:hover:bg-slate-600 hover:bg-blue-100 transition">
8383
<span>{item.name}</span>
8484
<span className="font-semibold">{item.bid}</span>
8585
</li>
@@ -88,10 +88,10 @@ const handleBuyClick = () => {
8888
</div>
8989

9090
<div className="flex gap-4 justify-center lg:justify-start">
91-
<Button className="bg-blue-800 text-white hover:bg-blue-700 px-6 py-3 rounded-lg"
91+
<Button className="bg-blue-800 text-white hover:bg-blue-700 px-6 py-3 rounded-lg dark:bg-blue-700 dark:hover:bg-blue-600"
9292
onClick={handleBuyClick}
9393
>Browse Marketplace</Button>
94-
<Button className="border-4 border-blue-800 text-blue-800 hover:bg-blue-800 hover:text-white px-6 py-3 rounded-lg"
94+
<Button className="border-4 border-blue-800 text-blue-800 hover:bg-blue-800 hover:text-white px-6 py-3 rounded-lg dark:border-blue-600 dark:text-blue-300 dark:hover:bg-blue-700"
9595
onClick={handleSellClick}
9696
>Sell an Item</Button>
9797
</div>

frontend/src/pages/Payment.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const Payment = () => {
7979
];
8080

8181
return (
82-
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-blue-50 py-8 px-4 sm:px-6 lg:px-8">
82+
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-blue-50 py-8 px-4 sm:px-6 lg:px-8 dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
8383
<div className="max-w-6xl mx-auto">
8484
{/* Header */}
8585
<motion.div

frontend/src/pages/ProductDetail.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export default function ProductDetailsPage() {
111111
};
112112

113113
return (
114-
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 px-4 py-10">
114+
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 px-4 py-10 dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
115115
<div className="absolute inset-0 -z-10">
116116
<div className="absolute -top-32 -left-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob"></div>
117117
<div className="absolute top-0 -right-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob animation-delay-2000"></div>
@@ -123,13 +123,13 @@ export default function ProductDetailsPage() {
123123
<Button
124124
onClick={() => navigate(-1)}
125125
variant="outline"
126-
className="flex items-center mb-6 border-2 border-blue-700 text-blue-700 hover:bg-blue-700 hover:text-white"
126+
className="flex items-center mb-6 border-2 border-blue-700 text-blue-700 hover:bg-blue-700 hover:text-white dark:text-blue-300"
127127
>
128128
<ArrowLeft className="mr-2 h-4 w-4" /> Back
129129
</Button>
130130

131131
{/* Product Content */}
132-
<div className="flex flex-col md:flex-row bg-white rounded-2xl shadow-lg overflow-hidden border border-blue-100">
132+
<div className="flex flex-col md:flex-row bg-white rounded-2xl shadow-lg overflow-hidden border border-blue-100 dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
133133
{/* Left- Image Section */}
134134
<div className="flex-1 p-6 flex flex-col items-center">
135135
<img

frontend/src/pages/Sell.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,20 @@ const Sell = () => {
6363
};
6464

6565
return (
66-
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 flex items-center justify-center px-4 py-12">
66+
<div className="relative min-h-screen bg-gradient-to-br from-blue-50 via-white to-blue-50 flex items-center justify-center px-4 py-12 dark:bg-gradient-to-br dark:from-slate-900 dark:via-black dark:to-slate-900 dark:text-gray-200">
6767
{/* Background blobs */}
6868
<div className="absolute inset-0 -z-10">
6969
<div className="absolute -top-32 -left-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob"></div>
7070
<div className="absolute top-0 -right-32 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-3xl animate-blob animation-delay-2000"></div>
7171
<div className="absolute bottom-0 left-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-20 blur-2xl animate-blob animation-delay-4000"></div>
7272
</div>
7373

74-
<Card className="w-full max-w-2xl bg-white/90 backdrop-blur-md border-2 border-blue-100 shadow-xl">
74+
<Card className="w-full max-w-2xl bg-white/90 backdrop-blur-md border-2 border-blue-100 shadow-xl dark:bg-slate-800/90 dark:border-slate-700">
7575
<CardHeader className="text-center space-y-2">
76-
<CardTitle className="text-4xl font-extrabold text-blue-800">
76+
<CardTitle className="text-4xl font-extrabold text-blue-800 dark:text-blue-300">
7777
Sell Your Item
7878
</CardTitle>
79-
<CardDescription className="text-lg text-gray-600">
79+
<CardDescription className="text-lg text-gray-600 dark:text-gray-300">
8080
List your items and connect with buyers on campus
8181
</CardDescription>
8282
</CardHeader>

0 commit comments

Comments
 (0)