Integrates www.gigafibre.ca (React/Vite) into the monorepo. Full git history accessible via `git log -- apps/website/`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import React, { useState, useEffect, useRef } from "react";
|
|
import { Navigate } from "react-router-dom";
|
|
import { supabase } from "@/integrations/supabase/client";
|
|
import { Loader2 } from "lucide-react";
|
|
|
|
export function ProtectedAdminRoute({ children }: { children: React.ReactNode }) {
|
|
const [loading, setLoading] = useState(true);
|
|
const [authorized, setAuthorized] = useState(false);
|
|
const initialCheckDone = useRef(false);
|
|
|
|
useEffect(() => {
|
|
const checkAdmin = async (userId: string) => {
|
|
const { data: roleRow } = await supabase
|
|
.from("user_roles")
|
|
.select("role")
|
|
.eq("user_id", userId)
|
|
.eq("role", "admin")
|
|
.maybeSingle();
|
|
setAuthorized(!!roleRow);
|
|
setLoading(false);
|
|
};
|
|
|
|
// Listen to auth state changes — but ignore null session until initial check is done
|
|
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
|
|
if (session?.user) {
|
|
initialCheckDone.current = true;
|
|
checkAdmin(session.user.id);
|
|
} else if (initialCheckDone.current) {
|
|
// Only redirect if we already confirmed the initial state
|
|
setAuthorized(false);
|
|
setLoading(false);
|
|
}
|
|
});
|
|
|
|
// Initial session check — this is the source of truth
|
|
supabase.auth.getSession().then(({ data: { session } }) => {
|
|
initialCheckDone.current = true;
|
|
if (session?.user) {
|
|
checkAdmin(session.user.id);
|
|
} else {
|
|
setAuthorized(false);
|
|
setLoading(false);
|
|
}
|
|
});
|
|
|
|
return () => subscription.unsubscribe();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center">
|
|
<Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!authorized) {
|
|
return <Navigate to="/admin/login" replace />;
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|