fix admin pages

This commit is contained in:
root
2026-05-17 17:37:13 -04:00
parent 0b73504455
commit 5ea1780134
12 changed files with 42 additions and 53 deletions
@@ -1,8 +1,7 @@
'use client'
import { useEffect, useState } from 'react'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface AdminUser {
id: string
@@ -29,7 +28,7 @@ export default function AdminUsersPage() {
async function fetchAdmins() {
try {
const res = await fetch(`${API_BASE}/admin/admins`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/admins`, {
headers: { Authorization: `Bearer ${getToken()}` },
cache: 'no-store',
})
@@ -50,7 +49,7 @@ export default function AdminUsersPage() {
setCreating(true)
setError(null)
try {
const res = await fetch(`${API_BASE}/admin/admins`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/admins`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` },
body: JSON.stringify(form),
@@ -1,8 +1,7 @@
'use client'
import { useEffect, useState } from 'react'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface AuditLog {
id: string
@@ -30,7 +29,7 @@ export default function AdminAuditLogsPage() {
useEffect(() => {
const token = localStorage.getItem('admin_token') ?? ''
fetch(`${API_BASE}/admin/audit-logs`, {
fetch(`${ADMIN_API_BASE}/admin/audit-logs`, {
headers: { Authorization: `Bearer ${token}` },
cache: 'no-store',
})
@@ -2,8 +2,7 @@
import { useEffect, useState } from 'react'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface Company {
id: string
@@ -216,7 +215,7 @@ export default function AdminBillingPage() {
try {
const params = new URLSearchParams({ pageSize: '50' })
if (status) params.set('status', status)
const res = await fetch(`${API_BASE}/admin/billing?${params}`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/billing?${params}`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
cache: 'no-store',
})
@@ -236,7 +235,7 @@ export default function AdminBillingPage() {
async function downloadInvoicePdf(invoiceId: string, createdAt: string) {
const token = localStorage.getItem('admin_token')
try {
const res = await fetch(`${API_BASE}/admin/billing/invoices/${invoiceId}/pdf`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/billing/invoices/${invoiceId}/pdf`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
})
if (!res.ok) throw new Error('Failed to generate PDF')
@@ -259,7 +258,7 @@ export default function AdminBillingPage() {
setInvoicesLoading(true)
const token = localStorage.getItem('admin_token')
try {
const res = await fetch(`${API_BASE}/admin/billing/${companyId}/invoices?pageSize=50`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/billing/${companyId}/invoices?pageSize=50`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
})
const json = await res.json()
@@ -3,8 +3,7 @@
import { useEffect, useState } from 'react'
import { useParams, useRouter } from 'next/navigation'
import Link from 'next/link'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface CompanyDetail {
id: string
@@ -239,8 +238,8 @@ export default function AdminCompanyDetailPage() {
const headers = { Authorization: `Bearer ${getToken()}` }
try {
const [cRes, aRes] = await Promise.all([
fetch(`${API_BASE}/admin/companies/${id}`, { headers, cache: 'no-store' }),
fetch(`${API_BASE}/admin/audit-logs?entityId=${id}&pageSize=10`, { headers, cache: 'no-store' }),
fetch(`${ADMIN_API_BASE}/admin/companies/${id}`, { headers, cache: 'no-store' }),
fetch(`${ADMIN_API_BASE}/admin/audit-logs?entityId=${id}&pageSize=10`, { headers, cache: 'no-store' }),
])
const cJson = await cRes.json()
const aJson = await aRes.json()
@@ -268,7 +267,7 @@ export default function AdminCompanyDetailPage() {
setSavedMessage(null)
setError(null)
try {
const res = await fetch(`${API_BASE}/admin/companies/${id}`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/companies/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` },
body: JSON.stringify({
@@ -346,7 +345,7 @@ export default function AdminCompanyDetailPage() {
setActioning(true)
setError(null)
try {
const res = await fetch(`${API_BASE}/admin/companies/${id}/status`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/companies/${id}/status`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` },
body: JSON.stringify({ status }),
@@ -364,7 +363,7 @@ export default function AdminCompanyDetailPage() {
async function deleteCompany() {
setActioning(true)
try {
const res = await fetch(`${API_BASE}/admin/companies/${id}`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/companies/${id}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${getToken()}` },
})
@@ -3,8 +3,7 @@
import { useEffect, useState } from 'react'
import Link from 'next/link'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface Company {
id: string
@@ -83,7 +82,7 @@ export default function AdminCompaniesPage() {
async function fetchCompanies() {
const token = localStorage.getItem('admin_token')
try {
const res = await fetch(`${API_BASE}/admin/companies`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/companies`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
cache: 'no-store',
})
@@ -109,7 +108,7 @@ export default function AdminCompaniesPage() {
setActioning(id)
const token = localStorage.getItem('admin_token')
try {
const res = await fetch(`${API_BASE}/admin/companies/${id}/status`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/companies/${id}/status`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) },
body: JSON.stringify({ status }),
@@ -1,8 +1,7 @@
'use client'
import { useCallback, useEffect, useRef, useState } from 'react'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
type ContainerStatus = 'PENDING' | 'CREATING' | 'RUNNING' | 'STOPPED' | 'RESTARTING' | 'REMOVING' | 'ERROR'
@@ -58,7 +57,7 @@ function LogsModal({ companyId, companyName, onClose }: { companyId: string; com
const fetchLogs = useCallback(async (lines: number) => {
setLoading(true)
try {
const res = await fetch(`${API_BASE}/admin/containers/${companyId}/logs?tail=${lines}`, { headers: authHeaders() })
const res = await fetch(`${ADMIN_API_BASE}/admin/containers/${companyId}/logs?tail=${lines}`, { headers: authHeaders() })
const json = await res.json()
setLogs(json.data?.logs ?? '')
} catch {
@@ -127,7 +126,7 @@ export default function ContainersPage() {
const fetchContainers = useCallback(async () => {
try {
const res = await fetch(`${API_BASE}/admin/containers`, { headers: authHeaders() })
const res = await fetch(`${ADMIN_API_BASE}/admin/containers`, { headers: authHeaders() })
const json = await res.json().catch(() => null)
if (!res.ok) {
throw new Error(json?.message ?? 'Failed to load containers.')
@@ -152,7 +151,7 @@ export default function ContainersPage() {
setProvisioning(true)
setProvisionResults(null)
try {
const res = await fetch(`${API_BASE}/admin/containers/provision-all`, { method: 'POST', headers: authHeaders() })
const res = await fetch(`${ADMIN_API_BASE}/admin/containers/provision-all`, { method: 'POST', headers: authHeaders() })
const json = await res.json().catch(() => null)
if (!res.ok) throw new Error(json?.message ?? 'Provisioning failed.')
setProvisionResults(json.data?.results ?? [])
@@ -171,8 +170,8 @@ export default function ContainersPage() {
const method = action === 'remove' ? 'DELETE' : 'POST'
const url =
action === 'remove'
? `${API_BASE}/admin/containers/${companyId}`
: `${API_BASE}/admin/containers/${companyId}/${action}`
? `${ADMIN_API_BASE}/admin/containers/${companyId}`
: `${ADMIN_API_BASE}/admin/containers/${companyId}/${action}`
const res = await fetch(url, { method, headers: authHeaders() })
const json = await res.json().catch(() => null)
if (!res.ok) {
+2 -3
View File
@@ -3,8 +3,7 @@
import { useEffect, useState } from 'react'
import Link from 'next/link'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface Metrics {
totalCompanies: number
@@ -50,7 +49,7 @@ export default function AdminDashboardPage() {
useEffect(() => {
const token = localStorage.getItem('admin_token') ?? ''
fetch(`${API_BASE}/admin/metrics`, {
fetch(`${ADMIN_API_BASE}/admin/metrics`, {
headers: { Authorization: `Bearer ${token}` },
cache: 'no-store',
})
@@ -2,8 +2,7 @@
import { useEffect, useState } from 'react'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface Renter {
id: string
@@ -75,7 +74,7 @@ export default function AdminRentersPage() {
async function fetchRenters() {
try {
const res = await fetch(`${API_BASE}/admin/renters`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/renters`, {
headers: { Authorization: `Bearer ${getToken()}` },
cache: 'no-store',
})
@@ -103,7 +102,7 @@ export default function AdminRentersPage() {
setActioning(id)
try {
const endpoint = isBlocked ? 'unblock' : 'block'
const res = await fetch(`${API_BASE}/admin/renters/${id}/${endpoint}`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/renters/${id}/${endpoint}`, {
method: 'POST',
headers: { Authorization: `Bearer ${getToken()}` },
})
@@ -11,8 +11,7 @@ import {
type MarketplaceLanguage,
} from '@rentaldrivego/types'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
interface Company {
id: string
@@ -187,11 +186,11 @@ export default function AdminSiteConfigPage() {
const token = localStorage.getItem('admin_token')
try {
const [companiesRes, homepageRes] = await Promise.all([
fetch(`${API_BASE}/admin/companies`, {
fetch(`${ADMIN_API_BASE}/admin/companies`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
cache: 'no-store',
}),
fetch(`${API_BASE}/admin/site-config/marketplace-homepage`, {
fetch(`${ADMIN_API_BASE}/admin/site-config/marketplace-homepage`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
cache: 'no-store',
}),
@@ -280,7 +279,7 @@ export default function AdminSiteConfigPage() {
const token = localStorage.getItem('admin_token')
try {
const res = await fetch(`${API_BASE}/admin/site-config/marketplace-homepage`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/site-config/marketplace-homepage`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
+2 -3
View File
@@ -3,8 +3,7 @@
import Link from 'next/link'
import { useState } from 'react'
import PublicShell from '@/components/PublicShell'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
export default function AdminForgotPasswordPage() {
const [email, setEmail] = useState('')
@@ -17,7 +16,7 @@ export default function AdminForgotPasswordPage() {
setLoading(true)
setError(null)
try {
const res = await fetch(`${API_BASE}/admin/auth/forgot-password`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/auth/forgot-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
+2 -3
View File
@@ -4,8 +4,7 @@ import Link from 'next/link'
import { useState, Suspense } from 'react'
import { useSearchParams, useRouter } from 'next/navigation'
import PublicShell from '@/components/PublicShell'
const API_BASE = '/api/v1'
import { ADMIN_API_BASE } from '@/lib/api'
export default function AdminResetPasswordPage() {
return (
@@ -33,7 +32,7 @@ function AdminResetPasswordContent() {
setLoading(true)
setError(null)
try {
const res = await fetch(`${API_BASE}/admin/auth/reset-password`, {
const res = await fetch(`${ADMIN_API_BASE}/admin/auth/reset-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, password }),
+5 -5
View File
@@ -1,10 +1,10 @@
const API_BASE =
(typeof window === 'undefined' ? process.env.API_INTERNAL_URL : '/api/v1')
?? process.env.NEXT_PUBLIC_API_URL
?? 'http://localhost:4000/api/v1'
export const ADMIN_API_BASE =
typeof window === 'undefined'
? (process.env.API_INTERNAL_URL ?? process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:4000/api/v1')
: (process.env.NEXT_PUBLIC_API_URL ?? '/admin/api/v1')
export async function adminFetch<T>(path: string, token?: string): Promise<T> {
const res = await fetch(`${API_BASE}${path}`, {
const res = await fetch(`${ADMIN_API_BASE}${path}`, {
cache: 'no-store',
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
})