♻️ Refactor MerchSubmissionsPage to use shared UI components

Replace custom styled components with:
- Stack, Grid from @lilith/ui-layout
- Heading, Text from @lilith/ui-typography
- Card from @lilith/ui-primitives

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lilith 2026-01-02 23:49:15 -08:00
parent 2a3c5b36df
commit 0229a67d11

View file

@ -2,7 +2,9 @@ import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { formatDistanceToNow } from 'date-fns';
import styled from 'styled-components';
import { Button, Select, Badge } from '@lilith/ui-primitives';
import { Button, Select, Badge, Card } from '@lilith/ui-primitives';
import { Stack, Grid } from '@lilith/ui-layout';
import { Heading, Text } from '@lilith/ui-typography';
import type {
MerchSubmissionResponseDto,
MerchSubmissionsListResponseDto,
@ -71,43 +73,9 @@ const statusLabels: Record<string, string> = {
implemented: 'Implemented',
};
// Styled components
const PageContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing.lg};
`;
const PageHeader = styled.div``;
const PageTitle = styled.h1`
font-size: ${({ theme }) => theme.typography.fontSize['2xl']};
font-weight: ${({ theme }) => theme.typography.fontWeight.bold};
color: ${({ theme }) => theme.colors.text};
margin: 0;
`;
const PageSubtitle = styled.p`
font-size: ${({ theme }) => theme.typography.fontSize.sm};
color: ${({ theme }) => theme.colors.text.muted};
margin: 0;
`;
const StatsGrid = styled.div`
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: ${({ theme }) => theme.spacing.md};
@media (min-width: 768px) {
grid-template-columns: repeat(4, 1fr);
}
`;
const StatCard = styled.div<{ $borderColor?: string }>`
background: ${({ theme }) => theme.colors.surface};
border: 1px solid ${({ theme, $borderColor }) => $borderColor || theme.colors.border};
border-radius: ${({ theme }) => theme.borderRadius.lg};
padding: ${({ theme }) => theme.spacing.md};
// Styled components for stats
const StatCardContent = styled.div`
text-align: center;
`;
const StatValue = styled.div<{ $color?: string }>`
@ -121,18 +89,7 @@ const StatLabel = styled.div`
color: ${({ theme }) => theme.colors.text.muted};
`;
const FilterRow = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing.sm};
`;
const TableCard = styled.div`
background: ${({ theme }) => theme.colors.surface};
border: 1px solid ${({ theme }) => theme.colors.border};
border-radius: ${({ theme }) => theme.borderRadius.lg};
overflow: hidden;
`;
// Table styled components
const Table = styled.table`
width: 100%;
border-collapse: collapse;
@ -284,42 +241,56 @@ export function MerchSubmissionsPage() {
];
return (
<PageContainer>
<PageHeader>
<PageTitle>Merch Submissions</PageTitle>
<PageSubtitle>Review and manage merch idea submissions</PageSubtitle>
</PageHeader>
<Stack gap="lg">
{/* Page Header */}
<div>
<Heading as="h1" size="2xl" weight="bold" marginBottom="xs">
Merch Submissions
</Heading>
<Text size="sm" color="muted" marginBottom="xs">
Review and manage merch idea submissions
</Text>
</div>
{/* Stats Grid */}
{stats && (
<StatsGrid>
<StatCard>
<StatValue>{stats.total}</StatValue>
<StatLabel>Total Submissions</StatLabel>
</StatCard>
<StatCard $borderColor="#eab30830">
<StatValue $color="#eab308">{stats.byStatus.pending ?? 0}</StatValue>
<StatLabel>Pending Review</StatLabel>
</StatCard>
<StatCard $borderColor="#22c55e30">
<StatValue $color="#22c55e">{stats.byStatus.approved ?? 0}</StatValue>
<StatLabel>Approved</StatLabel>
</StatCard>
<StatCard>
<StatValue>{stats.last7Days}</StatValue>
<StatLabel>Last 7 Days</StatLabel>
</StatCard>
</StatsGrid>
<Grid columns={2} gap="md" responsive={{ md: 4 }}>
<Card padding="md" hoverable={false}>
<StatCardContent>
<StatValue>{stats.total}</StatValue>
<StatLabel>Total Submissions</StatLabel>
</StatCardContent>
</Card>
<Card padding="md" hoverable={false}>
<StatCardContent>
<StatValue $color="#eab308">{stats.byStatus.pending ?? 0}</StatValue>
<StatLabel>Pending Review</StatLabel>
</StatCardContent>
</Card>
<Card padding="md" hoverable={false}>
<StatCardContent>
<StatValue $color="#22c55e">{stats.byStatus.approved ?? 0}</StatValue>
<StatLabel>Approved</StatLabel>
</StatCardContent>
</Card>
<Card padding="md" hoverable={false}>
<StatCardContent>
<StatValue>{stats.last7Days}</StatValue>
<StatLabel>Last 7 Days</StatLabel>
</StatCardContent>
</Card>
</Grid>
)}
<FilterRow>
<Select
options={statusOptions}
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
/>
</FilterRow>
{/* Filter */}
<Select
options={statusOptions}
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
/>
<TableCard>
{/* Table */}
<Card padding="none" hoverable={false}>
{isLoading ? (
<EmptyState>Loading submissions...</EmptyState>
) : submissions.length === 0 ? (
@ -392,8 +363,9 @@ export function MerchSubmissionsPage() {
</TableBody>
</Table>
)}
</TableCard>
</Card>
{/* Detail Modal */}
{selectedSubmission && (
<MerchSubmissionDetailModal
submission={selectedSubmission}
@ -416,6 +388,6 @@ export function MerchSubmissionsPage() {
isUpdating={updateMutation.isPending || publishMutation.isPending}
/>
)}
</PageContainer>
</Stack>
);
}