Add transaction status indicators to moderation UI

Implement visual indicators in the moderation queue and review manager to display the status of ongoing transactions. This includes states for processing, timeout, and cached results, providing users with clearer feedback on the system's activity.
This commit is contained in:
gpt-engineer-app[bot]
2025-11-07 16:07:48 +00:00
parent b917232220
commit e4bcad9680
5 changed files with 238 additions and 4 deletions

View File

@@ -39,6 +39,7 @@ import { ValidationBlockerDialog } from './ValidationBlockerDialog';
import { WarningConfirmDialog } from './WarningConfirmDialog';
import { ConflictResolutionModal } from './ConflictResolutionModal';
import { EditHistoryAccordion } from './EditHistoryAccordion';
import { TransactionStatusIndicator } from './TransactionStatusIndicator';
import { validateMultipleItems, ValidationResult } from '@/lib/entityValidationSchemas';
import { logger } from '@/lib/logger';
import { ModerationErrorBoundary } from '@/components/error';
@@ -83,6 +84,8 @@ export function SubmissionReviewManager({
message: string;
errorId?: string;
} | null>(null);
const [transactionStatus, setTransactionStatus] = useState<'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed'>('idle');
const [transactionMessage, setTransactionMessage] = useState<string | undefined>();
const { toast } = useToast();
const { isAdmin, isSuperuser } = useUserRole();
@@ -337,6 +340,7 @@ export function SubmissionReviewManager({
}
// Proceed with approval - wrapped with transaction resilience
setTransactionStatus('processing');
await executeTransaction(
'approval',
selectedIds,
@@ -400,10 +404,34 @@ export function SubmissionReviewManager({
onComplete();
onOpenChange(false);
setTransactionStatus('completed');
setTimeout(() => setTransactionStatus('idle'), 3000);
return data;
}
);
} catch (error: unknown) {
// Check for timeout
if (error && typeof error === 'object' && 'type' in error && error.type === 'timeout') {
setTransactionStatus('timeout');
setTransactionMessage(getErrorMessage(error));
}
// Check for cached/409
else if (error && typeof error === 'object' && ('status' in error && error.status === 409)) {
setTransactionStatus('cached');
setTransactionMessage('Using cached result from duplicate request');
}
// Generic failure
else {
setTransactionStatus('failed');
setTransactionMessage(getErrorMessage(error));
}
setTimeout(() => {
setTransactionStatus('idle');
setTransactionMessage(undefined);
}, 5000);
dispatch({ type: 'ERROR', payload: { error: getErrorMessage(error) } });
handleError(error, {
action: 'Approve Submission Items',
@@ -467,6 +495,7 @@ export function SubmissionReviewManager({
try {
// Wrap rejection with transaction resilience
setTransactionStatus('processing');
await executeTransaction(
'rejection',
selectedIds,
@@ -484,10 +513,34 @@ export function SubmissionReviewManager({
onComplete();
onOpenChange(false);
setTransactionStatus('completed');
setTimeout(() => setTransactionStatus('idle'), 3000);
return { success: true };
}
);
} catch (error: unknown) {
// Check for timeout
if (error && typeof error === 'object' && 'type' in error && error.type === 'timeout') {
setTransactionStatus('timeout');
setTransactionMessage(getErrorMessage(error));
}
// Check for cached/409
else if (error && typeof error === 'object' && ('status' in error && error.status === 409)) {
setTransactionStatus('cached');
setTransactionMessage('Using cached result from duplicate request');
}
// Generic failure
else {
setTransactionStatus('failed');
setTransactionMessage(getErrorMessage(error));
}
setTimeout(() => {
setTransactionStatus('idle');
setTransactionMessage(undefined);
}, 5000);
dispatch({ type: 'ERROR', payload: { error: getErrorMessage(error) } });
handleError(error, {
action: 'Reject Submission Items',
@@ -625,7 +678,10 @@ export function SubmissionReviewManager({
{isMobile ? (
<SheetContent side="bottom" className="h-[90vh] overflow-y-auto">
<SheetHeader>
<SheetTitle>Review Submission</SheetTitle>
<div className="flex items-center justify-between">
<SheetTitle>Review Submission</SheetTitle>
<TransactionStatusIndicator status={transactionStatus} message={transactionMessage} />
</div>
<SheetDescription>
{pendingCount} pending item(s) {selectedCount} selected
</SheetDescription>
@@ -635,7 +691,10 @@ export function SubmissionReviewManager({
) : (
<DialogContent className="max-w-5xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Review Submission</DialogTitle>
<div className="flex items-center justify-between">
<DialogTitle>Review Submission</DialogTitle>
<TransactionStatusIndicator status={transactionStatus} message={transactionMessage} />
</div>
<DialogDescription>
{pendingCount} pending item(s) {selectedCount} selected
</DialogDescription>