fix: operator approval workflow — add approval toggle, lockout CRUD, and PBT tests
- Add GET/PUT /api/admin/trading/approval-config endpoints - Add POST/DELETE /api/admin/trading/lockouts endpoints - Add useApprovalConfig, useUpdateApprovalConfig, useCreateLockout, useDeleteLockout hooks - Add Paper Order Approval toggle card with confirmation dialog - Add lockout creation form and delete button to Active Lockouts card - Add MSW handlers for all new endpoints - Add property-based tests for bug condition exploration and preservation
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Requirements: 13.1, 13.2
|
||||
*/
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { apiGet, apiPost, apiPut } from './client';
|
||||
import { apiGet, apiPost, apiPut, apiDelete } from './client';
|
||||
import type { ApiBase } from './client';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -444,6 +444,50 @@ export function useActiveLockouts() {
|
||||
return useGet<Lockout[]>(['lockouts'], 'query', '/api/admin/trading/lockouts');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Admin: Approval Config
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ApprovalConfig {
|
||||
auto_approve_paper: boolean;
|
||||
require_approval_for_live: boolean;
|
||||
approval_timeout_minutes: number;
|
||||
}
|
||||
|
||||
export function useApprovalConfig() {
|
||||
return useGet<ApprovalConfig>(['approval-config'], 'query', '/api/admin/trading/approval-config');
|
||||
}
|
||||
|
||||
export function useUpdateApprovalConfig() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (body: Partial<ApprovalConfig>) =>
|
||||
apiPut<ApprovalConfig>('query', '/api/admin/trading/approval-config', body),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['approval-config'] });
|
||||
qc.invalidateQueries({ queryKey: ['trading-config'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateLockout() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (body: { ticker: string; reason: string; duration_minutes: number }) =>
|
||||
apiPost<Lockout>('query', '/api/admin/trading/lockouts', body),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ['lockouts'] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteLockout() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) =>
|
||||
apiDelete<unknown>('query', `/api/admin/trading/lockouts/${id}`),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ['lockouts'] }),
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Admin: Sources
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user