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 client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<body id="page-top">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div class="font-light text-base text-gray-800 bg-white flex flex-col min-h-screen" id="root"></div>
<div class="font-light text-base text-gray-800 dark:text-gray-200 bg-white dark:bg-gray-900 flex flex-col min-h-screen" id="root"></div>
</body>

</html>
20 changes: 19 additions & 1 deletion client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import React, { Fragment, useReducer } from "react";
import React, { Fragment, useReducer, useEffect } from "react";
import Routes from "./components";
import { LayoutContext, layoutState, layoutReducer } from "./components/shop";

function App() {
const [data, dispatch] = useReducer(layoutReducer, layoutState);

// Apply dark class to document on initial load and when darkMode changes
useEffect(() => {
const root = document.documentElement;
const body = document.body;

if (data.darkMode) {
root.classList.add("dark");
body.classList.add("dark");
// Also set a data attribute for CSS targeting
root.setAttribute("data-theme", "dark");
} else {
root.classList.remove("dark");
body.classList.remove("dark");
root.setAttribute("data-theme", "light");
}
}, [data.darkMode]);

return (
<Fragment>
<LayoutContext.Provider value={{ data, dispatch }}>
Expand Down
23 changes: 14 additions & 9 deletions client/src/components/admin/partials/AdminNavber.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { Fragment } from "react";
import React, { Fragment, useContext } from "react";
import { useHistory } from "react-router-dom";
import { LayoutContext } from "../../shop";
import DarkModeToggle from "../../shop/partials/DarkModeToggle";

const AdminNavber = (props) => {
const history = useHistory();
const { data } = useContext(LayoutContext);

const logout = () => {
localStorage.removeItem("jwt");
Expand All @@ -13,12 +16,12 @@ const AdminNavber = (props) => {

return (
<Fragment>
<nav className="sticky z-10 flex items-center shadow-md justify-between px-4 py-4 md:px-8 top-0 w-full bg-white">
<nav className="sticky z-10 flex items-center shadow-md justify-between px-4 py-4 md:px-8 top-0 w-full bg-white dark:bg-gray-800">
{/* Large Screen Show */}
<div className="hidden lg:block lg:flex lg:items-center lg:space-x-4 mr-32">
<span>
<svg
className="w-8 h-8 cursor-pointer text-gray-600"
className="w-8 h-8 cursor-pointer text-gray-600 dark:text-gray-300"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
Expand All @@ -38,7 +41,7 @@ const AdminNavber = (props) => {
<span
onClick={(e) => history.push("/admin/dashboard")}
style={{ letterSpacing: "0.70rem" }}
className="flex items-left text-center font-bold uppercase text-gray-800 text-2xl cursor-pointer px-2 text-center"
className="flex items-left text-center font-bold uppercase text-gray-800 dark:text-white text-2xl cursor-pointer px-2 text-center"
>
Hayroo
</span>
Expand All @@ -63,16 +66,18 @@ const AdminNavber = (props) => {
<span
onClick={(e) => history.push("/admin/dashboard")}
style={{ letterSpacing: "0.10rem" }}
className="flex items-left text-center font-bold uppercase text-gray-800 text-2xl cursor-pointer px-2 text-center"
className="flex items-left text-center font-bold uppercase text-gray-800 dark:text-white text-2xl cursor-pointer px-2 text-center"
>
Hayroo
</span>
</div>
{/* Both Screen show */}
<div className="flex items-center">
<div className="hover:bg-gray-200 rounded-lg p-2" title="Search">
{/* Dark Mode Toggle Button */}
<DarkModeToggle />
<div className="hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg p-2" title="Search">
<svg
className="cursor-pointer w-8 h-8 text-gray-600 hover:text-gray-800"
className="cursor-pointer w-8 h-8 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
Expand All @@ -88,7 +93,7 @@ const AdminNavber = (props) => {
</div>
<div className="hover:bg-gray-200 rounded-lg p-2" title="Search">
<svg
className="cursor-pointer w-8 h-8 text-gray-600 hover:text-gray-800"
className="cursor-pointer w-8 h-8 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
Expand All @@ -108,7 +113,7 @@ const AdminNavber = (props) => {
title="Logout"
>
<svg
className="cursor-pointer w-8 h-8 text-gray-600 hover:text-gray-800"
className="cursor-pointer w-8 h-8 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
Expand Down
26 changes: 26 additions & 0 deletions client/src/components/shop/layout/layoutContext.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
// Get dark mode preference from localStorage or default to false
const getDarkModePreference = () => {
try {
const savedTheme = localStorage.getItem("darkMode");
if (savedTheme !== null) {
return JSON.parse(savedTheme);
}
} catch (e) {
console.error("Error reading darkMode from localStorage:", e);
}
return false;
};

export const layoutState = {
navberHamburger: false,
loginSignupModal: false,
Expand All @@ -9,6 +22,7 @@ export const layoutState = {
cartTotalCost: null,
orderSuccess: false,
loading: false,
darkMode: getDarkModePreference(),
};

export const layoutReducer = (state, action) => {
Expand Down Expand Up @@ -63,6 +77,18 @@ export const layoutReducer = (state, action) => {
...state,
loading: action.payload,
};
case "toggleDarkMode":
const newDarkMode = !state.darkMode;
// Persist to localStorage
try {
localStorage.setItem("darkMode", JSON.stringify(newDarkMode));
} catch (e) {
console.error("Error saving darkMode to localStorage:", e);
}
return {
...state,
darkMode: newDarkMode,
};
default:
return state;
}
Expand Down
55 changes: 55 additions & 0 deletions client/src/components/shop/partials/DarkModeToggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useContext } from "react";
import { LayoutContext } from "../index";

const DarkModeToggle = () => {
const { data, dispatch } = useContext(LayoutContext);

const toggleDarkMode = () => {
dispatch({ type: "toggleDarkMode" });
};

return (
<div
onClick={toggleDarkMode}
className="hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg px-2 py-2 cursor-pointer"
title={data.darkMode ? "Switch to Light Mode" : "Switch to Dark Mode"}
>
{data.darkMode ? (
// Sun icon for light mode (when in dark mode, clicking switches to light)
<svg
className="w-8 h-8 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
) : (
// Moon icon for dark mode (when in light mode, clicking switches to dark)
<svg
className="w-8 h-8 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
/>
</svg>
)}
</div>
);
};

export default DarkModeToggle;

19 changes: 11 additions & 8 deletions client/src/components/shop/partials/Navber.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "./style.css";
import { logout } from "./Action";
import { LayoutContext } from "../index";
import { isAdmin } from "../auth/fetchApi";
import DarkModeToggle from "./DarkModeToggle";

const Navber = (props) => {
const history = useHistory();
Expand All @@ -30,23 +31,23 @@ const Navber = (props) => {
return (
<Fragment>
{/* Navber Section */}
<nav className="fixed top-0 w-full z-20 shadow-lg lg:shadow-none bg-white">
<nav className="fixed top-0 w-full z-20 shadow-lg lg:shadow-none bg-white dark:bg-gray-800">
<div className="m-4 md:mx-12 md:my-6 grid grid-cols-4 lg:grid-cols-3">
<div className="hidden lg:block col-span-1 flex text-gray-600 mt-1">
<div className="hidden lg:block col-span-1 flex text-gray-600 dark:text-gray-300 mt-1">
<span
className="hover:bg-gray-200 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 cursor-pointer"
className="hover:bg-gray-200 dark:hover:bg-gray-700 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 dark:hover:text-white cursor-pointer"
onClick={(e) => history.push("/")}
>
Shop
</span>
<span
className="hover:bg-gray-200 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 cursor-pointer"
className="hover:bg-gray-200 dark:hover:bg-gray-700 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 dark:hover:text-white cursor-pointer"
onClick={(e) => history.push("/blog")}
>
Blog
</span>
<span
className="hover:bg-gray-200 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 cursor-pointer"
className="hover:bg-gray-200 dark:hover:bg-gray-700 px-4 py-3 rounded-lg font-light tracking-widest hover:text-gray-800 dark:hover:text-white cursor-pointer"
onClick={(e) => history.push("/contact-us")}
>
Contact us
Expand All @@ -71,23 +72,25 @@ const Navber = (props) => {
<span
onClick={(e) => history.push("/")}
style={{ letterSpacing: "0.10rem" }}
className="flex items-left text-center font-bold uppercase text-gray-800 text-2xl cursor-pointer px-2 text-center"
className="flex items-left text-center font-bold uppercase text-gray-800 dark:text-white text-2xl cursor-pointer px-2 text-center"
>
Hayroo
</span>
</div>
<div
onClick={(e) => history.push("/")}
style={{ letterSpacing: "0.70rem" }}
className="hidden lg:block flex items-left col-span-1 text-center text-gray-800 font-bold tracking-widest uppercase text-2xl cursor-pointer"
className="hidden lg:block flex items-left col-span-1 text-center text-gray-800 dark:text-white font-bold tracking-widest uppercase text-2xl cursor-pointer"
>
Hayroo
</div>
<div className="flex items-right col-span-2 lg:col-span-1 flex justify-end">
{/* Dark Mode Toggle Button */}
<DarkModeToggle />
{/* WishList Page Button */}
<div
onClick={(e) => history.push("/wish-list")}
className="hover:bg-gray-200 rounded-lg px-2 py-2 cursor-pointer"
className="hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg px-2 py-2 cursor-pointer"
title="Wishlist"
>
<svg
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/shop/partials/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Navber from "./Navber";
import Footer from "./Footer";
import CartModal from "./CartModal";
import DarkModeToggle from "./DarkModeToggle";

export { Navber, Footer, CartModal };
export { Navber, Footer, CartModal, DarkModeToggle };
3 changes: 2 additions & 1 deletion client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import {SnackbarProvider} from 'notistack'
import {SnackbarProvider} from 'notistack';
import "./styles/darkMode.css";
ReactDOM.render(
<React.StrictMode>
<SnackbarProvider maxSnack={3}>
Expand Down
Loading