feat(moderation-specific): ✨ Add threat level moderation page with API integration, UI components, and navigation updates
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
733b804bd5
commit
46e73d76a8
6 changed files with 1375 additions and 0 deletions
|
|
@ -98,6 +98,7 @@ import {
|
|||
ModerationOverviewPage,
|
||||
ModerationQueuePage,
|
||||
ModerationHistoryPage,
|
||||
ModerationThreatLevelsPage,
|
||||
} from './pages/moderation';
|
||||
|
||||
// Authentication
|
||||
|
|
@ -243,6 +244,7 @@ const AuthenticatedRoutes = () => (
|
|||
<Route path="/moderation" element={<ModerationOverviewPage />} />
|
||||
<Route path="/moderation/queue" element={<ModerationQueuePage />} />
|
||||
<Route path="/moderation/history" element={<ModerationHistoryPage />} />
|
||||
<Route path="/moderation/threat-levels" element={<ModerationThreatLevelsPage />} />
|
||||
|
||||
{/* CATCH-ALL 404 */}
|
||||
<Route path="*" element={
|
||||
|
|
|
|||
|
|
@ -248,6 +248,11 @@ export const NAVIGATION_SECTIONS: NavSection[] = [
|
|||
label: 'History',
|
||||
description: 'Full audit trail of all scored content',
|
||||
},
|
||||
{
|
||||
to: '/moderation/threat-levels',
|
||||
label: 'Threat Levels',
|
||||
description: 'User threat escalation levels and admin overrides',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ import type {
|
|||
ModerationQueueItem,
|
||||
ModerationStats,
|
||||
ModerationHistoryFilters,
|
||||
PaginatedThreatLevels,
|
||||
ThreatLevelFilters,
|
||||
UserThreatLevel,
|
||||
ThreatEscalationEvent,
|
||||
} from './types'
|
||||
|
||||
const MODERATION_API_URL = import.meta.env.VITE_MODERATION_API_URL || '/api/content-moderation'
|
||||
|
|
@ -88,3 +92,58 @@ export async function fetchModerationHistory(
|
|||
if (filters.endDate) { params.set('endDate', filters.endDate) }
|
||||
return moderationRequest<PaginatedModerationQueue>(`/queue/history?${params}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch paginated list of user threat levels with optional filters
|
||||
*/
|
||||
export async function fetchThreatLevels(
|
||||
filters: ThreatLevelFilters,
|
||||
): Promise<PaginatedThreatLevels> {
|
||||
const params = new URLSearchParams()
|
||||
params.set('page', String(filters.page))
|
||||
params.set('limit', String(filters.limit))
|
||||
if (filters.level) { params.set('level', filters.level) }
|
||||
if (filters.minScore !== undefined) { params.set('minScore', String(filters.minScore)) }
|
||||
if (filters.maxScore !== undefined) { params.set('maxScore', String(filters.maxScore)) }
|
||||
return moderationRequest<PaginatedThreatLevels>(`/threat-levels?${params}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single user's threat level record
|
||||
*/
|
||||
export async function fetchThreatLevel(userId: string): Promise<UserThreatLevel> {
|
||||
return moderationRequest<UserThreatLevel>(`/threat-levels/${userId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch escalation history timeline for a user
|
||||
*/
|
||||
export async function fetchEscalationHistory(userId: string): Promise<ThreatEscalationEvent[]> {
|
||||
return moderationRequest<ThreatEscalationEvent[]>(`/threat-levels/${userId}/history`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an admin override to a user's threat level
|
||||
*/
|
||||
export async function applyThreatOverride(
|
||||
userId: string,
|
||||
body: { level: string; adminId: string; notes: string },
|
||||
): Promise<UserThreatLevel> {
|
||||
return moderationRequest<UserThreatLevel>(`/threat-levels/${userId}`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset a user's threat level to SAFE and clear all violation counters
|
||||
*/
|
||||
export async function resetThreatLevel(
|
||||
userId: string,
|
||||
body: { adminId: string; notes: string },
|
||||
): Promise<UserThreatLevel> {
|
||||
return moderationRequest<UserThreatLevel>(`/threat-levels/${userId}/reset`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export { OverviewPage as ModerationOverviewPage } from './overview-page'
|
||||
export { QueuePage as ModerationQueuePage } from './queue-page'
|
||||
export { HistoryPage as ModerationHistoryPage } from './history-page'
|
||||
export { ThreatLevelsPage as ModerationThreatLevelsPage } from './threat-levels-page'
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -87,3 +87,69 @@ export interface ModerationHistoryFilters {
|
|||
startDate?: string
|
||||
endDate?: string
|
||||
}
|
||||
|
||||
// ─── Threat Escalation Types ──────────────────────────────────────────────────
|
||||
|
||||
export type ThreatLevel = 'safe' | 'caution' | 'warning' | 'danger' | 'suspended'
|
||||
|
||||
export type EscalationTrigger =
|
||||
| 'moderation_violation'
|
||||
| 'admin_override'
|
||||
| 'decay'
|
||||
| 'admin_reset'
|
||||
|
||||
export interface UserThreatLevel {
|
||||
id: string
|
||||
userId: string
|
||||
score: number
|
||||
level: ThreatLevel
|
||||
totalViolations: number
|
||||
criticalViolations: number
|
||||
highViolations: number
|
||||
mediumViolations: number
|
||||
lowViolations: number
|
||||
categoryBreakdown: Record<string, number>
|
||||
lastViolationAt: string | null
|
||||
lastEscalationAt: string | null
|
||||
sensitivityMultiplier: number
|
||||
restrictions: {
|
||||
suspended?: boolean
|
||||
rateLimit?: number
|
||||
queueForReview?: boolean
|
||||
}
|
||||
adminOverride: boolean
|
||||
adminOverrideBy: string | null
|
||||
adminOverrideAt: string | null
|
||||
adminNotes: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface ThreatEscalationEvent {
|
||||
id: string
|
||||
userId: string
|
||||
previousLevel: ThreatLevel
|
||||
newLevel: ThreatLevel
|
||||
previousScore: number
|
||||
newScore: number
|
||||
trigger: EscalationTrigger
|
||||
triggerContentScoreId: string | null
|
||||
metadata: Record<string, unknown>
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export interface ThreatLevelFilters {
|
||||
page: number
|
||||
limit: number
|
||||
level?: ThreatLevel | ''
|
||||
minScore?: number
|
||||
maxScore?: number
|
||||
}
|
||||
|
||||
export interface PaginatedThreatLevels {
|
||||
items: UserThreatLevel[]
|
||||
total: number
|
||||
page: number
|
||||
limit: number
|
||||
pages: number
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue