From 83991b13cae7d5a2b3a8792f1bfed3027c925d42 Mon Sep 17 00:00:00 2001 From: chan Date: Thu, 19 Mar 2026 12:57:00 +0900 Subject: [PATCH] feat: implement sticky header and inner scrolling for user list page --- .../src/features/users/UserListPage.tsx | 314 +++++++++--------- 1 file changed, 161 insertions(+), 153 deletions(-) diff --git a/adminfront/src/features/users/UserListPage.tsx b/adminfront/src/features/users/UserListPage.tsx index ebe23fbc..d6af7999 100644 --- a/adminfront/src/features/users/UserListPage.tsx +++ b/adminfront/src/features/users/UserListPage.tsx @@ -254,8 +254,8 @@ function UserListPage() { }; return ( -
-
+
+
{t("ui.admin.users.list.breadcrumb.section", "Users")} @@ -353,8 +353,8 @@ function UserListPage() {
- - + +
{t("ui.admin.users.list.registry.title", "User Registry")} @@ -368,8 +368,8 @@ function UserListPage() {
- -
+ +
{(errorMsg || fallbackError) && ( -
+
{errorMsg ?? fallbackError}
)} -
- - - - - 0 && - selectedUserIds.length === items.length - } - onChange={toggleSelectAll} - /> - - - {t("ui.admin.users.list.table.name_email", "NAME / EMAIL")} - - - {t("ui.admin.users.list.table.role", "ROLE")} - - - {t("ui.admin.users.list.table.status", "STATUS")} - - - {t( - "ui.admin.users.list.table.tenant_dept", - "TENANT / DEPT", - )} - - {/* Dynamic Columns from Schema */} - {userSchema.map( - (field) => - visibleColumns[field.key] !== false && ( - - {field.label} - - ), - )} - - {t("ui.admin.users.list.table.created", "CREATED")} - - - {t("ui.admin.users.list.table.actions", "ACTIONS")} - - - - - {query.isLoading && ( +
+
+
+ - - {t("msg.common.loading", "로딩 중...")} - - - )} - {!query.isLoading && items.length === 0 && ( - - - {t("msg.admin.users.list.empty", "검색 결과가 없습니다.")} - - - )} - {items.map((user) => ( - - + toggleSelectUser(user.id)} - /> - - -
-
- -
-
- {user.name} - - {user.email} - -
-
-
- - - {t(`ui.admin.role.${user.role}`, user.role)} - - - - 0 && + selectedUserIds.length === items.length } - > - {t(`ui.common.status.${user.status}`, user.status)} - - - -
- - {user.tenant?.name || user.companyCode || "-"} - - - {user.department || "-"} - -
-
- {/* Dynamic Metadata Cells */} + onChange={toggleSelectAll} + /> + + + {t( + "ui.admin.users.list.table.name_email", + "NAME / EMAIL", + )} + + + {t("ui.admin.users.list.table.role", "ROLE")} + + + {t("ui.admin.users.list.table.status", "STATUS")} + + + {t( + "ui.admin.users.list.table.tenant_dept", + "TENANT / DEPT", + )} + + {/* Dynamic Columns from Schema */} {userSchema.map( (field) => visibleColumns[field.key] !== false && ( - - {String(user.metadata?.[field.key] ?? "-")} - + + {field.label} + ), )} - - {new Date(user.createdAt).toLocaleDateString()} - - -
- - -
-
+ + {t("ui.admin.users.list.table.created", "CREATED")} + + + {t("ui.admin.users.list.table.actions", "ACTIONS")} +
- ))} - -
+ + + {query.isLoading && ( + + + {t("msg.common.loading", "로딩 중...")} + + + )} + {!query.isLoading && items.length === 0 && ( + + + {t( + "msg.admin.users.list.empty", + "검색 결과가 없습니다.", + )} + + + )} + {items.map((user) => ( + + + toggleSelectUser(user.id)} + /> + + +
+
+ +
+
+ {user.name} + + {user.email} + +
+
+
+ + + {t(`ui.admin.role.${user.role}`, user.role)} + + + + + {t(`ui.common.status.${user.status}`, user.status)} + + + +
+ + {user.tenant?.name || user.companyCode || "-"} + + + {user.department || "-"} + +
+
+ {/* Dynamic Metadata Cells */} + {userSchema.map( + (field) => + visibleColumns[field.key] !== false && ( + + {String(user.metadata?.[field.key] ?? "-")} + + ), + )} + + {new Date(user.createdAt).toLocaleDateString()} + + +
+ + +
+
+
+ ))} +
+ +
{/* Bulk Action Bar */} @@ -639,7 +647,7 @@ function UserListPage() { {/* Pagination */} {totalPages > 1 && ( -
+