woof. killed useClient and use nextjs api
CI / test (push) Successful in 5s

This commit is contained in:
2026-01-25 13:40:10 -05:00
parent 5b73d59c2c
commit 50ef395a38
19 changed files with 696 additions and 247 deletions
+8 -13
View File
@@ -74,8 +74,7 @@ const isUuid = (v: string) =>
v
);
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
// API routes now handled by Next.js /api routes (server-side)
const STORAGE_KEY = "gunbuilder-build-state";
@@ -337,8 +336,8 @@ function GunbuilderPageContent() {
const api = useApi();
// ✅ Auth: we need the token ready before calling /builds/me/*
const { token, loading: authLoading, getAuthHeaders } = useAuth();
// ✅ Auth: check if user is logged in
const { user, loading: authLoading } = useAuth();
const [platform, setPlatform] = useState<(typeof PLATFORMS)[number]>("AR15");
@@ -616,7 +615,7 @@ function GunbuilderPageContent() {
try {
const res = await fetch(
`${API_BASE_URL}/api/v1/catalog/products/by-ids`,
`/api/catalog/products/by-ids`,
{
method: "POST",
signal: controller.signal,
@@ -728,7 +727,7 @@ function GunbuilderPageContent() {
if (authLoading) return;
// If not logged in, don't spam the backend; show a helpful message instead.
if (!token) {
if (!user) {
setShareStatus("Please log in to load builds from your Vault.");
window.setTimeout(() => setShareStatus(null), 4500);
return;
@@ -738,14 +737,12 @@ function GunbuilderPageContent() {
try {
setShareStatus("Loading build…");
// NOTE: using fetch here avoids any “stale api instance” issues and lets us
// explicitly attach JWT headers.
// NOTE: using fetch here goes through our Next.js API routes with HTTP-only cookies
const res = await fetch(
`${API_BASE_URL}/api/v1/builds/me/${encodeURIComponent(uuidToLoad)}`,
`/api/builds/${encodeURIComponent(uuidToLoad)}`,
{
headers: {
"Content-Type": "application/json",
...getAuthHeaders(),
},
}
);
@@ -787,9 +784,7 @@ function GunbuilderPageContent() {
searchParams,
router,
authLoading,
token,
getAuthHeaders,
// API_BASE_URL is a module constant; no need to include
user,
]);
// -----------------------------
+8 -9
View File
@@ -18,8 +18,7 @@ type BuildDto = {
updatedAt?: string | null;
};
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
// API routes now handled by Next.js /api routes (server-side)
// UUID validator (defensive)
const isUuid = (v: string) =>
@@ -40,14 +39,14 @@ export default function VaultPage() {
// NOTE:
// - `loading` here is AuthContext hydration, not network.
// - `token` is the real gate for /me endpoints.
const { user, token, loading: authLoading } = useAuth();
// - Auth is handled by HTTP-only cookies automatically.
const { user, loading: authLoading } = useAuth();
const [builds, setBuilds] = useState<BuildDto[]>([]);
const [error, setError] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
const authed = !!user && !!token;
const authed = !!user;
// Redirect if not logged in (after auth hydrates)
useEffect(() => {
@@ -56,12 +55,12 @@ export default function VaultPage() {
}
}, [authLoading, authed, router]);
// When auth identity changes, clear stale list to avoid ghost builds
// When auth identity changes, clear stale list to avoid "ghost builds"
useEffect(() => {
if (authLoading) return;
setBuilds([]);
setError(null);
}, [authLoading, user?.uuid, token]);
}, [authLoading, user?.uuid]);
// Fetch user builds
useEffect(() => {
@@ -75,8 +74,8 @@ export default function VaultPage() {
try {
// IMPORTANT:
// Use api wrapper so Authorization: Bearer <token> is consistently applied.
const res = await api.get("/api/v1/builds/me");
// Use api wrapper which includes credentials (cookies) automatically.
const res = await api.get("/api/builds");
if (!res.ok) {
const text = await res.text().catch(() => "");