Commit ·
91b29b1
1
Parent(s): f08c3c4
Registration Initiated.
Browse files
frontend/app/components/header.tsx
CHANGED
|
@@ -2,45 +2,18 @@
|
|
| 2 |
|
| 3 |
import { Button } from "./ui/button";
|
| 4 |
import { useSidebar } from "./ui/sidebar";
|
| 5 |
-
import {
|
| 6 |
-
import {
|
| 7 |
|
| 8 |
export function Header() {
|
| 9 |
const { state, toggleSidebar } = useSidebar();
|
| 10 |
|
| 11 |
-
const [darkMode, setDarkMode] = useState<boolean>(() => {
|
| 12 |
-
try {
|
| 13 |
-
const stored = localStorage.getItem("theme");
|
| 14 |
-
if (stored) return stored === "dark";
|
| 15 |
-
return (
|
| 16 |
-
typeof window !== "undefined" &&
|
| 17 |
-
window.matchMedia?.("(prefers-color-scheme: dark)")?.matches
|
| 18 |
-
);
|
| 19 |
-
} catch {
|
| 20 |
-
return false;
|
| 21 |
-
}
|
| 22 |
-
});
|
| 23 |
-
|
| 24 |
-
useEffect(() => {
|
| 25 |
-
try {
|
| 26 |
-
const root = document.documentElement;
|
| 27 |
-
if (darkMode) root.classList.add("dark");
|
| 28 |
-
else root.classList.remove("dark");
|
| 29 |
-
localStorage.setItem("theme", darkMode ? "dark" : "light");
|
| 30 |
-
} catch {}
|
| 31 |
-
}, [darkMode]);
|
| 32 |
-
|
| 33 |
return (
|
| 34 |
<header className="flex place-content-between p-4">
|
| 35 |
<Button onClick={() => toggleSidebar()} variant="ghost" size="icon">
|
| 36 |
{state == "collapsed" ? <SidebarOpenIcon /> : <SidebarCloseIcon />}
|
| 37 |
</Button>
|
| 38 |
-
<
|
| 39 |
-
onClick={() => setDarkMode((v) => !v)}
|
| 40 |
-
variant="ghost" size="icon" aria-pressed={darkMode}
|
| 41 |
-
>
|
| 42 |
-
{darkMode ? <SunIcon /> : <MoonIcon />}
|
| 43 |
-
</Button>
|
| 44 |
</header>
|
| 45 |
);
|
| 46 |
}
|
|
|
|
| 2 |
|
| 3 |
import { Button } from "./ui/button";
|
| 4 |
import { useSidebar } from "./ui/sidebar";
|
| 5 |
+
import { ThemeToggle } from "./theme-toggle";
|
| 6 |
+
import { SidebarCloseIcon, SidebarOpenIcon } from "lucide-react";
|
| 7 |
|
| 8 |
export function Header() {
|
| 9 |
const { state, toggleSidebar } = useSidebar();
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
return (
|
| 12 |
<header className="flex place-content-between p-4">
|
| 13 |
<Button onClick={() => toggleSidebar()} variant="ghost" size="icon">
|
| 14 |
{state == "collapsed" ? <SidebarOpenIcon /> : <SidebarCloseIcon />}
|
| 15 |
</Button>
|
| 16 |
+
<ThemeToggle />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
</header>
|
| 18 |
);
|
| 19 |
}
|
frontend/app/components/theme-toggle.tsx
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Button } from "./ui/button";
|
| 2 |
+
import { useEffect, useState } from "react";
|
| 3 |
+
import { MoonIcon, SunIcon } from "lucide-react";
|
| 4 |
+
|
| 5 |
+
export function ThemeToggle() {
|
| 6 |
+
const [darkMode, setDarkMode] = useState<boolean>(() => {
|
| 7 |
+
try {
|
| 8 |
+
const stored = localStorage.getItem("theme");
|
| 9 |
+
if (stored) return stored === "dark";
|
| 10 |
+
return (
|
| 11 |
+
typeof window !== "undefined" &&
|
| 12 |
+
window.matchMedia?.("(prefers-color-scheme: dark)")?.matches
|
| 13 |
+
);
|
| 14 |
+
} catch {
|
| 15 |
+
return false;
|
| 16 |
+
}
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
useEffect(() => {
|
| 20 |
+
try {
|
| 21 |
+
const root = document.documentElement;
|
| 22 |
+
if (darkMode) root.classList.add("dark");
|
| 23 |
+
else root.classList.remove("dark");
|
| 24 |
+
localStorage.setItem("theme", darkMode ? "dark" : "light");
|
| 25 |
+
} catch {}
|
| 26 |
+
}, [darkMode]);
|
| 27 |
+
|
| 28 |
+
return (
|
| 29 |
+
<Button
|
| 30 |
+
onClick={() => setDarkMode((v) => !v)}
|
| 31 |
+
variant="ghost" size="icon" aria-pressed={darkMode}
|
| 32 |
+
>
|
| 33 |
+
{darkMode ? <SunIcon /> : <MoonIcon />}
|
| 34 |
+
</Button>
|
| 35 |
+
);
|
| 36 |
+
}
|
frontend/app/root.tsx
CHANGED
|
@@ -3,20 +3,24 @@ import {
|
|
| 3 |
Links,
|
| 4 |
Outlet,
|
| 5 |
Scripts,
|
|
|
|
| 6 |
ScrollRestoration,
|
| 7 |
isRouteErrorResponse,
|
| 8 |
} from "react-router";
|
| 9 |
import type { Route } from "./+types/root";
|
| 10 |
import { Header } from "./components/header";
|
| 11 |
import { ToastContainer } from "react-toastify";
|
| 12 |
-
import {
|
| 13 |
import { SidebarProvider } from "./components/sidebar-provider";
|
|
|
|
| 14 |
|
| 15 |
import "./app.css";
|
| 16 |
|
| 17 |
export const queryClient = new QueryClient();
|
| 18 |
|
| 19 |
export function Layout({ children }: { children: React.ReactNode }) {
|
|
|
|
|
|
|
| 20 |
return (
|
| 21 |
<html lang="en">
|
| 22 |
<head>
|
|
@@ -31,10 +35,19 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|
| 31 |
</head>
|
| 32 |
<body>
|
| 33 |
<QueryClientProvider client={queryClient}>
|
| 34 |
-
|
| 35 |
-
<
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
</QueryClientProvider>
|
| 39 |
<ToastContainer />
|
| 40 |
<ScrollRestoration />
|
|
|
|
| 3 |
Links,
|
| 4 |
Outlet,
|
| 5 |
Scripts,
|
| 6 |
+
useLocation,
|
| 7 |
ScrollRestoration,
|
| 8 |
isRouteErrorResponse,
|
| 9 |
} from "react-router";
|
| 10 |
import type { Route } from "./+types/root";
|
| 11 |
import { Header } from "./components/header";
|
| 12 |
import { ToastContainer } from "react-toastify";
|
| 13 |
+
import { ThemeToggle } from "./components/theme-toggle";
|
| 14 |
import { SidebarProvider } from "./components/sidebar-provider";
|
| 15 |
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
| 16 |
|
| 17 |
import "./app.css";
|
| 18 |
|
| 19 |
export const queryClient = new QueryClient();
|
| 20 |
|
| 21 |
export function Layout({ children }: { children: React.ReactNode }) {
|
| 22 |
+
const { pathname } = useLocation();
|
| 23 |
+
|
| 24 |
return (
|
| 25 |
<html lang="en">
|
| 26 |
<head>
|
|
|
|
| 35 |
</head>
|
| 36 |
<body>
|
| 37 |
<QueryClientProvider client={queryClient}>
|
| 38 |
+
{pathname.startsWith("/registration") ? (
|
| 39 |
+
<>
|
| 40 |
+
<header className="flex flex-row-reverse place-content-between p-4">
|
| 41 |
+
<ThemeToggle />
|
| 42 |
+
</header>
|
| 43 |
+
<main>{children}</main>
|
| 44 |
+
</>
|
| 45 |
+
) : (
|
| 46 |
+
<SidebarProvider>
|
| 47 |
+
<Header />
|
| 48 |
+
<main>{children}</main>
|
| 49 |
+
</SidebarProvider>
|
| 50 |
+
)}
|
| 51 |
</QueryClientProvider>
|
| 52 |
<ToastContainer />
|
| 53 |
<ScrollRestoration />
|
frontend/app/routes.ts
CHANGED
|
@@ -6,4 +6,5 @@ export default [
|
|
| 6 |
route("jobs/:id", "routes/jobs.$id.tsx"),
|
| 7 |
route("jobs/:jid/assessments/:id", "routes/jobs.$jid.assessments.$id.tsx"),
|
| 8 |
route("dashboard", "routes/dashboard.tsx"),
|
|
|
|
| 9 |
] satisfies RouteConfig;
|
|
|
|
| 6 |
route("jobs/:id", "routes/jobs.$id.tsx"),
|
| 7 |
route("jobs/:jid/assessments/:id", "routes/jobs.$jid.assessments.$id.tsx"),
|
| 8 |
route("dashboard", "routes/dashboard.tsx"),
|
| 9 |
+
route("registration", "routes/registration.tsx"),
|
| 10 |
] satisfies RouteConfig;
|
frontend/app/routes/registration.tsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { Route } from "./+types/registration";
|
| 2 |
+
|
| 3 |
+
export function meta({}: Route.MetaArgs) {
|
| 4 |
+
return [
|
| 5 |
+
{ title: "Registration" },
|
| 6 |
+
{
|
| 7 |
+
name: "description",
|
| 8 |
+
content: "Login to access your account or create a new one.",
|
| 9 |
+
},
|
| 10 |
+
];
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
export default function Registration() {
|
| 14 |
+
}
|