From 403a1c05a58548c8fe4d09a59cac1be52247f9ac Mon Sep 17 00:00:00 2001 From: Claude Code Date: Wed, 25 Mar 2026 23:56:36 -0700 Subject: [PATCH] =?UTF-8?q?feat(security-appeals):=20=E2=9C=A8=20Update=20?= =?UTF-8?q?AppealsPage=20component=20with=20status=20indicators,=20action?= =?UTF-8?q?=20buttons,=20and=20forms=20for=20security=20appeal=20managemen?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../pages/security/appeals/AppealsPage.tsx | 159 ++++-------------- 1 file changed, 36 insertions(+), 123 deletions(-) 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 1cf6d787a..2739d7582 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 @@ -20,63 +20,23 @@ import type { Appeal, AppealStats, PaginatedAppeals, ListAppealsQuery } from '@/ import { fetchAppeals, fetchAppealStats, reviewAppeal } from '@/api' import { AppealStatus } from '@/types' -const PageContainer = styled.div` - display: flex; - flex-direction: column; - gap: 1.5rem; -` - -const HeaderSection = styled.div` - margin-bottom: 1rem; -` - -const CardContent = styled.div` - padding: 1rem; -` - -const StatCardContent = styled.div` - text-align: center; - padding: 1rem; -` - -const StatValue = styled.div<{ $variant?: 'default' | 'warning' | 'danger' | 'success' }>` - font-size: 2rem; - font-weight: 700; - color: ${({ $variant }): string => - $variant === 'danger' - ? '#ef4444' - : $variant === 'warning' - ? '#f59e0b' - : $variant === 'success' - ? '#22c55e' - : 'var(--text-primary)'}; -` - -const StatLabel = styled.div` - font-size: 0.875rem; - color: var(--text-secondary); - margin-top: 0.25rem; -` - -const FiltersRow = styled.div` - display: flex; - gap: 1rem; - align-items: flex-end; -` - -const FilterGroup = styled.div` - display: flex; - flex-direction: column; - gap: 0.25rem; -` - -const FilterLabel = styled.label` - font-size: 0.75rem; - font-weight: 500; - color: var(--text-secondary); - text-transform: uppercase; - letter-spacing: 0.05em; -` +import { + PageContainer, + HeaderSection, + StatCardContent, + StatValue, + StatLabel, + CardHeader, + CardContent, + FiltersRow, + FilterGroup, + FilterLabel, + LoadingPlaceholder, + TableContainer, + AdminTable, + AdminTh, + AdminTd, +} from '@/components/admin-pages/SharedPageComponents' const StatusBadge = styled(Badge)<{ $status: AppealStatus }>` background: ${({ $status }): string => @@ -88,31 +48,6 @@ const StatusBadge = styled(Badge)<{ $status: AppealStatus }>` color: white; ` -const TableContainer = styled.div` - overflow-x: auto; -` - -const Table = styled.table` - width: 100%; - border-collapse: collapse; - font-size: 0.875rem; -` - -const Th = styled.th` - text-align: left; - padding: 0.75rem 1rem; - font-weight: 600; - color: var(--text-secondary); - border-bottom: 1px solid var(--border-color); - background: var(--bg-secondary); -` - -const Td = styled.td` - padding: 0.75rem 1rem; - border-bottom: 1px solid var(--border-color); - color: var(--text-primary); -` - const PaginationContainer = styled.div` display: flex; justify-content: space-between; @@ -179,34 +114,12 @@ const ModalActions = styled.div` border-top: 1px solid var(--border-color); ` -const CardHeader = styled.div` - padding: 1rem; - border-bottom: 1px solid var(--border-color); -` - const CardTitle = styled.h3` font-size: 1rem; font-weight: 600; margin: 0; ` -const LoadingPlaceholder = styled.div` - height: 2rem; - background: var(--bg-tertiary); - border-radius: 4px; - animation: pulse 1.5s infinite; - - @keyframes pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } - } -` - const STATUS_OPTIONS = [ { value: '', label: 'All Statuses' }, { value: AppealStatus.PENDING, label: 'Pending' }, @@ -396,32 +309,32 @@ export const AppealsPage = (): ReactElement => { ) : appeals.length === 0 ? ( No appeals found ) : ( - + - - - - - - - + Submitted + Email + Status + Detected Org + Country + Block Type + Actions {appeals.map((appeal) => ( - - - - - - - + ))} -
SubmittedEmailStatusDetected OrgCountryBlock TypeActions
+ {formatDistanceToNow(new Date(appeal.createdAt), { addSuffix: true })} - {appeal.email} + + {appeal.email} + {appeal.status} - {appeal.detectedOrg || '-'}{appeal.detectedCountry || '-'}{appeal.responseTier || '-'} + + {appeal.detectedOrg || '-'} + {appeal.detectedCountry || '-'} + {appeal.responseTier || '-'} + {appeal.status === AppealStatus.PENDING ? (
+ )}