[SYNC] feat: Add new feature modules with API clients and hooks

- dashboard: api + hooks
- geolocation: api + hooks
- mcp: api + hooks
- payment-terminals: api + hooks
- scanning: api + hooks
- shared/types: api.types.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-01-24 18:13:37 -06:00
parent 3a461cb184
commit 41ae4f195c
11 changed files with 2948 additions and 0 deletions

View File

@ -0,0 +1,152 @@
import { api } from '@services/api/axios-instance';
import type {
Dashboard,
DashboardWidget,
DashboardFilters,
DashboardsResponse,
CreateDashboardDto,
UpdateDashboardDto,
WidgetConfig,
DashboardMetrics,
} from '../../shared/types/api.types';
const BASE_URL = '/api/v1/dashboard';
export const dashboardApi = {
// Get all dashboards with filters
getAll: async (filters?: DashboardFilters): Promise<DashboardsResponse> => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.userId) params.append('userId', filters.userId);
if (filters?.isDefault !== undefined) params.append('isDefault', String(filters.isDefault));
if (filters?.isPublic !== undefined) params.append('isPublic', String(filters.isPublic));
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
if (filters?.sortBy) params.append('sortBy', filters.sortBy);
if (filters?.sortOrder) params.append('sortOrder', filters.sortOrder);
const response = await api.get<DashboardsResponse>(`${BASE_URL}?${params.toString()}`);
return response.data;
},
// Get dashboard by ID
getById: async (id: string): Promise<Dashboard> => {
const response = await api.get<Dashboard>(`${BASE_URL}/${id}`);
return response.data;
},
// Get user's default dashboard
getDefault: async (): Promise<Dashboard> => {
const response = await api.get<Dashboard>(`${BASE_URL}/default`);
return response.data;
},
// Create dashboard
create: async (data: CreateDashboardDto): Promise<Dashboard> => {
const response = await api.post<Dashboard>(BASE_URL, data);
return response.data;
},
// Update dashboard
update: async (id: string, data: UpdateDashboardDto): Promise<Dashboard> => {
const response = await api.patch<Dashboard>(`${BASE_URL}/${id}`, data);
return response.data;
},
// Delete dashboard
delete: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/${id}`);
},
// Duplicate dashboard
duplicate: async (id: string, name: string): Promise<Dashboard> => {
const response = await api.post<Dashboard>(`${BASE_URL}/${id}/duplicate`, { name });
return response.data;
},
// Set as default dashboard
setAsDefault: async (id: string): Promise<Dashboard> => {
const response = await api.patch<Dashboard>(`${BASE_URL}/${id}/default`);
return response.data;
},
// Share dashboard
share: async (id: string, userIds: string[]): Promise<void> => {
await api.post(`${BASE_URL}/${id}/share`, { userIds });
},
// Unshare dashboard
unshare: async (id: string, userIds: string[]): Promise<void> => {
await api.post(`${BASE_URL}/${id}/unshare`, { userIds });
},
// Get dashboard widgets
getWidgets: async (dashboardId: string): Promise<DashboardWidget[]> => {
const response = await api.get<DashboardWidget[]>(`${BASE_URL}/${dashboardId}/widgets`);
return response.data;
},
// Add widget to dashboard
addWidget: async (dashboardId: string, widget: CreateDashboardDto): Promise<DashboardWidget> => {
const response = await api.post<DashboardWidget>(`${BASE_URL}/${dashboardId}/widgets`, widget);
return response.data;
},
// Update widget
updateWidget: async (
dashboardId: string,
widgetId: string,
config: WidgetConfig
): Promise<DashboardWidget> => {
const response = await api.patch<DashboardWidget>(
`${BASE_URL}/${dashboardId}/widgets/${widgetId}`,
config
);
return response.data;
},
// Remove widget from dashboard
removeWidget: async (dashboardId: string, widgetId: string): Promise<void> => {
await api.delete(`${BASE_URL}/${dashboardId}/widgets/${widgetId}`);
},
// Get dashboard metrics
getMetrics: async (dashboardId: string, filters?: any): Promise<DashboardMetrics> => {
const params = new URLSearchParams();
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.period) params.append('period', filters.period);
const response = await api.get<DashboardMetrics>(
`${BASE_URL}/${dashboardId}/metrics?${params.toString()}`
);
return response.data;
},
// Refresh dashboard data
refresh: async (id: string): Promise<Dashboard> => {
const response = await api.post<Dashboard>(`${BASE_URL}/${id}/refresh`);
return response.data;
},
// Export dashboard
export: async (id: string, format: 'json' | 'pdf' | 'png'): Promise<Blob> => {
const response = await api.get(`${BASE_URL}/${id}/export?format=${format}`, {
responseType: 'blob',
});
return response.data;
},
// Import dashboard
import: async (file: File): Promise<Dashboard> => {
const formData = new FormData();
formData.append('file', file);
const response = await api.post<Dashboard>(`${BASE_URL}/import`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
},
};

View File

@ -0,0 +1,234 @@
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
import { dashboardApi } from '../api/dashboard.api';
import type {
Dashboard,
DashboardWidget,
DashboardFilters,
DashboardsResponse,
CreateDashboardDto,
UpdateDashboardDto,
WidgetConfig,
DashboardMetrics,
} from '../../shared/types/api.types';
// Query Keys
export const dashboardKeys = {
all: ['dashboard'] as const,
lists: () => [...dashboardKeys.all, 'list'] as const,
list: (filters: DashboardFilters) => [...dashboardKeys.lists(), filters] as const,
details: () => [...dashboardKeys.all, 'detail'] as const,
detail: (id: string) => [...dashboardKeys.details(), id] as const,
widgets: (id: string) => [...dashboardKeys.detail(id), 'widgets'] as const,
metrics: (id: string) => [...dashboardKeys.detail(id), 'metrics'] as const,
};
// Queries
export const useDashboards = (
filters?: DashboardFilters,
options?: Omit<UseQueryOptions<DashboardsResponse>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: dashboardKeys.list(filters || {}),
queryFn: () => dashboardApi.getAll(filters),
...options,
});
};
export const useDashboard = (
id: string,
options?: Omit<UseQueryOptions<Dashboard>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: dashboardKeys.detail(id),
queryFn: () => dashboardApi.getById(id),
enabled: !!id,
...options,
});
};
export const useDefaultDashboard = (
options?: Omit<UseQueryOptions<Dashboard>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...dashboardKeys.all, 'default'],
queryFn: () => dashboardApi.getDefault(),
...options,
});
};
export const useDashboardWidgets = (
dashboardId: string,
options?: Omit<UseQueryOptions<DashboardWidget[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: dashboardKeys.widgets(dashboardId),
queryFn: () => dashboardApi.getWidgets(dashboardId),
enabled: !!dashboardId,
...options,
});
};
export const useDashboardMetrics = (
dashboardId: string,
filters?: any,
options?: Omit<UseQueryOptions<DashboardMetrics>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...dashboardKeys.metrics(dashboardId), filters],
queryFn: () => dashboardApi.getMetrics(dashboardId, filters),
enabled: !!dashboardId,
...options,
});
};
// Mutations
export const useCreateDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateDashboardDto) => dashboardApi.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
},
});
};
export const useUpdateDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateDashboardDto }) =>
dashboardApi.update(id, data),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(id) });
},
});
};
export const useDeleteDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => dashboardApi.delete(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
},
});
};
export const useDuplicateDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, name }: { id: string; name: string }) => dashboardApi.duplicate(id, name),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
},
});
};
export const useSetAsDefaultDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => dashboardApi.setAsDefault(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
queryClient.invalidateQueries({ queryKey: [...dashboardKeys.all, 'default'] });
},
});
};
export const useShareDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, userIds }: { id: string; userIds: string[] }) =>
dashboardApi.share(id, userIds),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(id) });
},
});
};
export const useUnshareDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, userIds }: { id: string; userIds: string[] }) =>
dashboardApi.unshare(id, userIds),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(id) });
},
});
};
export const useAddWidget = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ dashboardId, widget }: { dashboardId: string; widget: CreateDashboardDto }) =>
dashboardApi.addWidget(dashboardId, widget),
onSuccess: (_, { dashboardId }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.widgets(dashboardId) });
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(dashboardId) });
},
});
};
export const useUpdateWidget = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ dashboardId, widgetId, config }: { dashboardId: string; widgetId: string; config: WidgetConfig }) =>
dashboardApi.updateWidget(dashboardId, widgetId, config),
onSuccess: (_, { dashboardId }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.widgets(dashboardId) });
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(dashboardId) });
},
});
};
export const useRemoveWidget = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ dashboardId, widgetId }: { dashboardId: string; widgetId: string }) =>
dashboardApi.removeWidget(dashboardId, widgetId),
onSuccess: (_, { dashboardId }) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.widgets(dashboardId) });
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(dashboardId) });
},
});
};
export const useRefreshDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => dashboardApi.refresh(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: dashboardKeys.metrics(id) });
},
});
};
export const useExportDashboard = () => {
return useMutation({
mutationFn: ({ id, format }: { id: string; format: 'json' | 'pdf' | 'png' }) =>
dashboardApi.export(id, format),
});
};
export const useImportDashboard = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (file: File) => dashboardApi.import(file),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardKeys.lists() });
},
});
};

View File

@ -0,0 +1,120 @@
import { api } from '@services/api/axios-instance';
import type {
Geolocation,
GeolocationFilters,
GeolocationsResponse,
CreateGeolocationDto,
UpdateGeolocationDto,
GeolocationQuery,
} from '../../shared/types/api.types';
const BASE_URL = '/api/v1/geolocation';
export const geolocationApi = {
// Get all geolocations with filters
getAll: async (filters?: GeolocationFilters): Promise<GeolocationsResponse> => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.countryId) params.append('countryId', filters.countryId);
if (filters?.regionId) params.append('regionId', filters.regionId);
if (filters?.cityId) params.append('cityId', filters.cityId);
if (filters?.postalCode) params.append('postalCode', filters.postalCode);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
if (filters?.sortBy) params.append('sortBy', filters.sortBy);
if (filters?.sortOrder) params.append('sortOrder', filters.sortOrder);
const response = await api.get<GeolocationsResponse>(`${BASE_URL}?${params.toString()}`);
return response.data;
},
// Get geolocation by ID
getById: async (id: string): Promise<Geolocation> => {
const response = await api.get<Geolocation>(`${BASE_URL}/${id}`);
return response.data;
},
// Create geolocation
create: async (data: CreateGeolocationDto): Promise<Geolocation> => {
const response = await api.post<Geolocation>(BASE_URL, data);
return response.data;
},
// Update geolocation
update: async (id: string, data: UpdateGeolocationDto): Promise<Geolocation> => {
const response = await api.patch<Geolocation>(`${BASE_URL}/${id}`, data);
return response.data;
},
// Delete geolocation
delete: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/${id}`);
},
// Geocode address
geocode: async (query: GeolocationQuery): Promise<Geolocation[]> => {
const params = new URLSearchParams();
if (query.address) params.append('address', query.address);
if (query.postalCode) params.append('postalCode', query.postalCode);
if (query.city) params.append('city', query.city);
if (query.country) params.append('country', query.country);
if (query.limit) params.append('limit', String(query.limit));
const response = await api.get<Geolocation[]>(`${BASE_URL}/geocode?${params.toString()}`);
return response.data;
},
// Reverse geocode (coordinates to address)
reverseGeocode: async (latitude: number, longitude: number): Promise<Geolocation> => {
const response = await api.get<Geolocation>(`${BASE_URL}/reverse?lat=${latitude}&lng=${longitude}`);
return response.data;
},
// Get countries
getCountries: async (): Promise<Geolocation[]> => {
const response = await api.get<Geolocation[]>(`${BASE_URL}/countries`);
return response.data;
},
// Get regions/states by country
getRegions: async (countryId: string): Promise<Geolocation[]> => {
const response = await api.get<Geolocation[]>(`${BASE_URL}/countries/${countryId}/regions`);
return response.data;
},
// Get cities by region
getCities: async (regionId: string): Promise<Geolocation[]> => {
const response = await api.get<Geolocation[]>(`${BASE_URL}/regions/${regionId}/cities`);
return response.data;
},
// Validate postal code
validatePostalCode: async (postalCode: string, countryId?: string): Promise<boolean> => {
const params = new URLSearchParams();
params.append('postalCode', postalCode);
if (countryId) params.append('countryId', countryId);
const response = await api.get<boolean>(`${BASE_URL}/validate-postal-code?${params.toString()}`);
return response.data;
},
// Get timezone by coordinates
getTimezone: async (latitude: number, longitude: number): Promise<string> => {
const response = await api.get<string>(`${BASE_URL}/timezone?lat=${latitude}&lng=${longitude}`);
return response.data;
},
// Calculate distance between two points
calculateDistance: async (
fromLat: number,
fromLng: number,
toLat: number,
toLng: number,
unit: 'km' | 'miles' = 'km'
): Promise<number> => {
const response = await api.get<number>(
`${BASE_URL}/distance?fromLat=${fromLat}&fromLng=${fromLng}&toLat=${toLat}&toLng=${toLng}&unit=${unit}`
);
return response.data;
},
};

