refactor: standardize quotation marks across all files and improve code consistency

This commit is contained in:
Julien Froidefond
2025-11-27 11:40:30 +01:00
parent cc1e8c20a6
commit b2efade4d5
107 changed files with 9471 additions and 5952 deletions

View File

@@ -1,10 +1,16 @@
"use client"
"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 { 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,
@@ -15,13 +21,21 @@ import {
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Download, Trash2, Upload, RefreshCw, Database, FileJson, Tags } from "lucide-react"
import type { BankingData } from "@/lib/types"
} from "@/components/ui/alert-dialog";
import {
Download,
Trash2,
Upload,
RefreshCw,
Database,
FileJson,
Tags,
} from "lucide-react";
import type { BankingData } from "@/lib/types";
export default function SettingsPage() {
const { data, isLoading, refresh, update } = useBankingData()
const [importing, setImporting] = useState(false)
const { data, isLoading, refresh, update } = useBankingData();
const [importing, setImporting] = useState(false);
if (isLoading || !data) {
return (
@@ -31,72 +45,80 @@ export default function SettingsPage() {
<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 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"
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
const file = (e.target as HTMLInputElement).files?.[0];
if (!file) return;
setImporting(true)
setImporting(true);
try {
const content = await file.text()
const importedData = JSON.parse(content) as BankingData
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
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")
update(importedData);
alert("Données importées avec succès");
} catch (error) {
alert("Erreur lors de l'import")
alert("Erreur lors de l'import");
} finally {
setImporting(false)
setImporting(false);
}
}
input.click()
}
};
input.click();
};
const resetData = () => {
localStorage.removeItem("banking-app-data")
window.location.reload()
}
localStorage.removeItem("banking-app-data");
window.location.reload();
};
const clearAllCategories = async () => {
try {
const response = await fetch("/api/banking/transactions/clear-categories", {
method: "POST",
})
if (!response.ok) throw new Error("Erreur")
refresh()
alert("Catégories supprimées de toutes les opérations")
const response = await fetch(
"/api/banking/transactions/clear-categories",
{
method: "POST",
},
);
if (!response.ok) throw new Error("Erreur");
refresh();
alert("Catégories supprimées de toutes les opérations");
} catch (error) {
console.error(error)
alert("Erreur lors de la suppression des catégories")
console.error(error);
alert("Erreur lors de la suppression des catégories");
}
}
};
const categorizedCount = data.transactions.filter((t) => t.categoryId).length
const categorizedCount = data.transactions.filter((t) => t.categoryId).length;
return (
<div className="flex h-screen bg-background">
@@ -105,7 +127,9 @@ export default function SettingsPage() {
<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>
<p className="text-muted-foreground">
Gérez vos données et préférences
</p>
</div>
<Card>
@@ -114,25 +138,37 @@ export default function SettingsPage() {
<Database className="w-5 h-5" />
Données
</CardTitle>
<CardDescription>Exportez ou importez vos données pour les sauvegarder ou les transférer</CardDescription>
<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
{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">
<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}>
<Button
onClick={importData}
variant="outline"
className="flex-1 bg-transparent"
disabled={importing}
>
<Upload className="w-4 h-4 mr-2" />
{importing ? "Import..." : "Importer"}
</Button>
@@ -146,31 +182,45 @@ export default function SettingsPage() {
<Trash2 className="w-5 h-5" />
Zone dangereuse
</CardTitle>
<CardDescription>Actions irréversibles - procédez avec prudence</CardDescription>
<CardDescription>
Actions irréversibles - procédez avec prudence
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
{/* Supprimer catégories des opérations */}
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline" className="w-full justify-start border-orange-300 text-orange-700 hover:bg-orange-50">
<Button
variant="outline"
className="w-full justify-start border-orange-300 text-orange-700 hover:bg-orange-50"
>
<Tags className="w-4 h-4 mr-2" />
Supprimer les catégories des opérations
<span className="ml-auto text-xs text-muted-foreground">
{categorizedCount} opération{categorizedCount > 1 ? "s" : ""} catégorisée{categorizedCount > 1 ? "s" : ""}
{categorizedCount} opération
{categorizedCount > 1 ? "s" : ""} catégorisée
{categorizedCount > 1 ? "s" : ""}
</span>
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Supprimer toutes les catégories ?</AlertDialogTitle>
<AlertDialogTitle>
Supprimer toutes les catégories ?
</AlertDialogTitle>
<AlertDialogDescription>
Cette action va retirer la catégorie de {categorizedCount} opération{categorizedCount > 1 ? "s" : ""}.
Les catégories elles-mêmes ne seront pas supprimées, seulement leur affectation aux opérations.
Cette action va retirer la catégorie de {categorizedCount}{" "}
opération{categorizedCount > 1 ? "s" : ""}. Les catégories
elles-mêmes ne seront pas supprimées, seulement leur
affectation aux opérations.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Annuler</AlertDialogCancel>
<AlertDialogAction onClick={clearAllCategories} className="bg-orange-600 hover:bg-orange-700">
<AlertDialogAction
onClick={clearAllCategories}
className="bg-orange-600 hover:bg-orange-700"
>
Supprimer les affectations
</AlertDialogAction>
</AlertDialogFooter>
@@ -180,7 +230,10 @@ export default function SettingsPage() {
{/* Réinitialiser toutes les données */}
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive" className="w-full justify-start">
<Button
variant="destructive"
className="w-full justify-start"
>
<Trash2 className="w-4 h-4 mr-2" />
Réinitialiser toutes les données
</Button>
@@ -189,13 +242,17 @@ export default function SettingsPage() {
<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.
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">
<AlertDialogAction
onClick={resetData}
className="bg-red-600 hover:bg-red-700"
>
Supprimer tout
</AlertDialogAction>
</AlertDialogFooter>
@@ -210,17 +267,21 @@ export default function SettingsPage() {
<FileJson className="w-5 h-5" />
Format OFX
</CardTitle>
<CardDescription>Informations sur l'import de fichiers</CardDescription>
<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.
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.
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>
@@ -228,5 +289,5 @@ export default function SettingsPage() {
</div>
</main>
</div>
)
);
}