finance-calculator/components/data-sync-dialog.tsx

150 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState } from "react"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { Upload, Download, AlertCircle, Loader2 } from "lucide-react"
import { LocalFinanceProduct } from "@/hooks/use-local-storage"
interface DataSyncDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
localProducts: LocalFinanceProduct[]
onSyncConfirm: () => Promise<void>
onSyncCancel: () => void
isSyncing: boolean
}
export function DataSyncDialog({
open,
onOpenChange,
localProducts,
onSyncConfirm,
onSyncCancel,
isSyncing
}: DataSyncDialogProps) {
const [selectedAction, setSelectedAction] = useState<'sync' | 'skip' | null>(null)
const handleConfirm = async () => {
if (selectedAction === 'sync') {
await onSyncConfirm()
} else {
onSyncCancel()
}
onOpenChange(false)
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<AlertCircle className="h-5 w-5 text-amber-500" />
</DialogTitle>
<DialogDescription>
{localProducts.length}
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<Alert className="border-blue-200 bg-blue-50">
<Upload className="h-4 w-4" />
<AlertDescription>
<strong></strong>
<ul className="mt-2 text-sm space-y-1">
<li> {localProducts.length} </li>
<li> : ¥{localProducts.reduce((sum, p) => sum + p.principal, 0).toLocaleString()}</li>
<li> : {Array.from(new Set(localProducts.map(p => p.currency))).join(', ')}</li>
</ul>
</AlertDescription>
</Alert>
<div className="space-y-3">
<div
className={`p-4 border rounded-lg cursor-pointer transition-all ${
selectedAction === 'sync'
? 'border-blue-500 bg-blue-50'
: 'border-gray-200 hover:border-blue-300'
}`}
onClick={() => setSelectedAction('sync')}
>
<div className="flex items-start space-x-3">
<input
type="radio"
name="syncAction"
checked={selectedAction === 'sync'}
onChange={() => setSelectedAction('sync')}
className="mt-1"
/>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<Upload className="h-4 w-4 text-blue-600" />
<h4 className="font-medium text-blue-800"></h4>
</div>
<p className="text-sm text-gray-600">
</p>
</div>
</div>
</div>
<div
className={`p-4 border rounded-lg cursor-pointer transition-all ${
selectedAction === 'skip'
? 'border-blue-500 bg-blue-50'
: 'border-gray-200 hover:border-blue-300'
}`}
onClick={() => setSelectedAction('skip')}
>
<div className="flex items-start space-x-3">
<input
type="radio"
name="syncAction"
checked={selectedAction === 'skip'}
onChange={() => setSelectedAction('skip')}
className="mt-1"
/>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<Download className="h-4 w-4 text-gray-600" />
<h4 className="font-medium text-gray-800">使</h4>
</div>
<p className="text-sm text-gray-600">
</p>
</div>
</div>
</div>
</div>
</div>
<DialogFooter className="flex justify-between">
<Button
variant="outline"
onClick={() => onOpenChange(false)}
disabled={isSyncing}
>
</Button>
<Button
onClick={handleConfirm}
disabled={!selectedAction || isSyncing}
>
{isSyncing && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
{isSyncing ? '处理中...' : '确认'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}