| // src/components/admin/AdminQuickActions.tsx | |
| import { Plus, Download, Upload, Shield, RefreshCw } from "lucide-react"; | |
| import { useState } from "react"; | |
| import { toast } from "react-toastify"; | |
| import api from "@/lib/api"; | |
| export function AdminQuickActions() { | |
| const [clearingCache, setClearingCache] = useState(false); | |
| const [exporting, setExporting] = useState(false); | |
| const handleClearCache = async () => { | |
| setClearingCache(true); | |
| try { | |
| const res = await api.post("/admin/system/clear-cache"); | |
| toast.success(res.data?.message || "System cache cleared successfully!"); | |
| } catch (error) { | |
| console.error(error); | |
| toast.error("Failed to clear system cache."); | |
| } finally { | |
| setClearingCache(false); | |
| } | |
| }; | |
| const handleExportData = async () => { | |
| setExporting(true); | |
| try { | |
| const response = await api.get("/admin/export/all", { | |
| responseType: "blob", | |
| }); | |
| const blob = new Blob([response.data], { type: "application/zip" }); | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement("a"); | |
| a.href = url; | |
| a.download = `backup-export-${new Date().toISOString().split("T")[0]}.zip`; | |
| a.click(); | |
| window.URL.revokeObjectURL(url); | |
| toast.success("System backup downloaded successfully!"); | |
| } catch (error) { | |
| console.error(error); | |
| toast.error("Failed to export backup data."); | |
| } finally { | |
| setExporting(false); | |
| } | |
| }; | |
| return ( | |
| <div className="bg-white/60 dark:bg-gray-800/60 backdrop-blur-md border border-gray-200/50 dark:border-gray-800/50 rounded-2xl p-6 shadow-xl relative overflow-hidden"> | |
| <div className="absolute top-0 left-0 w-20 h-20 bg-primary/5 rounded-full blur-2xl" /> | |
| <h2 className="text-lg font-semibold mb-1">Quick Tools</h2> | |
| <p className="text-xs text-gray-500 dark:text-gray-400 mb-5">Common administrator tasks</p> | |
| <div className="grid grid-cols-2 gap-4"> | |
| {/* Export Data */} | |
| <button | |
| onClick={handleExportData} | |
| disabled={exporting} | |
| className="flex flex-col items-center justify-center gap-2.5 p-4 rounded-xl bg-gray-50/50 dark:bg-gray-900/30 hover:bg-gray-100/50 dark:hover:bg-gray-800/30 border border-gray-100 dark:border-gray-800/60 transition group disabled:opacity-50" | |
| > | |
| <div className="w-10 h-10 rounded-full bg-emerald-500/10 dark:bg-emerald-500/20 text-emerald-600 dark:text-emerald-400 flex items-center justify-center group-hover:scale-110 transition duration-200"> | |
| {exporting ? <RefreshCw className="w-5 h-5 animate-spin" /> : <Download className="w-5 h-5" />} | |
| </div> | |
| <span className="text-xs font-semibold text-gray-700 dark:text-gray-300">Backup Data</span> | |
| </button> | |
| {/* Clear Cache */} | |
| <button | |
| onClick={handleClearCache} | |
| disabled={clearingCache} | |
| className="flex flex-col items-center justify-center gap-2.5 p-4 rounded-xl bg-gray-50/50 dark:bg-gray-900/30 hover:bg-gray-100/50 dark:hover:bg-gray-800/30 border border-gray-100 dark:border-gray-800/60 transition group disabled:opacity-50" | |
| > | |
| <div className="w-10 h-10 rounded-full bg-amber-500/10 dark:bg-amber-500/20 text-amber-600 dark:text-amber-400 flex items-center justify-center group-hover:scale-110 transition duration-200"> | |
| {clearingCache ? <RefreshCw className="w-5 h-5 animate-spin" /> : <Shield className="w-5 h-5" />} | |
| </div> | |
| <span className="text-xs font-semibold text-gray-700 dark:text-gray-300">Clear Cache</span> | |
| </button> | |
| {/* Create User Placeholder */} | |
| <button | |
| onClick={() => toast.info("User creation modal is under construction.")} | |
| className="flex flex-col items-center justify-center gap-2.5 p-4 rounded-xl bg-gray-50/50 dark:bg-gray-900/30 hover:bg-gray-100/50 dark:hover:bg-gray-800/30 border border-gray-100 dark:border-gray-800/60 transition group" | |
| > | |
| <div className="w-10 h-10 rounded-full bg-blue-500/10 dark:bg-blue-500/20 text-blue-600 dark:text-blue-400 flex items-center justify-center group-hover:scale-110 transition duration-200"> | |
| <Plus className="w-5 h-5" /> | |
| </div> | |
| <span className="text-xs font-semibold text-gray-700 dark:text-gray-300">Add User</span> | |
| </button> | |
| {/* Import Data Placeholder */} | |
| <button | |
| onClick={() => toast.info("Importing JSON backups will be available in v2.1")} | |
| className="flex flex-col items-center justify-center gap-2.5 p-4 rounded-xl bg-gray-50/50 dark:bg-gray-900/30 hover:bg-gray-100/50 dark:hover:bg-gray-800/30 border border-gray-100 dark:border-gray-800/60 transition group" | |
| > | |
| <div className="w-10 h-10 rounded-full bg-purple-500/10 dark:bg-purple-500/20 text-purple-600 dark:text-purple-400 flex items-center justify-center group-hover:scale-110 transition duration-200"> | |
| <Upload className="w-5 h-5" /> | |
| </div> | |
| <span className="text-xs font-semibold text-gray-700 dark:text-gray-300">Import Data</span> | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } |
Xet Storage Details
- Size:
- 5.2 kB
- Xet hash:
- 715dbf6d1440b61c6084b8a322c6ef4a49ea73bb5f0fec21da1d176de1b0f2a6
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.