import React, { useEffect, useState } from 'react'; import { scannerApi, type ScannerSchedule, type ScannerSecrets } from '../../lib/api'; import { Field, PrimaryButton, inputClass } from '../ui/form'; import { useToast } from '../Toast'; import { WEEKDAY_LABELS } from '../scanner/scannerUi'; /* * Reiter "Scanner" in den Einstellungen (nur Administratoren). * * Wann und wie oft der Scanner selbst sucht, und der kostenlose API-Schlüssel * für Adzuna. Die * Schlüssel kommen - wie der OpenAI-Schlüssel - nie zurück zum Browser. */ const INTERVALS = [15, 30, 60, 120, 180, 240, 360]; export const ScannerSettings: React.FC = () => { const { toast } = useToast(); const [schedule, setSchedule] = useState(null); const [secrets, setSecrets] = useState(null); const [keys, setKeys] = useState({ adzunaId: '', adzunaKey: '' }); const [busy, setBusy] = useState(false); useEffect(() => { scannerApi .settings() .then((data) => { setSchedule(data.settings); setSecrets(data.secrets); }) .catch((err) => toast(err instanceof Error ? err.message : 'Laden fehlgeschlagen.', 'error')); }, [toast]); const save = async (changes: Parameters[0]) => { setBusy(true); try { const data = await scannerApi.saveSettings(changes); setSchedule(data.settings); setSecrets(data.secrets); setKeys({ adzunaId: '', adzunaKey: '' }); toast('Gespeichert.', 'success'); } catch (err) { toast(err instanceof Error ? err.message : 'Speichern fehlgeschlagen.', 'error'); } finally { setBusy(false); } }; if (!schedule || !secrets) return

Wird geladen …

; const set = (changes: Partial) => setSchedule({ ...schedule, ...changes }); return (

Zeitplan

In diesem Fenster sucht der Scanner selbstständig. Außerhalb geht es nur über „Jetzt scannen“ im Dashboard. Gerechnet wird in deutscher Zeit.

{WEEKDAY_LABELS.map((label, index) => { const day = index + 1; const on = schedule.days.includes(day); return ( ); })}
set({ from: event.target.value })} className={inputClass} /> set({ to: event.target.value })} className={inputClass} />

Gesucht wird ohne Altersgrenze – das Alter der Anzeigen filtert das Dashboard („Anzeigenalter“).

void save(schedule)} > Zeitplan speichern

API-Schlüssel

Agentur für Arbeit, StepStone, karriere.at und freelancermap brauchen nichts. Adzuna (einzige Quelle für die Schweiz) gibt nach kostenloser Registrierung einen Schlüssel aus. Ohne Schlüssel wird es übersprungen.

setKeys({ ...keys, adzunaId })} hint="developer.adzuna.com → Register" /> setKeys({ ...keys, adzunaKey })} />
value.trim())} onClick={() => void save(Object.fromEntries(Object.entries(keys).filter(([, value]) => value.trim()))) } > Schlüssel speichern
); }; const KeyField: React.FC<{ label: string; current: string | null; value: string; onChange: (value: string) => void; hint?: string; }> = ({ label, current, value, onChange, hint }) => ( onChange(event.target.value)} placeholder={current ? '•••••••• (ersetzen)' : ''} autoComplete="off" spellCheck={false} className={`${inputClass} font-mono`} /> );