Jobsearcher

<?php
session_start();

// --- Config ---
define('CONFIG_FILE', __DIR__ . '/data/config.json');
define('SOURCES_FILE', __DIR__ . '/data/sources.json');
define('RESULTS_FILE', __DIR__ . '/data/results.json');
define('APP_PASSWORD', 'changeme123'); // <-- Passwort hier ändern

// --- Bootstrap ---
if (!is_dir(__DIR__ . '/data')) mkdir(__DIR__ . '/data', 0755, true);
if (!file_exists(CONFIG_FILE)) file_put_contents(CONFIG_FILE, json_encode(['api_key' => '', 'keywords' => 'Marketing Manager, Senior Marketing, Head of Marketing', 'location' => 'Karlsruhe, Pforzheim, Heilbronn'], JSON_PRETTY_PRINT));
if (!file_exists(SOURCES_FILE)) file_put_contents(SOURCES_FILE, json_encode([], JSON_PRETTY_PRINT));
if (!file_exists(RESULTS_FILE)) file_put_contents(RESULTS_FILE, json_encode([], JSON_PRETTY_PRINT));

function loadJson($file) { return json_decode(file_get_contents($file), true) ?? []; }
function saveJson($file, $data) { file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); }

// --- Auth ---
if (isset($_POST['logout'])) { session_destroy(); header('Location: index.php'); exit; }
if (isset($_POST['password'])) {
    if ($_POST['password'] === APP_PASSWORD) { $_SESSION['auth'] = true; }
    else { $loginError = 'Falsches Passwort.'; }
}
if (!isset($_SESSION['auth'])) { showLogin($loginError ?? null); exit; }

// --- Actions ---
$config = loadJson(CONFIG_FILE);
$sources = loadJson(SOURCES_FILE);
$results = loadJson(RESULTS_FILE);
$message = '';
$scanLog = [];

// Save config
if (isset($_POST['save_config'])) {
    $config['api_key'] = trim($_POST['api_key'] ?? '');
    $config['keywords'] = trim($_POST['keywords'] ?? '');
    $config['location'] = trim($_POST['location'] ?? '');
    saveJson(CONFIG_FILE, $config);
    $message = '✓ Einstellungen gespeichert.';
}

// Add source
if (isset($_POST['add_source'])) {
    $url = trim($_POST['source_url'] ?? '');
    $name = trim($_POST['source_name'] ?? '');
    if ($url && $name) {
        $sources[] = ['id' => uniqid(), 'name' => $name, 'url' => $url, 'active' => true];
        saveJson(SOURCES_FILE, $sources);
        $message = '✓ Quelle hinzugefügt.';
    }
}

// Toggle source
if (isset($_POST['toggle_source'])) {
    foreach ($sources as &$s) {
        if ($s['id'] === $_POST['toggle_source']) { $s['active'] = !$s['active']; }
    }
    saveJson(SOURCES_FILE, $sources);
    header('Location: index.php?tab=sources'); exit;
}

// Delete source
if (isset($_POST['delete_source'])) {
    $sources = array_values(array_filter($sources, fn($s) => $s['id'] !== $_POST['delete_source']));
    saveJson(SOURCES_FILE, $sources);
    header('Location: index.php?tab=sources'); exit;
}

// Delete result
if (isset($_POST['delete_result'])) {
    $results = array_values(array_filter($results, fn($r) => $r['id'] !== $_POST['delete_result']));
    saveJson(RESULTS_FILE, $results);
    header('Location: index.php?tab=results'); exit;
}

// Clear all results
if (isset($_POST['clear_results'])) {
    saveJson(RESULTS_FILE, []);
    $results = [];
    $message = '✓ Alle Ergebnisse gelöscht.';
}

