refactor: simplify Topbar component and remove unused code
- Removed breadcrumb functionality and related code from Topbar. - Consolidated mobile and desktop sidebar toggle logic. - Adjusted icon sizes and styles for consistency. - Cleaned up unused imports and props in Topbar. refactor: enhance DoctorDetailPage session editor UI - Improved layout and styling of session editor for better usability. - Removed advanced settings toggle and integrated relevant fields directly. - Added visual indicators for session slots and rest periods. refactor: streamline DoctorsPage component - Removed bulk selection functionality and related state management. - Simplified rendering logic for doctor list and adjusted table structure. - Cleaned up unused imports and components for better readability. refactor: optimize UsersPage component - Removed bulk selection and deletion functionality. - Simplified user table structure and adjusted column spans. - Cleaned up unused state and imports for improved clarity.
This commit is contained in:
@@ -165,18 +165,15 @@ export default function UsersPage() {
|
||||
const [search, setSearch] = useState('');
|
||||
const [role, setRole] = useState('');
|
||||
const [status, setStatus] = useState('');
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
const [deleteTarget, setDeleteTarget] = useState<AdminUser | null>(null);
|
||||
const [roleTarget, setRoleTarget] = useState<AdminUser | null>(null);
|
||||
const [confirmBulkDel, setConfirmBulkDel] = useState(false);
|
||||
const [bulkDeleting, setBulkDeleting] = useState(false);
|
||||
const [deleteTarget, setDeleteTarget] = useState<AdminUser | null>(null);
|
||||
const [roleTarget, setRoleTarget] = useState<AdminUser | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const t = setTimeout(() => { setSearch(searchInput); setPage(1); }, 350);
|
||||
return () => clearTimeout(t);
|
||||
}, [searchInput]);
|
||||
|
||||
useEffect(() => { setPage(1); setSelected([]); }, [role, status]);
|
||||
useEffect(() => { setPage(1); }, [role, status]);
|
||||
|
||||
// ── Queries ──
|
||||
|
||||
@@ -238,27 +235,6 @@ export default function UsersPage() {
|
||||
onError: (e: Error) => toast.error(e.message),
|
||||
});
|
||||
|
||||
// ── Bulk ──
|
||||
|
||||
const allSelected = items.length > 0 && items.every((u) => selected.includes(u.uuid));
|
||||
const toggleAll = () => setSelected(allSelected ? [] : items.map((u) => u.uuid));
|
||||
const toggleOne = (uuid: string) =>
|
||||
setSelected((prev) => prev.includes(uuid) ? prev.filter((id) => id !== uuid) : [...prev, uuid]);
|
||||
|
||||
const handleBulkDelete = async () => {
|
||||
setBulkDeleting(true);
|
||||
let count = 0;
|
||||
for (const uuid of selected) {
|
||||
try { await api.delete(`/api/v1/admin/users/${uuid}`); count++; } catch {}
|
||||
}
|
||||
setBulkDeleting(false);
|
||||
setConfirmBulkDel(false);
|
||||
setSelected([]);
|
||||
toast.success(`${formatNumber(count)} کاربر حذف شد`);
|
||||
qc.invalidateQueries({ queryKey: ['users'] });
|
||||
qc.invalidateQueries({ queryKey: ['users-stats'] });
|
||||
};
|
||||
|
||||
// ── KPI data ──
|
||||
|
||||
const kpiCards = [
|
||||
@@ -335,32 +311,11 @@ export default function UsersPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bulk bar */}
|
||||
{selected.length > 0 && (
|
||||
<div style={{
|
||||
padding: '10px 16px', background: 'var(--primary-soft)',
|
||||
borderBottom: '1px solid var(--border)',
|
||||
display: 'flex', alignItems: 'center', gap: 12,
|
||||
}}>
|
||||
<span style={{ fontSize: 13, color: 'var(--primary-700)', fontWeight: 600 }}>
|
||||
{formatNumber(selected.length)} کاربر انتخاب شده
|
||||
</span>
|
||||
<div style={{ display: 'flex', gap: 8, marginRight: 'auto' }}>
|
||||
<button className="btn danger sm" onClick={() => setConfirmBulkDel(true)}>حذف انتخابشدهها</button>
|
||||
<button className="btn ghost sm" onClick={() => setSelected([])}>لغو</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Table */}
|
||||
<div className="table-wrap">
|
||||
<table className="t">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: 42 }}>
|
||||
<input type="checkbox" checked={allSelected} onChange={toggleAll}
|
||||
style={{ accentColor: 'var(--primary)', cursor: 'pointer' }} />
|
||||
</th>
|
||||
<th>کاربر</th>
|
||||
<th>شماره موبایل</th>
|
||||
<th>نقش</th>
|
||||
@@ -372,7 +327,7 @@ export default function UsersPage() {
|
||||
<tbody>
|
||||
{usersQ.isLoading && Array.from({ length: 7 }).map((_, i) => (
|
||||
<tr key={i}>
|
||||
{Array.from({ length: 7 }).map((_, j) => (
|
||||
{Array.from({ length: 6 }).map((_, j) => (
|
||||
<td key={j}>
|
||||
<div className="skeleton" style={{ height: 14, borderRadius: 6, width: j === 1 ? '70%' : '55%' }} />
|
||||
</td>
|
||||
@@ -382,7 +337,7 @@ export default function UsersPage() {
|
||||
|
||||
{!usersQ.isLoading && items.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={7}>
|
||||
<td colSpan={6}>
|
||||
<div className="empty">هیچ کاربری یافت نشد</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -390,11 +345,6 @@ export default function UsersPage() {
|
||||
|
||||
{!usersQ.isLoading && items.map((user) => (
|
||||
<tr key={user.uuid}>
|
||||
<td>
|
||||
<input type="checkbox" checked={selected.includes(user.uuid)}
|
||||
onChange={() => toggleOne(user.uuid)}
|
||||
style={{ accentColor: 'var(--primary)', cursor: 'pointer' }} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="cell-user">
|
||||
<UserAvatar name={user.name} id={user.id} />
|
||||
@@ -454,17 +404,6 @@ export default function UsersPage() {
|
||||
onCancel={() => setDeleteTarget(null)}
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
open={confirmBulkDel}
|
||||
title="حذف گروهی"
|
||||
message={`آیا از حذف ${formatNumber(selected.length)} کاربر انتخابشده اطمینان دارید؟`}
|
||||
confirmLabel={`حذف ${formatNumber(selected.length)} کاربر`}
|
||||
danger
|
||||
loading={bulkDeleting}
|
||||
onConfirm={handleBulkDelete}
|
||||
onCancel={() => setConfirmBulkDel(false)}
|
||||
/>
|
||||
|
||||
{roleTarget && (
|
||||
<ChangeRoleModal
|
||||
user={roleTarget}
|
||||
|
||||
Reference in New Issue
Block a user