feat(public_page): allow unauthenticated browsing with auth-gated interactivity

- Add get_optional_user dependency; dashboard returns guest-safe payload
- AuthGuard only redirects /following and /notifications for guests
- Sidebar hides auth-required nav items and shows Sign In/Register for guests
- Dashboard shows trending bills as "Most Popular" for unauthenticated visitors
- FollowButton opens AuthModal instead of acting when not signed in
- Members page pins followed members at the top for quick unfollowing
- useFollows skips API call and invalidates dashboard on follow/unfollow

Authored-By: Jack Levy
This commit is contained in:
Jack Levy
2026-03-01 15:54:54 -05:00
parent 73881b2404
commit ddd74a02d5
9 changed files with 314 additions and 128 deletions

View File

@@ -1,11 +1,14 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { followsAPI } from "../api";
import { useAuthStore } from "@/stores/authStore";
export function useFollows() {
const token = useAuthStore((s) => s.token);
return useQuery({
queryKey: ["follows"],
queryFn: () => followsAPI.list(),
staleTime: 30 * 1000,
enabled: !!token,
});
}
@@ -14,7 +17,10 @@ export function useAddFollow() {
return useMutation({
mutationFn: ({ type, value }: { type: string; value: string }) =>
followsAPI.add(type, value),
onSuccess: () => qc.invalidateQueries({ queryKey: ["follows"] }),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ["follows"] });
qc.invalidateQueries({ queryKey: ["dashboard"] });
},
});
}
@@ -22,7 +28,10 @@ export function useRemoveFollow() {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: number) => followsAPI.remove(id),
onSuccess: () => qc.invalidateQueries({ queryKey: ["follows"] }),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ["follows"] });
qc.invalidateQueries({ queryKey: ["dashboard"] });
},
});
}