UsersTable.jsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import React from "react";
  2. import {
  3. ROLE_LABELS_DE,
  4. formatDateTimeDe,
  5. } from "@/components/admin/users/usersUi";
  6. import EditUserDialog from "@/components/admin/users/EditUserDialog";
  7. import DeleteUserDialog from "@/components/admin/users/DeleteUserDialog";
  8. import UserTemporaryPasswordField from "@/components/admin/users/UserTemporaryPasswordField";
  9. import { Badge } from "@/components/ui/badge";
  10. import {
  11. Table,
  12. TableBody,
  13. TableCell,
  14. TableHead,
  15. TableHeader,
  16. TableRow,
  17. } from "@/components/ui/table";
  18. function UserTableRow({ user, disabled = false, onUserUpdated }) {
  19. const [temporaryPassword, setTemporaryPassword] = React.useState("");
  20. const [mustChangePasswordAfterReset, setMustChangePasswordAfterReset] =
  21. React.useState(false);
  22. const must = Boolean(user.mustChangePassword || mustChangePasswordAfterReset);
  23. return (
  24. <TableRow>
  25. <TableCell className="truncate font-medium" title={user.username}>
  26. {user.username}
  27. </TableCell>
  28. <TableCell className="min-w-0">
  29. <span className="block truncate" title={user.email}>
  30. {user.email}
  31. </span>
  32. </TableCell>
  33. <TableCell>
  34. <Badge variant="secondary">{ROLE_LABELS_DE[user.role] || user.role}</Badge>
  35. </TableCell>
  36. <TableCell>
  37. {user.branchId ? (
  38. <Badge variant="outline">{user.branchId}</Badge>
  39. ) : (
  40. <span className="text-muted-foreground">—</span>
  41. )}
  42. </TableCell>
  43. <TableCell>
  44. {must ? (
  45. <Badge variant="destructive">Erforderlich</Badge>
  46. ) : (
  47. <Badge variant="secondary">Nein</Badge>
  48. )}
  49. </TableCell>
  50. <TableCell>
  51. <UserTemporaryPasswordField
  52. user={user}
  53. temporaryPassword={temporaryPassword}
  54. onTemporaryPasswordChange={setTemporaryPassword}
  55. onPasswordReset={() => setMustChangePasswordAfterReset(true)}
  56. disabled={disabled}
  57. compact
  58. />
  59. </TableCell>
  60. <TableCell className="text-xs text-muted-foreground">
  61. {formatDateTimeDe(user.updatedAt)}
  62. </TableCell>
  63. <TableCell className="sticky right-0 z-10 w-20 bg-card text-right">
  64. <div className="flex items-center justify-end gap-1">
  65. <EditUserDialog
  66. user={user}
  67. disabled={disabled}
  68. onUpdated={onUserUpdated}
  69. onPasswordReset={() => setMustChangePasswordAfterReset(true)}
  70. temporaryPassword={temporaryPassword}
  71. onTemporaryPasswordChange={setTemporaryPassword}
  72. />
  73. <DeleteUserDialog
  74. user={user}
  75. disabled={disabled}
  76. onDeleted={onUserUpdated}
  77. />
  78. </div>
  79. </TableCell>
  80. </TableRow>
  81. );
  82. }
  83. export default function UsersTable({ items, disabled = false, onUserUpdated }) {
  84. const list = Array.isArray(items) ? items : [];
  85. return (
  86. <Table className="min-w-[88rem] table-fixed">
  87. <TableHeader>
  88. <TableRow>
  89. <TableHead className="w-44">Benutzername</TableHead>
  90. <TableHead className="w-56">E-Mail</TableHead>
  91. <TableHead className="w-40">Rolle</TableHead>
  92. <TableHead className="w-16">NL</TableHead>
  93. <TableHead className="w-32">Passwortwechsel</TableHead>
  94. <TableHead className="w-56">Passwort</TableHead>
  95. <TableHead className="w-32">Aktualisiert</TableHead>
  96. <TableHead className="sticky right-0 z-20 w-20 bg-card text-right">
  97. Aktion
  98. </TableHead>
  99. </TableRow>
  100. </TableHeader>
  101. <TableBody>
  102. {list.map((user) => (
  103. <UserTableRow
  104. key={user.id}
  105. user={user}
  106. disabled={disabled}
  107. onUserUpdated={onUserUpdated}
  108. />
  109. ))}
  110. </TableBody>
  111. </Table>
  112. );
  113. }