Files
geograsim/App/pages/lehrplan.php
T
Adminator 7deec2a26d Lehrplan: Country-Helper + Landeinstellung live
- App/php/lib/Country.php: Kaskade session → classes → teachers →
  cookie → 'AT', Helper current()/flag()/label()/allCountries()
- App/php/api/country.php: GET + POST /api/country
- country-Spalten in teachers, classes, student_sessions (idempotent)
- Native-<select>-Picker im Header aller öffentlichen Seiten
  (modul-*.php, lehrplan.php, simulationen.php)
- Footer-Links "Andere Länder: 🇨🇭 🇩🇪 🇱🇮"
- lehrplan.php liest Default-Filter jetzt aus Country::current()
- iPad-freundlich: Native Select gibt Wheel-Picker auf iOS,
  Touch-Ziel >=40px

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 00:09:43 +02:00

666 lines
28 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
<?php
/**
* Lehrplan-Übersicht
* -------------------
* Gesammelte Lehrplan-Verankerungen für alle Simulationen, gruppiert nach
* didaktischem Kompetenzbereich, mit Filter für Land (AT/DE/CH/LI), Thema
* und Anker-Typ.
*
* URL: http://localhost/geograsim/App/lehrplan (Front-Controller)
* ?country=AT vorgewählter Länder-Filter (Default: AT)
* ?theme=klima vorgewählter Themen-Filter
* ?module=fluss vorgewähltes Modul
*/
require_once __DIR__ . '/../php/config/app.php';
require_once __DIR__ . '/../php/config/db.php';
require_once __DIR__ . '/../php/lib/EasyLang.php';
require_once __DIR__ . '/../php/lib/Country.php';
$db = getDB();
// Filter: Default ist das aktuelle Landes-Setting (Kaskade), per URL überschreibbar
$allowedCountries = ['AT', 'DE', 'CH', 'LI'];
if (isset($_GET['country'])) {
$qCountry = strtoupper(trim($_GET['country']));
if (!in_array($qCountry, $allowedCountries, true) && $qCountry !== 'ALL') {
$qCountry = Country::current();
}
} else {
$qCountry = Country::current();
}
$qTheme = preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['theme'] ?? ''));
$qModule = preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['module'] ?? ''));
// Alle Kompetenzen mit Zuordnungen + Ankern laden
$kompetenzen = $db->query('
SELECT id, key_slug, title, description, category, age_min, age_max, sort_order
FROM kompetenzen
ORDER BY sort_order, title
')->fetchAll();
// Module je Kompetenz
$modStmt = $db->prepare('
SELECT mi.module_id, mi.title, mi.icon, mi.card_image, mi.status, mi.page_url,
km.strength
FROM kompetenz_modules km
INNER JOIN module_info mi ON mi.module_id = km.module_id
WHERE km.kompetenz_id = ?
ORDER BY FIELD(km.strength, "primaer", "sekundaer"), mi.sort_order
');
// Anker je Kompetenz
$ankerStmt = $db->prepare("
SELECT anchor_type, country, region, school_type, grade, subject,
title, reference, reference_url, quote
FROM lehrplan_anchors
WHERE kompetenz_id = ?
ORDER BY FIELD(anchor_type, 'fach', 'uebergreifendes_thema', 'anderes_fach'),
country, sort_order
");
foreach ($kompetenzen as &$k) {
$modStmt->execute([$k['id']]);
$k['modules'] = $modStmt->fetchAll();
$ankerStmt->execute([$k['id']]);
$rows = $ankerStmt->fetchAll();
$k['anchors_fach'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'fach'));
$k['anchors_uebergreifend'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'uebergreifendes_thema'));
$k['anchors_andere_faecher'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'anderes_fach'));
$k['anchors_all'] = $rows;
}
unset($k);
// Zählungen (global) für Filter-Badges
$totalAnchors = (int) $db->query('SELECT COUNT(*) FROM lehrplan_anchors')->fetchColumn();
$countsByCountry = [];
foreach ($db->query("SELECT country, COUNT(*) AS n FROM lehrplan_anchors GROUP BY country") as $r) {
$countsByCountry[$r['country']] = (int)$r['n'];
}
$countsByType = [];
foreach ($db->query("SELECT anchor_type, COUNT(*) AS n FROM lehrplan_anchors GROUP BY anchor_type") as $r) {
$countsByType[$r['anchor_type']] = (int)$r['n'];
}
$bp = BASE_PATH;
$easyActive = EasyLang::isActive();
function esc(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
$countryMeta = [
'AT' => ['flag' => '🇦🇹', 'label' => 'Österreich'],
'DE' => ['flag' => '🇩🇪', 'label' => 'Deutschland'],
'CH' => ['flag' => '🇨🇭', 'label' => 'Schweiz'],
'LI' => ['flag' => '🇱🇮', 'label' => 'Liechtenstein'],
];
$categoryMeta = [
'klima' => ['label' => 'Klima'],
'natur' => ['label' => 'Naturgefahren'],
'raum' => ['label' => 'Raum'],
'gesellschaft' => ['label' => 'Gesellschaft'],
];
?><!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lehrplan-Übersicht — Lehrplan geograsim.at</title>
<meta name="description" content="Alle Lehrplan-Verankerungen der GeoGraSim-Simulationen für Österreich, Deutschland, Schweiz und Liechtenstein — gruppiert nach didaktischem Kompetenzbereich.">
<link rel="icon" type="image/svg+xml" href="<?= $bp ?>/favicon.svg">
<link rel="icon" type="image/png" href="<?= $bp ?>/favicon-96x96.png" sizes="96x96">
<link rel="stylesheet" href="<?= $bp ?>/assets/fonts/inter.css">
<link rel="stylesheet" href="<?= $bp ?>/assets/css/design-system.css">
<style>
body { overflow: auto; height: auto; min-height: 100vh; background: var(--ggs-bg); }
/* ===== Topbar (wie modul-detail) ===== */
.lp-topbar {
background: var(--ggs-white);
padding: .55rem 1.2rem;
display: flex; align-items: center; gap: .8rem;
border-bottom: 1px solid var(--ggs-border);
position: sticky; top: 0; z-index: 50;
}
.lp-topbar a { text-decoration: none; }
.lp-topbar-brand img { height: 40px; display: block; }
.lp-topbar .spacer { flex: 1; }
.lp-btn-sm {
padding: .5rem .85rem; border: 1px solid var(--ggs-border);
border-radius: var(--ggs-radius-sm); background: var(--ggs-white);
font-size: .78rem; font-weight: 600; cursor: pointer;
color: var(--ggs-text); font-family: inherit; text-decoration: none;
display: inline-flex; align-items: center; min-height: 40px;
}
.lp-btn-sm:hover { background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark); border-color: var(--ggs-fjord); }
.lp-btn-sm.lp-btn-primary { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
.lp-easy-pill { background: var(--ggs-moss-light); color: var(--ggs-moss-dark); border-color: var(--ggs-moss); font-weight: 700; }
/* ===== Hero ===== */
.lp-hero {
background: linear-gradient(135deg, var(--ggs-fjord-dark) 0%, var(--ggs-fjord) 100%);
color: var(--ggs-white);
padding: 2.5rem 1.5rem 3rem;
text-align: center;
}
.lp-hero h1 {
font-size: clamp(1.8rem, 4vw, 2.6rem);
font-weight: 900; letter-spacing: -.03em;
margin-bottom: .5rem;
}
.lp-hero p { font-size: 1.02rem; color: rgba(255,255,255,.88); max-width: 640px; margin: 0 auto 1.4rem; }
.lp-hero-stats { display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap; margin-top: 1.2rem; }
.lp-hero-stat { text-align: center; }
.lp-hero-stat-num { font-size: 1.8rem; font-weight: 900; display: block; }
.lp-hero-stat-lbl { font-size: .72rem; opacity: .8; text-transform: uppercase; letter-spacing: .08em; }
/* ===== Filter-Bar ===== */
.lp-filters {
max-width: 1100px; margin: -1.4rem auto 1.5rem;
padding: 1rem 1.2rem; background: var(--ggs-white);
border-radius: var(--ggs-radius-lg); box-shadow: var(--ggs-shadow-lg);
border: 1px solid var(--ggs-border);
position: relative; z-index: 5;
display: flex; flex-direction: column; gap: .9rem;
}
.lp-filter-row {
display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
}
.lp-filter-label {
font-size: .72rem; font-weight: 800; text-transform: uppercase;
letter-spacing: .08em; color: var(--ggs-text-muted);
min-width: 60px;
}
.lp-chip {
display: inline-flex; align-items: center; gap: .3rem;
padding: .55rem 1rem; border-radius: var(--ggs-radius-pill);
background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
font-size: .88rem; font-weight: 600; color: var(--ggs-text-muted);
cursor: pointer; transition: all .2s var(--ggs-ease); font-family: inherit;
min-height: 40px; min-width: 40px;
}
.lp-chip:hover { border-color: var(--ggs-fjord); color: var(--ggs-fjord); }
.lp-chip:active { transform: scale(0.96); }
.lp-chip.active { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
.lp-chip-badge {
font-size: .7rem; padding: 1px 6px; border-radius: var(--ggs-radius-pill);
background: var(--ggs-bg-dark); color: var(--ggs-text-muted);
font-weight: 700;
}
.lp-chip.active .lp-chip-badge {
background: rgba(255,255,255,.22); color: var(--ggs-white);
}
/* ===== Kompetenz-Karten ===== */
.lp-wrap { max-width: 1100px; margin: 0 auto 3rem; padding: 0 1.2rem; }
.lp-results-info {
font-size: .82rem; color: var(--ggs-text-muted);
margin-bottom: 1rem;
}
.lp-kompetenz {
background: var(--ggs-white); border: 1px solid var(--ggs-border);
border-radius: var(--ggs-radius-md);
padding: 1.4rem 1.6rem;
margin-bottom: 1.2rem;
scroll-margin-top: 80px;
}
.lp-kompetenz-head {
display: flex; flex-wrap: wrap; align-items: flex-start;
gap: .8rem; margin-bottom: .5rem;
}
.lp-kompetenz-title {
font-size: 1.3rem; font-weight: 900; color: var(--ggs-fjord-dark);
letter-spacing: -.02em;
}
.lp-kompetenz-cat {
font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark);
padding: 3px 10px; border-radius: var(--ggs-radius-pill);
}
.lp-kompetenz-age {
font-size: .75rem; color: var(--ggs-text-muted);
background: var(--ggs-bg-dark); padding: 3px 10px;
border-radius: var(--ggs-radius-pill);
}
.lp-kompetenz-desc {
font-size: .93rem; line-height: 1.55; color: var(--ggs-text);
margin-bottom: 1rem;
}
/* Modul-Cards innerhalb einer Kompetenz */
.lp-modules-label {
font-size: .72rem; font-weight: 800; text-transform: uppercase;
letter-spacing: .1em; color: var(--ggs-text-muted);
margin: .4rem 0 .5rem;
}
.lp-modules {
display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1.2rem;
}
.lp-module-card {
display: inline-flex; align-items: center; gap: .55rem;
padding: .55rem .95rem .55rem .7rem;
background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
border-radius: var(--ggs-radius-md);
text-decoration: none; color: var(--ggs-text);
transition: all .2s var(--ggs-ease);
min-height: 44px;
}
.lp-module-card:hover, .lp-module-card:active {
border-color: var(--ggs-fjord); background: var(--ggs-fjord-light);
transform: translateY(-1px);
}
.lp-module-icon { font-size: 1.3rem; line-height: 1; }
.lp-module-name { font-size: .92rem; font-weight: 700; color: var(--ggs-fjord-dark); }
.lp-module-strength {
font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
padding: 1px 6px; border-radius: var(--ggs-radius-sm);
background: var(--ggs-moss-light); color: var(--ggs-moss-dark);
}
.lp-module-strength.sekundaer { background: var(--ggs-bg-dark); color: var(--ggs-text-muted); }
.lp-module-status {
font-size: .6rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
padding: 1px 5px; border-radius: var(--ggs-radius-sm);
}
.lp-module-status.aktiv { background: var(--ggs-moss); color: var(--ggs-white); }
.lp-module-status.beta { background: var(--ggs-sand-dark); color: var(--ggs-white); }
.lp-module-status.geplant { background: var(--ggs-fjord); color: var(--ggs-white); opacity: .7; }
/* Anker — wie modul-detail */
.lp-anchor-group { margin-top: .8rem; }
.lp-anchor-group-head {
display: flex; align-items: baseline; gap: .6rem;
margin: .4rem 0 .5rem; flex-wrap: wrap;
}
.lp-anchor-group-title {
font-size: .72rem; font-weight: 800; text-transform: uppercase;
letter-spacing: .1em; color: var(--ggs-fjord-dark);
}
.lp-anchor-group-sub {
font-size: .72rem; color: var(--ggs-text-muted); font-weight: 500;
}
.lp-anchors { display: grid; gap: .55rem; }
.lp-anchor {
display: grid; grid-template-columns: 28px 1fr; gap: .6rem; align-items: start;
font-size: .9rem; padding: .6rem .8rem;
background: var(--ggs-bg); border-radius: var(--ggs-radius-sm);
border-left: 3px solid var(--ggs-fjord-light);
}
.lp-anchor-flag { font-size: 1.2rem; line-height: 1.3; text-align: center; }
.lp-anchor-meta { font-size: .75rem; color: var(--ggs-text-muted); margin-bottom: .15rem; }
.lp-anchor-title { font-weight: 700; color: var(--ggs-fjord-dark); margin-bottom: .2rem; }
.lp-anchor-quote { font-size: .88rem; color: var(--ggs-text); font-style: italic; line-height: 1.45; }
.lp-anchor-ref { font-size: .72rem; color: var(--ggs-text-muted); margin-top: .3rem; }
.lp-anchor-link {
color: var(--ggs-fjord); text-decoration: none; font-weight: 600;
border-bottom: 1px dotted var(--ggs-fjord); padding: 2px 0;
}
.lp-anchor-link:hover { color: var(--ggs-fjord-dark); border-bottom-style: solid; }
.lp-anchor--fach { border-left-color: var(--ggs-fjord); }
.lp-anchor--uebergreifendes_thema { border-left-color: var(--ggs-moss); background: var(--ggs-moss-light); }
.lp-anchor--anderes_fach { border-left-color: var(--ggs-sand-dark); background: var(--ggs-bg-dark); }
.lp-anchor--uebergreifendes_thema .lp-anchor-flag,
.lp-anchor--anderes_fach .lp-anchor-flag { opacity: .65; }
.lp-anchor.hidden { display: none; }
.lp-kompetenz-empty {
padding: 1rem 0; color: var(--ggs-text-muted); font-style: italic;
font-size: .9rem;
}
.lp-hint {
font-size: .82rem; color: var(--ggs-text-muted); font-style: italic;
margin-top: 1.5rem; max-width: 780px;
}
.lp-toc {
background: var(--ggs-white); border: 1px solid var(--ggs-border);
border-radius: var(--ggs-radius-md);
padding: 1rem 1.2rem;
margin-bottom: 1.2rem;
}
.lp-toc-title {
font-size: .72rem; font-weight: 800; text-transform: uppercase;
letter-spacing: .1em; color: var(--ggs-text-muted);
margin-bottom: .5rem;
}
.lp-toc-list { display: flex; flex-wrap: wrap; gap: .4rem; }
.lp-toc-item {
display: inline-flex; align-items: center; gap: .3rem;
padding: .35rem .75rem; border-radius: var(--ggs-radius-pill);
background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark);
font-size: .82rem; font-weight: 600; text-decoration: none;
transition: background .2s var(--ggs-ease);
min-height: 32px;
}
.lp-toc-item:hover { background: var(--ggs-fjord); color: var(--ggs-white); }
.lp-toc-count { font-size: .7rem; opacity: .7; }
/* Footer */
.lp-footer {
text-align: center; padding: 2rem 1rem 2.5rem;
font-size: .78rem; color: var(--ggs-text-muted);
border-top: 1px solid var(--ggs-border);
background: var(--ggs-white);
margin-top: 2rem;
}
.lp-footer img { height: 36px; opacity: .5; margin-bottom: .5rem; }
.lp-footer a { color: var(--ggs-fjord); text-decoration: none; padding: .3rem .2rem; }
@media (max-width: 900px) {
.lp-filter-row { flex-direction: column; align-items: flex-start; gap: .3rem; }
.lp-filter-label { min-width: 0; }
}
</style>
</head>
<body>
<header class="lp-topbar">
<a href="<?= $bp ?>/index.html" class="lp-topbar-brand" aria-label="GeoGraSim Startseite">
<img src="<?= $bp ?>/assets/img/geograsim_t.svg" alt="GeoGraSim">
</a>
<span class="spacer"></span>
<?php if ($easyActive): ?>
<span class="lp-btn-sm lp-easy-pill">🟢 Leichte Sprache</span>
<?php endif; ?>
<?php include __DIR__ . '/_partials/country_picker.php'; ?>
<a href="<?= $bp ?>/pages/simulationen.php" class="lp-btn-sm">Simulationen</a>
<a href="<?= $bp ?>/glossar" class="lp-btn-sm">Glossar</a>
<a href="<?= $bp ?>/login.html" class="lp-btn-sm lp-btn-primary">Anmelden</a>
</header>
<!-- HERO -->
<section class="lp-hero">
<h1>Lehrplan-Übersicht</h1>
<p>
Alle GeoGraSim-Simulationen sind auf didaktische Kompetenzbereiche
abgebildet. Für jeden Bereich zeigen wir, wo er in den Lehrplänen
für Österreich, Deutschland, Schweiz und Liechtenstein verankert ist —
fachlich, fächerübergreifend und mit Anknüpfungspunkten in weiteren Fächern.
</p>
<div class="lp-hero-stats">
<div class="lp-hero-stat"><span class="lp-hero-stat-num"><?= count($kompetenzen) ?></span><span class="lp-hero-stat-lbl">Kompetenzbereiche</span></div>
<div class="lp-hero-stat"><span class="lp-hero-stat-num"><?= $totalAnchors ?></span><span class="lp-hero-stat-lbl">Lehrplan-Anker</span></div>
<div class="lp-hero-stat"><span class="lp-hero-stat-num">4</span><span class="lp-hero-stat-lbl">Länder</span></div>
</div>
</section>
<!-- FILTER -->
<div class="lp-filters" id="lp-filters">
<div class="lp-filter-row">
<span class="lp-filter-label">Land</span>
<button type="button" class="lp-chip<?= $qCountry === 'ALL' ? ' active' : '' ?>" data-filter="country" data-value="ALL">
🌐 Alle <span class="lp-chip-badge"><?= $totalAnchors ?></span>
</button>
<?php foreach ($countryMeta as $c => $info): ?>
<button type="button" class="lp-chip<?= $qCountry === $c ? ' active' : '' ?>" data-filter="country" data-value="<?= esc($c) ?>">
<?= $info['flag'] ?> <?= esc($info['label']) ?>
<?php if (!empty($countsByCountry[$c])): ?>
<span class="lp-chip-badge"><?= $countsByCountry[$c] ?></span>
<?php endif; ?>
</button>
<?php endforeach; ?>
</div>
<div class="lp-filter-row">
<span class="lp-filter-label">Thema</span>
<button type="button" class="lp-chip<?= !$qTheme ? ' active' : '' ?>" data-filter="theme" data-value="">
Alle <span class="lp-chip-badge"><?= count($kompetenzen) ?></span>
</button>
<?php foreach ($kompetenzen as $k): ?>
<?php $slug = esc($k['key_slug']); ?>
<button type="button" class="lp-chip<?= $qTheme === $k['key_slug'] ? ' active' : '' ?>"
data-filter="theme" data-value="<?= $slug ?>">
<?= esc($k['title']) ?>
</button>
<?php endforeach; ?>
</div>
<div class="lp-filter-row">
<span class="lp-filter-label">Typ</span>
<button type="button" class="lp-chip active" data-filter="type" data-value="">
Alle <span class="lp-chip-badge"><?= $totalAnchors ?></span>
</button>
<button type="button" class="lp-chip" data-filter="type" data-value="fach">
Fachbezug <span class="lp-chip-badge"><?= $countsByType['fach'] ?? 0 ?></span>
</button>
<button type="button" class="lp-chip" data-filter="type" data-value="uebergreifendes_thema">
Fächerübergreifend <span class="lp-chip-badge"><?= $countsByType['uebergreifendes_thema'] ?? 0 ?></span>
</button>
<button type="button" class="lp-chip" data-filter="type" data-value="anderes_fach">
Andere Fächer <span class="lp-chip-badge"><?= $countsByType['anderes_fach'] ?? 0 ?></span>
</button>
</div>
</div>
<div class="lp-wrap">
<!-- TOC — Sprung zu Kompetenzen -->
<nav class="lp-toc" aria-label="Sprung zu Kompetenz">
<div class="lp-toc-title">Kompetenzbereiche auf dieser Seite</div>
<div class="lp-toc-list">
<?php foreach ($kompetenzen as $k):
$total = count($k['anchors_all']); ?>
<a class="lp-toc-item" href="#k-<?= esc($k['key_slug']) ?>">
<?= esc($k['title']) ?>
<span class="lp-toc-count"><?= $total ?></span>
</a>
<?php endforeach; ?>
</div>
</nav>
<div class="lp-results-info" id="lp-results-info"></div>
<?php foreach ($kompetenzen as $k): ?>
<article class="lp-kompetenz" id="k-<?= esc($k['key_slug']) ?>"
data-theme="<?= esc($k['key_slug']) ?>">
<header class="lp-kompetenz-head">
<div class="lp-kompetenz-title"><?= esc($k['title']) ?></div>
<?php if (!empty($k['category']) && isset($categoryMeta[$k['category']])): ?>
<span class="lp-kompetenz-cat"><?= esc($categoryMeta[$k['category']]['label']) ?></span>
<?php endif; ?>
<?php if (!empty($k['age_min']) && !empty($k['age_max'])): ?>
<span class="lp-kompetenz-age">👧 <?= (int)$k['age_min'] ?><?= (int)$k['age_max'] ?> Jahre</span>
<?php endif; ?>
</header>
<?php if (!empty($k['description'])): ?>
<p class="lp-kompetenz-desc"><?= esc($k['description']) ?></p>
<?php endif; ?>
<!-- Module, die dieser Kompetenz zugeordnet sind -->
<?php if (!empty($k['modules'])): ?>
<div class="lp-modules-label">Simulationen zu diesem Bereich</div>
<div class="lp-modules">
<?php foreach ($k['modules'] as $m): ?>
<a class="lp-module-card" href="<?= $bp ?>/<?= esc($m['page_url']) ?>">
<span class="lp-module-icon"><?= esc($m['icon']) ?></span>
<span class="lp-module-name"><?= esc($m['title']) ?></span>
<span class="lp-module-strength <?= esc($m['strength']) ?>">
<?= $m['strength'] === 'primaer' ? 'Primär' : 'Sekundär' ?>
</span>
<span class="lp-module-status <?= esc($m['status']) ?>"><?= esc($m['status']) ?></span>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Anker-Gruppen -->
<?php
$groups = [
['anchors_fach', 'Fachbezug', 'Direkte Zuordnung im Fach-Lehrplan'],
['anchors_uebergreifend', 'Fächerübergreifende Themen', 'Verbindliche Querschnittsthemen des Lehrplans'],
['anchors_andere_faecher', 'Anknüpfungspunkte in anderen Fächern', 'Wo das Thema zusätzlich auftaucht'],
];
foreach ($groups as [$key, $heading, $sub]):
$list = $k[$key] ?? [];
if (empty($list)) continue;
?>
<div class="lp-anchor-group" data-group-type="<?= esc($key) ?>">
<div class="lp-anchor-group-head">
<span class="lp-anchor-group-title"><?= esc($heading) ?></span>
<span class="lp-anchor-group-sub"><?= esc($sub) ?></span>
</div>
<div class="lp-anchors">
<?php foreach ($list as $a): ?>
<?php $cm = $countryMeta[$a['country']] ?? ['flag' => '🏳️', 'label' => $a['country']]; ?>
<div class="lp-anchor lp-anchor--<?= esc($a['anchor_type']) ?>"
data-country="<?= esc($a['country']) ?>"
data-anchor-type="<?= esc($a['anchor_type']) ?>">
<div class="lp-anchor-flag" title="<?= esc($cm['label']) ?>"><?= $cm['flag'] ?></div>
<div>
<div class="lp-anchor-meta">
<strong><?= esc($a['country']) ?></strong>
<?= $a['region'] ? ' · ' . esc($a['region']) : '' ?>
<?= $a['school_type'] ? ' · ' . esc($a['school_type']) : '' ?>
<?= $a['grade'] ? ' · ' . esc($a['grade']) : '' ?>
<?= $a['subject'] ? ' · ' . esc($a['subject']) : '' ?>
</div>
<div class="lp-anchor-title"><?= esc($a['title']) ?></div>
<?php if (!empty($a['quote'])): ?>
<div class="lp-anchor-quote">„<?= esc($a['quote']) ?>"</div>
<?php endif; ?>
<?php if (!empty($a['reference'])): ?>
<div class="lp-anchor-ref">
Quelle:
<?php if (!empty($a['reference_url'])): ?>
<a href="<?= esc($a['reference_url']) ?>" target="_blank"
rel="noopener noreferrer" class="lp-anchor-link"><?= esc($a['reference']) ?> ↗</a>
<?php else: ?>
<?= esc($a['reference']) ?>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
<?php if (empty($k['anchors_all'])): ?>
<div class="lp-kompetenz-empty">Noch keine Lehrplan-Anker hinterlegt.</div>
<?php endif; ?>
</article>
<?php endforeach; ?>
<p class="lp-hint">
Die Anker sind Beispiele — bitte mit dem konkreten Jahresplan abgleichen.
Für Länder ausserhalb des eingestellten Fokus zeigen wir vorerst
Referenz-Anker; fächerübergreifende Themen und andere Fächer bleiben
landes­unabhängig sichtbar.
</p>
</div>
<footer class="lp-footer">
<img src="<?= $bp ?>/assets/img/bildLogo.png" alt="">
<div>
Lehrplan geograsim.at ·
<a href="<?= $bp ?>/pages/simulationen.php">Simulationen</a> ·
<a href="<?= $bp ?>/glossar">Glossar</a> ·
<a href="<?= $bp ?>/ueber.html">Über</a> ·
<a href="<?= $bp ?>/impressum.html">Impressum</a> ·
<a href="<?= $bp ?>/datenschutz.html">Datenschutz</a>
</div>
<?php include __DIR__ . '/_partials/country_footer.php'; ?>
</footer>
<script>
// Filter-Logik: Land / Thema / Typ
(function () {
const filterBar = document.getElementById('lp-filters');
const resultsInfo = document.getElementById('lp-results-info');
const state = {
country: <?= json_encode($qCountry) ?>,
theme: <?= json_encode($qTheme) ?>,
type: '',
};
// Chips aktiv-Zustand beim Laden setzen (falls URL-Filter vorgewählt)
function activate(row, value) {
filterBar.querySelectorAll(`.lp-chip[data-filter="${row}"]`).forEach(c => {
c.classList.toggle('active', c.dataset.value === value);
});
}
filterBar.addEventListener('click', (e) => {
const btn = e.target.closest('.lp-chip');
if (!btn) return;
const filter = btn.dataset.filter;
const value = btn.dataset.value;
state[filter] = value;
activate(filter, value);
apply();
// URL aktualisieren, ohne Reload (damit Deep-Links funktionieren)
const params = new URLSearchParams();
if (state.country && state.country !== 'ALL') params.set('country', state.country);
if (state.theme) params.set('theme', state.theme);
const q = params.toString();
history.replaceState(null, '', q ? '?' + q : location.pathname);
});
function apply() {
let shownKomp = 0;
let shownAnchors = 0;
document.querySelectorAll('.lp-kompetenz').forEach(k => {
// Thema-Filter
if (state.theme && k.dataset.theme !== state.theme) {
k.style.display = 'none';
return;
}
k.style.display = '';
shownKomp++;
// Anker-Filter: Land + Typ
k.querySelectorAll('.lp-anchor').forEach(a => {
let hide = false;
// Land: nur Anker mit Land vs gewaehltem Land einblenden; uebergr. + andere_fach sind landes-agnostisch, aber haben country=AT o.ae. als Default
if (state.country && state.country !== 'ALL') {
const anchorCountry = a.dataset.country;
const type = a.dataset.anchorType;
// Bei Fach-Ankern strikt auf Land filtern; bei übergreifenden und andere_fach Anker nur AT-Anker zeigen (wo das Lehrplan-System uebergreifend AT ist).
// Alternative: Wenn country != AT gewaehlt, zeigen wir uebergreifende + andere_fach weiter,
// aber nur Fach-Anker werden gefiltert — so bleibt das Lehrplan-Prinzip sichtbar.
if (type === 'fach') {
if (anchorCountry && anchorCountry !== state.country) hide = true;
} else {
// Fuer uebergreifend/andere_fach: zeige nur die, deren country matched (meist AT)
if (anchorCountry && anchorCountry !== state.country) hide = true;
}
}
if (state.type && a.dataset.anchorType !== state.type) hide = true;
a.classList.toggle('hidden', hide);
if (!hide) shownAnchors++;
});
// Wenn in einer Kompetenz keine Anker sichtbar sind, Kompetenz ausblenden
const visibleInKomp = k.querySelectorAll('.lp-anchor:not(.hidden)').length;
if (visibleInKomp === 0 && (state.country !== 'ALL' || state.type)) {
k.style.display = 'none';
shownKomp--;
}
// Auch Anker-Gruppen ausblenden, wenn sie leer sind
k.querySelectorAll('.lp-anchor-group').forEach(g => {
const v = g.querySelectorAll('.lp-anchor:not(.hidden)').length;
g.style.display = v === 0 ? 'none' : '';
});
});
// Ergebnis-Info aktualisieren
const parts = [`${shownAnchors} Anker sichtbar`];
if (shownKomp !== <?= count($kompetenzen) ?>) parts.push(`${shownKomp} Kompetenzbereich(e)`);
resultsInfo.textContent = parts.join(' · ');
}
// Initial
apply();
})();
</script>
</body>
</html>