Enum for user role - somehow user page is currently unresponsive. Probably because of previous layout changes
This commit is contained in:
parent
bd6ee25910
commit
e6fd6d7d6f
5 changed files with 94 additions and 21 deletions
|
|
@ -1,9 +1,10 @@
|
||||||
import { AbstractDto } from "./AbstractDto.ts";
|
import {AbstractDto} from "./AbstractDto";
|
||||||
|
import {UserRole} from "../enums/UserRole";
|
||||||
|
|
||||||
export class UserDto extends AbstractDto {
|
export interface UserDto extends AbstractDto {
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
userName!: string;
|
userName: string;
|
||||||
email!: string;
|
email: string;
|
||||||
role?: string;
|
role?: UserRole;
|
||||||
}
|
}
|
||||||
52
frontend/src/api/enums/UserRole.ts
Normal file
52
frontend/src/api/enums/UserRole.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* User roles - Frontend version
|
||||||
|
* Content should match backend enum exactly
|
||||||
|
* However, we cannot use a basic enum here as we're using erasableSyntaxOnly.
|
||||||
|
*/
|
||||||
|
export const UserRole = {
|
||||||
|
USER: "user",
|
||||||
|
ADMIN: "admin",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// Create a type from the values
|
||||||
|
export type UserRole = typeof UserRole[keyof typeof UserRole];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper functions for UserRole in frontend
|
||||||
|
*/
|
||||||
|
export const UserRoleHelper = {
|
||||||
|
/**
|
||||||
|
* Get display name for role (German)
|
||||||
|
*/
|
||||||
|
getDisplayName(role: UserRole): string {
|
||||||
|
const displayNames: Record<UserRole, string> = {
|
||||||
|
[UserRole.USER]: "Benutzer",
|
||||||
|
[UserRole.ADMIN]: "Administrator",
|
||||||
|
};
|
||||||
|
return displayNames[role];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all roles with display names for dropdowns
|
||||||
|
*/
|
||||||
|
getRoleOptions(): Array<{ value: UserRole; label: string }> {
|
||||||
|
return Object.values(UserRole).map((role) => ({
|
||||||
|
value: role,
|
||||||
|
label: this.getDisplayName(role),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a string is a valid role
|
||||||
|
*/
|
||||||
|
isValidRole(value: string): value is UserRole {
|
||||||
|
return Object.values(UserRole).includes(value as UserRole);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all role values
|
||||||
|
*/
|
||||||
|
getAllRoles(): UserRole[] {
|
||||||
|
return Object.values(UserRole);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -1,18 +1,40 @@
|
||||||
type SelectFieldProps = {
|
type SelectFieldProps<T extends string> = {
|
||||||
value: string;
|
value: T;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: T) => void;
|
||||||
options: { value: string; label: string }[];
|
options: { value: T; label: string }[];
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SelectField - A dropdown styled consistently with input fields
|
* SelectField - A dropdown styled consistently with input fields
|
||||||
|
* Generic component that works with any string-based type (including string literals and enums)
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // With UserRole type
|
||||||
|
* <SelectField<UserRole>
|
||||||
|
* value={user.role}
|
||||||
|
* onChange={(role) => setUser({...user, role})}
|
||||||
|
* options={UserRoleHelper.getRoleOptions()}
|
||||||
|
* />
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // With plain strings
|
||||||
|
* <SelectField<string>
|
||||||
|
* value={status}
|
||||||
|
* onChange={setStatus}
|
||||||
|
* options={[{value: "active", label: "Active"}, {value: "inactive", label: "Inactive"}]}
|
||||||
|
* />
|
||||||
*/
|
*/
|
||||||
export default function SelectField({value, onChange, options, className = ''}: SelectFieldProps) {
|
export default function SelectField<T extends string>({
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
options,
|
||||||
|
className = ''
|
||||||
|
}: SelectFieldProps<T>) {
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange(e.target.value)}
|
onChange={(e) => onChange(e.target.value as T)}
|
||||||
className={`p-2 w-full border rounded-md bg-white border-gray-600 hover:border-blue-800 transition-colors text-gray-600 focus:outline-none focus:border-blue-900 cursor-pointer ${className}`}
|
className={`p-2 w-full border rounded-md bg-white border-gray-600 hover:border-blue-800 transition-colors text-gray-600 focus:outline-none focus:border-blue-900 cursor-pointer ${className}`}
|
||||||
>
|
>
|
||||||
{options.map((option) => (
|
{options.map((option) => (
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import PasswordField from "../basics/PasswordField";
|
||||||
import ButtonGroupLayout from "../basics/ButtonGroupLayout";
|
import ButtonGroupLayout from "../basics/ButtonGroupLayout";
|
||||||
import TextLinkButton from "../basics/TextLinkButton";
|
import TextLinkButton from "../basics/TextLinkButton";
|
||||||
import SelectField from "../basics/SelectField";
|
import SelectField from "../basics/SelectField";
|
||||||
|
import {UserRole, UserRoleHelper} from "../../api/enums/UserRole.ts";
|
||||||
|
|
||||||
type UserEditFormProps = {
|
type UserEditFormProps = {
|
||||||
user: UserDto;
|
user: UserDto;
|
||||||
|
|
@ -52,10 +53,7 @@ export default function UserEditForm({
|
||||||
};
|
};
|
||||||
|
|
||||||
// @todo API string
|
// @todo API string
|
||||||
const roleOptions = [
|
const roleOptions = UserRoleHelper.getRoleOptions();
|
||||||
{value: "user", label: "Benutzer"},
|
|
||||||
{value: "admin", label: "Administrator"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-6 py-2">
|
<div className="px-6 py-2">
|
||||||
|
|
@ -104,8 +102,8 @@ export default function UserEditForm({
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<>
|
<>
|
||||||
<label>Benutzergruppe</label>
|
<label>Benutzergruppe</label>
|
||||||
<SelectField
|
<SelectField<UserRole>
|
||||||
value={editedUser.role ?? "user"}
|
value={editedUser.role ?? UserRole.USER}
|
||||||
onChange={(value) =>
|
onChange={(value) =>
|
||||||
setEditedUser({...editedUser, role: value})
|
setEditedUser({...editedUser, role: value})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import type {UserListResponse} from "../../api/dtos/UserListResponse";
|
||||||
import UserList from "./UserList";
|
import UserList from "./UserList";
|
||||||
import UserEditForm from "./UserEditForm";
|
import UserEditForm from "./UserEditForm";
|
||||||
import ErrorPopup from "../basics/ErrorPopup";
|
import ErrorPopup from "../basics/ErrorPopup";
|
||||||
|
import {UserRole} from "../../api/enums/UserRole.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserManagementPage
|
* UserManagementPage
|
||||||
|
|
@ -39,8 +40,7 @@ export default function UserManagementPage() {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
//@todo API enum
|
//@todo API enum
|
||||||
const adminRole: string = "admin";
|
const isAdmin = currentUser?.role === UserRole.ADMIN;
|
||||||
const isAdmin = currentUser?.role === adminRole;
|
|
||||||
|
|
||||||
// Load current user and user list (if admin)
|
// Load current user and user list (if admin)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -52,7 +52,7 @@ export default function UserManagementPage() {
|
||||||
const me = await fetchCurrentUser();
|
const me = await fetchCurrentUser();
|
||||||
setCurrentUser(me);
|
setCurrentUser(me);
|
||||||
|
|
||||||
if (me.role === adminRole) {
|
if (me.role === UserRole.ADMIN) {
|
||||||
const userResponse: UserListResponse = await fetchAllUsers();
|
const userResponse: UserListResponse = await fetchAllUsers();
|
||||||
|
|
||||||
// Sort users alphabetically by last name, then first name
|
// Sort users alphabetically by last name, then first name
|
||||||
|
|
@ -140,7 +140,7 @@ export default function UserManagementPage() {
|
||||||
firstName: "",
|
firstName: "",
|
||||||
lastName: "",
|
lastName: "",
|
||||||
email: "",
|
email: "",
|
||||||
role: "user",
|
role: UserRole.USER,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue