Files
chinese-family-tree-2/app/settings/page.tsx
T
freedakgmail c033e46782 0.0.0.4
2025-11-22 23:49:24 +08:00

195 lines
8.1 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 { SiteHeader } from "@/components/site-header"
import { useFamily } from "@/context/family-context"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Download, Upload, AlertTriangle, RefreshCw, FileText, Bell } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { useRef, useState } from "react"
import { exportToGedcom, importFromGedcom } from "@/lib/gedcom"
import { NotificationSettings } from "@/components/settings/notification-settings"
export default function SettingsPage() {
const { treeData, loadData, resetData } = useFamily()
const [importStatus, setImportStatus] = useState<string>("")
const [gedcomStatus, setGedcomStatus] = useState<string>("")
const fileInputRef = useRef<HTMLInputElement>(null)
const gedcomInputRef = useRef<HTMLInputElement>(null)
return (
<div className="min-h-screen bg-background flex flex-col font-sans">
<SiteHeader />
<main className="container mx-auto py-8 px-4 md:px-6 flex-1 max-w-3xl">
<h1 className="text-3xl font-serif font-bold mb-8"> (Settings)</h1>
<div className="space-y-6">
{/* 通知设置 */}
<NotificationSettings />
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Download className="h-5 w-5" /> (Backup)
</CardTitle>
<CardDescription> JSON </CardDescription>
</CardHeader>
<CardContent>
<Button
onClick={() => {
const dataStr = JSON.stringify(treeData, null, 2)
const blob = new Blob([dataStr], { type: "application/json" })
const url = URL.createObjectURL(blob)
const link = document.createElement("a")
link.href = url
link.download = `family_tree_backup_${new Date().toISOString().split("T")[0]}.json`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}}
>
(Export JSON)
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Upload className="h-5 w-5" /> (Restore)
</CardTitle>
<CardDescription> JSON </CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Alert variant="destructive">
<AlertTriangle className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription></AlertDescription>
</Alert>
<div className="flex items-center gap-4">
<input
type="file"
ref={fileInputRef}
className="hidden"
accept=".json"
onChange={(e) => {
const file = e.target.files?.[0]
if (!file) return
const reader = new FileReader()
reader.onload = async (event) => {
try {
const json = JSON.parse(event.target?.result as string)
if (json.members && json.rootId) {
await loadData(json)
setImportStatus("导入成功!")
// Clear input so same file can be selected again if needed
if (fileInputRef.current) fileInputRef.current.value = ""
} else {
setImportStatus("错误:无效的数据格式")
}
} catch (err) {
console.error(err)
setImportStatus("错误:无法解析文件")
}
}
reader.readAsText(file)
}}
/>
<Button variant="outline" onClick={() => fileInputRef.current?.click()}>
...
</Button>
<span className="text-sm text-muted-foreground">{importStatus}</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="h-5 w-5" /> GEDCOM
</CardTitle>
<CardDescription>/ GEDCOM AncestryMyHeritage</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center gap-4">
<Button
variant="outline"
onClick={() => {
const gedcomText = exportToGedcom(treeData)
const blob = new Blob([gedcomText], { type: "text/plain;charset=utf-8" })
const url = URL.createObjectURL(blob)
const link = document.createElement("a")
link.href = url
link.download = `family_tree_${new Date().toISOString().split("T")[0]}.ged`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}}
>
<Download className="mr-2 h-4 w-4" />
GEDCOM
</Button>
<input
type="file"
ref={gedcomInputRef}
className="hidden"
accept=".ged,.gedcom"
onChange={(e) => {
const file = e.target.files?.[0]
if (!file) return
const reader = new FileReader()
reader.onload = async (event) => {
try {
const gedcomText = event.target?.result as string
const importedData = importFromGedcom(gedcomText)
await loadData(importedData)
setGedcomStatus("GEDCOM 导入成功!")
if (gedcomInputRef.current) gedcomInputRef.current.value = ""
} catch (err) {
console.error(err)
setGedcomStatus("错误:无法解析 GEDCOM 文件")
}
}
reader.readAsText(file)
}}
/>
<Button variant="outline" onClick={() => gedcomInputRef.current?.click()}>
<Upload className="mr-2 h-4 w-4" />
GEDCOM
</Button>
{gedcomStatus && <span className="text-sm text-muted-foreground">{gedcomStatus}</span>}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<RefreshCw className="h-5 w-5" />
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<Button
variant="destructive"
onClick={async () => {
if (confirm("确定要重置吗?所有更改将丢失。")) {
await resetData()
alert("数据已重置为演示状态。")
}
}}
>
</Button>
</CardContent>
</Card>
</div>
</main>
</div>
)
}