View File

@ -0,0 +1,177 @@
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
import { geolocationApi } from '../api/geolocation.api';
import type {
Geolocation,
GeolocationFilters,
GeolocationsResponse,
CreateGeolocationDto,
UpdateGeolocationDto,
GeolocationQuery,
} from '../types/api.types';
// Query Keys
export const geolocationKeys = {
all: ['geolocation'] as const,
lists: () => [...geolocationKeys.all, 'list'] as const,
list: (filters: GeolocationFilters) => [...geolocationKeys.lists(), filters] as const,
details: () => [...geolocationKeys.all, 'detail'] as const,
detail: (id: string) => [...geolocationKeys.details(), id] as const,
countries: () => [...geolocationKeys.all, 'countries'] as const,
regions: (countryId: string) => [...geolocationKeys.all, 'regions', countryId] as const,
cities: (regionId: string) => [...geolocationKeys.all, 'cities', regionId] as const,
};
// Queries
export const useGeolocations = (
filters?: GeolocationFilters,
options?: Omit<UseQueryOptions<GeolocationsResponse>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: geolocationKeys.list(filters || {}),
queryFn: () => geolocationApi.getAll(filters),
...options,
});
};
export const useGeolocation = (
id: string,
options?: Omit<UseQueryOptions<Geolocation>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: geolocationKeys.detail(id),
queryFn: () => geolocationApi.getById(id),
enabled: !!id,
...options,
});
};
export const useCountries = (
options?: Omit<UseQueryOptions<Geolocation[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: geolocationKeys.countries(),
queryFn: () => geolocationApi.getCountries(),
...options,
});
};
export const useRegions = (
countryId: string,
options?: Omit<UseQueryOptions<Geolocation[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: geolocationKeys.regions(countryId),
queryFn: () => geolocationApi.getRegions(countryId),
enabled: !!countryId,
...options,
});
};
export const useCities = (
regionId: string,
options?: Omit<UseQueryOptions<Geolocation[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: geolocationKeys.cities(regionId),
queryFn: () => geolocationApi.getCities(regionId),
enabled: !!regionId,
...options,
});
};
export const useGeocode = (
query: GeolocationQuery,
options?: Omit<UseQueryOptions<Geolocation[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...geolocationKeys.all, 'geocode', query],
queryFn: () => geolocationApi.geocode(query),
enabled: !!(query.address || query.postalCode || query.city || query.country),
...options,
});
};
export const useReverseGeocode = (
latitude: number,
longitude: number,
options?: Omit<UseQueryOptions<Geolocation>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...geolocationKeys.all, 'reverse', latitude, longitude],
queryFn: () => geolocationApi.reverseGeocode(latitude, longitude),
enabled: !!(latitude && longitude),
...options,
});
};
export const useTimezone = (
latitude: number,
longitude: number,
options?: Omit<UseQueryOptions<string>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...geolocationKeys.all, 'timezone', latitude, longitude],
queryFn: () => geolocationApi.getTimezone(latitude, longitude),
enabled: !!(latitude && longitude),
...options,
});
};
export const useDistance = (
fromLat: number,
fromLng: number,
toLat: number,
toLng: number,
unit: 'km' | 'miles' = 'km',
options?: Omit<UseQueryOptions<number>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...geolocationKeys.all, 'distance', fromLat, fromLng, toLat, toLng, unit],
queryFn: () => geolocationApi.calculateDistance(fromLat, fromLng, toLat, toLng, unit),
enabled: !!(fromLat && fromLng && toLat && toLng),
...options,
});
};
// Mutations
export const useCreateGeolocation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateGeolocationDto) => geolocationApi.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: geolocationKeys.lists() });
},
});
};
export const useUpdateGeolocation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateGeolocationDto }) =>
geolocationApi.update(id, data),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: geolocationKeys.lists() });
queryClient.invalidateQueries({ queryKey: geolocationKeys.detail(id) });
},
});
};
export const useDeleteGeolocation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => geolocationApi.delete(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: geolocationKeys.lists() });
},
});
};
export const useValidatePostalCode = () => {
return useMutation({
mutationFn: ({ postalCode, countryId }: { postalCode: string; countryId?: string }) =>
geolocationApi.validatePostalCode(postalCode, countryId),
});
};

