114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
import { useState } from "preact/hooks";
|
|
import { Role, UserWithRole } from "../db/sqlUserRepository.ts";
|
|
|
|
interface AdminCenterProps {
|
|
users: UserWithRole[];
|
|
roles: Role[];
|
|
}
|
|
|
|
export default function AdminCenter({ users, roles }: AdminCenterProps) {
|
|
// Local state for forms per user
|
|
const [formState, setFormState] = useState<
|
|
Record<string, { roleId: string }>
|
|
>(
|
|
() => {
|
|
const state: Record<string, { roleId: string }> = {};
|
|
users.forEach((u) => {
|
|
state[u.id] = { roleId: u.role };
|
|
});
|
|
return state;
|
|
},
|
|
);
|
|
|
|
const handleRoleChange = (userId: string, roleId: string) => {
|
|
setFormState((prev) => ({ ...prev, [userId]: { roleId } }));
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
type="button"
|
|
aria-label="Go back"
|
|
onClick={() => globalThis.location.href = "/"}
|
|
class="back-button"
|
|
>
|
|
<svg
|
|
width="32"
|
|
height="32"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<polyline points="15 18 9 12 15 6" />
|
|
</svg>
|
|
</button>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full bg-white rounded-xl shadow-lg">
|
|
<thead>
|
|
<tr class="bg-blue-100">
|
|
<th class="py-2 px-4 text-left">Name</th>
|
|
<th class="py-2 px-4 text-left">Email</th>
|
|
<th class="py-2 px-4 text-left">Role</th>
|
|
<th class="py-2 px-4"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{users.map((user) => (
|
|
<tr key={user.id} class="border-b hover:bg-blue-50">
|
|
<td class="py-2 px-4">{user.name}</td>
|
|
<td class="py-2 px-4">{user.email}</td>
|
|
<td class="py-2 px-4">
|
|
<form
|
|
method="post"
|
|
action="/admin-center"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<input type="hidden" name="rowUserId" value={user.id} />
|
|
<input
|
|
type="hidden"
|
|
name="inputUsers"
|
|
value={JSON.stringify(users)}
|
|
/>
|
|
<input
|
|
type="hidden"
|
|
name="inputRoles"
|
|
value={JSON.stringify(roles)}
|
|
/>
|
|
<select
|
|
name="selectedRole"
|
|
class="rounded border px-2 py-1"
|
|
value={formState[user.id]?.roleId || ""}
|
|
onChange={(e) =>
|
|
handleRoleChange(
|
|
user.id,
|
|
(e.target as HTMLSelectElement).value,
|
|
)}
|
|
>
|
|
<option value="">Select role</option>
|
|
{roles.map((role) => (
|
|
<option key={role.id} value={role.id}>
|
|
{role.description} ({role.id})
|
|
</option>
|
|
))}
|
|
</select>
|
|
<button
|
|
type="submit"
|
|
class="ml-2 px-3 py-1 rounded bg-blue-600 text-white hover:bg-blue-700 transition"
|
|
>
|
|
Save
|
|
</button>
|
|
</form>
|
|
</td>
|
|
<td></td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|