gaurv007 commited on
Commit
fe47291
·
verified ·
1 Parent(s): 692ed26

fix(auth): web/components/nav.tsx — fix nav not updating after login + add missing middleware

Browse files
Files changed (1) hide show
  1. web/components/nav.tsx +70 -33
web/components/nav.tsx CHANGED
@@ -1,14 +1,14 @@
1
  "use client";
2
 
3
  import Link from "next/link";
4
- import { usePathname } from "next/navigation";
5
  import type { LucideIcon } from "lucide-react";
6
  import {
7
  ShieldCheck, Menu, X, Crown, GitCompare, LayoutDashboard,
8
  ScanText, Settings, LogIn, Zap, Sparkles, CreditCard, UserCircle,
9
  LogOut, Users
10
  } from "lucide-react";
11
- import { useState, useEffect } from "react";
12
  import { createClient } from "@/lib/supabase/client";
13
 
14
  interface NavLink {
@@ -28,45 +28,82 @@ export function Nav() {
28
  const isAdmin = userRole === "admin";
29
  const hasTeam = !!userTeam;
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  useEffect(() => {
 
 
 
 
 
 
 
 
32
  try {
33
  const supabase = createClient();
34
- supabase.auth.getUser().then(async ({ data, error }) => {
35
- if (error) {
36
- console.error("Auth error:", error);
37
- setLoaded(true);
38
- return;
39
  }
40
- const user = data.user;
41
- setUserEmail(user?.email || null);
42
- if (user) {
43
- try {
44
- const { data: profile } = await supabase
45
- .from("profiles")
46
- .select("role, team_id")
47
- .eq("id", user.id)
48
- .single();
49
- setUserRole(profile?.role || "user");
50
- setUserTeam(profile?.team_id || null);
51
- } catch (err) {
52
- console.error("Profile error:", err);
53
- }
54
- }
55
- setLoaded(true);
56
- }).catch(err => {
57
- console.error("Unexpected error:", err);
58
- setLoaded(true);
59
  });
60
- } catch (err) {
61
- console.error("Supabase client init error:", err);
62
- // Fallback for when env variables are not found/configured
63
- setLoaded(true);
64
  }
65
- }, []);
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  async function handleSignOut() {
68
- const supabase = createClient();
69
- await supabase.auth.signOut();
 
 
 
 
70
  setUserEmail(null);
71
  setUserRole(null);
72
  setUserTeam(null);
 
1
  "use client";
2
 
3
  import Link from "next/link";
4
+ import { usePathname, useRouter } from "next/navigation";
5
  import type { LucideIcon } from "lucide-react";
6
  import {
7
  ShieldCheck, Menu, X, Crown, GitCompare, LayoutDashboard,
8
  ScanText, Settings, LogIn, Zap, Sparkles, CreditCard, UserCircle,
9
  LogOut, Users
10
  } from "lucide-react";
11
+ import { useState, useEffect, useCallback } from "react";
12
  import { createClient } from "@/lib/supabase/client";
13
 
14
  interface NavLink {
 
28
  const isAdmin = userRole === "admin";
29
  const hasTeam = !!userTeam;
30
 
31
+ // FIX v4.3: Extracted into a reusable function so it can be called
32
+ // both on mount AND when Supabase fires auth state changes.
33
+ const refreshAuth = useCallback(async () => {
34
+ try {
35
+ const supabase = createClient();
36
+ const { data: { user }, error } = await supabase.auth.getUser();
37
+
38
+ if (error || !user) {
39
+ setUserEmail(null);
40
+ setUserRole(null);
41
+ setUserTeam(null);
42
+ setLoaded(true);
43
+ return;
44
+ }
45
+
46
+ setUserEmail(user.email || null);
47
+
48
+ try {
49
+ const { data: profile } = await supabase
50
+ .from("profiles")
51
+ .select("role, team_id")
52
+ .eq("id", user.id)
53
+ .single();
54
+ setUserRole(profile?.role || "user");
55
+ setUserTeam(profile?.team_id || null);
56
+ } catch {
57
+ setUserRole("user");
58
+ setUserTeam(null);
59
+ }
60
+ } catch {
61
+ // Supabase client init error (env vars missing)
62
+ }
63
+ setLoaded(true);
64
+ }, []);
65
+
66
  useEffect(() => {
67
+ // Initial auth check
68
+ refreshAuth();
69
+
70
+ // FIX v4.3: Listen to Supabase onAuthStateChange.
71
+ // This fires on SIGNED_IN, SIGNED_OUT, TOKEN_REFRESHED, etc.
72
+ // Without this, Nav never updates after login because the useEffect
73
+ // only ran once on mount with [] deps.
74
+ let subscription: { unsubscribe: () => void } | null = null;
75
  try {
76
  const supabase = createClient();
77
+ const { data } = supabase.auth.onAuthStateChange((event) => {
78
+ // Re-fetch on any auth event
79
+ if (event === "SIGNED_IN" || event === "SIGNED_OUT" || event === "TOKEN_REFRESHED" || event === "INITIAL_SESSION") {
80
+ refreshAuth();
 
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  });
83
+ subscription = data.subscription;
84
+ } catch {
85
+ // env vars missing
 
86
  }
87
+
88
+ return () => {
89
+ subscription?.unsubscribe();
90
+ };
91
+ }, [refreshAuth]);
92
+
93
+ // FIX v4.3: Also re-check when pathname changes (covers router.push after login)
94
+ useEffect(() => {
95
+ if (loaded) {
96
+ refreshAuth();
97
+ }
98
+ }, [pathname, loaded, refreshAuth]);
99
 
100
  async function handleSignOut() {
101
+ try {
102
+ const supabase = createClient();
103
+ await supabase.auth.signOut();
104
+ } catch {
105
+ // ignore
106
+ }
107
  setUserEmail(null);
108
  setUserRole(null);
109
  setUserTeam(null);