// --- SCAN ---
if (isset($_POST['start_scan'])) {
    if (empty($config['api_key'])) {
        $message = '⚠ Bitte zuerst den Claude API Key in den Einstellungen eintragen.';
    } else {
        $activeSources = array_filter($sources, fn($s) => $s['active']);
        if (empty($activeSources)) {
            $message = '⚠ Keine aktiven Quellen vorhanden.';
        } else {
            $newJobs = [];
            $existingUrls = array_column($results, 'url');

            foreach ($activeSources as $source) {
                $scanLog[] = "Lese: " . $source['name'];
                $jobs = fetchRssFeed($source['url'], $source['name']);
                $scanLog[] = "→ " . count($jobs) . " Einträge gefunden";
                foreach ($jobs as $job) {
                    if (!in_array($job['url'], $existingUrls)) {
                        $newJobs[] = $job;
                        $existingUrls[] = $job['url'];
                    }
                }
            }

            $scanLog[] = "Neu gesamt: " . count($newJobs) . " Stellen";

            if (!empty($newJobs)) {
                $keywords = strtolower($config['keywords']);
                $kwList = array_map('trim', explode(',', $keywords));
                $location = strtolower($config['location']);
                $locList = array_map('trim', explode(',', $location));

                $filtered = array_filter($newJobs, function($job) use ($kwList, $locList) {
                    $text = strtolower($job['title'] . ' ' . $job['description']);
                    $locText = strtolower($job['location'] ?? $job['title'] . ' ' . $job['description']);
                    $kwMatch = false;
                    foreach ($kwList as $kw) { if ($kw && strpos($text, $kw) !== false) { $kwMatch = true; break; } }
                    if (!$kwMatch) return false;
                    if (empty(array_filter($locList))) return true;
                    foreach ($locList as $loc) { if ($loc && strpos($locText, $loc) !== false) return true; }
                    return false;
                });

                $filtered = array_values($filtered);
                $scanLog[] = "Nach Filter: " . count($filtered) . " relevante Stellen";

                foreach ($filtered as $job) {
                    $scanLog[] = "Bewerte: " . $job['title'];
                    $rating = rateJobWithClaude($job, $config['api_key']);
                    $results[] = [
                        'id' => uniqid(),
                        'title' => $job['title'],
                        'company' => $job['company'] ?? '',
                        'location' => $job['location'] ?? '',
                        'url' => $job['url'],
                        'source' => $job['source'],
                        'description' => substr($job['description'], 0, 500),
                        'rating' => $rating['rating'] ?? 'unbekannt',
                        'verdict' => $rating['verdict'] ?? '',
                        'summary' => $rating['summary'] ?? '',
                        'found_at' => date('d.m.Y H:i'),
                    ];
                }
                saveJson(RESULTS_FILE, $results);
                $message = '✓ Scan abgeschlossen. ' . count($filtered) . ' neue Stellen bewertet.';
            } else {
                $message = 'ℹ Keine neuen Stellen gefunden.';
            }
        }
    }
}

// --- Functions ---
function fetchRssFeed($url, $sourceName) {
    $jobs = [];
    $ctx = stream_context_create(['http' => ['timeout' => 15, 'header' => 'User-Agent: Mozilla/5.0 JobScout/1.0']]);
    $xml = @file_get_contents($url, false, $ctx);
    if (!$xml) return $jobs;
    libxml_use_internal_errors(true);
    $feed = simplexml_load_string($xml);
    if (!$feed) return $jobs;
    $items = $feed->channel->item ?? $feed->entry ?? [];
    foreach ($items as $item) {
        $title = (string)($item->title ?? '');
        $link = (string)($item->link ?? $item->id ?? '');
        if (is_object($item->link) && isset($item->link['href'])) $link = (string)$item->link['href'];
        $desc = strip_tags((string)($item->description ?? $item->summary ?? $item->content ?? ''));
        if ($title && $link) {
            $jobs[] = ['title' => $title, 'url' => $link, 'description' => $desc, 'company' => '', 'location' => '', 'source' => $sourceName];
        }
    }
    return $jobs;
}

