diff --git a/adminfront/src/features/users/UserListPage.tsx b/adminfront/src/features/users/UserListPage.tsx index fb4f5cb8..2f8325b9 100644 --- a/adminfront/src/features/users/UserListPage.tsx +++ b/adminfront/src/features/users/UserListPage.tsx @@ -8,13 +8,16 @@ import { ChevronLeft, ChevronRight, Users, + Download, FileDown, + FileSpreadsheet, Plus, RefreshCw, Search, Settings2, ShieldCheck, Trash2, + Upload, } from "lucide-react"; import * as React from "react"; import { Link, useNavigate } from "react-router-dom"; @@ -90,7 +93,10 @@ import { } from "../../lib/adminApi"; import { t } from "../../lib/i18n"; import { isSuperAdminRole } from "../../lib/roles"; -import { UserBulkUploadModal } from "./components/UserBulkUploadModal"; +import { + UserBulkUploadModal, + downloadUserTemplate, +} from "./components/UserBulkUploadModal"; import { normalizeUserStatusValue, type UserStatusValue, @@ -140,6 +146,7 @@ function UserListPage() { React.useState(""); const [sortConfig, setSortConfig] = React.useState | null>(null); + const [bulkUploadOpen, setBulkUploadOpen] = React.useState(false); const limit = 1000; const offset = (page - 1) * limit; @@ -486,27 +493,65 @@ function UserListPage() { {t("ui.common.refresh", "새로고침")} - - - query.refetch()} /> + + + + + + + + {t("ui.admin.users.csv_template", "템플릿 다운로드")} + + + { + e.preventDefault(); + setBulkUploadOpen(true); + }} + className="cursor-pointer" + > + + {t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")} + + + handleExport(false)} + disabled={exportMutation.isPending} + data-testid="user-export-menu-item" + className="cursor-pointer" + > + + {t("ui.common.export_without_ids", "UUID 제외 내보내기")} + + handleExport(true)} + disabled={exportMutation.isPending} + data-testid="user-export-with-ids-menu-item" + className="cursor-pointer" + > + + {t("ui.common.export_with_ids", "UUID 포함 내보내기")} + + + + query.refetch()} + /> - -