diff --git a/dashboard/src/components/common/LoadingSpinner.tsx b/dashboard/src/components/common/LoadingSpinner.tsx
new file mode 100644
index 0000000..8c11be5
--- /dev/null
+++ b/dashboard/src/components/common/LoadingSpinner.tsx
@@ -0,0 +1,19 @@
+interface LoadingSpinnerProps {
+ size?: 'sm' | 'md' | 'lg';
+}
+
+const sizeClasses = {
+ sm: 'w-4 h-4',
+ md: 'w-8 h-8',
+ lg: 'w-12 h-12',
+};
+
+export function LoadingSpinner({ size = 'md' }: LoadingSpinnerProps) {
+ return (
+
+ );
+}
diff --git a/dashboard/src/components/common/Pagination.tsx b/dashboard/src/components/common/Pagination.tsx
new file mode 100644
index 0000000..0fc04af
--- /dev/null
+++ b/dashboard/src/components/common/Pagination.tsx
@@ -0,0 +1,47 @@
+interface PaginationProps {
+ page: number;
+ pages: number;
+ total: number;
+ pageSize: number;
+ onPageChange: (page: number) => void;
+}
+
+export function Pagination({
+ page,
+ pages,
+ total,
+ pageSize,
+ onPageChange,
+}: PaginationProps) {
+ const start = (page - 1) * pageSize + 1;
+ const end = Math.min(page * pageSize, total);
+
+ return (
+
+
+ Showing {start} to{' '}
+ {end} of{' '}
+ {total} results
+
+
+
+
+ Page {page} of {pages}
+
+
+
+
+ );
+}
diff --git a/dashboard/src/components/common/SeverityBadge.tsx b/dashboard/src/components/common/SeverityBadge.tsx
new file mode 100644
index 0000000..ee92dd6
--- /dev/null
+++ b/dashboard/src/components/common/SeverityBadge.tsx
@@ -0,0 +1,32 @@
+import type { Severity } from '../../types/api';
+
+interface SeverityBadgeProps {
+ severity: Severity;
+ showLabel?: boolean;
+}
+
+const severityConfig: Record<
+ Severity,
+ { bg: string; text: string; label: string }
+> = {
+ critical: { bg: 'bg-red-100', text: 'text-red-800', label: 'Critical' },
+ high: { bg: 'bg-orange-100', text: 'text-orange-800', label: 'High' },
+ medium: { bg: 'bg-yellow-100', text: 'text-yellow-800', label: 'Medium' },
+ low: { bg: 'bg-blue-100', text: 'text-blue-800', label: 'Low' },
+ info: { bg: 'bg-gray-100', text: 'text-gray-800', label: 'Info' },
+};
+
+export function SeverityBadge({
+ severity,
+ showLabel = true,
+}: SeverityBadgeProps) {
+ const config = severityConfig[severity];
+
+ return (
+
+ {showLabel && config.label}
+
+ );
+}
diff --git a/dashboard/src/components/deliberation/VerdictBadge.tsx b/dashboard/src/components/deliberation/VerdictBadge.tsx
new file mode 100644
index 0000000..d363811
--- /dev/null
+++ b/dashboard/src/components/deliberation/VerdictBadge.tsx
@@ -0,0 +1,53 @@
+import type { Verdict } from '../../types/api';
+
+interface VerdictBadgeProps {
+ verdict: Verdict | null;
+ confidence?: number | null;
+ size?: 'sm' | 'md';
+}
+
+const verdictConfig: Record = {
+ approve: {
+ bg: 'bg-green-100',
+ text: 'text-green-800',
+ icon: '✓',
+ label: 'Approved',
+ },
+ request_changes: {
+ bg: 'bg-red-100',
+ text: 'text-red-800',
+ icon: '✗',
+ label: 'Changes Requested',
+ },
+ comment: {
+ bg: 'bg-blue-100',
+ text: 'text-blue-800',
+ icon: '💬',
+ label: 'Comment',
+ },
+};
+
+export function VerdictBadge({ verdict, confidence, size = 'md' }: VerdictBadgeProps) {
+ if (!verdict) {
+ return (
+
+ Pending
+
+ );
+ }
+
+ const config = verdictConfig[verdict];
+ const sizeClasses = size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-3 py-1 text-sm';
+
+ return (
+
+ {config.icon}
+ {config.label}
+ {confidence !== undefined && confidence !== null && (
+ ({Math.round(confidence * 100)}%)
+ )}
+
+ );
+}