Spaces:
Running
Running
File size: 5,495 Bytes
a27839e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { ScrollArea } from "@/components/ui/scroll-area";
import { DiffResult } from "@/services/diffPatch";
import { Card, CardContent } from "@/components/ui/card";
interface DiffReviewModalProps {
isOpen: boolean;
onClose: () => void;
diffResult: DiffResult | null;
onApply: () => void;
}
const DiffReviewModal = ({ isOpen, onClose, diffResult, onApply }: DiffReviewModalProps) => {
const [isApplying, setIsApplying] = useState(false);
const handleApply = async () => {
setIsApplying(true);
try {
await onApply();
onClose();
} finally {
setIsApplying(false);
}
};
if (!diffResult) return null;
let oldLineNum = 1;
let newLineNum = 1;
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="max-w-4xl h-[80vh] flex flex-col">
<DialogHeader>
<DialogTitle className="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-2">
<path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M14 15H9"/>
<path d="M16 12c.5523 0 1-.4477 1-1s-.4477-1-1-1-.999.4477-.999 1 .4467 1 .999 1Z"/>
<path d="M16 18c1.6569 0 3-1.3431 3-3s-1.3431-3-3-3-3 1.3431-3 3 1.3431 3 3 3Z"/>
<path d="m17 2 4 4"/>
<path d="M21 2 12 11"/>
</svg>
Code Changes Review
</DialogTitle>
</DialogHeader>
<div className="text-sm text-gray-500 mb-2 flex items-center">
<span className="bg-green-100 text-green-800 px-2 py-1 rounded mr-2">+{diffResult.added} lines</span>
<span className="bg-red-100 text-red-800 px-2 py-1 rounded">-{diffResult.removed} lines</span>
</div>
<Card className="flex-1 border border-gray-200 min-h-0">
<CardContent className="p-0 h-full">
<ScrollArea className="h-full font-mono text-sm bg-gray-50 rounded-md">
<div className="p-4">
{diffResult.changes.map((change, changeIndex) => {
const lines = change.value.endsWith('\n') ? change.value.slice(0, -1).split('\n') : change.value.split('\n');
return lines.map((line, lineIndex) => {
let currentOldLine = ' ';
let currentNewLine = ' ';
if (change.removed) {
currentOldLine = String(oldLineNum++);
} else if (change.added) {
currentNewLine = String(newLineNum++);
} else {
currentOldLine = String(oldLineNum++);
currentNewLine = String(newLineNum++);
}
return (
<div
key={`${changeIndex}-${lineIndex}`}
className={`flex items-start py-0.5 ${
change.added ? 'bg-green-100' :
change.removed ? 'bg-red-100' : ''
}`}
>
<span className="w-10 text-right pr-2 text-gray-400 select-none">{currentOldLine}</span>
<span className="w-10 text-right pr-2 text-gray-400 select-none">{currentNewLine}</span>
<span className={`w-6 text-center font-bold ${
change.added ? 'text-green-700' :
change.removed ? 'text-red-700' : 'text-gray-500'
}`}>
{change.added ? '+' : change.removed ? '-' : ' '}
</span>
<span className={`flex-1 whitespace-pre-wrap break-all ${
change.added ? 'text-green-900' :
change.removed ? 'text-red-900' : 'text-gray-800'
}`}>
{line}
</span>
</div>
);
});
})}
</div>
</ScrollArea>
</CardContent>
</Card>
<DialogFooter className="flex space-x-2 pt-4">
<Button variant="outline" onClick={onClose} className="border-gray-300">
Cancel
</Button>
<Button
onClick={handleApply}
disabled={isApplying}
className="bg-gradient-to-r from-blue-600 to-indigo-700 hover:from-blue-700 hover:to-indigo-800"
>
{isApplying ? (
<>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-2 animate-spin">
<path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>
Applying...
</>
) : (
"Apply Changes"
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
export default DiffReviewModal; |