View File

@ -0,0 +1,277 @@
import { api } from '@services/api/axios-instance';
import type {
McpServer,
McpTool,
McpResource,
McpPrompt,
McpFilters,
McpServersResponse,
CreateMcpServerDto,
UpdateMcpServerDto,
McpServerStatus,
McpExecutionResult,
McpToolCall,
McpResourceAccess,
} from '../../shared/types/api.types';
const BASE_URL = '/api/v1/mcp';
export const mcpApi = {
// Get all MCP servers with filters
getAll: async (filters?: McpFilters): Promise<McpServersResponse> => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.status) params.append('status', filters.status);
if (filters?.protocol) params.append('protocol', filters.protocol);
if (filters?.isConnected !== undefined) params.append('isConnected', String(filters.isConnected));
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
if (filters?.sortBy) params.append('sortBy', filters.sortBy);
if (filters?.sortOrder) params.append('sortOrder', filters.sortOrder);
const response = await api.get<McpServersResponse>(`${BASE_URL}?${params.toString()}`);
return response.data;
},
// Get MCP server by ID
getById: async (id: string): Promise<McpServer> => {
const response = await api.get<McpServer>(`${BASE_URL}/${id}`);
return response.data;
},
// Create MCP server
create: async (data: CreateMcpServerDto): Promise<McpServer> => {
const response = await api.post<McpServer>(BASE_URL, data);
return response.data;
},
// Update MCP server
update: async (id: string, data: UpdateMcpServerDto): Promise<McpServer> => {
const response = await api.patch<McpServer>(`${BASE_URL}/${id}`, data);
return response.data;
},
// Delete MCP server
delete: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/${id}`);
},
// Connect to MCP server
connect: async (id: string): Promise<McpServer> => {
const response = await api.post<McpServer>(`${BASE_URL}/${id}/connect`);
return response.data;
},
// Disconnect from MCP server
disconnect: async (id: string): Promise<McpServer> => {
const response = await api.post<McpServer>(`${BASE_URL}/${id}/disconnect`);
return response.data;
},
// Get server status
getStatus: async (id: string): Promise<McpServerStatus> => {
const response = await api.get<McpServerStatus>(`${BASE_URL}/${id}/status`);
return response.data;
},
// Get available tools for server
getTools: async (serverId: string): Promise<McpTool[]> => {
const response = await api.get<McpTool[]>(`${BASE_URL}/${serverId}/tools`);
return response.data;
},
// Get tool details
getTool: async (serverId: string, toolName: string): Promise<McpTool> => {
const response = await api.get<McpTool>(`${BASE_URL}/${serverId}/tools/${toolName}`);
return response.data;
},
// Execute tool
executeTool: async (
serverId: string,
toolName: string,
args: Record<string, any>
): Promise<McpExecutionResult> => {
const response = await api.post<McpExecutionResult>(
`${BASE_URL}/${serverId}/tools/${toolName}/execute`,
{ args }
);
return response.data;
},
// Get available resources for server
getResources: async (serverId: string): Promise<McpResource[]> => {
const response = await api.get<McpResource[]>(`${BASE_URL}/${serverId}/resources`);
return response.data;
},
// Get resource details
getResource: async (serverId: string, resourceName: string): Promise<McpResource> => {
const response = await api.get<McpResource>(`${BASE_URL}/${serverId}/resources/${resourceName}`);
return response.data;
},
// Read resource content
readResource: async (
serverId: string,
resourceName: string,
uri?: string
): Promise<{ contents: any[] }> => {
const params = new URLSearchParams();
if (uri) params.append('uri', uri);
const response = await api.get<{ contents: any[] }>(
`${BASE_URL}/${serverId}/resources/${resourceName}/read?${params.toString()}`
);
return response.data;
},
// Get available prompts for server
getPrompts: async (serverId: string): Promise<McpPrompt[]> => {
const response = await api.get<McpPrompt[]>(`${BASE_URL}/${serverId}/prompts`);
return response.data;
},
// Get prompt details
getPrompt: async (serverId: string, promptName: string): Promise<McpPrompt> => {
const response = await api.get<McpPrompt>(`${BASE_URL}/${serverId}/prompts/${promptName}`);
return response.data;
},
// Execute prompt
executePrompt: async (
serverId: string,
promptName: string,
args?: Record<string, any>
): Promise<{ messages: any[] }> => {
const response = await api.post<{ messages: any[] }>(
`${BASE_URL}/${serverId}/prompts/${promptName}/execute`,
{ args }
);
return response.data;
},
// Get tool execution history
getToolHistory: async (
serverId: string,
filters?: {
toolName?: string;
startDate?: string;
endDate?: string;
status?: 'success' | 'error';
page?: number;
limit?: number;
}
): Promise<{ executions: McpToolCall[]; total: number }> => {
const params = new URLSearchParams();
if (filters?.toolName) params.append('toolName', filters.toolName);
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.status) params.append('status', filters.status);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
const response = await api.get<{ executions: McpToolCall[]; total: number }>(
`${BASE_URL}/${serverId}/tools/history?${params.toString()}`
);
return response.data;
},
// Get resource access history
getResourceHistory: async (
serverId: string,
filters?: {
resourceName?: string;
startDate?: string;
endDate?: string;
page?: number;
limit?: number;
}
): Promise<{ accesses: McpResourceAccess[]; total: number }> => {
const params = new URLSearchParams();
if (filters?.resourceName) params.append('resourceName', filters.resourceName);
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
const response = await api.get<{ accesses: McpResourceAccess[]; total: number }>(
`${BASE_URL}/${serverId}/resources/history?${params.toString()}`
);
return response.data;
},
// Test server connection
testConnection: async (serverConfig: CreateMcpServerDto): Promise<{ success: boolean; error?: string }> => {
const response = await api.post<{ success: boolean; error?: string }>(
`${BASE_URL}/test-connection`,
serverConfig
);
return response.data;
},
// Get server logs
getLogs: async (
id: string,
filters?: {
startDate?: string;
endDate?: string;
level?: 'error' | 'warn' | 'info' | 'debug';
page?: number;
limit?: number;
}
): Promise<{ logs: any[]; total: number }> => {
const params = new URLSearchParams();
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.level) params.append('level', filters.level);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
const response = await api.get<{ logs: any[]; total: number }>(
`${BASE_URL}/${id}/logs?${params.toString()}`
);
return response.data;
},
// Restart server
restart: async (id: string): Promise<McpServer> => {
const response = await api.post<McpServer>(`${BASE_URL}/${id}/restart`);
return response.data;
},
// Get server metrics
getMetrics: async (id: string): Promise<{
uptime: number;
totalRequests: number;
successfulRequests: number;
failedRequests: number;
averageResponseTime: number;
memoryUsage: number;
cpuUsage: number;
}> => {
const response = await api.get<any>(`${BASE_URL}/${id}/metrics`);
return response.data;
},
// Export server configuration
exportConfig: async (id: string): Promise<Blob> => {
const response = await api.get(`${BASE_URL}/${id}/export`, {
responseType: 'blob',
});
return response.data;
},
// Import server configuration
importConfig: async (file: File): Promise<McpServer> => {
const formData = new FormData();
formData.append('file', file);
const response = await api.post<McpServer>(`${BASE_URL}/import`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
},
};

View File

@ -0,0 +1,363 @@
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
import { mcpApi } from '../api/mcp.api';
import type {
McpServer,
McpTool,
McpResource,
McpPrompt,
McpFilters,
McpServersResponse,
CreateMcpServerDto,
UpdateMcpServerDto,
McpServerStatus,
McpExecutionResult,
McpToolCall,
McpResourceAccess,
} from '../../shared/types/api.types';
// Query Keys
export const mcpKeys = {
all: ['mcp'] as const,
lists: () => [...mcpKeys.all, 'list'] as const,
list: (filters: McpFilters) => [...mcpKeys.lists(), filters] as const,
details: () => [...mcpKeys.all, 'detail'] as const,
detail: (id: string) => [...mcpKeys.details(), id] as const,
status: (id: string) => [...mcpKeys.detail(id), 'status'] as const,
tools: (serverId: string) => [...mcpKeys.detail(serverId), 'tools'] as const,
tool: (serverId: string, toolName: string) =>
[...mcpKeys.tools(serverId), toolName] as const,
resources: (serverId: string) => [...mcpKeys.detail(serverId), 'resources'] as const,
resource: (serverId: string, resourceName: string) =>
[...mcpKeys.resources(serverId), resourceName] as const,
prompts: (serverId: string) => [...mcpKeys.detail(serverId), 'prompts'] as const,
prompt: (serverId: string, promptName: string) =>
[...mcpKeys.prompts(serverId), promptName] as const,
toolHistory: (serverId: string) => [...mcpKeys.detail(serverId), 'toolHistory'] as const,
resourceHistory: (serverId: string) => [...mcpKeys.detail(serverId), 'resourceHistory'] as const,
logs: (id: string) => [...mcpKeys.detail(id), 'logs'] as const,
metrics: (id: string) => [...mcpKeys.detail(id), 'metrics'] as const,
};
// Queries
export const useMcpServers = (
filters?: McpFilters,
options?: Omit<UseQueryOptions<McpServersResponse>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.list(filters || {}),
queryFn: () => mcpApi.getAll(filters),
...options,
});
};
export const useMcpServer = (
id: string,
options?: Omit<UseQueryOptions<McpServer>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.detail(id),
queryFn: () => mcpApi.getById(id),
enabled: !!id,
...options,
});
};
export const useMcpServerStatus = (
id: string,
options?: Omit<UseQueryOptions<McpServerStatus>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.status(id),
queryFn: () => mcpApi.getStatus(id),
enabled: !!id,
...options,
});
};
export const useMcpServerTools = (
serverId: string,
options?: Omit<UseQueryOptions<McpTool[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.tools(serverId),
queryFn: () => mcpApi.getTools(serverId),
enabled: !!serverId,
...options,
});
};
export const useMcpServerTool = (
serverId: string,
toolName: string,
options?: Omit<UseQueryOptions<McpTool>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.tool(serverId, toolName),
queryFn: () => mcpApi.getTool(serverId, toolName),
enabled: !!(serverId && toolName),
...options,
});
};
export const useMcpServerResources = (
serverId: string,
options?: Omit<UseQueryOptions<McpResource[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.resources(serverId),
queryFn: () => mcpApi.getResources(serverId),
enabled: !!serverId,
...options,
});
};
export const useMcpServerResource = (
serverId: string,
resourceName: string,
options?: Omit<UseQueryOptions<McpResource>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.resource(serverId, resourceName),
queryFn: () => mcpApi.getResource(serverId, resourceName),
enabled: !!(serverId && resourceName),
...options,
});
};
export const useMcpServerPrompts = (
serverId: string,
options?: Omit<UseQueryOptions<McpPrompt[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.prompts(serverId),
queryFn: () => mcpApi.getPrompts(serverId),
enabled: !!serverId,
...options,
});
};
export const useMcpServerPrompt = (
serverId: string,
promptName: string,
options?: Omit<UseQueryOptions<McpPrompt>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: mcpKeys.prompt(serverId, promptName),
queryFn: () => mcpApi.getPrompt(serverId, promptName),
enabled: !!(serverId && promptName),
...options,
});
};
export const useMcpToolHistory = (
serverId: string,
filters?: {
toolName?: string;
startDate?: string;
endDate?: string;
status?: 'success' | 'error';
page?: number;
limit?: number;
},
options?: Omit<UseQueryOptions<{ executions: McpToolCall[]; total: number }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...mcpKeys.toolHistory(serverId), filters],
queryFn: () => mcpApi.getToolHistory(serverId, filters),
enabled: !!serverId,
...options,
});
};
export const useMcpResourceHistory = (
serverId: string,
filters?: {
resourceName?: string;
startDate?: string;
endDate?: string;
page?: number;
limit?: number;
},
options?: Omit<UseQueryOptions<{ accesses: McpResourceAccess[]; total: number }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...mcpKeys.resourceHistory(serverId), filters],
queryFn: () => mcpApi.getResourceHistory(serverId, filters),
enabled: !!serverId,
...options,
});
};
export const useMcpServerLogs = (
id: string,
filters?: {
startDate?: string;
endDate?: string;
level?: 'error' | 'warn' | 'info' | 'debug';
page?: number;
limit?: number;
},
options?: Omit<UseQueryOptions<{ logs: any[]; total: number }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...mcpKeys.logs(id), filters],
queryFn: () => mcpApi.getLogs(id, filters),
enabled: !!id,
...options,
});
};
// Mutations
export const useCreateMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateMcpServerDto) => mcpApi.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: mcpKeys.lists() });
},
});
};
export const useUpdateMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateMcpServerDto }) =>
mcpApi.update(id, data),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.lists() });
queryClient.invalidateQueries({ queryKey: mcpKeys.detail(id) });
},
});
};
export const useDeleteMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => mcpApi.delete(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: mcpKeys.lists() });
},
});
};
export const useConnectMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => mcpApi.connect(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.status(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.tools(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.resources(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.prompts(id) });
},
});
};
export const useDisconnectMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => mcpApi.disconnect(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.status(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.tools(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.resources(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.prompts(id) });
},
});
};
export const useExecuteMcpTool = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
serverId,
toolName,
args
}: {
serverId: string;
toolName: string;
args: Record<string, any>;
}) => mcpApi.executeTool(serverId, toolName, args),
onSuccess: (_, { serverId }) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.toolHistory(serverId) });
},
});
};
export const useReadMcpResource = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
serverId,
resourceName,
uri
}: {
serverId: string;
resourceName: string;
uri?: string;
}) => mcpApi.readResource(serverId, resourceName, uri),
onSuccess: (_, { serverId }) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.resourceHistory(serverId) });
},
});
};
export const useExecuteMcpPrompt = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
serverId,
promptName,
args
}: {
serverId: string;
promptName: string;
args?: Record<string, any>;
}) => mcpApi.executePrompt(serverId, promptName, args),
});
};
export const useTestMcpConnection = () => {
return useMutation({
mutationFn: (serverConfig: CreateMcpServerDto) => mcpApi.testConnection(serverConfig),
});
};
export const useRestartMcpServer = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => mcpApi.restart(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: mcpKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: mcpKeys.status(id) });
},
});
};
export const useExportMcpConfig = () => {
return useMutation({
mutationFn: (id: string) => mcpApi.exportConfig(id),
});
};
export const useImportMcpConfig = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (file: File) => mcpApi.importConfig(file),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: mcpKeys.lists() });
},
});
};

View File

@ -0,0 +1,234 @@
import { api } from '@services/api/axios-instance';
import type {
PaymentTerminal,
PaymentTerminalTransaction,
PaymentTerminalFilters,
PaymentTerminalsResponse,
CreatePaymentTerminalDto,
UpdatePaymentTerminalDto,
TerminalStatus,
TransactionStatus,
PaymentMethod,
} from '../../shared/types/api.types';
const BASE_URL = '/api/v1/payment-terminals';
export const paymentTerminalsApi = {
// Get all payment terminals with filters
getAll: async (filters?: PaymentTerminalFilters): Promise<PaymentTerminalsResponse> => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.storeId) params.append('storeId', filters.storeId);
if (filters?.status) params.append('status', filters.status);
if (filters?.terminalType) params.append('terminalType', filters.terminalType);
if (filters?.paymentMethod) params.append('paymentMethod', filters.paymentMethod);
if (filters?.isActive !== undefined) params.append('isActive', String(filters.isActive));
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
if (filters?.sortBy) params.append('sortBy', filters.sortBy);
if (filters?.sortOrder) params.append('sortOrder', filters.sortOrder);
const response = await api.get<PaymentTerminalsResponse>(`${BASE_URL}?${params.toString()}`);
return response.data;
},
// Get payment terminal by ID
getById: async (id: string): Promise<PaymentTerminal> => {
const response = await api.get<PaymentTerminal>(`${BASE_URL}/${id}`);
return response.data;
},
// Create payment terminal
create: async (data: CreatePaymentTerminalDto): Promise<PaymentTerminal> => {
const response = await api.post<PaymentTerminal>(BASE_URL, data);
return response.data;
},
// Update payment terminal
update: async (id: string, data: UpdatePaymentTerminalDto): Promise<PaymentTerminal> => {
const response = await api.patch<PaymentTerminal>(`${BASE_URL}/${id}`, data);
return response.data;
},
// Delete payment terminal
delete: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/${id}`);
},
// Activate terminal
activate: async (id: string): Promise<PaymentTerminal> => {
const response = await api.post<PaymentTerminal>(`${BASE_URL}/${id}/activate`);
return response.data;
},
// Deactivate terminal
deactivate: async (id: string): Promise<PaymentTerminal> => {
const response = await api.post<PaymentTerminal>(`${BASE_URL}/${id}/deactivate`);
return response.data;
},
// Get terminal status
getStatus: async (id: string): Promise<TerminalStatus> => {
const response = await api.get<TerminalStatus>(`${BASE_URL}/${id}/status`);
return response.data;
},
// Get terminal transactions
getTransactions: async (
terminalId: string,
filters?: {
startDate?: string;
endDate?: string;
status?: TransactionStatus;
paymentMethod?: PaymentMethod;
page?: number;
limit?: number;
}
): Promise<{ transactions: PaymentTerminalTransaction[]; total: number }> => {
const params = new URLSearchParams();
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.status) params.append('status', filters.status);
if (filters?.paymentMethod) params.append('paymentMethod', filters.paymentMethod);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
const response = await api.get<{ transactions: PaymentTerminalTransaction[]; total: number }>(
`${BASE_URL}/${terminalId}/transactions?${params.toString()}`
);
return response.data;
},
// Process payment through terminal
processPayment: async (
terminalId: string,
paymentData: {
amount: number;
currency: string;
paymentMethod: PaymentMethod;
reference?: string;
metadata?: Record<string, any>;
}
): Promise<PaymentTerminalTransaction> => {
const response = await api.post<PaymentTerminalTransaction>(
`${BASE_URL}/${terminalId}/process-payment`,
paymentData
);
return response.data;
},
// Refund transaction
refundTransaction: async (
terminalId: string,
transactionId: string,
amount?: number,
reason?: string
): Promise<PaymentTerminalTransaction> => {
const response = await api.post<PaymentTerminalTransaction>(
`${BASE_URL}/${terminalId}/transactions/${transactionId}/refund`,
{ amount, reason }
);
return response.data;
},
// Void transaction
voidTransaction: async (
terminalId: string,
transactionId: string,
reason?: string
): Promise<PaymentTerminalTransaction> => {
const response = await api.post<PaymentTerminalTransaction>(
`${BASE_URL}/${terminalId}/transactions/${transactionId}/void`,
{ reason }
);
return response.data;
},
// Get transaction by ID
getTransaction: async (
terminalId: string,
transactionId: string
): Promise<PaymentTerminalTransaction> => {
const response = await api.get<PaymentTerminalTransaction>(
`${BASE_URL}/${terminalId}/transactions/${transactionId}`
);
return response.data;
},
// Sync terminal with provider
sync: async (id: string): Promise<PaymentTerminal> => {
const response = await api.post<PaymentTerminal>(`${BASE_URL}/${id}/sync`);
return response.data;
},
// Get terminal configuration
getConfig: async (id: string): Promise<any> => {
const response = await api.get<any>(`${BASE_URL}/${id}/config`);
return response.data;
},
// Update terminal configuration
updateConfig: async (id: string, config: any): Promise<PaymentTerminal> => {
const response = await api.patch<PaymentTerminal>(`${BASE_URL}/${id}/config`, config);
return response.data;
},
// Get terminal health check
healthCheck: async (id: string): Promise<{ healthy: boolean; issues: string[] }> => {
const response = await api.get<{ healthy: boolean; issues: string[] }>(
`${BASE_URL}/${id}/health-check`
);
return response.data;
},
// Reboot terminal
reboot: async (id: string): Promise<void> => {
await api.post(`${BASE_URL}/${id}/reboot`);
},
// Get terminal logs
getLogs: async (
id: string,
filters?: {
startDate?: string;
endDate?: string;
level?: 'error' | 'warn' | 'info' | 'debug';
page?: number;
limit?: number;
}
): Promise<{ logs: any[]; total: number }> => {
const params = new URLSearchParams();
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.level) params.append('level', filters.level);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
const response = await api.get<{ logs: any[]; total: number }>(
`${BASE_URL}/${id}/logs?${params.toString()}`
);
return response.data;
},
// Export transactions
exportTransactions: async (
terminalId: string,
format: 'json' | 'csv' | 'pdf',
filters?: {
startDate?: string;
endDate?: string;
status?: TransactionStatus;
}
): Promise<Blob> => {
const params = new URLSearchParams();
params.append('format', format);
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.status) params.append('status', filters.status);
const response = await api.get(`${BASE_URL}/${terminalId}/transactions/export?${params.toString()}`, {
responseType: 'blob',
});
return response.data;
},
};

