geraete/app/(app)/users/AssignGroupForm.tsx
2025-11-24 08:59:14 +01:00

95 lines
2.6 KiB
TypeScript

// app/(app)/users/components/AssignGroupForm.tsx
'use client';
import { useState, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import Dropdown from '@/components/ui/Dropdown';
import type { SimpleGroup, UserWithAvatar } from './types';
type Props = {
user: UserWithAvatar;
defaultGroupId: string | null;
allGroups: SimpleGroup[];
};
export default function AssignGroupForm({
user,
defaultGroupId,
allGroups,
}: Props) {
const router = useRouter();
const [pending, startTransition] = useTransition();
const [groupId, setGroupId] = useState<string>(defaultGroupId ?? 'none');
async function updateGroup(nextGroupId: string) {
setGroupId(nextGroupId);
startTransition(async () => {
try {
const res = await fetch('/api/users/assign-group', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: user.nwkennung,
groupId: nextGroupId,
}),
});
if (!res.ok) {
console.error(
'Fehler beim Zuordnen der Gruppe',
await res.text(),
);
}
router.refresh();
} catch (err) {
console.error('Fehler beim Zuordnen der Gruppe', err);
}
});
}
const currentLabel =
groupId === 'none'
? 'Ohne Gruppe'
: allGroups.find((g) => g.id === groupId)?.name ?? 'Gruppe wählen';
return (
<div className="flex items-center gap-2">
<Dropdown
triggerVariant="button"
label={currentLabel}
ariaLabel="Gruppe auswählen"
align="left"
disabled={pending}
triggerClassName="inline-flex items-center rounded-md bg-white px-2 py-1 text-xs font-normal text-gray-900 shadow-sm inset-ring-1 inset-ring-gray-300 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed dark:bg-gray-900 dark:text-gray-100 dark:inset-ring-gray-700"
sections={[
{
id: 'groups',
items: [
{
id: 'none',
label: 'Ohne Gruppe',
disabled: pending && groupId === 'none',
onClick: () => updateGroup('none'),
},
...allGroups.map((g) => ({
id: g.id,
label: g.name,
disabled: pending && groupId === g.id,
onClick: () => updateGroup(g.id),
})),
],
},
]}
/>
{pending && (
<span className="text-xs text-gray-500 dark:text-gray-400">
Speichere&nbsp;
</span>
)}
</div>
);
}