'use client'; import { useState, useEffect, useCallback } from 'react'; import { Box, TextField, Select, MenuItem, FormControl, InputLabel, Card, CardContent, Alert, Chip, Avatar, IconButton, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from '@mui/material'; import { DataGrid, GridColDef, GridActionsCellItem, GridRowParams, GridPaginationModel } from '@mui/x-data-grid'; import { Visibility, Block, Delete, AdminPanelSettings, Person, PersonOff } from '@mui/icons-material'; interface User { id: string; email: string; name: string | null; role: string; createdAt: string; lastLoginAt: string | null; _count: { chatConversations: number; prayerRequests: number; bookmarks: number; }; } interface UserDetailModalProps { userId: string | null; open: boolean; onClose: () => void; onUserUpdate: (userId: string, action: string) => void; } function UserDetailModal({ userId, open, onClose, onUserUpdate }: UserDetailModalProps) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (userId && open) { const fetchUser = async () => { setLoading(true); try { const response = await fetch(`/api/admin/users/${userId}`, { credentials: 'include' }); if (response.ok) { const data = await response.json(); setUser(data.user); } } catch (error) { console.error('Error fetching user:', error); } finally { setLoading(false); } }; fetchUser(); } }, [userId, open]); const handleAction = async (action: string) => { if (!userId) return; try { const response = await fetch(`/api/admin/users/${userId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ action }) }); if (response.ok) { onUserUpdate(userId, action); onClose(); } } catch (error) { console.error('Error updating user:', error); } }; return ( User Details {loading ? ( Loading... ) : user ? ( {user.name || 'Unknown User'} {user.email} Account Information Joined: {new Date(user.createdAt).toLocaleDateString()} Last Login: {user.lastLoginAt ? new Date(user.lastLoginAt).toLocaleDateString() : 'Never'} Activity Summary Conversations: {user._count.chatConversations} Prayer Requests: {user._count.prayerRequests} Bookmarks: {user._count.bookmarks} Notes: {user._count.notes} {user.role !== 'admin' && ( {user.role === 'suspended' ? ( ) : ( )} {user.role === 'user' && ( )} )} ) : ( User not found )} ); } export function UserDataGrid() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [paginationModel, setPaginationModel] = useState({ page: 0, pageSize: 10, }); const [rowCount, setRowCount] = useState(0); const [search, setSearch] = useState(''); const [roleFilter, setRoleFilter] = useState('all'); const [selectedUserId, setSelectedUserId] = useState(null); const [modalOpen, setModalOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [userToDelete, setUserToDelete] = useState(null); const fetchUsers = useCallback(async () => { setLoading(true); try { const params = new URLSearchParams({ page: paginationModel.page.toString(), pageSize: paginationModel.pageSize.toString(), search, role: roleFilter }); const response = await fetch(`/api/admin/users?${params}`, { credentials: 'include' }); if (response.ok) { const data = await response.json(); setUsers(data.users); setRowCount(data.pagination.total); } else { setError('Failed to load users'); } } catch (error) { setError('Network error loading users'); } finally { setLoading(false); } }, [paginationModel, search, roleFilter]); useEffect(() => { fetchUsers(); }, [fetchUsers]); const handleUserUpdate = useCallback((userId: string, action: string) => { // Refresh the data after user update fetchUsers(); }, [fetchUsers]); const handleViewUser = (params: GridRowParams) => { setSelectedUserId(params.id as string); setModalOpen(true); }; const handleDeleteUser = (params: GridRowParams) => { setUserToDelete(params.row as User); setDeleteDialogOpen(true); }; const confirmDeleteUser = async () => { if (!userToDelete) return; try { const response = await fetch(`/api/admin/users/${userToDelete.id}`, { method: 'DELETE', credentials: 'include' }); if (response.ok) { fetchUsers(); setDeleteDialogOpen(false); setUserToDelete(null); } } catch (error) { console.error('Error deleting user:', error); } }; const getRoleChip = (role: string) => { const colors: Record = { admin: 'error', moderator: 'warning', user: 'primary', suspended: 'default' }; return ( ); }; const columns: GridColDef[] = [ { field: 'name', headerName: 'User', flex: 1, minWidth: 200, renderCell: (params) => ( {(params.row.name || params.row.email)[0].toUpperCase()} {params.row.name || 'Unknown User'} {params.row.email} ) }, { field: 'role', headerName: 'Role', width: 120, renderCell: (params) => getRoleChip(params.value) }, { field: 'createdAt', headerName: 'Joined', width: 120, renderCell: (params) => new Date(params.value).toLocaleDateString() }, { field: 'lastLoginAt', headerName: 'Last Login', width: 120, renderCell: (params) => params.value ? new Date(params.value).toLocaleDateString() : 'Never' }, { field: 'activity', headerName: 'Activity', width: 120, renderCell: (params) => ( {params.row._count.chatConversations} chats {params.row._count.prayerRequests} prayers ) }, { field: 'actions', type: 'actions', headerName: 'Actions', width: 120, getActions: (params) => { const actions = [ } label="View" onClick={() => handleViewUser(params)} /> ]; // Only show delete for non-admin users if (params.row.role !== 'admin') { actions.push( } label="Delete" onClick={() => handleDeleteUser(params)} /> ); } return actions; } } ]; return ( {/* Filters */} setSearch(e.target.value)} size="small" sx={{ minWidth: 250 }} /> Role {error && ( {error} )} {/* Data Grid */} {/* User Detail Modal */} setModalOpen(false)} onUserUpdate={handleUserUpdate} /> {/* Delete Confirmation Dialog */} setDeleteDialogOpen(false)} maxWidth="sm" fullWidth > Delete User Are you sure you want to delete user {userToDelete?.name || userToDelete?.email}? This action cannot be undone. All user data including conversations, prayer requests, and bookmarks will be permanently deleted. ); }