Fix Admin Interface
This commit is contained in:
@@ -28,6 +28,11 @@ import {
|
||||
UpdateStationRequest,
|
||||
} from '../types/admin.types';
|
||||
|
||||
export interface AuditLogsResponse {
|
||||
logs: AdminAuditLog[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
// Admin access verification
|
||||
export const adminApi = {
|
||||
// Verify admin access
|
||||
@@ -56,8 +61,8 @@ export const adminApi = {
|
||||
},
|
||||
|
||||
// Audit logs
|
||||
listAuditLogs: async (): Promise<AdminAuditLog[]> => {
|
||||
const response = await apiClient.get<AdminAuditLog[]>('/admin/audit-logs');
|
||||
listAuditLogs: async (): Promise<AuditLogsResponse> => {
|
||||
const response = await apiClient.get<AuditLogsResponse>('/admin/audit-logs');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
|
||||
@@ -30,11 +30,11 @@ export const makeSchema = z.object({
|
||||
|
||||
export const modelSchema = z.object({
|
||||
name: z.string().min(1, 'Name is required'),
|
||||
makeId: z.string().min(1, 'Select a make'),
|
||||
makeId: z.coerce.string().min(1, 'Select a make'),
|
||||
});
|
||||
|
||||
export const yearSchema = z.object({
|
||||
modelId: z.string().min(1, 'Select a model'),
|
||||
modelId: z.coerce.string().min(1, 'Select a model'),
|
||||
year: z
|
||||
.coerce.number()
|
||||
.int()
|
||||
@@ -44,12 +44,12 @@ export const yearSchema = z.object({
|
||||
|
||||
export const trimSchema = z.object({
|
||||
name: z.string().min(1, 'Name is required'),
|
||||
yearId: z.string().min(1, 'Select a year'),
|
||||
yearId: z.coerce.string().min(1, 'Select a year'),
|
||||
});
|
||||
|
||||
export const engineSchema = z.object({
|
||||
name: z.string().min(1, 'Name is required'),
|
||||
trimId: z.string().min(1, 'Select a trim'),
|
||||
trimId: z.coerce.string().min(1, 'Select a trim'),
|
||||
displacement: z.string().optional(),
|
||||
cylinders: z
|
||||
.preprocess(
|
||||
@@ -96,22 +96,22 @@ export const buildDefaultValues = (
|
||||
case 'models':
|
||||
return {
|
||||
name: (entity as CatalogModel).name,
|
||||
makeId: (entity as CatalogModel).makeId,
|
||||
makeId: String((entity as CatalogModel).makeId),
|
||||
};
|
||||
case 'years':
|
||||
return {
|
||||
modelId: (entity as CatalogYear).modelId,
|
||||
modelId: String((entity as CatalogYear).modelId),
|
||||
year: (entity as CatalogYear).year,
|
||||
};
|
||||
case 'trims':
|
||||
return {
|
||||
name: (entity as CatalogTrim).name,
|
||||
yearId: (entity as CatalogTrim).yearId,
|
||||
yearId: String((entity as CatalogTrim).yearId),
|
||||
};
|
||||
case 'engines':
|
||||
return {
|
||||
name: (entity as CatalogEngine).name,
|
||||
trimId: (entity as CatalogEngine).trimId,
|
||||
trimId: String((entity as CatalogEngine).trimId),
|
||||
displacement: (entity as CatalogEngine).displacement ?? undefined,
|
||||
cylinders: (entity as CatalogEngine).cylinders ?? undefined,
|
||||
fuel_type: (entity as CatalogEngine).fuel_type ?? undefined,
|
||||
@@ -125,22 +125,22 @@ export const buildDefaultValues = (
|
||||
case 'models':
|
||||
return {
|
||||
name: '',
|
||||
makeId: context.make?.id ?? '',
|
||||
makeId: context.make?.id ? String(context.make.id) : '',
|
||||
};
|
||||
case 'years':
|
||||
return {
|
||||
modelId: context.model?.id ?? '',
|
||||
modelId: context.model?.id ? String(context.model.id) : '',
|
||||
year: undefined,
|
||||
};
|
||||
case 'trims':
|
||||
return {
|
||||
name: '',
|
||||
yearId: context.year?.id ?? '',
|
||||
yearId: context.year?.id ? String(context.year.id) : '',
|
||||
};
|
||||
case 'engines':
|
||||
return {
|
||||
name: '',
|
||||
trimId: context.trim?.id ?? '',
|
||||
trimId: context.trim?.id ? String(context.trim.id) : '',
|
||||
displacement: '',
|
||||
fuel_type: '',
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useAuth0 } from '@auth0/auth0-react';
|
||||
import { adminApi } from '../api/admin.api';
|
||||
import { adminApi, AuditLogsResponse } from '../api/admin.api';
|
||||
import { AdminAuditLog } from '../types/admin.types';
|
||||
|
||||
/**
|
||||
@@ -67,11 +67,11 @@ export function useAuditLogStream(
|
||||
|
||||
// Query for fetching audit logs
|
||||
const {
|
||||
data: rawLogs = [],
|
||||
data: auditLogResponse,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
} = useQuery<AuditLogsResponse>({
|
||||
queryKey: ['auditLogs', resourceType, offset, limit],
|
||||
queryFn: async () => {
|
||||
const logs = await adminApi.listAuditLogs();
|
||||
@@ -87,21 +87,29 @@ export function useAuditLogStream(
|
||||
});
|
||||
|
||||
// Filter logs by resource type if specified
|
||||
const rawLogs = auditLogResponse?.logs;
|
||||
const logs = Array.isArray(rawLogs) ? rawLogs : [];
|
||||
const totalFromApi =
|
||||
typeof auditLogResponse?.total === 'number'
|
||||
? auditLogResponse.total
|
||||
: logs.length;
|
||||
|
||||
const filteredLogs = resourceType
|
||||
? rawLogs.filter((log) => log.resourceType === resourceType)
|
||||
: rawLogs;
|
||||
? logs.filter((log) => log.resourceType === resourceType)
|
||||
: logs;
|
||||
|
||||
// Apply pagination
|
||||
const paginatedLogs = filteredLogs.slice(offset, offset + limit);
|
||||
|
||||
// Calculate pagination state
|
||||
const paginationTotal = resourceType ? filteredLogs.length : totalFromApi;
|
||||
const pagination: PaginationState = {
|
||||
offset,
|
||||
limit,
|
||||
total: filteredLogs.length,
|
||||
total: paginationTotal,
|
||||
};
|
||||
|
||||
const hasMore = offset + limit < filteredLogs.length;
|
||||
const hasMore = offset + limit < paginationTotal;
|
||||
|
||||
/**
|
||||
* Navigate to next page
|
||||
|
||||
Reference in New Issue
Block a user