diff --git a/frontend/src/pages/TeamDashboardPage.css b/frontend/src/pages/TeamDashboardPage.css
index 88d2aa1..5c9c4d2 100644
--- a/frontend/src/pages/TeamDashboardPage.css
+++ b/frontend/src/pages/TeamDashboardPage.css
@@ -61,93 +61,18 @@
font-size: 1.25rem;
}
-/* Projects Table */
-.projects-table-container {
- background: var(--color-bg);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- overflow: hidden;
-}
-
-.projects-table {
- width: 100%;
- border-collapse: collapse;
-}
-
-.projects-table th {
- text-align: left;
- padding: 0.75rem 1rem;
- font-size: 0.75rem;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: var(--color-text-muted);
- background: var(--color-bg-secondary);
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
- border-right: 1px solid rgba(0, 0, 0, 0.06);
-}
-
-.projects-table th:last-child {
- border-right: none;
-}
-
-.projects-table td {
- padding: 0.75rem 1rem;
- font-size: 0.875rem;
- vertical-align: middle;
- border-bottom: 1px solid rgba(0, 0, 0, 0.06);
- border-right: 1px solid rgba(0, 0, 0, 0.06);
-}
-
-.projects-table td:last-child {
- border-right: none;
-}
-
-.projects-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-.project-row {
- cursor: pointer;
- transition: background 0.1s ease;
-}
-
-.project-row:hover {
- background: var(--color-bg-secondary);
-}
-
-.project-name-link {
- font-weight: 500;
- color: var(--color-text);
- text-decoration: none;
-}
-
-.project-name-link:hover {
- color: var(--color-primary);
-}
-
-.project-description-cell {
- color: var(--color-text-secondary);
- max-width: 300px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
+/* Table utility classes */
.text-muted {
color: var(--color-text-muted);
}
-.actions-cell {
- width: 48px;
- text-align: right;
-}
-
.btn-ghost {
background: transparent;
color: var(--color-text-muted);
border: none;
padding: 0.375rem;
+ cursor: pointer;
+ border-radius: var(--radius-sm);
}
.btn-ghost:hover {
diff --git a/frontend/src/pages/TeamDashboardPage.tsx b/frontend/src/pages/TeamDashboardPage.tsx
index 56e7bb3..00acbce 100644
--- a/frontend/src/pages/TeamDashboardPage.tsx
+++ b/frontend/src/pages/TeamDashboardPage.tsx
@@ -5,6 +5,7 @@ import { getTeam, listTeamProjects, createProject } from '../api';
import { useAuth } from '../contexts/AuthContext';
import { Badge } from '../components/Badge';
import { Breadcrumb } from '../components/Breadcrumb';
+import { DataTable } from '../components/DataTable';
import './TeamDashboardPage.css';
function TeamDashboardPage() {
@@ -202,64 +203,65 @@ function TeamDashboardPage() {
)}
) : (
-
-
-
-
- | Name |
- Description |
- Visibility |
- Created By |
- {isAdminOrOwner && | }
-
-
-
- {projects?.items.map(project => (
- navigate(`/project/${project.name}`)}
+ project.id}
+ onRowClick={(project) => navigate(`/project/${project.name}`)}
+ columns={[
+ {
+ key: 'name',
+ header: 'Name',
+ render: (project) => (
+ e.stopPropagation()}
>
- |
- e.stopPropagation()}
- >
- {project.name}
-
- |
-
- {project.description || —}
- |
-
-
- {project.is_public ? 'Public' : 'Private'}
-
- |
- {project.created_by} |
- {isAdminOrOwner && (
-
-
- |
- )}
-
- ))}
-
-
-
+ {project.name}
+
+ ),
+ },
+ {
+ key: 'description',
+ header: 'Description',
+ className: 'cell-description',
+ render: (project) => project.description || —,
+ },
+ {
+ key: 'visibility',
+ header: 'Visibility',
+ render: (project) => (
+
+ {project.is_public ? 'Public' : 'Private'}
+
+ ),
+ },
+ {
+ key: 'created_by',
+ header: 'Created By',
+ render: (project) => {project.created_by},
+ },
+ ...(isAdminOrOwner ? [{
+ key: 'actions',
+ header: '',
+ render: (project: Project) => (
+
+ ),
+ }] : []),
+ ]}
+ />
)}
{projects && projects.pagination.total > 10 && (
diff --git a/frontend/src/pages/TeamsPage.css b/frontend/src/pages/TeamsPage.css
index a081e29..56a0428 100644
--- a/frontend/src/pages/TeamsPage.css
+++ b/frontend/src/pages/TeamsPage.css
@@ -171,60 +171,7 @@
color: var(--color-text-muted);
}
-/* Table */
-.teams-table-container {
- background: var(--color-bg);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- overflow: hidden;
-}
-
-.teams-table {
- width: 100%;
- border-collapse: collapse;
-}
-
-.teams-table th {
- text-align: left;
- padding: 0.75rem 1rem;
- font-size: 0.75rem;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: var(--color-text-muted);
- background: var(--color-bg-secondary);
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
- border-right: 1px solid rgba(0, 0, 0, 0.06);
-}
-
-.teams-table th:last-child {
- border-right: none;
-}
-
-.teams-table td {
- padding: 0.75rem 1rem;
- font-size: 0.875rem;
- vertical-align: middle;
- border-bottom: 1px solid rgba(0, 0, 0, 0.06);
- border-right: 1px solid rgba(0, 0, 0, 0.06);
-}
-
-.teams-table td:last-child {
- border-right: none;
-}
-
-.teams-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-.team-row {
- cursor: pointer;
- transition: background 0.1s ease;
-}
-
-.team-row:hover {
- background: var(--color-bg-secondary);
-}
+/* Table cell styles */
.team-name-cell {
display: flex;
diff --git a/frontend/src/pages/TeamsPage.tsx b/frontend/src/pages/TeamsPage.tsx
index 102acf1..9a08dc4 100644
--- a/frontend/src/pages/TeamsPage.tsx
+++ b/frontend/src/pages/TeamsPage.tsx
@@ -4,6 +4,7 @@ import { TeamDetail, TeamCreate, PaginatedResponse } from '../types';
import { listTeams, createTeam } from '../api';
import { useAuth } from '../contexts/AuthContext';
import { Badge } from '../components/Badge';
+import { DataTable } from '../components/DataTable';
import './TeamsPage.css';
function TeamsPage() {
@@ -265,53 +266,54 @@ function TeamsPage() {
)}
) : (
-
-
-
-
- | Name |
- Description |
- Role |
- Members |
- Projects |
-
-
-
- {filteredTeams.map(team => (
- navigate(`/teams/${team.slug}`)}
- >
- |
-
- e.stopPropagation()}
- >
- {team.name}
-
- @{team.slug}
-
- |
-
- {team.description || —}
- |
-
- {team.user_role && (
-
- {roleConfig[team.user_role]?.label || team.user_role}
-
- )}
- |
- {team.member_count} |
- {team.project_count} |
-
- ))}
-
-
-
+ team.id}
+ onRowClick={(team) => navigate(`/teams/${team.slug}`)}
+ columns={[
+ {
+ key: 'name',
+ header: 'Name',
+ render: (team) => (
+
+ e.stopPropagation()}
+ >
+ {team.name}
+
+ @{team.slug}
+
+ ),
+ },
+ {
+ key: 'description',
+ header: 'Description',
+ className: 'cell-description',
+ render: (team) => team.description || —,
+ },
+ {
+ key: 'role',
+ header: 'Role',
+ render: (team) => team.user_role ? (
+
+ {roleConfig[team.user_role]?.label || team.user_role}
+
+ ) : null,
+ },
+ {
+ key: 'members',
+ header: 'Members',
+ render: (team) => {team.member_count},
+ },
+ {
+ key: 'projects',
+ header: 'Projects',
+ render: (team) => {team.project_count},
+ },
+ ]}
+ />
)}
);