Files
logbuch/components/BeoSelector.tsx
Reinhard X. Fürst 4e53a7a5cd Initial implementation: Logbuch Sternwarte Welzheim
Vollständige Next.js 16 Webanwendung als Logbuch für die Sternwarte Welzheim.
4 Kuppeln (West/Ost/Süd/Pluto), BEO-basierte Authentifizierung mit erzwungenem
Passwort-Wechsel beim Erstlogin, MySQL-Backend, Docker-Deployment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 17:11:27 +02:00

71 lines
2.0 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';
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));
function add(id: string) {
if (!id) return;
const beo = all.find((b) => b.ID === parseInt(id));
if (beo) onChange([...selected, beo]);
}
function remove(id: number) {
onChange(selected.filter((b) => b.ID !== id));
}
return (
<div className="space-y-2">
<div className="flex flex-wrap gap-2">
{selected.map((b) => (
<span
key={b.ID}
className="inline-flex items-center gap-1 bg-blue-100 text-blue-800 text-sm px-2 py-1 rounded-full"
>
{b.Kuerzel} {b.Name}
<button
type="button"
onClick={() => remove(b.ID)}
className="ml-1 text-blue-600 hover:text-red-600 font-bold leading-none"
aria-label={`${b.Kuerzel} entfernen`}
>
×
</button>
</span>
))}
</div>
{available.length > 0 && (
<select
className="px-3 py-1.5 border-2 border-gray-400 rounded-lg bg-white text-sm focus:border-blue-500 focus:outline-none"
value=""
onChange={(e) => add(e.target.value)}
>
<option value="">+ BEO hinzufügen</option>
{available.map((b) => (
<option key={b.ID} value={b.ID}>
{b.Kuerzel} {b.Name}
</option>
))}
</select>
)}
</div>
);
}