feat: add data export functionality to settings page and update admin reports table
- Introduced "Export Data" card in settings for exporting user data as a JSON file. - Added `exportData` method to `UserService` for handling data export requests. - Updated admin reports table with a new "Cible" column to display target information.
This commit is contained in:
@@ -104,6 +104,7 @@ export default function AdminReportsPage() {
|
|||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Signalé par</TableHead>
|
<TableHead>Signalé par</TableHead>
|
||||||
|
<TableHead>Cible</TableHead>
|
||||||
<TableHead>Raison</TableHead>
|
<TableHead>Raison</TableHead>
|
||||||
<TableHead>Description</TableHead>
|
<TableHead>Description</TableHead>
|
||||||
<TableHead>Statut</TableHead>
|
<TableHead>Statut</TableHead>
|
||||||
@@ -114,13 +115,13 @@ export default function AdminReportsPage() {
|
|||||||
<TableBody>
|
<TableBody>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={5} className="text-center py-8">
|
<TableCell colSpan={7} className="text-center py-8">
|
||||||
Chargement...
|
Chargement...
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : reports.length === 0 ? (
|
) : reports.length === 0 ? (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={5} className="text-center py-8">
|
<TableCell colSpan={7} className="text-center py-8">
|
||||||
Aucun signalement trouvé.
|
Aucun signalement trouvé.
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
Sun,
|
Sun,
|
||||||
Trash2,
|
Trash2,
|
||||||
User as UserIcon,
|
User as UserIcon,
|
||||||
|
Download,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
@@ -69,6 +70,7 @@ export default function SettingsPage() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isSaving, setIsSaving] = React.useState(false);
|
const [isSaving, setIsSaving] = React.useState(false);
|
||||||
const [isDeleting, setIsDeleting] = React.useState(false);
|
const [isDeleting, setIsDeleting] = React.useState(false);
|
||||||
|
const [isExporting, setIsExporting] = React.useState(false);
|
||||||
const [mounted, setMounted] = React.useState(false);
|
const [mounted, setMounted] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@@ -144,6 +146,29 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleExportData = async () => {
|
||||||
|
setIsExporting(true);
|
||||||
|
try {
|
||||||
|
const data = await UserService.exportData();
|
||||||
|
const blob = new Blob([JSON.stringify(data, null, 2)], {
|
||||||
|
type: "application/json",
|
||||||
|
});
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute("download", `memegoat-data-${user?.username}.json`);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
toast.success("Vos données ont été exportées avec succès.");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Erreur lors de l'exportation des données.");
|
||||||
|
} finally {
|
||||||
|
setIsExporting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-2xl mx-auto py-12 px-4">
|
<div className="max-w-2xl mx-auto py-12 px-4">
|
||||||
<div className="flex items-center gap-3 mb-8">
|
<div className="flex items-center gap-3 mb-8">
|
||||||
@@ -294,6 +319,47 @@ export default function SettingsPage() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card className="border-none shadow-sm">
|
||||||
|
<CardHeader className="pb-4">
|
||||||
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
<Download className="h-5 w-5 text-primary" />
|
||||||
|
<CardTitle>Portabilité des données</CardTitle>
|
||||||
|
</div>
|
||||||
|
<CardDescription>
|
||||||
|
Conformément au RGPD, vous pouvez exporter l'intégralité de vos données rattachées à votre compte.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 p-4 rounded-lg bg-white dark:bg-zinc-900 border">
|
||||||
|
<div className="space-y-1">
|
||||||
|
<p className="font-bold">Exporter mes données</p>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Téléchargez un fichier JSON contenant votre profil, vos mèmes et vos favoris.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={handleExportData}
|
||||||
|
disabled={isExporting}
|
||||||
|
className="font-semibold"
|
||||||
|
>
|
||||||
|
{isExporting ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
Exportation...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Download className="h-4 w-4 mr-2" />
|
||||||
|
Exporter mes données
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card className="border-destructive/20 shadow-sm bg-destructive/5">
|
<Card className="border-destructive/20 shadow-sm bg-destructive/5">
|
||||||
<CardHeader className="pb-4">
|
<CardHeader className="pb-4">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
|||||||
@@ -53,4 +53,9 @@ export const UserService = {
|
|||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async exportData(): Promise<any> {
|
||||||
|
const { data } = await api.get("/users/me/export");
|
||||||
|
return data;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user