View File

@ -0,0 +1,331 @@
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
import { paymentTerminalsApi } from '../api/payment-terminals.api';
import type {
PaymentTerminal,
PaymentTerminalTransaction,
PaymentTerminalFilters,
PaymentTerminalsResponse,
CreatePaymentTerminalDto,
UpdatePaymentTerminalDto,
TerminalStatus,
TransactionStatus,
PaymentMethod,
} from '../../shared/types/api.types';
// Query Keys
export const paymentTerminalsKeys = {
all: ['payment-terminals'] as const,
lists: () => [...paymentTerminalsKeys.all, 'list'] as const,
list: (filters: PaymentTerminalFilters) => [...paymentTerminalsKeys.lists(), filters] as const,
details: () => [...paymentTerminalsKeys.all, 'detail'] as const,
detail: (id: string) => [...paymentTerminalsKeys.details(), id] as const,
transactions: (terminalId: string) => [...paymentTerminalsKeys.detail(terminalId), 'transactions'] as const,
transaction: (terminalId: string, transactionId: string) =>
[...paymentTerminalsKeys.transactions(terminalId), transactionId] as const,
status: (id: string) => [...paymentTerminalsKeys.detail(id), 'status'] as const,
config: (id: string) => [...paymentTerminalsKeys.detail(id), 'config'] as const,
logs: (id: string) => [...paymentTerminalsKeys.detail(id), 'logs'] as const,
metrics: (id: string) => [...paymentTerminalsKeys.detail(id), 'metrics'] as const,
};
// Queries
export const usePaymentTerminals = (
filters?: PaymentTerminalFilters,
options?: Omit<UseQueryOptions<PaymentTerminalsResponse>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.list(filters || {}),
queryFn: () => paymentTerminalsApi.getAll(filters),
...options,
});
};
export const usePaymentTerminal = (
id: string,
options?: Omit<UseQueryOptions<PaymentTerminal>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.detail(id),
queryFn: () => paymentTerminalsApi.getById(id),
enabled: !!id,
...options,
});
};
export const usePaymentTerminalTransactions = (
terminalId: string,
filters?: {
startDate?: string;
endDate?: string;
status?: TransactionStatus;
paymentMethod?: PaymentMethod;
page?: number;
limit?: number;
},
options?: Omit<UseQueryOptions<{ transactions: PaymentTerminalTransaction[]; total: number }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...paymentTerminalsKeys.transactions(terminalId), filters],
queryFn: () => paymentTerminalsApi.getTransactions(terminalId, filters),
enabled: !!terminalId,
...options,
});
};
export const usePaymentTerminalTransaction = (
terminalId: string,
transactionId: string,
options?: Omit<UseQueryOptions<PaymentTerminalTransaction>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.transaction(terminalId, transactionId),
queryFn: () => paymentTerminalsApi.getTransaction(terminalId, transactionId),
enabled: !!(terminalId && transactionId),
...options,
});
};
export const usePaymentTerminalStatus = (
id: string,
options?: Omit<UseQueryOptions<TerminalStatus>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.status(id),
queryFn: () => paymentTerminalsApi.getStatus(id),
enabled: !!id,
...options,
});
};
export const usePaymentTerminalConfig = (
id: string,
options?: Omit<UseQueryOptions<any>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.config(id),
queryFn: () => paymentTerminalsApi.getConfig(id),
enabled: !!id,
...options,
});
};
export const usePaymentTerminalHealthCheck = (
id: string,
options?: Omit<UseQueryOptions<{ healthy: boolean; issues: string[] }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...paymentTerminalsKeys.detail(id), 'health'],
queryFn: () => paymentTerminalsApi.healthCheck(id),
enabled: !!id,
...options,
});
};
export const usePaymentTerminalLogs = (
id: string,
filters?: {
startDate?: string;
endDate?: string;
level?: 'error' | 'warn' | 'info' | 'debug';
page?: number;
limit?: number;
},
options?: Omit<UseQueryOptions<{ logs: any[]; total: number }>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: [...paymentTerminalsKeys.logs(id), filters],
queryFn: () => paymentTerminalsApi.getLogs(id, filters),
enabled: !!id,
...options,
});
};
export const usePaymentTerminalMetrics = (
id: string,
options?: Omit<UseQueryOptions<any>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: paymentTerminalsKeys.metrics(id),
queryFn: () => paymentTerminalsApi.getMetrics(id),
enabled: !!id,
...options,
});
};
// Mutations
export const useCreatePaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreatePaymentTerminalDto) => paymentTerminalsApi.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.lists() });
},
});
};
export const useUpdatePaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdatePaymentTerminalDto }) =>
paymentTerminalsApi.update(id, data),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.lists() });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
},
});
};
export const useDeletePaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => paymentTerminalsApi.delete(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.lists() });
},
});
};
export const useActivatePaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => paymentTerminalsApi.activate(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.lists() });
},
});
};
export const useDeactivatePaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => paymentTerminalsApi.deactivate(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.lists() });
},
});
};
export const useProcessPayment = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
terminalId,
paymentData
}: {
terminalId: string;
paymentData: {
amount: number;
currency: string;
paymentMethod: PaymentMethod;
reference?: string;
metadata?: Record<string, any>;
};
}) => paymentTerminalsApi.processPayment(terminalId, paymentData),
onSuccess: (_, { terminalId }) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.transactions(terminalId) });
},
});
};
export const useRefundTransaction = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
terminalId,
transactionId,
amount,
reason
}: {
terminalId: string;
transactionId: string;
amount?: number;
reason?: string;
}) => paymentTerminalsApi.refundTransaction(terminalId, transactionId, amount, reason),
onSuccess: (_, { terminalId }) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.transactions(terminalId) });
},
});
};
export const useVoidTransaction = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
terminalId,
transactionId,
reason
}: {
terminalId: string;
transactionId: string;
reason?: string;
}) => paymentTerminalsApi.voidTransaction(terminalId, transactionId, reason),
onSuccess: (_, { terminalId }) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.transactions(terminalId) });
},
});
};
export const useSyncPaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => paymentTerminalsApi.sync(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.status(id) });
},
});
};
export const useUpdatePaymentTerminalConfig = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, config }: { id: string; config: any }) =>
paymentTerminalsApi.updateConfig(id, config),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.config(id) });
},
});
};
export const useRebootPaymentTerminal = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => paymentTerminalsApi.reboot(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: paymentTerminalsKeys.status(id) });
},
});
};
export const useExportTransactions = () => {
return useMutation({
mutationFn: ({
terminalId,
format,
filters
}: {
terminalId: string;
format: 'json' | 'csv' | 'pdf';
filters?: {
startDate?: string;
endDate?: string;
status?: TransactionStatus;
};
}) => paymentTerminalsApi.exportTransactions(terminalId, format, filters),
});
};

