mkcart / frontend /src /components /UserManagement.jsx
Kumar
updated
c2efbe6
import React, { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
Users, Search, RefreshCw, Plus, Eye, Edit, Trash2, ChevronLeft, ChevronRight, X, User
} from 'lucide-react';
import styles from './UserManagement.module.css';
const UserManagement = ({
users,
usersLoading,
userPagination,
setUserPagination,
userFilter,
setUserFilter,
searchQuery,
setSearchQuery,
lastUpdate,
formatLastUpdate,
formatDate,
handleManualRefresh,
setShowAddUserModal,
setSelectedUser,
setShowUserModal,
setEditingUser,
deleteUser,
setIsFormActive
}) => {
return (
<div className={styles['management-content']}>
<div className={`${styles['content-header']} ${styles['user-management-header']}`}>
{}
<div className={styles['order-header-column-1']}>
<div className={styles['order-header-title-section']}>
<h2 className={styles['order-header-title']}>User Management</h2>
<span className={styles['order-header-badge']}>
Last updated: {formatLastUpdate(lastUpdate)}
</span>
</div>
<div className={styles['user-header-search-section']}>
<div className={styles['search-bar']} style={{position:'relative'}}>
<Search size={20} />
<input
type="text"
placeholder="Search users..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
{searchQuery && (
<button
type="button"
style={{position:'absolute',right:8,top:'50%',transform:'translateY(-50%)',background:'none',border:'none',padding:0,cursor:'pointer'}}
onClick={() => { setSearchQuery(''); handleManualRefresh(); }}
aria-label="Clear search"
>
<X size={16} />
</button>
)}
</div>
<button
className={`${styles['add-btn']} ${styles['adv-btn']} ${styles['order-refresh-btn']}`}
onClick={() => {
handleManualRefresh();
}}
disabled={usersLoading}
>
<RefreshCw size={20} className={usersLoading ? styles['animate-spin'] : ''} />
{usersLoading ? 'Loading...' : 'Refresh'}
</button>
</div>
</div>
{}
<div className={styles['user-header-column-2']}>
<select
value={userFilter}
onChange={(e) => setUserFilter(e.target.value)}
className={`${styles['filter-select']} ${styles['glass']} ${styles['user-filter-select']}`}
>
<option value="all">All Users</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
<button
className={`${styles['add-btn']} ${styles['adv-btn']} ${styles['user-add-btn']}`}
onClick={() => {
setShowAddUserModal(true);
setIsFormActive(true);
}}
>
<Plus size={20} />
Add User
</button>
</div>
</div>
<div className={`${styles['data-table']} ${styles['glass']} ${styles['user-data-table']}`} style={{boxShadow:'0 8px 32px var(--color-shadow)',marginTop:24}}>
<div className={`${styles['table-header']} ${styles['user-table-header']}`} style={{position:'sticky',top:0,zIndex:2}}>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>Name</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>Email</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>City</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>Phone</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>Status</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>Joined</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>Actions</div>
</div>
{}
{usersLoading ? (
Array.from({length: userPagination.limit}).map((_,i) => (
<div key={i} className={`${styles['table-row']} ${styles['user-table-row']}`} style={{opacity:0.7}}>
{[...Array(8)].map((_,j) => (
<div key={j} className={`${styles['table-cell']} ${styles['user-table-cell']}`}>
<div className={styles['skeleton-shimmer']} style={{height:18,borderRadius:6,background:'linear-gradient(90deg,rgba(200,200,220,0.08) 25%,rgba(180,180,200,0.18) 50%,rgba(200,200,220,0.08) 75%)',animation:'shimmer 1.2s infinite linear'}}></div>
</div>
))}
</div>
))
) : users.length > 0 ? (
users.map((user, index) => (
<motion.div
key={user._id}
className={`${styles['table-row']} ${styles['user-table-row']} ${styles['user-table-row-hover']} ${index % 2 === 0 ? styles['user-table-row-alternate'] : ''}`}
whileHover={{scale:1.01,boxShadow:'0 4px 24px var(--color-shadow)'}}
style={{transition:'box-shadow 0.2s,background 0.3s'}}
>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>
<div className={styles['user-info']}>
<div className={`${styles['user-avatar']} ${styles['glass']}`}>
<User size={20} />
</div>
<span>{user.name}</span>
</div>
</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>{user.email}</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>{user.recentCity}</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-left']}`}>{user.recentPhone}</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>
<span className={`${styles['status-badge']} ${user.isActive ? styles['active'] : styles['inactive']}`}>{user.isActive ? 'Active' : 'Inactive'}</span>
</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>{formatDate(user?.createdAt)}</div>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['table-cell-center']}`}>
<div className={styles['action-buttons-container']}>
<motion.button
className={`${styles['action-button']} ${styles['view']}`}
whileTap={{scale:0.95}}
onClick={() => { setSelectedUser(user); setShowUserModal(true); }}
>
<Plus size={20} />
</motion.button>
<motion.button
className={`${styles['action-button']} ${styles['edit']}`}
whileTap={{scale:0.95}}
onClick={() => { setEditingUser(user); setShowUserModal(true); }}
>
<Edit size={20} />
</motion.button>
<motion.button
className={`${styles['action-button']} ${styles['delete']}`}
whileTap={{scale:0.95}}
onClick={() => deleteUser(user._id)}
>
<Trash2 size={20} />
</motion.button>
</div>
</div>
</motion.div>
))
) : (
<div className={`${styles['table-row']} ${styles['user-table-row']}`}>
<div className={`${styles['table-cell']} ${styles['user-table-cell']} ${styles['empty-state-container']}`} colSpan="5" style={{textAlign: 'center', padding: '40px 20px'}}>
<div className={styles['empty-state-content']}>
<Users size={48} className={styles['empty-state-icon']} />
<div className={styles['empty-state-text']}>
<p className={styles['empty-state-title']}>
{searchQuery ? 'No users found matching your search' : 'No users found'}
</p>
<p className={styles['empty-state-subtitle']}>
{searchQuery ? 'Try adjusting your search terms' : 'Users will appear here once they register'}
</p>
</div>
{searchQuery ? (
<button
className={`${styles['adv-btn']} ${styles['empty-state-button']} ${styles['clear']}`}
onClick={() => setSearchQuery('')}
>
Clear Search
</button>
) : (
<button
className={`${styles['adv-btn']} ${styles['empty-state-button']} ${styles['add']}`}
onClick={() => {
setShowAddUserModal(true);
setIsFormActive(true);
}}
>
<Plus size={16} className={styles['empty-state-button-icon']} />
Add First User
</button>
)}
</div>
</div>
</div>
)}
</div>
<div className={`${styles['pagination']} ${styles['user-pagination']}`} style={{marginTop:24,display:'flex',justifyContent:'center',gap:16}}>
<button
className={`${styles['pagination-btn']} ${styles['adv-btn']}`}
disabled={userPagination.page === 1}
onClick={() => setUserPagination(prev => ({ ...prev, page: prev.page - 1 }))}
>
<ChevronLeft size={20} />
</button>
<span className={`${styles['pagination-info']} ${styles['user-pagination-info']}`} style={{fontWeight:600}}>
Page {userPagination.page} of {userPagination.pages}
</span>
<button
className={`${styles['pagination-btn']} ${styles['adv-btn']}`}
disabled={userPagination.page === userPagination.pages}
onClick={() => setUserPagination(prev => ({ ...prev, page: prev.page + 1 }))}
>
<ChevronRight size={20} />
</button>
</div>
</div>
);
};
export default UserManagement;