feat: add backoffice API client with NEXT_PUBLIC_BACKOFFICE_URL env var

This commit is contained in:
Tiago Yamamoto 2025-12-23 23:56:12 -03:00
parent b7987dead9
commit 35d3032d52
2 changed files with 89 additions and 2 deletions

View file

@ -10,11 +10,18 @@
NEXT_PUBLIC_API_URL=http://localhost:8521
# Backoffice API URL (NestJS backend for Stripe, admin dashboard)
# Examples:
# Local: http://localhost:3001
# Production: https://backoffice.gohorsejobs.com
NEXT_PUBLIC_BACKOFFICE_URL=http://localhost:3001
# Seeder API URL (for admin operations)
NEXT_PUBLIC_SEEDER_API_URL=http://localhost:3001
NEXT_PUBLIC_SEEDER_API_URL=http://localhost:3002
# Scraper API URL (for importing scraped jobs)
NEXT_PUBLIC_SCRAPER_API_URL=http://localhost:3002
NEXT_PUBLIC_SCRAPER_API_URL=http://localhost:3003
# Vercel Analytics (optional)
NEXT_PUBLIC_VERCEL_ANALYTICS=false

View file

@ -462,3 +462,83 @@ export const profileApi = {
return res.json();
}
};
// =============================================================================
// BACKOFFICE API (Stripe, Admin Dashboard, etc.)
// =============================================================================
const BACKOFFICE_URL = process.env.NEXT_PUBLIC_BACKOFFICE_URL || "";
async function backofficeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const token = localStorage.getItem("token");
const headers = {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
...options.headers,
};
const response = await fetch(`${BACKOFFICE_URL}${endpoint}`, {
...options,
headers,
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || `Request failed with status ${response.status}`);
}
if (response.status === 204) {
return {} as T;
}
return response.json();
}
export interface DashboardStats {
totalCompanies: number;
activeSubscriptions: number;
monthlyRevenue: number;
newCompaniesThisMonth: number;
}
export interface RevenueByMonth {
month: string;
revenue: number;
}
export interface SubscriptionsByPlan {
plan: string;
count: number;
}
export interface CheckoutSessionRequest {
priceId: string;
successUrl: string;
cancelUrl: string;
}
export interface CheckoutSessionResponse {
url: string;
sessionId: string;
}
export const backofficeApi = {
// Admin Dashboard
admin: {
getStats: () => backofficeRequest<DashboardStats>("/admin/stats"),
getRevenue: () => backofficeRequest<RevenueByMonth[]>("/admin/revenue"),
getSubscriptionsByPlan: () => backofficeRequest<SubscriptionsByPlan[]>("/admin/subscriptions-by-plan"),
},
// Stripe
stripe: {
createCheckoutSession: (data: CheckoutSessionRequest) =>
backofficeRequest<CheckoutSessionResponse>("/stripe/checkout", {
method: "POST",
body: JSON.stringify(data),
}),
createBillingPortal: (returnUrl: string) =>
backofficeRequest<{ url: string }>("/stripe/portal", {
method: "POST",
body: JSON.stringify({ returnUrl }),
}),
},
};