View File

@ -0,0 +1,188 @@
import { api } from '@services/api/axios-instance';
import type {
ScanningSession,
ScanningDevice,
ScanningResult,
ScanningFilters,
ScanningSessionsResponse,
CreateScanningSessionDto,
UpdateScanningSessionDto,
ScanningConfig,
ScanningTemplate,
} from '../../shared/types/api.types';
const BASE_URL = '/api/v1/scanning';
export const scanningApi = {
// Get all scanning sessions with filters
getAll: async (filters?: ScanningFilters): Promise<ScanningSessionsResponse> => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.deviceId) params.append('deviceId', filters.deviceId);
if (filters?.status) params.append('status', filters.status);
if (filters?.userId) params.append('userId', filters.userId);
if (filters?.startDate) params.append('startDate', filters.startDate);
if (filters?.endDate) params.append('endDate', filters.endDate);
if (filters?.page) params.append('page', String(filters.page));
if (filters?.limit) params.append('limit', String(filters.limit));
if (filters?.sortBy) params.append('sortBy', filters.sortBy);
if (filters?.sortOrder) params.append('sortOrder', filters.sortOrder);
const response = await api.get<ScanningSessionsResponse>(`${BASE_URL}?${params.toString()}`);
return response.data;
},
// Get scanning session by ID
getById: async (id: string): Promise<ScanningSession> => {
const response = await api.get<ScanningSession>(`${BASE_URL}/${id}`);
return response.data;
},
// Create scanning session
create: async (data: CreateScanningSessionDto): Promise<ScanningSession> => {
const response = await api.post<ScanningSession>(BASE_URL, data);
return response.data;
},
// Update scanning session
update: async (id: string, data: UpdateScanningSessionDto): Promise<ScanningSession> => {
const response = await api.patch<ScanningSession>(`${BASE_URL}/${id}`, data);
return response.data;
},
// Delete scanning session
delete: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/${id}`);
},
// Start scanning session
start: async (id: string): Promise<ScanningSession> => {
const response = await api.post<ScanningSession>(`${BASE_URL}/${id}/start`);
return response.data;
},
// Pause scanning session
pause: async (id: string): Promise<ScanningSession> => {
const response = await api.post<ScanningSession>(`${BASE_URL}/${id}/pause`);
return response.data;
},
// Resume scanning session
resume: async (id: string): Promise<ScanningSession> => {
const response = await api.post<ScanningSession>(`${BASE_URL}/${id}/resume`);
return response.data;
},
// Stop scanning session
stop: async (id: string): Promise<ScanningSession> => {
const response = await api.post<ScanningSession>(`${BASE_URL}/${id}/stop`);
return response.data;
},
// Get scanning results for session
getResults: async (sessionId: string): Promise<ScanningResult[]> => {
const response = await api.get<ScanningResult[]>(`${BASE_URL}/${sessionId}/results`);
return response.data;
},
// Get scanning devices
getDevices: async (): Promise<ScanningDevice[]> => {
const response = await api.get<ScanningDevice[]>(`${BASE_URL}/devices`);
return response.data;
},
// Get device by ID
getDevice: async (id: string): Promise<ScanningDevice> => {
const response = await api.get<ScanningDevice>(`${BASE_URL}/devices/${id}`);
return response.data;
},
// Register scanning device
registerDevice: async (device: Partial<ScanningDevice>): Promise<ScanningDevice> => {
const response = await api.post<ScanningDevice>(`${BASE_URL}/devices`, device);
return response.data;
},
// Update device
updateDevice: async (id: string, device: Partial<ScanningDevice>): Promise<ScanningDevice> => {
const response = await api.patch<ScanningDevice>(`${BASE_URL}/devices/${id}`, device);
return response.data;
},
// Remove device
removeDevice: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/devices/${id}`);
},
// Get scanning templates
getTemplates: async (): Promise<ScanningTemplate[]> => {
const response = await api.get<ScanningTemplate[]>(`${BASE_URL}/templates`);
return response.data;
},
// Get template by ID
getTemplate: async (id: string): Promise<ScanningTemplate> => {
const response = await api.get<ScanningTemplate>(`${BASE_URL}/templates/${id}`);
return response.data;
},
// Create scanning template
createTemplate: async (template: Partial<ScanningTemplate>): Promise<ScanningTemplate> => {
const response = await api.post<ScanningTemplate>(`${BASE_URL}/templates`, template);
return response.data;
},
// Update template
updateTemplate: async (id: string, template: Partial<ScanningTemplate>): Promise<ScanningTemplate> => {
const response = await api.patch<ScanningTemplate>(`${BASE_URL}/templates/${id}`, template);
return response.data;
},
// Delete template
deleteTemplate: async (id: string): Promise<void> => {
await api.delete(`${BASE_URL}/templates/${id}`);
},
// Get scanning configuration
getConfig: async (): Promise<ScanningConfig> => {
const response = await api.get<ScanningConfig>(`${BASE_URL}/config`);
return response.data;
},
// Update scanning configuration
updateConfig: async (config: Partial<ScanningConfig>): Promise<ScanningConfig> => {
const response = await api.patch<ScanningConfig>(`${BASE_URL}/config`, config);
return response.data;
},
// Export scanning results
exportResults: async (sessionId: string, format: 'json' | 'csv' | 'pdf'): Promise<Blob> => {
const response = await api.get(`${BASE_URL}/${sessionId}/export?format=${format}`, {
responseType: 'blob',
});
return response.data;
},
// Import scanning data
importData: async (file: File, sessionId?: string): Promise<ScanningResult[]> => {
const formData = new FormData();
formData.append('file', file);
if (sessionId) formData.append('sessionId', sessionId);
const response = await api.post<ScanningResult[]>(`${BASE_URL}/import`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
},
// Validate scanned data
validateData: async (data: any, templateId: string): Promise<{ valid: boolean; errors: string[] }> => {
const response = await api.post<{ valid: boolean; errors: string[] }>(
`${BASE_URL}/validate`,
{ data, templateId }
);
return response.data;
},
};

