188 lines
6.8 KiB
TypeScript
188 lines
6.8 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { Sidebar } from "@/components/dashboard/sidebar"
|
|
import { useBankingData } from "@/lib/hooks"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
AlertDialogTrigger,
|
|
} from "@/components/ui/alert-dialog"
|
|
import { Download, Trash2, Upload, RefreshCw, Database, FileJson } from "lucide-react"
|
|
import type { BankingData } from "@/lib/types"
|
|
|
|
export default function SettingsPage() {
|
|
const { data, isLoading, refresh, update } = useBankingData()
|
|
const [importing, setImporting] = useState(false)
|
|
|
|
if (isLoading || !data) {
|
|
return (
|
|
<div className="flex h-screen">
|
|
<Sidebar />
|
|
<main className="flex-1 flex items-center justify-center">
|
|
<RefreshCw className="w-8 h-8 animate-spin text-muted-foreground" />
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const exportData = () => {
|
|
const dataStr = JSON.stringify(data, null, 2)
|
|
const blob = new Blob([dataStr], { type: "application/json" })
|
|
const url = URL.createObjectURL(blob)
|
|
const a = document.createElement("a")
|
|
a.href = url
|
|
a.download = `fintrack-backup-${new Date().toISOString().split("T")[0]}.json`
|
|
document.body.appendChild(a)
|
|
a.click()
|
|
document.body.removeChild(a)
|
|
URL.revokeObjectURL(url)
|
|
}
|
|
|
|
const importData = () => {
|
|
const input = document.createElement("input")
|
|
input.type = "file"
|
|
input.accept = ".json"
|
|
input.onchange = async (e) => {
|
|
const file = (e.target as HTMLInputElement).files?.[0]
|
|
if (!file) return
|
|
|
|
setImporting(true)
|
|
try {
|
|
const content = await file.text()
|
|
const importedData = JSON.parse(content) as BankingData
|
|
|
|
// Validate structure
|
|
if (!importedData.accounts || !importedData.transactions || !importedData.categories || !importedData.folders) {
|
|
alert("Format de fichier invalide")
|
|
return
|
|
}
|
|
|
|
update(importedData)
|
|
alert("Données importées avec succès")
|
|
} catch (error) {
|
|
alert("Erreur lors de l'import")
|
|
} finally {
|
|
setImporting(false)
|
|
}
|
|
}
|
|
input.click()
|
|
}
|
|
|
|
const resetData = () => {
|
|
localStorage.removeItem("banking-app-data")
|
|
window.location.reload()
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-screen bg-background">
|
|
<Sidebar />
|
|
<main className="flex-1 overflow-auto">
|
|
<div className="p-6 space-y-6 max-w-2xl">
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-foreground">Paramètres</h1>
|
|
<p className="text-muted-foreground">Gérez vos données et préférences</p>
|
|
</div>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Database className="w-5 h-5" />
|
|
Données
|
|
</CardTitle>
|
|
<CardDescription>Exportez ou importez vos données pour les sauvegarder ou les transférer</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="flex items-center justify-between p-4 bg-muted rounded-lg">
|
|
<div>
|
|
<p className="font-medium">Statistiques</p>
|
|
<p className="text-sm text-muted-foreground">
|
|
{data.accounts.length} comptes, {data.transactions.length} transactions, {data.categories.length}{" "}
|
|
catégories
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-2">
|
|
<Button onClick={exportData} variant="outline" className="flex-1 bg-transparent">
|
|
<Download className="w-4 h-4 mr-2" />
|
|
Exporter (JSON)
|
|
</Button>
|
|
<Button onClick={importData} variant="outline" className="flex-1 bg-transparent" disabled={importing}>
|
|
<Upload className="w-4 h-4 mr-2" />
|
|
{importing ? "Import..." : "Importer"}
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card className="border-red-200">
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2 text-red-600">
|
|
<Trash2 className="w-5 h-5" />
|
|
Zone dangereuse
|
|
</CardTitle>
|
|
<CardDescription>Actions irréversibles - procédez avec prudence</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button variant="destructive">
|
|
<Trash2 className="w-4 h-4 mr-2" />
|
|
Réinitialiser toutes les données
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Êtes-vous sûr ?</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
Cette action supprimera définitivement tous vos comptes, transactions, catégories et dossiers.
|
|
Cette action est irréversible.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Annuler</AlertDialogCancel>
|
|
<AlertDialogAction onClick={resetData} className="bg-red-600 hover:bg-red-700">
|
|
Supprimer tout
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<FileJson className="w-5 h-5" />
|
|
Format OFX
|
|
</CardTitle>
|
|
<CardDescription>Informations sur l'import de fichiers</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="prose prose-sm text-muted-foreground">
|
|
<p>
|
|
L'application accepte les fichiers au format OFX (Open Financial Exchange) ou QFX. Ces fichiers sont
|
|
généralement disponibles depuis l'espace client de votre banque.
|
|
</p>
|
|
<p className="mt-2">
|
|
Lors de l'import, les transactions sont automatiquement catégorisées selon les mots-clés définis. Les
|
|
doublons sont détectés et ignorés automatiquement.
|
|
</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|