Skip to content
Merged
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
5 changes: 3 additions & 2 deletions src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ const getInitials = (value: string) => {
return `${tokens[0][0]}${tokens[tokens.length - 1][0]}`.toUpperCase();
};

const Header = ({ isAdmin = false }: { isAdmin?: boolean }) => {
const { role, user } = useAuthRole();
const Header = () => {
const { role, user, isAdmin: roleIsAdmin } = useAuthRole();
const router = useRouter();
const [profileOpen, setProfileOpen] = useState(false);
const isAdmin = router.pathname === "/admin/page" || roleIsAdmin;
const isPanelist = role?.slug === "admin" || role?.slug?.includes("panel");
const displayName = user?.user_metadata?.full_name ?? user?.user_metadata?.name ?? null;
const displayEmail = user?.email ?? null;
Expand Down
4 changes: 2 additions & 2 deletions src/components/layout/PageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import Header from "./Header";
import Footer from "./Footer";
import { ReactNode } from "react";

const PageLayout: React.FC<{ children: ReactNode, isAdmin?: boolean }> = ({ children, isAdmin = false }) => {
const PageLayout: React.FC<{ children: ReactNode }> = ({ children }) => {
return (
<div className="min-h-screen flex flex-col bg-[#F6F6F7]">
<Header isAdmin={isAdmin} />
<Header />
<main className="flex-grow">
{children}
</main>
Expand Down
37 changes: 30 additions & 7 deletions src/lib/useAuthRole.ts → src/lib/useAuthRole.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from "react";
import { createContext, useContext, useCallback, useEffect, useState, ReactNode } from "react";
import type { User } from "@supabase/supabase-js";
import { fetchMyRole, isAllowed, type Role } from "./roles";
import { client } from "./supabase/supabase";
Expand All @@ -14,11 +14,20 @@ export type AuthRoleState = {
refresh: () => Promise<void>;
};

/**
* Current user's role + allowed pages. Falls back to the default role
* (Member) when the user has no row yet.
*/
export function useAuthRole(): AuthRoleState {
const defaultAuthRoleState: AuthRoleState = {
loading: true,
userId: null,
user: null,
role: null,
routes: [],
isAdmin: false,
can: () => false,
refresh: async () => {},
};

const AuthRoleContext = createContext<AuthRoleState>(defaultAuthRoleState);

export function AuthRoleProvider({ children }: { children: ReactNode }) {
const [loading, setLoading] = useState(true);
const [userId, setUserId] = useState<string | null>(null);
const [user, setUser] = useState<User | null>(null);
Expand Down Expand Up @@ -54,7 +63,7 @@ export function useAuthRole(): AuthRoleState {
return () => sub.subscription.unsubscribe();
}, [load]);

return {
const value: AuthRoleState = {
loading,
userId,
user,
Expand All @@ -64,6 +73,20 @@ export function useAuthRole(): AuthRoleState {
can: (path: string) => isAllowed(routes, path),
refresh: load,
};

return (
<AuthRoleContext.Provider value={value}>
{children}
</AuthRoleContext.Provider>
);
}

/**
* Current user's role + allowed pages. Falls back to the default role
* (Member) when the user has no row yet.
*/
export function useAuthRole(): AuthRoleState {
return useContext(AuthRoleContext);
}

/**
Expand Down
22 changes: 10 additions & 12 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@ import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import PageLayout from "@/components/layout/PageLayout";
import { useRouter } from "next/router";
import { useAuthRole } from "@/lib/useAuthRole";
import { AuthRoleProvider } from "@/lib/useAuthRole";

const queryClient = new QueryClient();

export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const {role} = useAuthRole();
const isAdmin = router.pathname === "/admin/page" || role?.slug === "admin";

return (
<QueryClientProvider client={queryClient}>
<PageLayout isAdmin={isAdmin}>
<TooltipProvider>
<Toaster />
<Sonner />
<Component {...pageProps} />
</TooltipProvider>
</PageLayout>
<AuthRoleProvider>
<PageLayout>
<TooltipProvider>
<Toaster />
<Sonner />
<Component {...pageProps} />
</TooltipProvider>
</PageLayout>
</AuthRoleProvider>
</QueryClientProvider>
);
}
Loading
Loading