View File

@ -0,0 +1,311 @@
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
import { scanningApi } from '../api/scanning.api';
import type {
ScanningSession,
ScanningDevice,
ScanningResult,
ScanningFilters,
ScanningSessionsResponse,
CreateScanningSessionDto,
UpdateScanningSessionDto,
ScanningConfig,
ScanningTemplate,
DeviceStatus,
ScanningStatus,
} from '../../shared/types/api.types';
// Query Keys
export const scanningKeys = {
all: ['scanning'] as const,
lists: () => [...scanningKeys.all, 'list'] as const,
list: (filters: ScanningFilters) => [...scanningKeys.lists(), filters] as const,
details: () => [...scanningKeys.all, 'detail'] as const,
detail: (id: string) => [...scanningKeys.details(), id] as const,
devices: () => [...scanningKeys.all, 'devices'] as const,
device: (id: string) => [...scanningKeys.devices(), id] as const,
templates: () => [...scanningKeys.all, 'templates'] as const,
template: (id: string) => [...scanningKeys.templates(), id] as const,
results: (sessionId: string) => [...scanningKeys.detail(sessionId), 'results'] as const,
config: () => [...scanningKeys.all, 'config'] as const,
};
// Queries
export const useScanningSessions = (
filters?: ScanningFilters,
options?: Omit<UseQueryOptions<ScanningSessionsResponse>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.list(filters || {}),
queryFn: () => scanningApi.getAll(filters),
...options,
});
};
export const useScanningSession = (
id: string,
options?: Omit<UseQueryOptions<ScanningSession>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.detail(id),
queryFn: () => scanningApi.getById(id),
enabled: !!id,
...options,
});
};
export const useScanningDevices = (
options?: Omit<UseQueryOptions<ScanningDevice[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.devices(),
queryFn: () => scanningApi.getDevices(),
...options,
});
};
export const useScanningDevice = (
id: string,
options?: Omit<UseQueryOptions<ScanningDevice>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.device(id),
queryFn: () => scanningApi.getDevice(id),
enabled: !!id,
...options,
});
};
export const useScanningTemplates = (
options?: Omit<UseQueryOptions<ScanningTemplate[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.templates(),
queryFn: () => scanningApi.getTemplates(),
...options,
});
};
export const useScanningTemplate = (
id: string,
options?: Omit<UseQueryOptions<ScanningTemplate>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.template(id),
queryFn: () => scanningApi.getTemplate(id),
enabled: !!id,
...options,
});
};
export const useScanningResults = (
sessionId: string,
options?: Omit<UseQueryOptions<ScanningResult[]>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.results(sessionId),
queryFn: () => scanningApi.getResults(sessionId),
enabled: !!sessionId,
...options,
});
};
export const useScanningConfig = (
options?: Omit<UseQueryOptions<ScanningConfig>, 'queryKey' | 'queryFn'>
) => {
return useQuery({
queryKey: scanningKeys.config(),
queryFn: () => scanningApi.getConfig(),
...options,
});
};
// Mutations
export const useCreateScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateScanningSessionDto) => scanningApi.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.lists() });
},
});
};
export const useUpdateScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateScanningSessionDto }) =>
scanningApi.update(id, data),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.lists() });
queryClient.invalidateQueries({ queryKey: scanningKeys.detail(id) });
},
});
};
export const useDeleteScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.delete(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.lists() });
},
});
};
export const useStartScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.start(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: scanningKeys.lists() });
},
});
};
export const usePauseScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.pause(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.detail(id) });
},
});
};
export const useResumeScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.resume(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.detail(id) });
},
});
};
export const useStopScanningSession = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.stop(id),
onSuccess: (_, id) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: scanningKeys.results(id) });
},
});
};
export const useRegisterScanningDevice = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (device: Partial<ScanningDevice>) => scanningApi.registerDevice(device),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.devices() });
},
});
};
export const useUpdateScanningDevice = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, device }: { id: string; device: Partial<ScanningDevice> }) =>
scanningApi.updateDevice(id, device),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.devices() });
queryClient.invalidateQueries({ queryKey: scanningKeys.device(id) });
},
});
};
export const useRemoveScanningDevice = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.removeDevice(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.devices() });
},
});
};
export const useCreateScanningTemplate = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (template: Partial<ScanningTemplate>) => scanningApi.createTemplate(template),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.templates() });
},
});
};
export const useUpdateScanningTemplate = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, template }: { id: string; template: Partial<ScanningTemplate> }) =>
scanningApi.updateTemplate(id, template),
onSuccess: (_, { id }) => {
queryClient.invalidateQueries({ queryKey: scanningKeys.templates() });
queryClient.invalidateQueries({ queryKey: scanningKeys.template(id) });
},
});
};
export const useDeleteScanningTemplate = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => scanningApi.deleteTemplate(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.templates() });
},
});
};
export const useUpdateScanningConfig = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (config: Partial<ScanningConfig>) => scanningApi.updateConfig(config),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: scanningKeys.config() });
},
});
};
export const useExportScanningResults = () => {
return useMutation({
mutationFn: ({ sessionId, format }: { sessionId: string; format: 'json' | 'csv' | 'pdf' }) =>
scanningApi.exportResults(sessionId, format),
});
};
export const useImportScanningData = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ file, sessionId }: { file: File; sessionId?: string }) =>
scanningApi.importData(file, sessionId),
onSuccess: (_, { sessionId }) => {
if (sessionId) {
queryClient.invalidateQueries({ queryKey: scanningKeys.results(sessionId) });
}
},
});
};
export const useValidateScanningData = () => {
return useMutation({
mutationFn: ({ data, templateId }: { data: any; templateId: string }) =>
scanningApi.validateData(data, templateId),
});
};

