mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
Add ACMCC app source, Supabase backend, and project config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { Loader2, AlertTriangle, CheckCircle, RotateCcw } from 'lucide-react';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
|
||||
export function CallLogRestoreDialog({ open, onOpenChange, onSuccess }) {
|
||||
const { user } = useAuth();
|
||||
const { toast } = useToast();
|
||||
|
||||
const [step, setStep] = useState('analyze');
|
||||
const [analysis, setAnalysis] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [result, setResult] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (open && step === 'analyze') {
|
||||
performAnalysis();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const performAnalysis = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// Placeholder: In production, use fetchCallLogsForRestoration
|
||||
setAnalysis({ count: 0, records: [], issues: [] });
|
||||
setStep('review');
|
||||
} catch (err) {
|
||||
toast({ variant: "destructive", title: "Analysis Failed", description: err.message });
|
||||
onOpenChange(false);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRestore = async () => {
|
||||
if (!analysis) return;
|
||||
setStep('restoring');
|
||||
|
||||
try {
|
||||
// Placeholder: In production, use restoreCallLogs
|
||||
const res = { successCount: analysis.records.length, errors: [] };
|
||||
setResult(res);
|
||||
setStep('result');
|
||||
if (onSuccess) onSuccess();
|
||||
} catch (err) {
|
||||
toast({ variant: "destructive", title: "Restoration Failed", description: err.message });
|
||||
setStep('review');
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setStep('analyze');
|
||||
setAnalysis(null);
|
||||
setResult(null);
|
||||
onOpenChange(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleClose}>
|
||||
<DialogContent className="sm:max-w-[600px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<RotateCcw className="w-5 h-5 text-amber-600" />
|
||||
Call Log Restoration
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Scan and verify integrity of recent call logs.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="py-4">
|
||||
{step === 'analyze' && (
|
||||
<div className="flex flex-col items-center justify-center py-8">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-blue-600 mb-4" />
|
||||
<p className="text-sm text-slate-500">Scanning call logs...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 'review' && analysis && (
|
||||
<div className="space-y-4">
|
||||
<div className="bg-amber-50 border border-amber-200 rounded-lg p-4 flex items-start gap-3">
|
||||
<AlertTriangle className="w-5 h-5 text-amber-600 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h4 className="font-medium text-amber-900 text-sm">Review Findings</h4>
|
||||
<p className="text-sm text-amber-800 mt-1">
|
||||
Found <strong>{analysis.count}</strong> recent call logs.
|
||||
{analysis.issues.length > 0
|
||||
? ` Detected ${analysis.issues.length} potential integrity issues.`
|
||||
: " No critical issues detected."}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-slate-600">
|
||||
Proceeding will attempt to correct any metadata issues and verify record consistency.
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 'restoring' && (
|
||||
<div className="flex flex-col items-center justify-center py-8">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-green-600 mb-4" />
|
||||
<p className="text-sm text-slate-500">Processing records...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 'result' && result && (
|
||||
<div className="space-y-4">
|
||||
<div className="bg-green-50 border border-green-200 rounded-lg p-4 flex items-start gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-green-600 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h4 className="font-medium text-green-900 text-sm">Process Complete</h4>
|
||||
<p className="text-sm text-green-800 mt-1">
|
||||
Successfully processed {result.successCount} records.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{result.errors.length > 0 && (
|
||||
<ScrollArea className="h-[100px] w-full border rounded-md p-2 bg-red-50 text-xs text-red-700">
|
||||
{result.errors.map((e, i) => (
|
||||
<div key={i} className="mb-1">Error with ID {e.id}: {e.message}</div>
|
||||
))}
|
||||
</ScrollArea>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
{step === 'review' && (
|
||||
<>
|
||||
<Button variant="outline" onClick={handleClose}>Cancel</Button>
|
||||
<Button onClick={handleRestore} className="bg-amber-600 hover:bg-amber-700 text-white">
|
||||
Proceed
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{step === 'result' && (
|
||||
<Button onClick={handleClose}>Close</Button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user