finance-calculator/components/data-sync-dialog.tsx
2025-06-14 21:26:38 +08:00

150 lines
5.5 KiB
TypeScript
Raw Permalink 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 text-foreground">
<AlertCircle className="h-5 w-5 text-amber-500 dark:text-amber-400" />
</DialogTitle>
<DialogDescription>
{localProducts.length}
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<Alert className="border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-950/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 dark:border-blue-600 dark:bg-blue-950/50'
: 'border-border hover:border-blue-300 dark:hover:border-blue-600 bg-background'
}`}
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 dark:text-blue-400" />
<h4 className="font-medium text-blue-800 dark:text-blue-200"></h4>
</div>
<p className="text-sm text-muted-foreground">
</p>
</div>
</div>
</div>
<div
className={`p-4 border rounded-lg cursor-pointer transition-all ${
selectedAction === 'skip'
? 'border-blue-500 bg-blue-50 dark:border-blue-600 dark:bg-blue-950/50'
: 'border-border hover:border-blue-300 dark:hover:border-blue-600 bg-background'
}`}
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-muted-foreground" />
<h4 className="font-medium text-foreground">使</h4>
</div>
<p className="text-sm text-muted-foreground">
</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>
)
}