View File

@ -0,0 +1,561 @@
// Geolocation Types
export interface Geolocation {
id: string;
country: string;
countryCode: string;
region?: string;
regionCode?: string;
city?: string;
postalCode?: string;
latitude?: number;
longitude?: number;
timezone?: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface GeolocationFilters {
search?: string;
countryId?: string;
regionId?: string;
cityId?: string;
postalCode?: string;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
export interface GeolocationsResponse {
data: Geolocation[];
total: number;
page: number;
limit: number;
totalPages: number;
}
export interface CreateGeolocationDto {
country: string;
countryCode: string;
region?: string;
regionCode?: string;
city?: string;
postalCode?: string;
latitude?: number;
longitude?: number;
timezone?: string;
}
export interface UpdateGeolocationDto {
country?: string;
countryCode?: string;
region?: string;
regionCode?: string;
city?: string;
postalCode?: string;
latitude?: number;
longitude?: number;
timezone?: string;
isActive?: boolean;
}
export interface GeolocationQuery {
address?: string;
postalCode?: string;
city?: string;
country?: string;
limit?: number;
}
// Dashboard Types
export interface Dashboard {
id: string;
name: string;
description?: string;
userId: string;
isDefault: boolean;
isPublic: boolean;
layout: DashboardLayout;
widgets: DashboardWidget[];
createdAt: string;
updatedAt: string;
}
export interface DashboardLayout {
columns: number;
gap: number;
breakpoints: {
lg: number;
md: number;
sm: number;
xs: number;
};
}
export interface DashboardWidget {
id: string;
dashboardId: string;
type: WidgetType;
title: string;
config: WidgetConfig;
position: {
x: number;
y: number;
w: number;
h: number;
};
createdAt: string;
updatedAt: string;
}
export type WidgetType =
| 'chart'
| 'metric'
| 'table'
| 'list'
| 'calendar'
| 'map'
| 'text'
| 'image'
| 'iframe';
export interface WidgetConfig {
[key: string]: any;
dataSource?: string;
refreshInterval?: number;
filters?: Record<string, any>;
chartType?: 'line' | 'bar' | 'pie' | 'area' | 'scatter';
metricConfig?: {
label: string;
format: string;
showTrend: boolean;
};
}
export interface DashboardFilters {
search?: string;
userId?: string;
isDefault?: boolean;
isPublic?: boolean;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
export interface DashboardsResponse {
data: Dashboard[];
total: number;
page: number;
limit: number;
totalPages: number;
}
export interface CreateDashboardDto {
name: string;
description?: string;
isDefault?: boolean;
isPublic?: boolean;
layout?: DashboardLayout;
}
export interface UpdateDashboardDto {
name?: string;
description?: string;
isDefault?: boolean;
isPublic?: boolean;
layout?: DashboardLayout;
}
export interface DashboardMetrics {
totalWidgets: number;
activeWidgets: number;
lastUpdated: string;
refreshRate: number;
dataPoints: number;
}
// Scanning Types
export interface ScanningSession {
id: string;
name: string;
deviceId: string;
userId: string;
status: ScanningStatus;
templateId?: string;
config: ScanningConfig;
results: ScanningResult[];
startedAt?: string;
pausedAt?: string;
stoppedAt?: string;
createdAt: string;
updatedAt: string;
}
export type ScanningStatus =
| 'idle'
| 'scanning'
| 'paused'
| 'completed'
| 'error'
| 'cancelled';
export interface ScanningDevice {
id: string;
name: string;
type: string;
model: string;
serialNumber?: string;
ipAddress?: string;
port?: number;
protocol: string;
config: Record<string, any>;
status: DeviceStatus;
lastSeen?: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export type DeviceStatus =
| 'online'
| 'offline'
| 'error'
| 'maintenance';
export interface ScanningResult {
id: string;
sessionId: string;
scanIndex: number;
data: Record<string, any>;
isValid: boolean;
errors?: string[];
warnings?: string[];
scannedAt: string;
processedAt?: string;
}
export interface ScanningFilters {
search?: string;
deviceId?: string;
status?: ScanningStatus;
userId?: string;
startDate?: string;
endDate?: string;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
export interface ScanningSessionsResponse {
data: ScanningSession[];
total: number;
page: number;
limit: number;
totalPages: number;
}
export interface CreateScanningSessionDto {
name: string;
deviceId: string;
templateId?: string;
config?: ScanningConfig;
}
export interface UpdateScanningSessionDto {
name?: string;
deviceId?: string;
templateId?: string;
config?: ScanningConfig;
}
export interface ScanningConfig {
scanInterval: number;
batchSize: number;
maxRetries: number;
timeout: number;
validationRules: ValidationRule[];
outputFormat: 'json' | 'xml' | 'csv';
compression: boolean;
}
export interface ValidationRule {
field: string;
type: 'required' | 'format' | 'range' | 'custom';
value?: any;
message: string;
}
export interface ScanningTemplate {
id: string;
name: string;
description?: string;
fields: TemplateField[];
config: ScanningConfig;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface TemplateField {
name: string;
type: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
required: boolean;
validation?: ValidationRule[];
defaultValue?: any;
}
// Payment Terminals Types
export interface PaymentTerminal {
id: string;
name: string;
storeId: string;
terminalType: string;
serialNumber: string;
model: string;
manufacturer: string;
ipAddress?: string;
port?: number;
paymentMethods: PaymentMethod[];
status: TerminalStatus;
isActive: boolean;
config: PaymentTerminalConfig;
lastHeartbeat?: string;
createdAt: string;
updatedAt: string;
}
export type TerminalStatus =
| 'online'
| 'offline'
| 'error'
| 'maintenance'
| 'initializing';
export type PaymentMethod =
| 'credit_card'
| 'debit_card'
| 'cash'
| 'mobile_payment'
| 'bank_transfer'
| 'check'
| 'cryptocurrency';
export interface PaymentTerminalTransaction {
id: string;
terminalId: string;
amount: number;
currency: string;
paymentMethod: PaymentMethod;
status: TransactionStatus;
reference?: string;
authorizationCode?: string;
errorCode?: string;
errorMessage?: string;
metadata?: Record<string, any>;
createdAt: string;
updatedAt: string;
}
export type TransactionStatus =
| 'pending'
| 'approved'
| 'declined'
| 'cancelled'
| 'refunded'
| 'voided'
| 'error';
export interface PaymentTerminalFilters {
search?: string;
storeId?: string;
status?: TerminalStatus;
terminalType?: string;
paymentMethod?: PaymentMethod;
isActive?: boolean;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
export interface PaymentTerminalsResponse {
data: PaymentTerminal[];
total: number;
page: number;
limit: number;
totalPages: number;
}
export interface CreatePaymentTerminalDto {
name: string;
storeId: string;
terminalType: string;
serialNumber: string;
model: string;
manufacturer: string;
ipAddress?: string;
port?: number;
paymentMethods: PaymentMethod[];
config?: PaymentTerminalConfig;
}
export interface UpdatePaymentTerminalDto {
name?: string;
storeId?: string;
terminalType?: string;
model?: string;
manufacturer?: string;
ipAddress?: string;
port?: number;
paymentMethods?: PaymentMethod[];
config?: PaymentTerminalConfig;
isActive?: boolean;
}
export interface PaymentTerminalConfig {
connectionTimeout: number;
responseTimeout: number;
maxRetries: number;
retryDelay: number;
enableLogging: boolean;
logLevel: 'error' | 'warn' | 'info' | 'debug';
customSettings: Record<string, any>;
}
// MCP (Model Context Protocol) Types
export interface McpServer {
id: string;
name: string;
description?: string;
protocol: string;
version: string;
endpoint: string;
config: McpServerConfig;
status: McpServerStatus;
isConnected: boolean;
lastConnectedAt?: string;
tools: McpTool[];
resources: McpResource[];
prompts: McpPrompt[];
createdAt: string;
updatedAt: string;
}
export interface McpServerConfig {
timeout: number;
retries: number;
headers?: Record<string, string>;
auth?: {
type: 'bearer' | 'basic' | 'api_key';
token?: string;
username?: string;
password?: string;
apiKey?: string;
};
customSettings?: Record<string, any>;
}
export interface McpServerStatus {
healthy: boolean;
uptime: number;
version: string;
capabilities: string[];
lastError?: string;
}
export interface McpTool {
name: string;
description: string;
inputSchema: Record<string, any>;
isAsync: boolean;
}
export interface McpResource {
uri: string;
name: string;
description?: string;
mimeType?: string;
}
export interface McpPrompt {
name: string;
description?: string;
arguments?: McpPromptArgument[];
}
export interface McpPromptArgument {
name: string;
description?: string;
required?: boolean;
}
export interface McpFilters {
search?: string;
status?: string;
protocol?: string;
isConnected?: boolean;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
export interface McpServersResponse {
data: McpServer[];
total: number;
page: number;
limit: number;
totalPages: number;
}
export interface CreateMcpServerDto {
name: string;
description?: string;
protocol: string;
version: string;
endpoint: string;
config: McpServerConfig;
}
export interface UpdateMcpServerDto {
name?: string;
description?: string;
protocol?: string;
version?: string;
endpoint?: string;
config?: McpServerConfig;
}
export interface McpExecutionResult {
success: boolean;
result?: any;
error?: string;
executionTime: number;
}
export interface McpToolCall {
id: string;
serverId: string;
toolName: string;
args: Record<string, any>;
status: 'success' | 'error';
result?: any;
error?: string;
executionTime: number;
createdAt: string;
}
export interface McpResourceAccess {
id: string;
serverId: string;
resourceUri: string;
action: 'read' | 'write' | 'delete';
status: 'success' | 'error';
result?: any;
error?: string;
executionTime: number;
createdAt: string;
}