"use client"; import { useState } from "react"; import useSWR from "swr"; import { useAuth } from "@/contexts/auth-context"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Plus, Pencil, Trash2, KeyRound, Shield, Users } from "lucide-react"; import { toast } from "sonner"; const fetcher = (url: string) => fetch(url).then((r) => r.json()); const SECTIONS = [ { id: "dashboard", label: "Dashboard" }, { id: "components", label: "Components" }, { id: "products", label: "Products" }, { id: "production", label: "Production" }, { id: "supplier-pos", label: "Supplier POs" }, { id: "customer-orders", label: "Customer Orders" }, { id: "stock-history", label: "Stock History" }, { id: "stock-take", label: "Stock Take" }, { id: "logistics", label: "Logistics" }, { id: "suppliers", label: "Suppliers" }, { id: "customers", label: "Customers" }, ]; interface UserData { id: number; email: string; name: string; role: "admin" | "user"; is_active: boolean; permissions: { sections: string[]; can_view_financial: boolean; can_edit: boolean; can_create: boolean; can_delete: boolean; can_download: boolean; }; created_at: string; } const defaultPermissions = { sections: [] as string[], can_view_financial: false, can_edit: false, can_create: false, can_delete: false, can_download: false, }; export default function SettingsPage() { const { user: currentUser } = useAuth(); const { data: users = [], mutate } = useSWR("/api/users", fetcher); const [dialogOpen, setDialogOpen] = useState(false); const [editingUser, setEditingUser] = useState(null); const [passwordDialogOpen, setPasswordDialogOpen] = useState(false); const [passwordUserId, setPasswordUserId] = useState(null); const [newPassword, setNewPassword] = useState(""); const [saving, setSaving] = useState(false); const [form, setForm] = useState({ email: "", name: "", password: "", role: "user" as "admin" | "user", permissions: { ...defaultPermissions }, }); // Check if current user is admin if (currentUser?.role !== "admin") { return (

Access Denied

You don't have permission to access user settings.

); } function openCreateDialog() { setEditingUser(null); setForm({ email: "", name: "", password: "", role: "user", permissions: { ...defaultPermissions }, }); setDialogOpen(true); } function openEditDialog(user: UserData) { setEditingUser(user); setForm({ email: user.email, name: user.name, password: "", role: user.role, permissions: { ...defaultPermissions, ...(user.permissions || {}), sections: user.permissions?.sections || [], }, }); setDialogOpen(true); } function toggleSection(sectionId: string) { setForm((prev) => { const sections = prev.permissions.sections.includes(sectionId) ? prev.permissions.sections.filter((s) => s !== sectionId) : [...prev.permissions.sections, sectionId]; return { ...prev, permissions: { ...prev.permissions, sections }, }; }); } function togglePermission(key: keyof typeof defaultPermissions) { if (key === "sections") return; setForm((prev) => ({ ...prev, permissions: { ...prev.permissions, [key]: !prev.permissions[key], }, })); } async function handleSave() { if (!form.email || !form.name) { toast.error("Email and name are required"); return; } if (!editingUser && !form.password) { toast.error("Password is required for new users"); return; } setSaving(true); try { const url = editingUser ? `/api/users/${editingUser.id}` : "/api/users"; const method = editingUser ? "PUT" : "POST"; const payload: Record = { email: form.email, name: form.name, role: form.role, permissions: form.permissions, }; if (form.password) { payload.password = form.password; } const res = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Failed to save"); } toast.success(editingUser ? "User updated" : "User created"); setDialogOpen(false); mutate(); } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to save"); } finally { setSaving(false); } } async function handleDelete(userId: number) { if (userId === currentUser?.id) { toast.error("You cannot delete your own account"); return; } if (!confirm("Are you sure you want to delete this user?")) return; try { const res = await fetch(`/api/users/${userId}`, { method: "DELETE" }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Failed to delete"); } toast.success("User deleted"); mutate(); } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to delete"); } } function openPasswordDialog(userId: number) { setPasswordUserId(userId); setNewPassword(""); setPasswordDialogOpen(true); } async function handleResetPassword() { if (!newPassword || newPassword.length < 6) { toast.error("Password must be at least 6 characters"); return; } setSaving(true); try { const res = await fetch(`/api/users/${passwordUserId}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password: newPassword }), }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Failed to reset password"); } toast.success("Password updated"); setPasswordDialogOpen(false); } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to reset password"); } finally { setSaving(false); } } return (
{/* Header */}

User Management

Manage users, roles, and permissions

{/* Users Table */} Users {users.length} user{users.length !== 1 ? "s" : ""} registered Name Email Role Sections Permissions Actions {users.map((user) => ( {user.name} {user.email} {user.role} {user.role === "admin" ? ( All ) : ( {user.permissions?.sections?.length || 0} section{(user.permissions?.sections?.length || 0) !== 1 ? "s" : ""} )}
{user.role === "admin" ? ( Full Access ) : ( <> {user.permissions?.can_view_financial && Financial} {user.permissions?.can_edit && Edit} {user.permissions?.can_create && Create} {user.permissions?.can_delete && Delete} {user.permissions?.can_download && Download} )}
{user.id !== currentUser?.id && ( )}
))}
{/* User Dialog */} {editingUser ? "Edit User" : "Create User"}
{/* Basic Info */}
setForm({ ...form, name: e.target.value })} placeholder="Full name" />
setForm({ ...form, email: e.target.value })} placeholder="user@company.com" />
setForm({ ...form, password: e.target.value })} placeholder={editingUser ? "Leave blank to keep current" : "Min 6 characters"} />
{form.role === "user" && ( <> {/* Section Access */}

Select which sections this user can access

{SECTIONS.map((section) => (
toggleSection(section.id)} />
))}
{/* Permissions */}
togglePermission("can_view_financial")} />

See prices, costs, and financial data

togglePermission("can_edit")} />

Modify existing data

togglePermission("can_create")} />

Add new components, products, etc.

togglePermission("can_delete")} />

Remove data permanently

togglePermission("can_download")} />

Export CSVs and download reports (view only if disabled)

)} {form.role === "admin" && (

Admin users have full access

Admins can access all sections, view financial data, and perform all actions including user management.

)}
{/* Password Reset Dialog */} Reset Password
setNewPassword(e.target.value)} placeholder="Min 6 characters" className="mt-2" />
); }