diff --git a/__tests__/components/sync-status-indicator.test.tsx b/__tests__/components/sync-status-indicator.test.tsx new file mode 100644 index 0000000..d10459f --- /dev/null +++ b/__tests__/components/sync-status-indicator.test.tsx @@ -0,0 +1,25 @@ +import { render, screen } from '@testing-library/react' +import { SyncStatusIndicator } from '@/components/bible/sync-status-indicator' + +describe('SyncStatusIndicator', () => { + it('should show synced state', () => { + render() + expect(screen.getByTestId('sync-status-synced')).toBeInTheDocument() + }) + + it('should show syncing state with spinner', () => { + render() + expect(screen.getByTestId('sync-status-syncing')).toBeInTheDocument() + }) + + it('should show error state', () => { + render() + expect(screen.getByTestId('sync-status-error')).toBeInTheDocument() + expect(screen.getByText('Network error')).toBeInTheDocument() + }) + + it('should show pending count', () => { + render() + expect(screen.getByText('3 pending')).toBeInTheDocument() + }) +}) diff --git a/components/bible/sync-status-indicator.tsx b/components/bible/sync-status-indicator.tsx new file mode 100644 index 0000000..e03dfba --- /dev/null +++ b/components/bible/sync-status-indicator.tsx @@ -0,0 +1,85 @@ +'use client' +import { Box, Chip, CircularProgress, Tooltip, Typography } from '@mui/material' +import CloudSyncIcon from '@mui/icons-material/CloudSync' +import CheckCircleIcon from '@mui/icons-material/CheckCircle' +import ErrorIcon from '@mui/icons-material/Error' +import ScheduleIcon from '@mui/icons-material/Schedule' + +interface SyncStatusIndicatorProps { + status: 'synced' | 'syncing' | 'pending' | 'error' + pendingCount?: number + errorMessage?: string +} + +export function SyncStatusIndicator({ + status, + pendingCount = 0, + errorMessage +}: SyncStatusIndicatorProps) { + if (status === 'synced') { + return ( + + } + label="Synced" + variant="outlined" + color="success" + size="small" + sx={{ fontWeight: 500 }} + /> + + ) + } + + if (status === 'syncing') { + return ( + + } + label="Syncing..." + variant="filled" + color="primary" + size="small" + sx={{ fontWeight: 500 }} + /> + + ) + } + + if (status === 'pending') { + return ( + + } + label={`${pendingCount} pending`} + variant="outlined" + color="warning" + size="small" + sx={{ fontWeight: 500 }} + /> + + ) + } + + // error + return ( + + + + + + Sync Error + + {errorMessage && ( + + {errorMessage} + + )} + + + + ) +}