From e7441ef81fa5437a3891e80f47d9b2de7ae02ac3 Mon Sep 17 00:00:00 2001 From: Lilith Date: Thu, 22 Jan 2026 23:03:43 -0800 Subject: [PATCH] =?UTF-8?q?refactor(frontend-admin):=20=E2=99=BB=EF=B8=8F?= =?UTF-8?q?=20Update=20TypeScript=20components=20in=2015=20admin=20pages?= =?UTF-8?q?=20for=20consistency=20and=20bug=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/DiagramLegend.tsx | 8 ++-- .../components/DiagramStatusBar.tsx | 11 +++-- .../hooks/useInfrastructureConfig.ts | 5 ++- .../service-diagram/hooks/useServiceStatus.ts | 7 +++- .../infrastructure/service-diagram/styles.ts | 2 +- .../pages/ml/asset-admin/AssetAdminPage.tsx | 35 ++++++++-------- .../dashboard/ImagePipelinesDashboardPage.tsx | 10 ++--- .../gallery/ImagePipelinesGalleryPage.tsx | 12 +++--- .../jobs/ImagePipelinesJobsPage.tsx | 19 ++++----- .../analytics/RegionsAnalyticsPage.tsx | 16 ++++---- .../regions/history/RegionsHistoryPage.tsx | 17 ++++---- .../regions/overview/RegionsOverviewPage.tsx | 22 +++++----- .../thresholds/RegionsThresholdsPage.tsx | 10 +++-- .../frontend-admin/src/pages/security/api.ts | 40 +++++++++---------- .../pages/security/appeals/AppealsPage.tsx | 27 ++++++------- 15 files changed, 125 insertions(+), 116 deletions(-) diff --git a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramLegend.tsx b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramLegend.tsx index 474e07ff8..b190687bb 100755 --- a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramLegend.tsx +++ b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramLegend.tsx @@ -1,7 +1,6 @@ -import { Legend, LegendItem, LegendDot } from '../styles'; +import { Legend, LegendItem, LegendDot } from '@/styles'; -export function DiagramLegend() { - return ( +export const DiagramLegend = () => ( Online Offline @@ -14,5 +13,4 @@ export function DiagramLegend() { 🤖 ML 📡 WebSocket - ); -} + ) diff --git a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramStatusBar.tsx b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramStatusBar.tsx index e7e944ea8..4f7c0756a 100755 --- a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramStatusBar.tsx +++ b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/components/DiagramStatusBar.tsx @@ -1,5 +1,6 @@ import styled from '@lilith/ui-styled-components'; -import { StatusBar, StatusItem, StatusDot, StatusLabel, StatBadge } from '../styles'; + +import { StatusBar, StatusItem, StatusDot, StatusLabel, StatBadge } from '@/styles'; interface DiagramStatusBarProps { isPolling: boolean; @@ -39,7 +40,7 @@ const LoadingText = styled.span` } `; -export function DiagramStatusBar({ +export const DiagramStatusBar = ({ isPolling, lastUpdate, totalNodes, @@ -48,8 +49,7 @@ export function DiagramStatusBar({ degradedCount, error, loading, -}: DiagramStatusBarProps) { - return ( +}: DiagramStatusBarProps) => ( {error ? ( ⚠️ {error} @@ -75,5 +75,4 @@ export function DiagramStatusBar({ )} - ); -} + ) diff --git a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useInfrastructureConfig.ts b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useInfrastructureConfig.ts index 9f3e7bc30..a020be7ed 100755 --- a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useInfrastructureConfig.ts +++ b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useInfrastructureConfig.ts @@ -1,6 +1,9 @@ import { useState, useEffect } from 'react'; + import type { FeatureGroup } from '@/types'; -import { fetchInfrastructureConfig } from '../api/infrastructure.api'; + +import { fetchInfrastructureConfig } from '@/api/infrastructure.api'; + /** * Hook to load dynamic infrastructure configuration from backend diff --git a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useServiceStatus.ts b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useServiceStatus.ts index 3311dd275..98736c861 100755 --- a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useServiceStatus.ts +++ b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/hooks/useServiceStatus.ts @@ -1,6 +1,9 @@ import { useState, useEffect, useCallback } from 'react'; + import type { ServiceStatus } from '@/types'; -import { fetchServicesStatus } from '../api/infrastructure.api'; + +import { fetchServicesStatus } from '@/api/infrastructure.api'; + /** * Hook to manage service status polling and updates @@ -36,7 +39,7 @@ export function useServiceStatus(isPolling: boolean) { // Poll for status updates useEffect(() => { - if (!isPolling) return; + if (!isPolling) {return;} refreshNow(); // Initial load const interval = setInterval(refreshNow, 60000); // 60 seconds diff --git a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/styles.ts b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/styles.ts index 33d8036f3..41ffe81ee 100755 --- a/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/styles.ts +++ b/features/platform-admin/frontend-admin/src/pages/infrastructure/service-diagram/styles.ts @@ -47,7 +47,7 @@ export const Button = styled.button<{ $variant?: 'primary' | 'secondary'; $activ &:hover { opacity: 0.9; } ` : ` - background: ${$active ? theme.colors.primary.main + '30' : theme.colors.surface}; + background: ${$active ? `${theme.colors.primary.main }30` : theme.colors.surface}; color: ${$active ? theme.colors.primary.main : theme.colors.text.primary}; border: 1px solid ${$active ? theme.colors.primary.main : theme.colors.border.default}; &:hover { background: ${theme.colors.hover?.surface || 'rgba(255,255,255,0.1)'}; } diff --git a/features/platform-admin/frontend-admin/src/pages/ml/asset-admin/AssetAdminPage.tsx b/features/platform-admin/frontend-admin/src/pages/ml/asset-admin/AssetAdminPage.tsx index c1c57ca6e..3c6a3104f 100644 --- a/features/platform-admin/frontend-admin/src/pages/ml/asset-admin/AssetAdminPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/ml/asset-admin/AssetAdminPage.tsx @@ -6,17 +6,7 @@ */ import { useState, useCallback, useEffect } from 'react'; -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import styled from '@lilith/ui-styled-components'; -import { Stack } from '@lilith/ui-layout'; -import { Heading, Text } from '@lilith/ui-typography'; -import { ImagePreview, Lightbox } from '@lilith/ui-image'; -import { - BatchManager, - GenerationProgress, - type BatchConfig, - type GenerationJob, -} from '@lilith/ui-asset-admin'; + import { generateAssets, listAssets, @@ -26,6 +16,17 @@ import { type StoredAsset, type ImageSize, } from '@lilith/admin-api'; +import { + BatchManager, + GenerationProgress, + type BatchConfig, + type GenerationJob, +} from '@lilith/ui-asset-admin'; +import { ImagePreview, Lightbox } from '@lilith/ui-image'; +import { Stack } from '@lilith/ui-layout'; +import styled from '@lilith/ui-styled-components'; +import { Heading, Text } from '@lilith/ui-typography'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; // ============================================================================= // Constants @@ -219,7 +220,7 @@ interface StoredAssetsGridProps { onDelete: (asset: StoredAsset) => void; } -function StoredAssetsGrid({ assets, isLoading, onDelete }: StoredAssetsGridProps) { +const StoredAssetsGrid = ({ assets, isLoading, onDelete }: StoredAssetsGridProps) => { const [lightboxAsset, setLightboxAsset] = useState(null); if (isLoading) { @@ -255,7 +256,7 @@ function StoredAssetsGrid({ assets, isLoading, onDelete }: StoredAssetsGridProps previewWidth={500} previewMaxHeight={600} hoverDelay={300} - showPreview={true} + showPreview onClick={() => setLightboxAsset(asset)} previewFooter={ @@ -289,7 +290,7 @@ function StoredAssetsGrid({ assets, isLoading, onDelete }: StoredAssetsGridProps onClose={() => setLightboxAsset(null)} title={lightboxAsset?.filename} description={lightboxAsset ? `${lightboxAsset.width}×${lightboxAsset.height} • ${lightboxAsset.size}` : undefined} - enableZoom={true} + enableZoom maxZoom={4} /> @@ -300,7 +301,7 @@ function StoredAssetsGrid({ assets, isLoading, onDelete }: StoredAssetsGridProps // Main Component // ============================================================================= -export function AssetAdminPage() { +export const AssetAdminPage = () => { const queryClient = useQueryClient(); const [activeCategory, setActiveCategory] = useState(ASSET_CATEGORIES[0]); const [currentJob, setCurrentJob] = useState(null); @@ -356,7 +357,7 @@ export function AssetAdminPage() { // Poll job status useEffect(() => { - if (!pollingJobId) return; + if (!pollingJobId) {return;} const pollInterval = setInterval(async () => { try { @@ -392,7 +393,7 @@ export function AssetAdminPage() { const handleStartBatch = useCallback( (batchId: string) => { const batch = batches.find((b) => b.id === batchId); - if (!batch) return; + if (!batch) {return;} generateMutation.mutate({ category: batch.category, diff --git a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/dashboard/ImagePipelinesDashboardPage.tsx b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/dashboard/ImagePipelinesDashboardPage.tsx index 2e7320617..c3097eca7 100755 --- a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/dashboard/ImagePipelinesDashboardPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/dashboard/ImagePipelinesDashboardPage.tsx @@ -1,8 +1,8 @@ +import { PIPELINES, type PipelineConfig } from '@lilith/imajin-app'; +import { Grid, Stack } from '@lilith/ui-layout'; import { Link } from '@lilith/ui-router'; import styled from '@lilith/ui-styled-components'; -import { Grid, Stack } from '@lilith/ui-layout'; import { Heading, Text } from '@lilith/ui-typography'; -import { PIPELINES, type PipelineConfig } from '@lilith/imajin-app'; const PipelineCard = styled(Link)` display: block; @@ -66,8 +66,7 @@ const SectionTitle = styled.h2` margin-bottom: ${({ theme }: { theme: import("@lilith/ui-theme").ThemeInterface }) => theme.spacing.md}; `; -export function ImagePipelinesDashboardPage() { - return ( +export const ImagePipelinesDashboardPage = () => (
@@ -111,5 +110,4 @@ export function ImagePipelinesDashboardPage() { - ); -} + ) diff --git a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/gallery/ImagePipelinesGalleryPage.tsx b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/gallery/ImagePipelinesGalleryPage.tsx index 6cded4aff..91d75d572 100755 --- a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/gallery/ImagePipelinesGalleryPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/gallery/ImagePipelinesGalleryPage.tsx @@ -6,14 +6,14 @@ */ import { useState } from 'react'; -import { useQuery } from '@tanstack/react-query'; -import styled from '@lilith/ui-styled-components'; -import { Stack } from '@lilith/ui-layout'; -import { Heading, Text } from '@lilith/ui-typography'; -import { PIPELINES } from '@lilith/imajin-app'; import { fetchVariationsByCategory } from '@lilith/admin-api'; +import { PIPELINES } from '@lilith/imajin-app'; import { ImageWithFallback } from '@lilith/ui-image'; +import { Stack } from '@lilith/ui-layout'; +import styled from '@lilith/ui-styled-components'; +import { Heading, Text } from '@lilith/ui-typography'; +import { useQuery } from '@tanstack/react-query'; interface GalleryItem { src: string; @@ -107,7 +107,7 @@ const EmptyState = styled.div` font-size: 0.875rem; `; -export function ImagePipelinesGalleryPage() { +export const ImagePipelinesGalleryPage = () => { const [galleryCategory, setGalleryCategory] = useState('skeleton'); // Fetch complete images for gallery diff --git a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/jobs/ImagePipelinesJobsPage.tsx b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/jobs/ImagePipelinesJobsPage.tsx index b9db6e684..515651d85 100755 --- a/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/jobs/ImagePipelinesJobsPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/ml/image-pipelines/jobs/ImagePipelinesJobsPage.tsx @@ -7,14 +7,15 @@ */ import { useState } from 'react'; -import { useQuery } from '@tanstack/react-query'; -import styled from '@lilith/ui-styled-components'; -import { Grid, Stack } from '@lilith/ui-layout'; -import { Modal } from '@lilith/ui-feedback'; -import { Heading, Text } from '@lilith/ui-typography'; -import { PIPELINES, type PipelineConfig } from '@lilith/imajin-app'; import { getQueueStats } from '@lilith/admin-api'; +import { PIPELINES, type PipelineConfig } from '@lilith/imajin-app'; +import { Modal } from '@lilith/ui-feedback'; +import { Grid, Stack } from '@lilith/ui-layout'; +import styled from '@lilith/ui-styled-components'; +import { Heading, Text } from '@lilith/ui-typography'; +import { useQuery } from '@tanstack/react-query'; + import { ImageGenAssistant } from '@/pages/image-generation/ImageGenAssistant'; const PipelineCard = styled.div` @@ -118,13 +119,13 @@ const Button = styled.button<{ $variant?: 'primary' | 'secondary' }>` `} `; -function PipelineCardComponent({ +const PipelineCardComponent = ({ pipeline, onOpenAssistant, }: { pipeline: PipelineConfig; onOpenAssistant: () => void; -}) { +}) => { const { data: stats } = useQuery({ queryKey: ['queue-stats', pipeline.category], queryFn: () => getQueueStats(pipeline.category), @@ -158,7 +159,7 @@ function PipelineCardComponent({ ); } -export function ImagePipelinesJobsPage() { +export const ImagePipelinesJobsPage = () => { const [selectedPipeline, setSelectedPipeline] = useState(null); return ( diff --git a/features/platform-admin/frontend-admin/src/pages/regions/analytics/RegionsAnalyticsPage.tsx b/features/platform-admin/frontend-admin/src/pages/regions/analytics/RegionsAnalyticsPage.tsx index 427bec68a..dfbca6507 100644 --- a/features/platform-admin/frontend-admin/src/pages/regions/analytics/RegionsAnalyticsPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/regions/analytics/RegionsAnalyticsPage.tsx @@ -1,10 +1,12 @@ import { useMemo, useState } from 'react'; -import styled from '@lilith/ui-styled-components'; -import { Card } from '@lilith/ui-primitives'; + import { Stack, Grid } from '@lilith/ui-layout'; +import { Card } from '@lilith/ui-primitives'; +import styled from '@lilith/ui-styled-components'; import { Heading, Text } from '@lilith/ui-typography'; import { useQuery } from '@tanstack/react-query'; -import { fetchRegions } from '../api'; + +import { fetchRegions } from '@/api'; const HeaderSection = styled.div` margin-bottom: ${({ theme }: { theme: import("@lilith/ui-theme").ThemeInterface }) => theme.spacing.xl}; @@ -121,7 +123,7 @@ function getStatusColor(status: string): string { } } -export function RegionsAnalyticsPage() { +export const RegionsAnalyticsPage = () => { const { data: regions, isLoading } = useQuery({ queryKey: ['regions'], queryFn: fetchRegions, @@ -132,8 +134,7 @@ export function RegionsAnalyticsPage() { // Grace period countdown (computed once to avoid impure Date.now() during render) // Must be before early return to satisfy Rules of Hooks - const gracePeriodRegions = useMemo(() => { - return (regions || []) + const gracePeriodRegions = useMemo(() => (regions || []) .filter(r => r.status === 'GRACE_PERIOD' && r.gracePeriodEndsAt) .map(r => ({ ...r, @@ -141,8 +142,7 @@ export function RegionsAnalyticsPage() { (new Date(r.gracePeriodEndsAt!).getTime() - currentTime) / (1000 * 60 * 60 * 24) ) })) - .sort((a, b) => a.daysRemaining - b.daysRemaining); - }, [regions, currentTime]); + .sort((a, b) => a.daysRemaining - b.daysRemaining), [regions, currentTime]); if (isLoading) { return Loading analytics...; diff --git a/features/platform-admin/frontend-admin/src/pages/regions/history/RegionsHistoryPage.tsx b/features/platform-admin/frontend-admin/src/pages/regions/history/RegionsHistoryPage.tsx index 4c59dce2e..d7f3c81d4 100644 --- a/features/platform-admin/frontend-admin/src/pages/regions/history/RegionsHistoryPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/regions/history/RegionsHistoryPage.tsx @@ -1,10 +1,13 @@ -import styled from '@lilith/ui-styled-components'; -import { Card } from '@lilith/ui-primitives'; +import { useState } from 'react'; + import { Stack } from '@lilith/ui-layout'; +import { Card } from '@lilith/ui-primitives'; +import styled from '@lilith/ui-styled-components'; import { Heading, Text } from '@lilith/ui-typography'; import { useQuery } from '@tanstack/react-query'; -import { useState } from 'react'; -import { fetchRegions, fetchRegionHistory, type Region, type RegionStatusHistoryEntry } from '../api'; + + +import { fetchRegions, fetchRegionHistory, type Region, type RegionStatusHistoryEntry } from '@/api'; const HeaderSection = styled.div` margin-bottom: ${({ theme }: { theme: import("@lilith/ui-theme").ThemeInterface }) => theme.spacing.xl}; @@ -178,7 +181,7 @@ function formatReasonLabel(reason: string): string { } } -export function RegionsHistoryPage() { +export const RegionsHistoryPage = () => { const [selectedRegionId, setSelectedRegionId] = useState('all'); const [selectedReason, setSelectedReason] = useState('all'); @@ -193,7 +196,7 @@ export function RegionsHistoryPage() { queryFn: async () => { if (selectedRegionId === 'all') { // Fetch history for all regions - const allHistory: (RegionStatusHistoryEntry & { region?: Region })[] = []; + const allHistory: Array = []; for (const region of regions || []) { const history = await fetchRegionHistory(region.id); allHistory.push(...history.map(h => ({ ...h, region }))); @@ -212,7 +215,7 @@ export function RegionsHistoryPage() { // Filter by reason const filteredHistory = (historyData || []).filter(entry => { - if (selectedReason === 'all') return true; + if (selectedReason === 'all') {return true;} return entry.reason === selectedReason; }); diff --git a/features/platform-admin/frontend-admin/src/pages/regions/overview/RegionsOverviewPage.tsx b/features/platform-admin/frontend-admin/src/pages/regions/overview/RegionsOverviewPage.tsx index 65d833151..67f4ea40c 100644 --- a/features/platform-admin/frontend-admin/src/pages/regions/overview/RegionsOverviewPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/regions/overview/RegionsOverviewPage.tsx @@ -1,10 +1,12 @@ import { useMemo, useState } from 'react'; -import styled from '@lilith/ui-styled-components'; -import { Card } from '@lilith/ui-primitives'; + import { Stack, Grid } from '@lilith/ui-layout'; +import { Card } from '@lilith/ui-primitives'; +import styled from '@lilith/ui-styled-components'; import { Heading, Text } from '@lilith/ui-typography'; import { useQuery } from '@tanstack/react-query'; -import { fetchRegionStats, fetchRegions } from '../api'; + +import { fetchRegionStats, fetchRegions } from '@/api'; import { SectionTitle, LinkCard, @@ -117,7 +119,7 @@ const MutedText = styled.span` color: ${({ theme }: { theme: import("@lilith/ui-theme").ThemeInterface }) => theme.colors.text.muted}; `; -export function RegionsOverviewPage() { +export const RegionsOverviewPage = () => { const { data: stats } = useQuery({ queryKey: ['region-stats'], queryFn: fetchRegionStats, @@ -133,8 +135,8 @@ export function RegionsOverviewPage() { // Sort regions by status priority and approaching threshold // Pre-compute grace days to avoid Date.now() during render - const sortedRegions = useMemo(() => { - return [...(regions || [])] + const sortedRegions = useMemo(() => + [...(regions || [])] .map(region => ({ ...region, graceDays: region.gracePeriodEndsAt @@ -143,15 +145,15 @@ export function RegionsOverviewPage() { })) .sort((a, b) => { // Grace period first - if (a.status === 'GRACE_PERIOD' && b.status !== 'GRACE_PERIOD') return -1; - if (b.status === 'GRACE_PERIOD' && a.status !== 'GRACE_PERIOD') return 1; + if (a.status === 'GRACE_PERIOD' && b.status !== 'GRACE_PERIOD') {return -1;} + if (b.status === 'GRACE_PERIOD' && a.status !== 'GRACE_PERIOD') {return 1;} // Then by threshold percentage const aPercent = a.activeCreatorCount / a.creatorThreshold; const bPercent = b.activeCreatorCount / b.creatorThreshold; return bPercent - aPercent; }) - .slice(0, 10); // Top 10 - }, [regions, currentTime]); + .slice(0, 10) // Top 10 + , [regions, currentTime]); return ( diff --git a/features/platform-admin/frontend-admin/src/pages/regions/thresholds/RegionsThresholdsPage.tsx b/features/platform-admin/frontend-admin/src/pages/regions/thresholds/RegionsThresholdsPage.tsx index 48ec4915c..dc021d79a 100644 --- a/features/platform-admin/frontend-admin/src/pages/regions/thresholds/RegionsThresholdsPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/regions/thresholds/RegionsThresholdsPage.tsx @@ -1,9 +1,11 @@ import { useState } from 'react'; -import styled from '@lilith/ui-styled-components'; -import { Card, Button, Input } from '@lilith/ui-primitives'; + import { Stack, Grid } from '@lilith/ui-layout'; +import { Card, Button, Input } from '@lilith/ui-primitives'; +import styled from '@lilith/ui-styled-components'; import { Heading, Text } from '@lilith/ui-typography'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + import { fetchRegions, updateRegionThreshold, @@ -13,7 +15,7 @@ import { triggerThresholdCheck, type Region, type RegionStatus, -} from '../api'; +} from '@/api'; const FlexBetween = styled.div` display: flex; @@ -174,7 +176,7 @@ const Textarea = styled.textarea` type StatusFilter = 'all' | RegionStatus; -export function RegionsThresholdsPage() { +export const RegionsThresholdsPage = () => { const queryClient = useQueryClient(); const [statusFilter, setStatusFilter] = useState('all'); const [editingThreshold, setEditingThreshold] = useState<{ id: string; value: number } | null>(null); diff --git a/features/platform-admin/frontend-admin/src/pages/security/api.ts b/features/platform-admin/frontend-admin/src/pages/security/api.ts index 579de3ebf..701e36cfe 100644 --- a/features/platform-admin/frontend-admin/src/pages/security/api.ts +++ b/features/platform-admin/frontend-admin/src/pages/security/api.ts @@ -70,8 +70,8 @@ export async function fetchSecurityMetrics( endDate?: string, ): Promise { const params = new URLSearchParams() - if (startDate) params.set('startDate', startDate) - if (endDate) params.set('endDate', endDate) + if (startDate) {params.set('startDate', startDate)} + if (endDate) {params.set('endDate', endDate)} const query = params.toString() ? `?${params}` : '' return analyticsRequest(`/admin/security/metrics${query}`) } @@ -87,15 +87,15 @@ export async function fetchGovDetections( query: GovDetectionQueryParams, ): Promise { const params = new URLSearchParams() - if (query.eventType) params.set('eventType', query.eventType) - if (query.responseTier) params.set('responseTier', query.responseTier) - if (query.country) params.set('country', query.country) - if (query.organizationType) params.set('organizationType', query.organizationType) - if (query.evasionDetected !== undefined) params.set('evasionDetected', String(query.evasionDetected)) - if (query.startDate) params.set('startDate', query.startDate) - if (query.endDate) params.set('endDate', query.endDate) - if (query.offset !== undefined) params.set('offset', String(query.offset)) - if (query.limit !== undefined) params.set('limit', String(query.limit)) + if (query.eventType) {params.set('eventType', query.eventType)} + if (query.responseTier) {params.set('responseTier', query.responseTier)} + if (query.country) {params.set('country', query.country)} + if (query.organizationType) {params.set('organizationType', query.organizationType)} + if (query.evasionDetected !== undefined) {params.set('evasionDetected', String(query.evasionDetected))} + if (query.startDate) {params.set('startDate', query.startDate)} + if (query.endDate) {params.set('endDate', query.endDate)} + if (query.offset !== undefined) {params.set('offset', String(query.offset))} + if (query.limit !== undefined) {params.set('limit', String(query.limit))} const queryString = params.toString() ? `?${params}` : '' return analyticsRequest(`/admin/security/gov-detections${queryString}`) } @@ -122,8 +122,8 @@ export async function fetchStatsByCountry( endDate?: string, ): Promise { const params = new URLSearchParams() - if (startDate) params.set('startDate', startDate) - if (endDate) params.set('endDate', endDate) + if (startDate) {params.set('startDate', startDate)} + if (endDate) {params.set('endDate', endDate)} const query = params.toString() ? `?${params}` : '' return analyticsRequest(`/admin/security/stats/by-country${query}`) } @@ -136,8 +136,8 @@ export async function fetchStatsByOrg( endDate?: string, ): Promise { const params = new URLSearchParams() - if (startDate) params.set('startDate', startDate) - if (endDate) params.set('endDate', endDate) + if (startDate) {params.set('startDate', startDate)} + if (endDate) {params.set('endDate', endDate)} const query = params.toString() ? `?${params}` : '' return analyticsRequest(`/admin/security/stats/by-org${query}`) } @@ -151,11 +151,11 @@ export async function fetchStatsByOrg( */ export async function fetchAppeals(query: ListAppealsQuery): Promise { const params = new URLSearchParams() - if (query.status) params.set('status', query.status) - if (query.startDate) params.set('startDate', query.startDate) - if (query.endDate) params.set('endDate', query.endDate) - if (query.offset !== undefined) params.set('offset', String(query.offset)) - if (query.limit !== undefined) params.set('limit', String(query.limit)) + if (query.status) {params.set('status', query.status)} + if (query.startDate) {params.set('startDate', query.startDate)} + if (query.endDate) {params.set('endDate', query.endDate)} + if (query.offset !== undefined) {params.set('offset', String(query.offset))} + if (query.limit !== undefined) {params.set('limit', String(query.limit))} const queryString = params.toString() ? `?${params}` : '' return safetyRequest(`/admin/appeals${queryString}`) } diff --git a/features/platform-admin/frontend-admin/src/pages/security/appeals/AppealsPage.tsx b/features/platform-admin/frontend-admin/src/pages/security/appeals/AppealsPage.tsx index d34aadba6..c6323d33d 100644 --- a/features/platform-admin/frontend-admin/src/pages/security/appeals/AppealsPage.tsx +++ b/features/platform-admin/frontend-admin/src/pages/security/appeals/AppealsPage.tsx @@ -5,18 +5,19 @@ */ import { useState, useCallback } from 'react' -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' + +import { Modal } from '@lilith/ui-feedback' +import { Grid } from '@lilith/ui-layout' +import { Card, Badge, Button, Select, Textarea } from '@lilith/ui-primitives' import styled from '@lilith/ui-styled-components' +import { Heading, Text } from '@lilith/ui-typography' +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { format, formatDistanceToNow } from 'date-fns' -import { Card, Badge, Button, Select, Textarea } from '@lilith/ui-primitives' -import { Grid } from '@lilith/ui-layout' -import { Heading, Text } from '@lilith/ui-typography' -import { Modal } from '@lilith/ui-feedback' +import type { Appeal, AppealStats, PaginatedAppeals, ListAppealsQuery } from '@/types' -import { fetchAppeals, fetchAppealStats, reviewAppeal } from '../api' -import type { Appeal, AppealStats, PaginatedAppeals, ListAppealsQuery } from '../types' -import { AppealStatus } from '../types' +import { fetchAppeals, fetchAppealStats, reviewAppeal } from '@/api' +import { AppealStatus } from '@/types' const PageContainer = styled.div` display: flex; @@ -221,8 +222,7 @@ interface StatCardProps { variant?: 'default' | 'warning' | 'danger' | 'success' } -function StatCard({ title, value, loading, variant = 'default' }: StatCardProps): React.ReactElement { - return ( +const StatCard = ({ title, value, loading, variant = 'default' }: StatCardProps): React.ReactElement => ( {loading ? ( @@ -234,9 +234,8 @@ function StatCard({ title, value, loading, variant = 'default' }: StatCardProps) ) -} -export function AppealsPage(): React.ReactElement { +export const AppealsPage = (): React.ReactElement => { const queryClient = useQueryClient() const [filters, setFilters] = useState({ @@ -300,7 +299,7 @@ export function AppealsPage(): React.ReactElement { }, []) const handleApprove = useCallback((): void => { - if (!selectedAppeal) return + if (!selectedAppeal) {return} reviewMutation.mutate({ id: selectedAppeal.id, approved: true, @@ -309,7 +308,7 @@ export function AppealsPage(): React.ReactElement { }, [selectedAppeal, reviewNotes, reviewMutation]) const handleDeny = useCallback((): void => { - if (!selectedAppeal) return + if (!selectedAppeal) {return} reviewMutation.mutate({ id: selectedAppeal.id, approved: false,