diff --git a/client/src/App.jsx b/client/src/App.jsx index 12bc56e..383f976 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -9,6 +9,7 @@ import RemoveBackground from "./pages/RemoveBackground" import ReviewResume from "./pages/ReviewResume" import Community from "./pages/Community" import REmoveObject from "./pages/RemoveObject" +import ManagePlan from "./pages/ManagePlan" import { ThemeProvider } from "./context/ThemeContext" import {Toaster} from 'react-hot-toast' @@ -32,6 +33,7 @@ const App = () => { } /> } /> } /> + } /> diff --git a/client/src/App.test.jsx b/client/src/App.test.jsx index 8058246..5edf4ad 100644 --- a/client/src/App.test.jsx +++ b/client/src/App.test.jsx @@ -29,6 +29,7 @@ jest.mock("./pages/RemoveBackground", () => () =>
Remove Background Page () =>
Remove Object Page
); jest.mock("./pages/ReviewResume", () => () =>
Review Resume Page
); jest.mock("./pages/Community", () => () =>
Community Page
); +jest.mock("./pages/ManagePlan", () => () =>
Manage Plan Page
); // ---- MOCK CLERK ---- jest.mock("@clerk/clerk-react", () => ({ @@ -95,4 +96,14 @@ describe("App Routing", () => { expect(screen.getByText("Community Page")).toBeInTheDocument(); }); + + test("renders Manage Plan page", () => { + render( + + + + ); + + expect(screen.getByText("Manage Plan Page")).toBeInTheDocument(); + }); }); diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx index e7794cb..940cb9a 100644 --- a/client/src/components/Navbar.jsx +++ b/client/src/components/Navbar.jsx @@ -29,7 +29,7 @@ const navItems = [ { to: "/ai/community", label: "Community", Icon: Users }, ]; -const Navbar = ({ theme: propTheme, setTheme: propSetTheme }) => { +const Navbar = ({ theme: propTheme, setTheme: propSetTheme, setSidebar }) => { const navigate = useNavigate(); const location = useLocation(); const { user } = useUser(); @@ -107,7 +107,13 @@ const Navbar = ({ theme: propTheme, setTheme: propSetTheme }) => {
{/* Mobile menu toggle */}
- {/* MOBILE MENU */} - {mobileOpen && ( + {/* MOBILE MENU - only shown when no sidebar is managed externally */} + {mobileOpen && !setSidebar && (
{ @@ -31,7 +31,7 @@ const Sidebar = ({ sidebar, setSidebar }) => {

{user?.fullName}

diff --git a/client/src/pages/Layout.jsx b/client/src/pages/Layout.jsx index 98f7fa4..2f85f04 100644 --- a/client/src/pages/Layout.jsx +++ b/client/src/pages/Layout.jsx @@ -1,11 +1,14 @@ +import { useState } from "react"; import { Outlet } from "react-router-dom"; import { SignIn, useUser } from "@clerk/clerk-react"; import Navbar from "@/components/Navbar"; +import Sidebar from "@/components/Sidebar"; import { useTheme } from "@/context/ThemeContext"; const Layout = () => { const { user, isLoaded } = useUser(); const { theme } = useTheme(); + const [sidebar, setSidebar] = useState(false); if (!isLoaded) { return ( @@ -18,13 +21,23 @@ const Layout = () => { } return user ? ( -
- +
+ - {/* offset for fixed navbar */} -
- -
+
+ +
+ +
+
+ + {/* Overlay to close sidebar on mobile */} + {sidebar && ( +
setSidebar(false)} + /> + )}
) : (
{ + const { theme } = useTheme(); + const isDark = theme === "dark"; + + return ( +
+
+ {/* Header */} +
+
+ +
+
+

Manage Plan

+

+ Current plan:{" "} + + Premium + +

+
+
+ + {/* Pricing Table */} +
+ +
+
+
+ ); +}; + +export default ManagePlan; diff --git a/server/middlewares/auth.js b/server/middlewares/auth.js index a825c01..e281263 100644 --- a/server/middlewares/auth.js +++ b/server/middlewares/auth.js @@ -9,16 +9,10 @@ export const auth = async (req, res, next) => { const user = await clerkClient.users.getUser(userId); - if (!hasPremiumPlan && user.privateMetadata.free_usage) { - req.free_usage = user.privateMetadata.free_usage + if (!hasPremiumPlan) { + req.free_usage = user.privateMetadata.free_usage ?? 0; } else { - await clerkClient.users.updateUserMetadata(userId, { - privateMetadata: { - free_usage: 0 - } - }) req.free_usage = 0; - } req.plan = hasPremiumPlan ? 'premium' : 'free'; @@ -26,6 +20,4 @@ export const auth = async (req, res, next) => { } catch (error) { res.json({ success: false, message: error.message }) } - - } \ No newline at end of file