function rateJobWithClaude($job, $apiKey) {
    $profile = <<<PROFILE
Frederik ist Senior Marketing Manager mit 15+ Jahren Erfahrung, davon 2,5 Jahre B2B-IT (Microsoft, Security, KI, Cloud).
Kernkompetenz: Komplexe technische Themen verständlich kommunizieren, Marketing als System aufbauen.
Sucht: Teamlead / Head of Marketing oder Senior Marketing Manager.
Branche bevorzugt: IT, SaaS, Mittelstand, Technologieunternehmen, erklärungsbedürftige Produkte.
Region: Karlsruhe, Pforzheim, Heilbronn, BaWü (40km um Eisingen/Pforzheim).
No-Gos: Reine Ausführungsrollen, konzernweit gesteuerte Satelliten-Marketingstellen, kein Gestaltungsspielraum.
Gehalt Senior: ~65k€, Teamlead: 76-80k€.
PROFILE;

    $prompt = "Bewerte diese Stellenanzeige für Frederik:\n\nTitel: {$job['title']}\nBeschreibung: {$job['description']}\n\nProfil:\n$profile\n\nAntworte NUR mit gültigem JSON (kein Markdown, keine Backticks):\n{\"rating\": \"gruen|gelb|rot\", \"verdict\": \"Ein Satz Urteil\", \"summary\": \"2-3 Sätze Begründung\"}";

    $payload = json_encode(['model' => 'claude-sonnet-4-20250514', 'max_tokens' => 300, 'messages' => [['role' => 'user', 'content' => $prompt]]]);
    $ctx = stream_context_create(['http' => ['method' => 'POST', 'timeout' => 30, 'header' => "Content-Type: application/json\r\nx-api-key: $apiKey\r\nanthropid-version: 2023-06-01\r\n", 'content' => $payload]]);
    $response = @file_get_contents('https://api.anthropic.com/v1/messages', false, $ctx);
    if (!$response) return ['rating' => 'unbekannt', 'verdict' => 'API nicht erreichbar', 'summary' => ''];
    $data = json_decode($response, true);
    $text = $data['content'][0]['text'] ?? '';
    $text = preg_replace('/```json|```/', '', $text);
    $parsed = json_decode(trim($text), true);
    return $parsed ?: ['rating' => 'unbekannt', 'verdict' => $text, 'summary' => ''];
}

$tab = $_GET['tab'] ?? 'results';

// Sort results
usort($results, function($a, $b) {
    $order = ['gruen' => 0, 'gelb' => 1, 'rot' => 2, 'unbekannt' => 3];
    return ($order[$a['rating']] ?? 3) <=> ($order[$b['rating']] ?? 3);
});

