mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 07:31:12 -05:00
feat: Implement enhanced moderation system
This commit is contained in:
96
src/components/moderation/ConflictResolutionDialog.tsx
Normal file
96
src/components/moderation/ConflictResolutionDialog.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { useState } from 'react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { AlertCircle } from 'lucide-react';
|
||||
import { type DependencyConflict, type SubmissionItemWithDeps } from '@/lib/submissionItemsService';
|
||||
|
||||
interface ConflictResolutionDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
conflicts: DependencyConflict[];
|
||||
items: SubmissionItemWithDeps[];
|
||||
onResolve: () => void;
|
||||
}
|
||||
|
||||
export function ConflictResolutionDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
conflicts,
|
||||
items,
|
||||
onResolve,
|
||||
}: ConflictResolutionDialogProps) {
|
||||
const [resolutions, setResolutions] = useState<Record<string, string>>({});
|
||||
|
||||
const handleResolutionChange = (itemId: string, action: string) => {
|
||||
setResolutions(prev => ({ ...prev, [itemId]: action }));
|
||||
};
|
||||
|
||||
const allConflictsResolved = conflicts.every(
|
||||
conflict => resolutions[conflict.itemId]
|
||||
);
|
||||
|
||||
const handleApply = () => {
|
||||
// TODO: Apply resolutions
|
||||
onResolve();
|
||||
onOpenChange(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Resolve Dependency Conflicts</DialogTitle>
|
||||
<DialogDescription>
|
||||
{conflicts.length} conflict(s) found. Choose how to resolve each one.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-6 py-4">
|
||||
{conflicts.map((conflict) => {
|
||||
const item = items.find(i => i.id === conflict.itemId);
|
||||
|
||||
return (
|
||||
<div key={conflict.itemId} className="space-y-3">
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
<p className="font-medium">
|
||||
{item?.item_type.replace('_', ' ').toUpperCase()}: {item?.item_data.name}
|
||||
</p>
|
||||
<p className="text-sm mt-1">{conflict.message}</p>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<RadioGroup
|
||||
value={resolutions[conflict.itemId] || ''}
|
||||
onValueChange={(value) => handleResolutionChange(conflict.itemId, value)}
|
||||
>
|
||||
{conflict.suggestions.map((suggestion, idx) => (
|
||||
<div key={idx} className="flex items-center space-x-2">
|
||||
<RadioGroupItem value={suggestion.action} id={`${conflict.itemId}-${idx}`} />
|
||||
<Label htmlFor={`${conflict.itemId}-${idx}`} className="cursor-pointer">
|
||||
{suggestion.label}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleApply} disabled={!allConflictsResolved}>
|
||||
Apply & Approve
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user