import { DeleteOutlined, EditOutlined, PlusOutlined, UserOutlined } from "@ant-design/icons"; import { useTranslate } from "@refinedev/core"; import { Button, Form, Input, message, Modal, Popconfirm, Select, Space, Table, Tag, Typography } from "antd"; import React, { useCallback, useEffect, useState } from "react"; import { hasRole, useAuth, User } from "../../contexts/auth"; import { getAPIURL } from "../../utils/url"; const { Title, Text } = Typography; interface UserFormValues { username: string; password?: string; role: "admin" | "editor" | "operator" | "viewer"; } export const UserSettings: React.FC = () => { const t = useTranslate(); const { user: currentUser, token, authStatus, logout } = useAuth(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [editingUser, setEditingUser] = useState(null); const [form] = Form.useForm(); const apiUrl = getAPIURL(); const fetchUsers = useCallback(async () => { if (!token) return; setLoading(true); try { const res = await fetch(`${apiUrl}/auth/users`, { headers: { Authorization: `Bearer ${token}` }, }); if (res.ok) { setUsers(await res.json()); } } catch (err) { console.error("Failed to fetch users:", err); } finally { setLoading(false); } }, [apiUrl, token]); useEffect(() => { if (authStatus?.enabled && hasRole(currentUser, "admin")) { fetchUsers(); } }, [authStatus, currentUser, fetchUsers]); const handleCreate = async (values: UserFormValues) => { try { const res = await fetch(`${apiUrl}/auth/users`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify(values), }); if (!res.ok) { const error = await res.json(); throw new Error(error.detail || "Failed to create user"); } message.success(t("settings.users.created")); setModalOpen(false); form.resetFields(); fetchUsers(); } catch (err) { message.error(err instanceof Error ? err.message : "Failed to create user"); } }; const handleUpdate = async (values: UserFormValues) => { if (!editingUser) return; try { const body: Partial = { role: values.role }; if (values.password) { body.password = values.password; } const res = await fetch(`${apiUrl}/auth/users/${editingUser.id}`, { method: "PATCH", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!res.ok) { const error = await res.json(); throw new Error(error.detail || "Failed to update user"); } message.success(t("settings.users.updated")); setModalOpen(false); setEditingUser(null); form.resetFields(); fetchUsers(); } catch (err) { message.error(err instanceof Error ? err.message : "Failed to update user"); } }; const handleDelete = async (userId: number) => { try { const res = await fetch(`${apiUrl}/auth/users/${userId}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) { const error = await res.json(); throw new Error(error.detail || "Failed to delete user"); } message.success(t("settings.users.deleted")); fetchUsers(); } catch (err) { message.error(err instanceof Error ? err.message : "Failed to delete user"); } }; const openCreateModal = () => { setEditingUser(null); form.resetFields(); form.setFieldsValue({ role: "viewer" }); setModalOpen(true); }; const openEditModal = (user: User) => { setEditingUser(user); form.setFieldsValue({ username: user.username, role: user.role, password: undefined }); setModalOpen(true); }; const roleColors: Record = { admin: "red", editor: "blue", operator: "green", viewer: "default", }; // If auth is not enabled, show message if (!authStatus?.enabled) { return (
{t("settings.users.auth_disabled")} {t("settings.users.auth_disabled_hint")}
); } // If user is not admin, show access denied if (!hasRole(currentUser, "admin")) { return (
{t("settings.users.admin_required")} {t("settings.users.admin_required_hint")}
); } return ( <>
{t("settings.users.title")}
dataSource={users} rowKey="id" loading={loading} pagination={false} columns={[ { title: t("settings.users.username"), dataIndex: "username", key: "username", render: (username: string, record: User) => ( {username} {record.id === currentUser?.id && {t("settings.users.you")}} ), }, { title: t("settings.users.role"), dataIndex: "role", key: "role", render: (role: string) => {role.toUpperCase()}, }, { title: t("settings.users.status"), dataIndex: "is_active", key: "is_active", render: (isActive: boolean) => ( {isActive ? t("settings.users.active") : t("settings.users.inactive")} ), }, { title: t("settings.users.actions"), key: "actions", width: 120, render: (_: unknown, record: User) => ( )} ); }; export default UserSettings;