// --- Output ---
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JobScout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Syne:wght@400;600;700;800&display=swap" rel="stylesheet">
<style>
  :root {
    --bg: #0e0f11;
    --surface: #16181c;
    --border: #2a2d35;
    --accent: #c8f135;
    --accent2: #4af0c4;
    --text: #e8eaf0;
    --muted: #6b7280;
    --gruen: #4af0c4;
    --gelb: #f5c842;
    --rot: #f05a5a;
    --font-head: 'Syne', sans-serif;
    --font-mono: 'DM Mono', monospace;
  }
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  body { background: var(--bg); color: var(--text); font-family: var(--font-mono); min-height: 100vh; }

  /* Header */
  .header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem 2rem; border-bottom: 1px solid var(--border); }
  .logo { font-family: var(--font-head); font-weight: 800; font-size: 1.4rem; color: var(--accent); letter-spacing: -0.03em; }
  .logo span { color: var(--muted); font-weight: 400; }
  .logout-btn { background: none; border: 1px solid var(--border); color: var(--muted); padding: .4rem .9rem; cursor: pointer; font-family: var(--font-mono); font-size: .75rem; border-radius: 4px; transition: all .2s; }
  .logout-btn:hover { border-color: var(--accent); color: var(--accent); }

  /* Nav */
  .nav { display: flex; gap: 0; border-bottom: 1px solid var(--border); padding: 0 2rem; }
  .nav a { padding: .85rem 1.2rem; font-size: .8rem; color: var(--muted); text-decoration: none; border-bottom: 2px solid transparent; transition: all .2s; letter-spacing: .05em; text-transform: uppercase; }
  .nav a.active { color: var(--accent); border-bottom-color: var(--accent); }
  .nav a:hover:not(.active) { color: var(--text); }

  /* Main */
  .main { max-width: 1100px; margin: 0 auto; padding: 2rem; }

  /* Message */
  .msg { background: #1a1f2e; border: 1px solid var(--accent2); color: var(--accent2); padding: .75rem 1.1rem; border-radius: 6px; margin-bottom: 1.5rem; font-size: .85rem; }

  /* Scan bar */
  .scan-bar { display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem; }
  .btn-scan { background: var(--accent); color: #0e0f11; border: none; padding: .75rem 2rem; font-family: var(--font-head); font-weight: 700; font-size: .95rem; cursor: pointer; border-radius: 6px; transition: all .2s; letter-spacing: .02em; }
  .btn-scan:hover { background: #d9ff50; transform: translateY(-1px); }
  .btn-scan:active { transform: translateY(0); }
  .scan-meta { color: var(--muted); font-size: .78rem; }

  /* Results table */
  .results-grid { display: flex; flex-direction: column; gap: .6rem; }
  .result-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 1.1rem 1.3rem; display: grid; grid-template-columns: 36px 1fr auto; gap: .75rem; align-items: start; transition: border-color .2s; }
  .result-card:hover { border-color: #3a3d45; }
  .result-card.gruen { border-left: 3px solid var(--gruen); }
  .result-card.gelb { border-left: 3px solid var(--gelb); }
  .result-card.rot { border-left: 3px solid var(--rot); }
  .result-card.unbekannt { border-left: 3px solid var(--muted); }

  .ampel { width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; margin-top: 2px; }
  .ampel.gruen { background: var(--gruen); box-shadow: 0 0 12px rgba(74,240,196,.4); }
  .ampel.gelb { background: var(--gelb); box-shadow: 0 0 12px rgba(245,200,66,.4); }
  .ampel.rot { background: var(--rot); box-shadow: 0 0 12px rgba(240,90,90,.4); }
  .ampel.unbekannt { background: var(--muted); }

  .result-body {}
  .result-title { font-family: var(--font-head); font-weight: 700; font-size: 1rem; color: var(--text); margin-bottom: .25rem; }
  .result-title a { color: inherit; text-decoration: none; }
  .result-title a:hover { color: var(--accent); }
  .result-meta { color: var(--muted); font-size: .75rem; margin-bottom: .4rem; }
  .result-verdict { color: var(--text); font-size: .82rem; margin-bottom: .25rem; }
  .result-summary { color: var(--muted); font-size: .78rem; line-height: 1.5; }
  .result-actions { display: flex; flex-direction: column; gap: .4rem; align-items: flex-end; }
  .tag { font-size: .7rem; padding: .2rem .55rem; border-radius: 3px; font-family: var(--font-mono); }
  .tag.gruen { background: rgba(74,240,196,.12); color: var(--gruen); }
  .tag.gelb { background: rgba(245,200,66,.12); color: var(--gelb); }
  .tag.rot { background: rgba(240,90,90,.12); color: var(--rot); }
  .tag.muted { background: rgba(107,114,128,.12); color: var(--muted); }

  .btn-del { background: none; border: none; color: var(--muted); cursor: pointer; font-size: .75rem; padding: .3rem .5rem; }
  .btn-del:hover { color: var(--rot); }

  /* Empty state */
  .empty { text-align: center; padding: 4rem 2rem; color: var(--muted); }
  .empty-icon { font-size: 3rem; margin-bottom: 1rem; opacity: .4; }
  .empty h3 { font-family: var(--font-head); color: var(--text); margin-bottom: .5rem; }

  /* Sources */
  .sources-grid { display: flex; flex-direction: column; gap: .6rem; margin-bottom: 2rem; }
  .source-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: .9rem 1.2rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
  .source-info { flex: 1; min-width: 0; }
  .source-name { font-family: var(--font-head); font-weight: 600; font-size: .9rem; }
  .source-url { color: var(--muted); font-size: .72rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 500px; }
  .source-actions { display: flex; gap: .5rem; align-items: center; flex-shrink: 0; }
  .status-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
  .status-dot.on { background: var(--gruen); }
  .status-dot.off { background: var(--muted); }

  .btn-sm { background: none; border: 1px solid var(--border); color: var(--muted); padding: .3rem .7rem; cursor: pointer; font-family: var(--font-mono); font-size: .72rem; border-radius: 4px; transition: all .15s; }
  .btn-sm:hover { border-color: var(--accent2); color: var(--accent2); }
  .btn-sm.danger:hover { border-color: var(--rot); color: var(--rot); }

  /* Forms */
  .form-section { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 1.5rem; margin-bottom: 1.5rem; }
  .form-section h3 { font-family: var(--font-head); font-weight: 700; margin-bottom: 1.2rem; font-size: 1rem; color: var(--accent); }
  .form-row { display: flex; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
  .form-group { flex: 1; min-width: 200px; }
  label { display: block; font-size: .75rem; color: var(--muted); margin-bottom: .4rem; text-transform: uppercase; letter-spacing: .05em; }
  input[type=text], input[type=password] { width: 100%; background: var(--bg); border: 1px solid var(--border); color: var(--text); padding: .6rem .9rem; font-family: var(--font-mono); font-size: .85rem; border-radius: 5px; outline: none; transition: border-color .2s; }
  input:focus { border-color: var(--accent2); }
  .btn-save { background: var(--accent2); color: #0e0f11; border: none; padding: .6rem 1.5rem; font-family: var(--font-head); font-weight: 700; font-size: .85rem; cursor: pointer; border-radius: 5px; transition: all .2s; }
  .btn-save:hover { background: #6df5d5; }

  /* Scan log */
  .scan-log { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; margin-top: 1.5rem; font-size: .78rem; color: var(--muted); line-height: 1.8; }
  .scan-log-title { color: var(--accent); font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; margin-bottom: .5rem; }

  /* Badge */
  .badge { background: var(--accent); color: #0e0f11; font-size: .65rem; padding: .15rem .45rem; border-radius: 3px; font-weight: 700; margin-left: .5rem; }

  /* Stats bar */
  .stats-bar { display: flex; gap: 1.5rem; margin-bottom: 1.5rem; flex-wrap: wrap; }
  .stat { display: flex; align-items: center; gap: .5rem; font-size: .8rem; }
  .stat-dot { width: 10px; height: 10px; border-radius: 50%; }

  /* Hint box */
  .hint { background: #1a1f2e; border: 1px solid #2a3a5e; border-radius: 6px; padding: 1rem 1.2rem; font-size: .8rem; color: #8899cc; line-height: 1.6; margin-bottom: 1.5rem; }
  .hint strong { color: var(--accent2); }
</style>
</head>
<body>

<div class="header">
  <div class="logo">Job<span>Scout</span></div>
  <form method="post"><button class="logout-btn" name="logout" value="1">Abmelden</button></form>
</div>

<nav class="nav">
  <a href="?tab=results" class="<?= $tab==='results'?'active':'' ?>">Ergebnisse<?php $c=count($results); if($c>0) echo "<span class='badge'>$c</span>"; ?></a>
  <a href="?tab=sources" class="<?= $tab==='sources'?'active':'' ?>">Quellen<?php $sc=count($sources); if($sc>0) echo "<span class='badge'>$sc</span>"; ?></a>
  <a href="?tab=settings" class="<?= $tab==='settings'?'active':'' ?>">Einstellungen</a>
</nav>

<div class="main">

<?php if ($message): ?>
<div class="msg"><?= htmlspecialchars($message) ?></div>
<?php endif; ?>

<?php if ($tab === 'results'): ?>

  <div class="scan-bar">
    <form method="post">
      <button class="btn-scan" name="start_scan" value="1">▶ Jetzt suchen</button>
    </form>
    <div class="scan-meta"><?= count($sources) ?> Quellen · <?= count(array_filter($sources, fn($s)=>$s['active'])) ?> aktiv</div>
  </div>

  <?php if (!empty($scanLog)): ?>
  <div class="scan-log">
    <div class="scan-log-title">Scan-Protokoll</div>
    <?php foreach ($scanLog as $line) echo htmlspecialchars($line) . "<br>"; ?>
  </div>
  <?php endif; ?>

  <?php if (!empty($results)): ?>
  <?php
    $g = count(array_filter($results, fn($r)=>$r['rating']==='gruen'));
    $y = count(array_filter($results, fn($r)=>$r['rating']==='gelb'));
    $r = count(array_filter($results, fn($r)=>$r['rating']==='rot'));
  ?>
  <div class="stats-bar">
    <div class="stat"><div class="stat-dot" style="background:var(--gruen)"></div><?= $g ?> Gut passend</div>
    <div class="stat"><div class="stat-dot" style="background:var(--gelb)"></div><?= $y ?> Mit Einschränkungen</div>
    <div class="stat"><div class="stat-dot" style="background:var(--rot)"></div><?= $r ?> Nicht empfohlen</div>
    <div style="margin-left:auto">
      <form method="post" onsubmit="return confirm('Wirklich alle löschen?')">
        <button class="btn-sm danger" name="clear_results" value="1">Alle löschen</button>
      </form>
    </div>
  </div>

  <div class="results-grid">
    <?php foreach ($results as $result): ?>
    <?php $r = $result['rating'] ?? 'unbekannt'; ?>
    <div class="result-card <?= htmlspecialchars($r) ?>">
      <div class="ampel <?= htmlspecialchars($r) ?>"></div>
      <div class="result-body">
        <div class="result-title"><a href="<?= htmlspecialchars($result['url']) ?>" target="_blank"><?= htmlspecialchars($result['title']) ?></a></div>
        <div class="result-meta"><?= htmlspecialchars($result['company'] ?: '—') ?> · <?= htmlspecialchars($result['location'] ?: '—') ?> · <?= htmlspecialchars($result['source']) ?> · <?= htmlspecialchars($result['found_at']) ?></div>
        <?php if ($result['verdict']): ?><div class="result-verdict"><?= htmlspecialchars($result['verdict']) ?></div><?php endif; ?>
        <?php if ($result['summary']): ?><div class="result-summary"><?= htmlspecialchars($result['summary']) ?></div><?php endif; ?>
      </div>
      <div class="result-actions">
        <span class="tag <?= htmlspecialchars($r) ?>"><?= $r==='gruen'?'✓ Gut':($r==='gelb'?'~ Prüfen':($r==='rot'?'✗ Nein':'?')) ?></span>
        <form method="post">
          <input type="hidden" name="delete_result" value="<?= htmlspecialchars($result['id']) ?>">
          <button class="btn-del" title="Löschen">✕</button>
        </form>
      </div>
    </div>
    <?php endforeach; ?>
  </div>

  <?php else: ?>
  <div class="empty">
    <div class="empty-icon">◎</div>
    <h3>Noch keine Ergebnisse</h3>
    <p>Quellen einrichten und auf „Jetzt suchen" klicken.</p>
  </div>
  <?php endif; ?>

<?php elseif ($tab === 'sources'): ?>

  <div class="hint">
    <strong>RSS-Feed URLs</strong> der Stellenbörsen hier eintragen. Die meisten Jobportale bieten RSS-Feeds für Suchergebnisse an — die URL bekommst du, indem du eine Suche startest und dann auf „RSS" oder „Feed abonnieren" klickst. <strong>Tipps für gute Quellen:</strong> Arbeitsagentur (jobsuche.arbeitsagentur.de → RSS-Symbol), Stepstone, Indeed, sowie Karriereseiten direkt bei Unternehmen.
  </div>

  <?php if (!empty($sources)): ?>
  <div class="sources-grid">
    <?php foreach ($sources as $source): ?>
    <div class="source-card">
      <div class="status-dot <?= $source['active'] ? 'on' : 'off' ?>"></div>
      <div class="source-info">
        <div class="source-name"><?= htmlspecialchars($source['name']) ?></div>
        <div class="source-url"><?= htmlspecialchars($source['url']) ?></div>
      </div>
      <div class="source-actions">
        <form method="post">
          <input type="hidden" name="toggle_source" value="<?= htmlspecialchars($source['id']) ?>">
          <button class="btn-sm"><?= $source['active'] ? 'Deaktivieren' : 'Aktivieren' ?></button>
        </form>
        <form method="post" onsubmit="return confirm('Quelle löschen?')">
          <input type="hidden" name="delete_source" value="<?= htmlspecialchars($source['id']) ?>">
          <button class="btn-sm danger">Löschen</button>
        </form>
      </div>
    </div>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>

  <div class="form-section">
    <h3>Neue Quelle hinzufügen</h3>
    <form method="post">
      <div class="form-row">
        <div class="form-group">
          <label>Name der Quelle</label>
          <input type="text" name="source_name" placeholder="z.B. Stepstone Marketing BaWü">
        </div>
        <div class="form-group">
          <label>RSS-Feed URL</label>
          <input type="text" name="source_url" placeholder="https://www.stepstone.de/...rss...">
        </div>
      </div>
      <button class="btn-save" name="add_source" value="1">Quelle hinzufügen</button>
    </form>
  </div>

<?php elseif ($tab === 'settings'): ?>

  <div class="form-section">
    <h3>Claude API Key</h3>
    <form method="post">
      <div class="form-row">
        <div class="form-group">
          <label>API Key</label>
          <input type="text" name="api_key" value="<?= htmlspecialchars($config['api_key'] ?? '') ?>" placeholder="sk-ant-...">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label>Suchbegriffe (kommagetrennt)</label>
          <input type="text" name="keywords" value="<?= htmlspecialchars($config['keywords'] ?? '') ?>" placeholder="Marketing Manager, Head of Marketing">
        </div>
        <div class="form-group">
          <label>Standorte (kommagetrennt)</label>
          <input type="text" name="location" value="<?= htmlspecialchars($config['location'] ?? '') ?>" placeholder="Karlsruhe, Pforzheim, Heilbronn">
        </div>
      </div>
      <button class="btn-save" name="save_config" value="1">Einstellungen speichern</button>
    </form>
  </div>

  <div class="hint">
    <strong>API Key anlegen:</strong> Gehe auf <strong>console.anthropic.com</strong> → Account anlegen → „API Keys" → „Create Key". Den Key einmalig hier eintragen, er wird lokal auf deinem Server gespeichert. Kosten: ca. 0,01–0,05 € pro bewerteter Stelle (sehr günstig).<br><br>
    <strong>Passwort ändern:</strong> Öffne die Datei <code>index.php</code> und ändere in Zeile 6 den Wert <code>changeme123</code> auf ein eigenes Passwort.
  </div>

<?php endif; ?>

</div>
</body>
</html>
<?php

function showLogin($error = null) {
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JobScout · Login</title>
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=DM+Mono&display=swap" rel="stylesheet">
<style>
  :root { --bg:#0e0f11; --surface:#16181c; --border:#2a2d35; --accent:#c8f135; --text:#e8eaf0; --muted:#6b7280; }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body { background: var(--bg); color: var(--text); font-family: 'DM Mono', monospace; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
  .box { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 2.5rem; width: 360px; }
  .logo { font-family: 'Syne', sans-serif; font-weight: 800; font-size: 1.8rem; color: var(--accent); margin-bottom: .4rem; }
  .sub { color: var(--muted); font-size: .8rem; margin-bottom: 2rem; }
  label { display: block; font-size: .75rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: .4rem; }
  input[type=password] { width: 100%; background: var(--bg); border: 1px solid var(--border); color: var(--text); padding: .7rem 1rem; font-family: 'DM Mono', monospace; font-size: .9rem; border-radius: 6px; outline: none; margin-bottom: 1rem; }
  input:focus { border-color: var(--accent); }
  button { width: 100%; background: var(--accent); color: #0e0f11; border: none; padding: .75rem; font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1rem; cursor: pointer; border-radius: 6px; }
  .error { color: #f05a5a; font-size: .8rem; margin-bottom: 1rem; }
</style>
</head>
<body>
<div class="box">
  <div class="logo">JobScout</div>
  <div class="sub">Dein persönliches Stellenradar</div>
  <form method="post">
    <?php if ($error): ?><div class="error"><?= htmlspecialchars($error) ?></div><?php endif; ?>
    <label>Passwort</label>
    <input type="password" name="password" autofocus>
    <button type="submit">Einloggen</button>
  </form>
</div>
</body>
</html>
<?php
}
?>
Nach oben scrollen