Files
logbuch/components/BeoSelector.tsx
Reinhard X. Fürst a0fb6d8089 Various UX improvements and bug fixes
- Fix mustChangePassword session flag for users with pw=NULL
- Add PrF (Private Führung) as new ArtFuehrung type
- Split datetime-local into separate date + TimePicker5 (5-min steps, auto-repeat)
- Responsive Beginn/Ende layout: stacked on mobile, inline on desktop
- Sort BEOs alphabetically by Kürzel in selector
- Title shows active kuppel; hide user display in header
- Selected BEOs show Kürzel only (name stays in dropdown)
- Session timeout reduced to 1 hour
- Add CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 18:02:47 +02:00

68 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useEffect, useState } from 'react';
import type { BeoOption } from '@/types/logbuch';
import CustomSelect from './CustomSelect';
interface Props {
selected: BeoOption[];
onChange: (beos: BeoOption[]) => void;
}
export default function BeoSelector({ selected, onChange }: Props) {
const [all, setAll] = useState<BeoOption[]>([]);
useEffect(() => {
fetch('/api/beos')
.then((r) => { if (!r.ok) throw new Error('Fehler'); return r.json(); })
.then(setAll)
.catch(() => {});
}, []);
const selectedIds = new Set(selected.map((b) => b.ID));
const available = all
.filter((b) => !selectedIds.has(b.ID))
.sort((a, b) => a.Kuerzel.localeCompare(b.Kuerzel));
function add(value: string) {
const beo = all.find((b) => b.ID === parseInt(value));
if (beo) onChange([...selected, beo]);
}
function remove(id: number) {
onChange(selected.filter((b) => b.ID !== id));
}
return (
<div className="space-y-3">
<div className="flex flex-wrap gap-2">
{selected.map((b) => (
<span
key={b.ID}
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-base px-3 py-1.5 rounded-full"
>
{b.Kuerzel}
<button
type="button"
onClick={() => remove(b.ID)}
className="flex items-center justify-center w-7 h-7 rounded-full text-blue-600 hover:bg-red-100 hover:text-red-600 font-bold text-xl leading-none"
aria-label={`${b.Kuerzel} entfernen`}
>
×
</button>
</span>
))}
</div>
{available.length > 0 && (
<CustomSelect
placeholder="+ BEOs hinzufügen"
options={available.map((b) => ({ value: String(b.ID), label: `${b.Kuerzel}${b.Name}` }))}
onChange={add}
keepOpen
/>
)}
</div>
);
}