// app/(app)/users/UsersCsvImportButton.tsx 'use client'; import { useRef, useState } from 'react'; import { useRouter } from 'next/navigation'; import Button from '@/components/ui/Button'; type SimpleGroup = { id: string; name: string; }; type Props = { groups: SimpleGroup[]; }; export default function UsersCsvImportButton({ groups }: Props) { const router = useRouter(); const fileInputRef = useRef(null); const [importing, setImporting] = useState(false); const [importError, setImportError] = useState(null); const [importSummary, setImportSummary] = useState(null); // Hilfsfunktion: Gruppe sicherstellen (existiert oder neu anlegen) async function ensureGroupId( name: string, cache: Map, ): Promise { const trimmed = name.trim(); if (!trimmed) return null; const cached = cache.get(trimmed); if (cached) return cached; const res = await fetch('/api/user-groups', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: trimmed }), }); if (!res.ok) { const data = await res.json().catch(() => null); console.error('Fehler beim Anlegen der Gruppe', res.status, data); return null; } const data = await res.json(); const id = data.id as string; cache.set(trimmed, id); return id; } async function handleImportCsv( e: React.ChangeEvent, ): Promise { const file = e.target.files?.[0]; if (!file) return; setImporting(true); setImportError(null); setImportSummary(null); try { const text = await file.text(); // Gruppen-Cache (Name -> ID), Start mit bestehenden Gruppen const groupCache = new Map(); for (const g of groups) { groupCache.set(g.name.trim(), g.id); } let createdCount = 0; let skippedCount = 0; const lines = text .split(/\r?\n/) .map((l) => l.trim()) .filter((l) => l.length > 0); for (let index = 0; index < lines.length; index++) { const line = lines[index]; // ⬅️ Erste Zeile immer ignorieren (Header) if (index === 0) { continue; } // Format: NwKennung;Nachname;Vorname;Arbeitsname;Gruppe const parts = line.split(';'); if (parts.length < 4) { console.warn('Zeile übersprungen (falsches Format):', line); skippedCount++; continue; } const [ nwkennungRaw, lastNameRaw, firstNameRaw, arbeitsnameRaw, groupRaw, ] = parts; const nwkennung = (nwkennungRaw ?? '').trim().toLowerCase(); const lastName = (lastNameRaw ?? '').trim(); const firstName = (firstNameRaw ?? '').trim(); const arbeitsname = (arbeitsnameRaw ?? '').trim(); const groupName = (groupRaw ?? '').trim(); // NwKennung + Name + Arbeitsname als Pflichtfelder if (!nwkennung || !lastName || !firstName || !arbeitsname) { console.warn( 'Zeile übersprungen (Pflichtfelder leer):', line, ); skippedCount++; continue; } let groupId: string | null = null; if (groupName) { groupId = await ensureGroupId(groupName, groupCache); if (!groupId) { console.warn( 'Zeile übersprungen (Gruppe konnte nicht angelegt werden):', line, ); skippedCount++; continue; } } const res = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nwkennung, // ⬅ NEU arbeitsname, firstName, lastName, groupId, }), }); if (!res.ok) { const data = await res.json().catch(() => null); console.error( 'Fehler beim Anlegen der Person aus CSV:', res.status, data, 'Zeile:', line, ); skippedCount++; continue; } createdCount++; } setImportSummary( `Import abgeschlossen: ${createdCount} Personen importiert, ${skippedCount} Zeilen übersprungen.`, ); router.refresh(); } catch (err: any) { console.error('Fehler beim CSV-Import', err); setImportError( err instanceof Error ? err.message : 'Fehler beim CSV-Import.', ); } finally { setImporting(false); if (e.target) { e.target.value = ''; } } } return (
{importSummary && (

{importSummary}

)} {importError && (

{importError}

)}
); }