2026-02-15 17:38:16 +01:00

190 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. 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 { SettingsSection } from '@/components/settings'
import { Button } from '@/components/ui/button'
import { Download, Upload, Trash2, Loader2 } from 'lucide-react'
import { toast } from 'sonner'
import { useLanguage } from '@/lib/i18n'
export default function DataSettingsPage() {
const { t } = useLanguage()
const [isExporting, setIsExporting] = useState(false)
const [isImporting, setIsImporting] = useState(false)
const [isDeleting, setIsDeleting] = useState(false)
const handleExport = async () => {
setIsExporting(true)
try {
const response = await fetch('/api/notes/export')
if (response.ok) {
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `keep-notes-export-${new Date().toISOString().split('T')[0]}.json`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
toast.success(t('dataManagement.export.success'))
}
} catch (error) {
console.error('Export error:', error)
toast.error(t('dataManagement.export.failed'))
} finally {
setIsExporting(false)
}
}
const handleImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0]
if (!file) return
setIsImporting(true)
try {
const formData = new FormData()
formData.append('file', file)
const response = await fetch('/api/notes/import', {
method: 'POST',
body: formData
})
if (response.ok) {
const result = await response.json()
toast.success(t('dataManagement.import.success', { count: result.count }))
window.location.reload()
} else {
throw new Error('Import failed')
}
} catch (error) {
console.error('Import error:', error)
toast.error(t('dataManagement.import.failed'))
} finally {
setIsImporting(false)
event.target.value = ''
}
}
const handleDeleteAll = async () => {
if (!confirm(t('dataManagement.delete.confirm'))) {
return
}
setIsDeleting(true)
try {
const response = await fetch('/api/notes/delete-all', { method: 'POST' })
if (response.ok) {
toast.success(t('dataManagement.delete.success'))
window.location.reload()
}
} catch (error) {
console.error('Delete error:', error)
toast.error(t('dataManagement.delete.failed'))
} finally {
setIsDeleting(false)
}
}
return (
<div className="space-y-6">
<div>
<h1 className="text-3xl font-bold mb-2">{t('dataManagement.title')}</h1>
<p className="text-gray-600 dark:text-gray-400">
{t('dataManagement.toolsDescription')}
</p>
</div>
<SettingsSection
title={`💾 ${t('dataManagement.export.title')}`}
icon={<span className="text-2xl">💾</span>}
description={t('dataManagement.export.description')}
>
<div className="flex items-center justify-between py-4">
<div>
<p className="font-medium">{t('dataManagement.export.title')}</p>
<p className="text-sm text-gray-600 dark:text-gray-400">
{t('dataManagement.export.description')}
</p>
</div>
<Button
onClick={handleExport}
disabled={isExporting}
>
{isExporting ? (
<Loader2 className="h-4 w-4 animate-spin mr-2" />
) : (
<Download className="h-4 w-4 mr-2" />
)}
{isExporting ? t('dataManagement.exporting') : t('dataManagement.export.button')}
</Button>
</div>
</SettingsSection>
<SettingsSection
title={`📥 ${t('dataManagement.import.title')}`}
icon={<span className="text-2xl">📥</span>}
description={t('dataManagement.import.description')}
>
<div className="flex items-center justify-between py-4">
<div>
<p className="font-medium">{t('dataManagement.import.title')}</p>
<p className="text-sm text-gray-600 dark:text-gray-400">
{t('dataManagement.import.description')}
</p>
</div>
<div>
<input
type="file"
accept=".json"
onChange={handleImport}
disabled={isImporting}
className="hidden"
id="import-file"
/>
<Button
onClick={() => document.getElementById('import-file')?.click()}
disabled={isImporting}
>
{isImporting ? (
<Loader2 className="h-4 w-4 animate-spin mr-2" />
) : (
<Upload className="h-4 w-4 mr-2" />
)}
{isImporting ? t('dataManagement.importing') : t('dataManagement.import.button')}
</Button>
</div>
</div>
</SettingsSection>
<SettingsSection
title={`⚠️ ${t('dataManagement.dangerZone')}`}
icon={<span className="text-2xl"></span>}
description={t('dataManagement.dangerZoneDescription')}
>
<div className="flex items-center justify-between py-4 border-t border-red-200 dark:border-red-900">
<div>
<p className="font-medium text-red-600 dark:text-red-400">{t('dataManagement.delete.title')}</p>
<p className="text-sm text-gray-600 dark:text-gray-400">
{t('dataManagement.delete.description')}
</p>
</div>
<Button
variant="destructive"
onClick={handleDeleteAll}
disabled={isDeleting}
>
{isDeleting ? (
<Loader2 className="h-4 w-4 animate-spin mr-2" />
) : (
<Trash2 className="h-4 w-4 mr-2" />
)}
{isDeleting ? t('dataManagement.deleting') : t('dataManagement.delete.button')}
</Button>
</div>
</SettingsSection>
</div>
)
}