Files
thrilltrack-explorer/src-old/components/moderation/EscalationDialog.tsx

148 lines
4.2 KiB
TypeScript

import { useState } from 'react';
import { AlertTriangle, AlertCircle } from 'lucide-react';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
interface EscalationDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onEscalate: (reason: string) => Promise<void>;
submissionType: string;
error?: { message: string; errorId?: string } | null;
}
const escalationReasons = [
'Complex dependency issue',
'Potential policy violation',
'Unclear submission content',
'Requires admin judgment',
'Technical issue',
'Other',
];
export function EscalationDialog({
open,
onOpenChange,
onEscalate,
submissionType,
error,
}: EscalationDialogProps) {
const [selectedReason, setSelectedReason] = useState('');
const [additionalNotes, setAdditionalNotes] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const handleEscalate = async () => {
const reason = selectedReason === 'Other'
? additionalNotes
: `${selectedReason}${additionalNotes ? ': ' + additionalNotes : ''}`;
if (!reason.trim()) return;
setIsSubmitting(true);
try {
await onEscalate(reason);
setSelectedReason('');
setAdditionalNotes('');
onOpenChange(false);
} finally {
setIsSubmitting(false);
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<AlertTriangle className="h-5 w-5 text-destructive" />
Escalate Submission
</DialogTitle>
<DialogDescription>
Escalating this {submissionType} will mark it as high priority and notify senior moderators.
</DialogDescription>
</DialogHeader>
{error && (
<Alert variant="destructive" className="mt-4">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Escalation Failed</AlertTitle>
<AlertDescription>
<div className="space-y-2">
<p className="text-sm">{error.message}</p>
{error.errorId && (
<p className="text-xs font-mono bg-destructive/10 px-2 py-1 rounded">
Reference: {error.errorId.slice(0, 8)}
</p>
)}
</div>
</AlertDescription>
</Alert>
)}
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label>Escalation Reason</Label>
<Select value={selectedReason} onValueChange={setSelectedReason}>
<SelectTrigger>
<SelectValue placeholder="Select a reason" />
</SelectTrigger>
<SelectContent>
{escalationReasons.map((reason) => (
<SelectItem key={reason} value={reason}>
{reason}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Additional Notes</Label>
<Textarea
value={additionalNotes}
onChange={(e) => setAdditionalNotes(e.target.value)}
placeholder="Provide any additional context..."
rows={4}
className="resize-none"
/>
</div>
</div>
<DialogFooter>
<Button
variant="outline"
onClick={() => onOpenChange(false)}
disabled={isSubmitting}
>
Cancel
</Button>
<Button
variant="destructive"
onClick={handleEscalate}
disabled={!selectedReason || isSubmitting}
>
{isSubmitting ? 'Escalating...' : 'Escalate'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}