refactor: whitespace fixes
This commit is contained in:
@@ -2,54 +2,63 @@ import { DotIcon } from "@phosphor-icons/react";
|
||||
import "@fontsource/knewave/400.css";
|
||||
|
||||
interface LogoProps {
|
||||
scale?: number;
|
||||
type?: "inline" | "mono" | "logo" | null;
|
||||
ul?: boolean;
|
||||
scale?: number;
|
||||
type?: "inline" | "mono" | "logo" | null;
|
||||
ul?: boolean;
|
||||
}
|
||||
|
||||
export default function Logo({ scale = 1, type = null, ul = false }: LogoProps) {
|
||||
if (type === "inline") {
|
||||
return (
|
||||
<span className={"text-accent font-display italic "}>
|
||||
pi<span className="text-primary">.</span> ku
|
||||
<span className="text-primary">.</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "mono") {
|
||||
return (
|
||||
<span className="font-display italic font-bold border-b-3 border-dashed border-stone-800/50">
|
||||
pi. ku.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "logo") {
|
||||
return (
|
||||
<img src="/android-chrome-512x512.png" alt="Pi. Ku. logo" className="mx-auto" width={scale * 100} />
|
||||
);
|
||||
}
|
||||
|
||||
export default function Logo({
|
||||
scale = 1,
|
||||
type = null,
|
||||
ul = false,
|
||||
}: LogoProps) {
|
||||
if (type === "inline") {
|
||||
return (
|
||||
<div
|
||||
role="img"
|
||||
aria-label="Pi. Ku. logo"
|
||||
className={`inline-flex items-baseline justify-center leading-none select-none ${ul ? "ul-wavy" : ""}`}
|
||||
style={{ fontFamily: "'Knewave', serif", scale }}
|
||||
>
|
||||
<span className="text-3xl font-light text-accent">Pi</span>
|
||||
<DotIcon
|
||||
weight="fill"
|
||||
size={12}
|
||||
className="text-primary translate-y-1 -mx-px"
|
||||
/>
|
||||
<span className="text-3xl font-light text-accent"> Ku</span>
|
||||
<DotIcon
|
||||
weight="fill"
|
||||
size={12}
|
||||
className="text-primary translate-y-1 -mx-px"
|
||||
/>
|
||||
</div>
|
||||
<span className={"text-accent font-display italic "}>
|
||||
pi<span className="text-primary">.</span> ku
|
||||
<span className="text-primary">.</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "mono") {
|
||||
return (
|
||||
<span className="font-display italic font-bold border-b-3 border-dashed border-stone-800/50">
|
||||
pi. ku.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "logo") {
|
||||
return (
|
||||
<img
|
||||
src="/android-chrome-512x512.png"
|
||||
alt="Pi. Ku. logo"
|
||||
className="mx-auto"
|
||||
width={scale * 100}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
role="img"
|
||||
aria-label="Pi. Ku. logo"
|
||||
className={`inline-flex items-baseline justify-center leading-none select-none ${ul ? "ul-wavy" : ""}`}
|
||||
style={{ fontFamily: "'Knewave', serif", scale }}
|
||||
>
|
||||
<span className="text-3xl font-light text-accent">Pi</span>
|
||||
<DotIcon
|
||||
weight="fill"
|
||||
size={12}
|
||||
className="text-primary translate-y-1 -mx-px"
|
||||
/>
|
||||
<span className="text-3xl font-light text-accent"> Ku</span>
|
||||
<DotIcon
|
||||
weight="fill"
|
||||
size={12}
|
||||
className="text-primary translate-y-1 -mx-px"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,125 +3,125 @@ import { MemoryRouter, Route, Routes } from "react-router-dom";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { mockUser } from "../../test/fixtures/user.fixture";
|
||||
import { useAuthStore } from "../store/useAuthStore";
|
||||
import { ProtectedRoute, AutoRedirectRoute } from "./RouteGuards";
|
||||
import { AutoRedirectRoute, ProtectedRoute } from "./RouteGuards";
|
||||
|
||||
function renderGuard(ui: React.ReactNode, mountPath: "/protected" | "/public") {
|
||||
return render(
|
||||
<MemoryRouter initialEntries={[mountPath]}>
|
||||
<Routes>
|
||||
<Route path="/login" element={<div>Login Page</div>} />
|
||||
<Route path="/drawer" element={<div>Drawer Page</div>} />
|
||||
<Route path="/protected" element={ui} />
|
||||
<Route path="/public" element={ui} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
return render(
|
||||
<MemoryRouter initialEntries={[mountPath]}>
|
||||
<Routes>
|
||||
<Route path="/login" element={<div>Login Page</div>} />
|
||||
<Route path="/drawer" element={<div>Drawer Page</div>} />
|
||||
<Route path="/protected" element={ui} />
|
||||
<Route path="/public" element={ui} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
useAuthStore.setState({
|
||||
accessToken: null,
|
||||
user: null,
|
||||
isInitializing: true,
|
||||
});
|
||||
useAuthStore.setState({
|
||||
accessToken: null,
|
||||
user: null,
|
||||
isInitializing: true,
|
||||
});
|
||||
});
|
||||
|
||||
describe("ProtectedRoute", () => {
|
||||
it("should show SplashScreen while auth is initializing", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: true,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
|
||||
expect(screen.getByText(/Unsealing/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText("Secret")).not.toBeInTheDocument();
|
||||
it("should show SplashScreen while auth is initializing", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: true,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
|
||||
it("should redirect unauthenticated users to /login", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
expect(screen.getByText("Login Page")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Secret")).not.toBeInTheDocument();
|
||||
expect(screen.getByText(/Unsealing/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText("Secret")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should redirect unauthenticated users to /login", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
expect(screen.getByText("Login Page")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Secret")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should render page for authenticated users", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: "token",
|
||||
user: mockUser,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
|
||||
expect(screen.getByText("Secret")).toBeInTheDocument();
|
||||
it("should render page for authenticated users", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: "token",
|
||||
user: mockUser,
|
||||
});
|
||||
renderGuard(
|
||||
<ProtectedRoute>
|
||||
<div>Secret</div>
|
||||
</ProtectedRoute>,
|
||||
"/protected",
|
||||
);
|
||||
|
||||
expect(screen.getByText("Secret")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("PublicRoute", () => {
|
||||
it("should show SplashScreen while auth is initializing", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: true,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Page</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText(/Unsealing/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText("Login Page")).not.toBeInTheDocument();
|
||||
it("should show SplashScreen while auth is initializing", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: true,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Page</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText(/Unsealing/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText("Login Page")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should redirect authenticated users to /drawer", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: "token",
|
||||
user: mockUser,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Form</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText("Drawer Page")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Login Form")).not.toBeInTheDocument();
|
||||
it("should redirect authenticated users to /drawer", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: "token",
|
||||
user: mockUser,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Form</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText("Drawer Page")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Login Form")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should render page for unauthenticated users", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Form</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText("Login Form")).toBeInTheDocument();
|
||||
it("should render page for unauthenticated users", () => {
|
||||
useAuthStore.setState({
|
||||
isInitializing: false,
|
||||
accessToken: null,
|
||||
user: null,
|
||||
});
|
||||
renderGuard(
|
||||
<AutoRedirectRoute>
|
||||
<div>Login Form</div>
|
||||
</AutoRedirectRoute>,
|
||||
"/public",
|
||||
);
|
||||
expect(screen.getByText("Login Form")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,16 +9,16 @@ import SplashScreen from "./SplashScreen";
|
||||
* state so the Login component can link them back after sign-in
|
||||
*/
|
||||
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
const { isAuthenticated, isInitializing } = useAuth();
|
||||
const location = useLocation();
|
||||
const { isAuthenticated, isInitializing } = useAuth();
|
||||
const location = useLocation();
|
||||
|
||||
if (isInitializing) return <SplashScreen />;
|
||||
if (isInitializing) return <SplashScreen />;
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to={ROUTES.LOGIN} state={{ from: location }} replace />;
|
||||
}
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to={ROUTES.LOGIN} state={{ from: location }} replace />;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,13 +26,13 @@ export function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
* If authenticated, redirect all the auth related flows to the drawer
|
||||
*/
|
||||
export function AutoRedirectRoute({ children }: { children: React.ReactNode }) {
|
||||
const { isAuthenticated, isInitializing } = useAuth();
|
||||
const { isAuthenticated, isInitializing } = useAuth();
|
||||
|
||||
if (isInitializing) return <SplashScreen />;
|
||||
if (isInitializing) return <SplashScreen />;
|
||||
|
||||
if (isAuthenticated) {
|
||||
return <Navigate to={ROUTES.DRAWER} replace />;
|
||||
}
|
||||
if (isAuthenticated) {
|
||||
return <Navigate to={ROUTES.DRAWER} replace />;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user