feat(security-appeals): ✨ Update AppealsPage component with status indicators, action buttons, and forms for security appeal management
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
e8421add08
commit
403a1c05a5
1 changed files with 36 additions and 123 deletions
|
|
@ -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 ? (
|
||||
<EmptyState>No appeals found</EmptyState>
|
||||
) : (
|
||||
<Table>
|
||||
<AdminTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<Th>Submitted</Th>
|
||||
<Th>Email</Th>
|
||||
<Th>Status</Th>
|
||||
<Th>Detected Org</Th>
|
||||
<Th>Country</Th>
|
||||
<Th>Block Type</Th>
|
||||
<Th>Actions</Th>
|
||||
<AdminTh>Submitted</AdminTh>
|
||||
<AdminTh>Email</AdminTh>
|
||||
<AdminTh>Status</AdminTh>
|
||||
<AdminTh>Detected Org</AdminTh>
|
||||
<AdminTh>Country</AdminTh>
|
||||
<AdminTh>Block Type</AdminTh>
|
||||
<AdminTh>Actions</AdminTh>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{appeals.map((appeal) => (
|
||||
<tr key={appeal.id}>
|
||||
<Td title={format(new Date(appeal.createdAt), 'PPpp')}>
|
||||
<AdminTd title={format(new Date(appeal.createdAt), 'PPpp')}>
|
||||
{formatDistanceToNow(new Date(appeal.createdAt), { addSuffix: true })}
|
||||
</Td>
|
||||
<Td>{appeal.email}</Td>
|
||||
<Td>
|
||||
</AdminTd>
|
||||
<AdminTd>{appeal.email}</AdminTd>
|
||||
<AdminTd>
|
||||
<StatusBadge $status={appeal.status}>{appeal.status}</StatusBadge>
|
||||
</Td>
|
||||
<Td>{appeal.detectedOrg || '-'}</Td>
|
||||
<Td>{appeal.detectedCountry || '-'}</Td>
|
||||
<Td>{appeal.responseTier || '-'}</Td>
|
||||
<Td>
|
||||
</AdminTd>
|
||||
<AdminTd>{appeal.detectedOrg || '-'}</AdminTd>
|
||||
<AdminTd>{appeal.detectedCountry || '-'}</AdminTd>
|
||||
<AdminTd>{appeal.responseTier || '-'}</AdminTd>
|
||||
<AdminTd>
|
||||
{appeal.status === AppealStatus.PENDING ? (
|
||||
<Button size="sm" variant="secondary" onClick={(): void => handleReviewClick(appeal)}>
|
||||
Review
|
||||
|
|
@ -433,11 +346,11 @@ export const AppealsPage = (): ReactElement => {
|
|||
: '-'}
|
||||
</span>
|
||||
)}
|
||||
</Td>
|
||||
</AdminTd>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</AdminTable>
|
||||
)}
|
||||
</TableContainer>
|
||||
<CardContent>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue