mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 10:40:58 +00:00
225 lines
10 KiB
TypeScript
225 lines
10 KiB
TypeScript
import { useState } from "react";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/shared/common/ui/card";
|
|
import {
|
|
Tabs,
|
|
TabsContent,
|
|
TabsList,
|
|
TabsTrigger,
|
|
} from "@/shared/common/ui/tabs";
|
|
import { Input } from "@/shared/common/ui/input";
|
|
import { Button } from "@/shared/common/ui/button";
|
|
import { Shield, Save, Trash2, Plus, Edit2 } from "lucide-react";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/shared/common/ui/dialog";
|
|
import PasswordSettingsForm from "@/super-admin/components/settings/PasswordSettingsForm";
|
|
import { usePasswordSettingsQuery, usePasswordSettingsMutations } from "@/super-admin/hooks/usePasswordSettings";
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
} from "@/shared/common/ui/alert-dialog";
|
|
import { toast } from "sonner";
|
|
|
|
export default function SettingsPage() {
|
|
const [createDialogOpen, setCreateDialogOpen] = useState(false);
|
|
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
|
|
const { data: passwordSettings, refetch: refetchPasswordSettings } = usePasswordSettingsQuery();
|
|
const { delete: deleteMutation } = usePasswordSettingsMutations();
|
|
|
|
const handleDeletePasswordSettings = async () => {
|
|
if (!passwordSettings?.id) {
|
|
toast.error("No password settings to delete");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
console.log("Attempting to delete password settings with ID:", passwordSettings.id);
|
|
await deleteMutation.mutateAsync(passwordSettings.id);
|
|
console.log("Delete successful, closing dialog");
|
|
setDeleteDialogOpen(false);
|
|
} catch (error) {
|
|
console.error("Delete error:", error);
|
|
toast.error("Failed to delete password settings");
|
|
}
|
|
};
|
|
|
|
const handleEditPasswordSettings = () => {
|
|
if (passwordSettings?.id) {
|
|
setEditDialogOpen(true);
|
|
}
|
|
};
|
|
|
|
const handleCreateSuccess = () => {
|
|
setCreateDialogOpen(false);
|
|
refetchPasswordSettings();
|
|
};
|
|
|
|
const handleEditSuccess = () => {
|
|
setEditDialogOpen(false);
|
|
refetchPasswordSettings();
|
|
};
|
|
|
|
return (
|
|
<div className="p-6 space-y-6">
|
|
<Card className="shadow-lg border-gray-200 dark:border-gray-700">
|
|
<CardHeader>
|
|
<CardTitle className="text-xl font-semibold">
|
|
System Settings
|
|
</CardTitle>
|
|
<CardDescription>
|
|
Configure system-wide settings for your organization
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Tabs defaultValue="security" className="w-full">
|
|
{/* Only Security Tab */}
|
|
{/* Security Settings */}
|
|
<TabsContent value="security" className="space-y-4">
|
|
<div className="flex justify-between items-center mb-4">
|
|
<h3 className="text-lg font-semibold">Password Settings</h3>
|
|
</div>
|
|
|
|
{!passwordSettings ? (
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<p className="text-center text-gray-600 dark:text-gray-400 mb-4">
|
|
No password settings configured yet
|
|
</p>
|
|
<div className="flex justify-center">
|
|
<Dialog open={createDialogOpen} onOpenChange={setCreateDialogOpen}>
|
|
<DialogTrigger asChild>
|
|
<Button className="bg-primary hover:bg-primary/90">
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
Create Password Settings
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
<DialogHeader>
|
|
<DialogTitle>Create Password Settings</DialogTitle>
|
|
</DialogHeader>
|
|
<PasswordSettingsForm
|
|
onSuccessCallback={handleCreateSuccess}
|
|
isDialogForm={true}
|
|
/>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
) : (
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<div className="border rounded-lg overflow-hidden">
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr className="bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
|
|
<th className="px-6 py-3 text-left text-sm font-semibold text-gray-900 dark:text-white">Setting</th>
|
|
<th className="px-6 py-3 text-left text-sm font-semibold text-gray-900 dark:text-white">Value</th>
|
|
<th className="px-6 py-3 text-right text-sm font-semibold text-gray-900 dark:text-white">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr className="border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">Minimum Password Length</td>
|
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-400">{passwordSettings.minimumPasswordLength}</td>
|
|
<td rowSpan={5} className="px-6 py-4 text-right">
|
|
<div className="flex justify-end gap-2">
|
|
<Dialog open={editDialogOpen} onOpenChange={setEditDialogOpen}>
|
|
<DialogTrigger asChild>
|
|
<Button variant="outline" size="sm" onClick={handleEditPasswordSettings}>
|
|
<Edit2 className="h-4 w-4 mr-2" />
|
|
Update
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
<DialogHeader>
|
|
<DialogTitle>Update Password Settings</DialogTitle>
|
|
</DialogHeader>
|
|
<PasswordSettingsForm
|
|
onSuccessCallback={handleEditSuccess}
|
|
isDialogForm={true}
|
|
/>
|
|
</DialogContent>
|
|
</Dialog>
|
|
<Button
|
|
variant="destructive"
|
|
size="sm"
|
|
onClick={() => setDeleteDialogOpen(true)}>
|
|
<Trash2 className="h-4 w-4 mr-2" />
|
|
Delete
|
|
</Button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr className="border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">Maximum Password Length</td>
|
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-400">{passwordSettings.maximumPasswordLength}</td>
|
|
</tr>
|
|
<tr className="border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">Password Expiry (Days)</td>
|
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-400">{passwordSettings.passwordExpiry}</td>
|
|
</tr>
|
|
<tr className="border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">Session Timeout (Minutes)</td>
|
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-400">{passwordSettings.sessionTimeout}</td>
|
|
</tr>
|
|
<tr className="hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">Default Password Enabled</td>
|
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-400">
|
|
{passwordSettings.isDefaultPasswordEnabled ? "Yes" : "No"}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
</TabsContent>
|
|
</Tabs>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Delete Confirmation Dialog */}
|
|
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Delete Password Settings</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
Are you sure you want to delete the password settings? This action cannot be undone.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<div className="flex justify-end gap-3">
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<Button
|
|
onClick={handleDeletePasswordSettings}
|
|
className="bg-red-600 hover:bg-red-700"
|
|
disabled={deleteMutation.isPending}>
|
|
{deleteMutation.isPending ? "Deleting..." : "Delete"}
|
|
</Button>
|
|
</div>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</div>
|
|
);
|
|
}
|
|
|