setSearchQuery(toEnglishDigits(e.target.value))}
- className="w-full px-4 py-2 border border-slate-300 dark:border-slate-700 rounded-lg bg-transparent text-slate-900 dark:text-white focus:ring-2 focus:ring-blue-500"
- dir="auto"
- />
+ {/* --- ستون سمت چپ: فرم ویرایش --- */}
+
+
+ {/* بخش جستجو و هدر (ثابت در بالا) */}
+
+
+ { t.workspace?.members || "Members" }
+
- {isSearching &&
{t.workspace?.searching || "Searching..."}
}
-
- {searchError && !isSearching && (
-
-
- {t.workspace?.userNotFound || "No user found with this exact number."}
-
- )}
-
- {searchResult && !isSearching && (
-
-
- {searchResult.profile_picture ? (
-

- ) : (
-
- {searchResult.first_name?.[0] || "U"}
-
- )}
-
-
- {searchResult.first_name} {searchResult.last_name}
-
-
- {toPersianNum(searchResult.mobile)}
-
-
-
+ {canManageMembers && (
+
+
setSearchQuery(toEnglishDigits(e.target.value))}
+ className="w-full px-4 py-2 border border-slate-300 dark:border-slate-700 rounded-lg bg-transparent text-slate-900 dark:text-white focus:ring-2 focus:ring-blue-500"
+ dir="auto"
+ />
-
-
-
-
-
+ {isSearching &&
{t.workspace?.searching || "Searching..."}
}
+
+ {searchError && !isSearching && (
+
+
+ {t.workspace?.userNotFound || "No user found with this exact number."}
+
+ )}
+
+ {searchResult && !isSearching && (
+
+
+ {searchResult.profile_picture ? (
+

+ ) : (
+
+ {searchResult.first_name?.[0] || "U"}
+
+ )}
+
+
+ {searchResult.first_name} {searchResult.last_name}
+
+
+ {toPersianNum(searchResult.mobile)}
+
+
+
+
+
+
+
+ )}
)}
- )}
-
- {t.workspace?.loading || "Loading more members..."}
}
- >
- {members.map((m) => {
- const isThisMemberTheFirstOwner = m.user?.id === workspaceOwnerId;
- const canChangeThisUserRole = canManageMembers && !isThisMemberTheFirstOwner && (isFirstOwner || m.role !== 'owner');
+ {/* لیست اعضا (با قابلیت اسکرول مجزا) */}
+
+ {t.workspace?.loading || "Loading more members..."}
}
+ >
+ {members.map((m) => {
+ const isThisMemberTheFirstOwner = m.user?.id === workspaceOwnerId;
+ const canChangeThisUserRole = canManageMembers && !isThisMemberTheFirstOwner && (isFirstOwner || m.role !== 'owner');
- return (
-
-
- {m.user?.profile_picture ? (
-

- ) : (
-
- {m.user?.name?.[0] || m.user?.first_name?.[0] || "U"}
+ return (
+
+
+ {m.user?.profile_picture ? (
+

+ ) : (
+
+ {m.user?.name?.[0] || m.user?.first_name?.[0] || "U"}
+
+ )}
+
+
+ {m.user?.name || `${m.user?.first_name || ''} ${m.user?.last_name || ''}`.trim() || 'Unknown'}
+
+
{toPersianNum(m.user?.mobile)}
- )}
-
-
- {m.user?.name || `${m.user?.first_name || ''} ${m.user?.last_name || ''}`.trim() || 'Unknown'}
-
-
{toPersianNum(m.user?.mobile)}
+
+
+
+ {canChangeThisUserRole ? (
+
-
-
- {canChangeThisUserRole ? (
-
- ) : (
-
- {m.role === 'owner' && }
- {m.role ? t.workspace?.roles?.[m.role] || m.role : "-"}
-
- )}
-
- {canManageMembers && !isThisMemberTheFirstOwner && (isFirstOwner || m.role !== 'owner') && (
-
- )}
-
-
- );
- })}
-
- {members.length === 0 && !isLoadingMembers && (
-
- {t.workspace?.noMembers || "No members found."}
-
- )}
+ );
+ })}
+
+ {members.length === 0 && !isLoadingMembers && (
+
+
+
+ {t.workspace?.noMembers || "No members found."}
+
+
+ )}
+
@@ -442,13 +508,13 @@ export default function EditWorkspace() {
variant="secondary"
onClick={() => setIsDeleteDialogOpen(false)}
>
- {t.workspace?.cancel || "Cancel"}
+ {t.actions?.cancel || "Cancel"}
diff --git a/src/pages/Workspaces.tsx b/src/pages/Workspaces.tsx
index cf3c01f..96c9a94 100644
--- a/src/pages/Workspaces.tsx
+++ b/src/pages/Workspaces.tsx
@@ -1,13 +1,16 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
-import { Plus, Edit2, Trash2, Eye } from 'lucide-react';
+import { Plus, Trash2, Pencil, ChevronRight } from 'lucide-react';
import { toast } from 'sonner';
import { fetchWorkspaces, deleteWorkspace, type Workspace } from '../api/workspaces';
import { useAppContext } from '../context/AppContext';
import { useTranslation } from '../hooks/useTranslation';
import FilterBar from '../components/FilterBar';
import { Button } from '../components/ui/button';
+import { Input } from '../components/ui/input';
+import { Card, CardContent, CardTitle } from '../components/ui/card';
import { Pagination } from '../components/Pagination';
+import { Modal } from '../components/Modal';
type WorkspaceRole = "owner" | "admin" | "member" | "guest";
@@ -33,12 +36,11 @@ export default function Workspaces() {
const [workspaces, setWorkspaces] = useState
([]);
const [isLoading, setIsLoading] = useState(true);
const [searchQuery, setSearchQuery] = useState('');
- const [ordering, setOrdering] = useState('-updated_at');
+ const [ordering, setOrdering] = useState('-created_at');
- // تنظیمات پاژینیشن
const [currentPage, setCurrentPage] = useState(1);
const [totalItems, setTotalItems] = useState(0);
- const [limit, setLimit] = useState(9);
+ const [limit, setLimit] = useState(10);
const [deleteModal, setDeleteModal] = useState<{isOpen: boolean; workspace: Workspace | null}>({isOpen: false, workspace: null});
const [deleteInput, setDeleteInput] = useState('');
@@ -48,13 +50,13 @@ export default function Workspaces() {
const { t } = useTranslation();
const orderingOptions = [
- { value: '-updated_at', label: t.workspace?.orderByUpdatedDesc || 'Recently Updated' },
- { value: '-created_at', label: t.workspace?.orderByCreatedDesc || 'Newest First' },
- { value: 'created_at', label: t.workspace?.orderByCreatedAsc || 'Oldest First' },
- { value: 'name', label: t.workspace?.orderByName || 'Name (A-Z)' },
+ { value: '-created_at', label: t.ordering?.createdAtDesc || 'Newest First' },
+ { value: 'created_at', label: t.ordering?.createdAt || 'Oldest First' },
+ { value: 'name', label: t.ordering?.name || 'Name (A-Z)' },
+ { value: '-name', label: t.ordering?.nameDesc || 'Name (Z-A)' },
+ { value: '-updated_at', label: t.ordering?.updatedAtDesc || 'Recently Updated' },
];
- // وقتی جستجو یا ترتیب تغییر کرد، به صفحه اول برگرد
useEffect(() => {
setCurrentPage(1);
}, [searchQuery, ordering]);
@@ -79,7 +81,6 @@ export default function Workspaces() {
const data = await fetchWorkspaces(params as any);
- // استخراج هوشمند نتایج و تعداد کل
const items = Array.isArray(data) ? data : (data?.results || []);
const count = !Array.isArray(data) && data?.count !== undefined ? data.count : items.length;
@@ -92,7 +93,7 @@ export default function Workspaces() {
}
};
- const confirmDelete = async () => {
+ const confirmDelete = async () => {
if (!deleteModal.workspace) return;
try {
const deletedId = deleteModal.workspace.id;
@@ -100,7 +101,6 @@ export default function Workspaces() {
loadWorkspaces();
- // ارسال سیگنال به کل اپلیکیشن برای آپدیت نوار ناوبری
window.dispatchEvent(new CustomEvent('workspace_deleted', {
detail: { id: deletedId }
}));
@@ -114,7 +114,7 @@ export default function Workspaces() {
};
return (
-
+
{t.workspace?.title || 'Workspaces'}
@@ -122,7 +122,7 @@ export default function Workspaces() {
) : (
- <>
-
+
+
{workspaces.map((workspace) => {
const isOwner = workspace.owner === user?.id || workspace.my_role === 'owner';
const isAdmin = workspace.my_role === 'admin' || isOwner;
return (
-
-
-
-
- {workspace.name}
-
-
+
+
+
+
+
+ {workspace.name}
+
+
+
+
+ {workspace.description || t.workspace?.noDescription || 'No description'}
+
-
- {workspace.description || t.workspace?.noDescription || 'No description'}
-
-
-
-
+
+ {isOwner && (
+
+ )}
+
+ {isAdmin && (
+
+ )}
- {isAdmin && (
- )}
-
- {isOwner && (
-
- )}
-
-
+
+
+
);
})}
{workspaces.length === 0 && (
-
+
{t.workspace?.emptyState || 'No workspaces found'}
)}
- >
+ currentPage={currentPage}
+ totalCount={totalItems}
+ limit={limit}
+ onPageChange={setCurrentPage}
+ onLimitChange={setLimit}
+ pageSizeOptions={[10, 20, 50]}
+ />
+
)}
- {/* Delete Modal */}
- {deleteModal.isOpen && deleteModal.workspace && (
-
-
-
{t.workspace?.deleteTitle || 'Delete Workspace'}
-
- {t.workspace?.deleteWarning || 'To confirm deletion, please type the workspace name:'} {deleteModal.workspace.name}
-
-
setDeleteInput(e.target.value)}
- placeholder={deleteModal.workspace.name}
- className="w-full border rounded-xl p-3 mb-6 bg-slate-50 dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-900 dark:text-white outline-none focus:ring-2 focus:ring-red-500 transition-shadow"
- />
-
+ {deleteModal.workspace && (
+ {
+ setDeleteModal({ isOpen: false, workspace: null });
+ setDeleteInput('');
+ }}
+ title={t.workspace?.deleteTitle || 'Delete Workspace'}
+ maxWidth="max-w-md"
+ footer={
+ <>
-
+ >
+ }
+ >
+
+
+ {t.workspace?.deleteWarning || 'To confirm deletion, please type the workspace name:'} {deleteModal.workspace.name}
+
+
+
setDeleteInput(e.target.value)}
+ placeholder={deleteModal.workspace.name}
+ />
-
+
)}
);