Favoritenseite jetzt dynamisch
This commit is contained in:
+502
-37
@@ -40,17 +40,375 @@ $pageTitle = 'Favoriten - AstroTools';
|
||||
$headerIntroPre = 'Merkliste';
|
||||
$headerIntroTitle = 'Favoriten';
|
||||
$headerIntroSub = 'Satelliten und Kleinplaneten zentral verwalten.';
|
||||
$htmxTriggers = [];
|
||||
|
||||
function h(?string $value): string
|
||||
{
|
||||
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
function isHtmxRequest(): bool
|
||||
{
|
||||
return strtolower((string) ($_SERVER['HTTP_HX_REQUEST'] ?? '')) === 'true';
|
||||
}
|
||||
|
||||
function renderMessages(string $successMessage, array $errors, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div id="favorites-messages"<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>>
|
||||
<?php if ($successMessage !== ''): ?>
|
||||
<p class="msg-success"><?= h($successMessage) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<ul class="msg-error">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?= h($error) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function renderLocationsSection(array $locations, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div class="card" id="locations-section"<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>>
|
||||
<h2>Standorte</h2>
|
||||
<?php if (empty($locations)): ?>
|
||||
<p class="hint">Es sind noch keine Standorte gespeichert.</p>
|
||||
<?php else: ?>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Breitengrad</th>
|
||||
<th>Laengengrad</th>
|
||||
<th>Hoehe</th>
|
||||
<th>Zeitzone</th>
|
||||
<th>Standard</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($locations as $location): ?>
|
||||
<tr>
|
||||
<td><?= h($location['name']) ?></td>
|
||||
<td><?= h((string) $location['latitude']) ?></td>
|
||||
<td><?= h((string) $location['longitude']) ?></td>
|
||||
<td><?= h($location['elevation'] !== null ? (string) $location['elevation'] . ' m' : '-') ?></td>
|
||||
<td><?= h($location['timezone']) ?></td>
|
||||
<td><?= (int) $location['is_default'] === 1 ? '*' : '-' ?></td>
|
||||
<td class="action-cell">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary js-edit-location"
|
||||
data-location-id="<?= (int) $location['id'] ?>"
|
||||
data-location-name="<?= h((string) $location['name']) ?>"
|
||||
data-location-latitude="<?= h((string) $location['latitude']) ?>"
|
||||
data-location-longitude="<?= h((string) $location['longitude']) ?>"
|
||||
data-location-elevation="<?= h($location['elevation'] !== null ? (string) $location['elevation'] : '') ?>"
|
||||
data-location-timezone="<?= h((string) $location['timezone']) ?>"
|
||||
data-location-default="<?= (int) $location['is_default'] === 1 ? '1' : '0' ?>"
|
||||
>Bearbeiten</button>
|
||||
<?php if ((int) $location['is_default'] !== 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standard-Standort wird gesetzt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="set_default_location">
|
||||
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">Als Standard</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php if (count($locations) > 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standort wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Standort wirklich loeschen?');">
|
||||
<input type="hidden" name="action" value="delete_location">
|
||||
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Loeschen</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<span class="hint">Letzter Standort</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function renderSatelliteSearchResults(string $satelliteSearchQuery, array $satelliteSearchResults, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div
|
||||
id="satellite-search-results"
|
||||
class="favorites-search-results<?= $satelliteSearchQuery !== '' ? ' has-results' : '' ?>"
|
||||
aria-live="polite"
|
||||
<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>
|
||||
>
|
||||
<?php if ($satelliteSearchQuery === ''): ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Noch keine Suche gestartet.</p>
|
||||
<p class="hint">Suche nach Namen oder NORAD-ID, um passende Satelliten direkt hier einzublenden.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-summary">
|
||||
<h2>Suchergebnisse</h2>
|
||||
<p class="hint">
|
||||
<?= count($satelliteSearchResults) ?> Treffer fuer <strong><?= h($satelliteSearchQuery) ?></strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php if (empty($satelliteSearchResults)): ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Keine passenden Satelliten gefunden.</p>
|
||||
<p class="hint">Probiere einen Namen wie <strong>ISS</strong> oder eine NORAD-ID wie <strong>25544</strong>.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-table-wrap">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>NORAD</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($satelliteSearchResults as $satellite): ?>
|
||||
<tr>
|
||||
<td><?= h($satellite['object_name']) ?></td>
|
||||
<td><?= h((string) $satellite['norad_cat_id']) ?></td>
|
||||
<td>
|
||||
<?php if ((int) $satellite['already_added'] === 1): ?>
|
||||
<span class="hint">Bereits hinzugefuegt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satellit wird hinzugefuegt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="add_satellite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-primary">Hinzufuegen</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function renderMinorplanetSearchResults(string $minorplanetSearchQuery, array $minorplanetSearchResults, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div
|
||||
id="minorplanet-search-results"
|
||||
class="favorites-search-results<?= $minorplanetSearchQuery !== '' ? ' has-results' : '' ?>"
|
||||
aria-live="polite"
|
||||
<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>
|
||||
>
|
||||
<?php if ($minorplanetSearchQuery === ''): ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Noch keine Suche gestartet.</p>
|
||||
<p class="hint">Suche nach Nummer oder Bezeichnung, um passende Kleinplaneten direkt hier einzublenden.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-summary">
|
||||
<h2>Suchergebnisse</h2>
|
||||
<p class="hint">
|
||||
<?= count($minorplanetSearchResults) ?> Treffer fuer <strong><?= h($minorplanetSearchQuery) ?></strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php if (empty($minorplanetSearchResults)): ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Keine passenden Kleinplaneten gefunden.</p>
|
||||
<p class="hint">Probiere eine Nummer wie <strong>1</strong> oder eine Bezeichnung wie <strong>Ceres</strong>.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-table-wrap">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bezeichnung</th>
|
||||
<th>Nummer</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($minorplanetSearchResults as $minorplanet): ?>
|
||||
<tr>
|
||||
<td><?= h($minorplanet['designation_text'] ?: $minorplanet['desig_packed']) ?></td>
|
||||
<td><?= h($minorplanet['mp_number'] !== null ? (string) $minorplanet['mp_number'] : '-') ?></td>
|
||||
<td>
|
||||
<?php if ((int) $minorplanet['already_added'] === 1): ?>
|
||||
<span class="hint">Bereits hinzugefuegt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplanet wird hinzugefuegt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="add_minorplanet">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-primary">Hinzufuegen</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function renderTrackedSatellitesSection(array $trackedSatellites, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div class="card" id="tracked-satellites-section"<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>>
|
||||
<h2>Meine Satelliten</h2>
|
||||
<?php if (empty($trackedSatellites)): ?>
|
||||
<p class="hint">Du hast noch keine Satelliten ausgewaehlt.</p>
|
||||
<?php else: ?>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>NORAD</th>
|
||||
<th>Favorit</th>
|
||||
<th>Hinzugefuegt</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($trackedSatellites as $satellite): ?>
|
||||
<tr>
|
||||
<td><?= h($satellite['object_name']) ?></td>
|
||||
<td><?= h((string) $satellite['norad_cat_id']) ?></td>
|
||||
<td><?= (int) $satellite['is_favorite'] === 1 ? '*' : '-' ?></td>
|
||||
<td><?= h($satellite['created_at']) ?></td>
|
||||
<td class="action-cell">
|
||||
<?php if (count($trackedSatellites) <= 1 && (int) $satellite['is_favorite'] === 1): ?>
|
||||
<span class="hint">Favorit bleibt gesetzt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satelliten-Favorit wird aktualisiert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="toggle_satellite_favorite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">
|
||||
<?= (int) $satellite['is_favorite'] === 1 ? 'Favorit entfernen' : 'Als Favorit' ?>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php if (count($trackedSatellites) > 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satellit wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Satellit wirklich entfernen?');">
|
||||
<input type="hidden" name="action" value="remove_satellite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<span class="hint">Letzter Satellit</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function renderTrackedMinorplanetsSection(array $trackedMinorplanets, bool $oob = false): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<div class="card" id="tracked-minorplanets-section"<?= $oob ? ' hx-swap-oob="outerHTML"' : '' ?>>
|
||||
<h2>Meine Kleinplaneten</h2>
|
||||
<?php if (empty($trackedMinorplanets)): ?>
|
||||
<p class="hint">Du hast noch keine Kleinplaneten ausgewaehlt.</p>
|
||||
<?php else: ?>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bezeichnung</th>
|
||||
<th>Nummer</th>
|
||||
<th>Favorit</th>
|
||||
<th>Hinzugefuegt</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($trackedMinorplanets as $minorplanet): ?>
|
||||
<tr>
|
||||
<td><?= h($minorplanet['designation_text'] ?: $minorplanet['desig_packed']) ?></td>
|
||||
<td><?= h($minorplanet['mp_number'] !== null ? (string) $minorplanet['mp_number'] : '-') ?></td>
|
||||
<td><?= (int) $minorplanet['is_favorite'] === 1 ? '*' : '-' ?></td>
|
||||
<td><?= h($minorplanet['created_at']) ?></td>
|
||||
<td class="action-cell">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplaneten-Favorit wird aktualisiert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="toggle_minorplanet_favorite">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">
|
||||
<?= (int) $minorplanet['is_favorite'] === 1 ? 'Favorit entfernen' : 'Als Favorit' ?>
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplanet wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Kleinplanet wirklich entfernen?');">
|
||||
<input type="hidden" name="action" value="remove_minorplanet">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
function validTimezone(string $timezone): bool
|
||||
{
|
||||
return in_array($timezone, timezone_identifiers_list(), true);
|
||||
}
|
||||
|
||||
if (isHtmxRequest()) {
|
||||
$hxCurrentUrl = trim((string) ($_SERVER['HTTP_HX_CURRENT_URL'] ?? ''));
|
||||
if ($hxCurrentUrl !== '') {
|
||||
$queryString = (string) parse_url($hxCurrentUrl, PHP_URL_QUERY);
|
||||
if ($queryString !== '') {
|
||||
parse_str($queryString, $hxQueryParams);
|
||||
if ($satelliteSearchQuery === '' && isset($hxQueryParams['sat_q'])) {
|
||||
$satelliteSearchQuery = trim((string) $hxQueryParams['sat_q']);
|
||||
}
|
||||
if ($minorplanetSearchQuery === '' && isset($hxQueryParams['mp_q'])) {
|
||||
$minorplanetSearchQuery = trim((string) $hxQueryParams['mp_q']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setExclusiveFavorite(PDO $pdo, string $tableName, string $idColumn, int $userId, int $entityId): bool
|
||||
{
|
||||
$pdo->beginTransaction();
|
||||
@@ -611,6 +969,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
$pdo->commit();
|
||||
$successMessage = 'Der Standort wurde aktualisiert.';
|
||||
$htmxTriggers['favorites:location-updated'] = true;
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
@@ -949,6 +1308,32 @@ $stmtTrackedMinorplanets->execute([
|
||||
]);
|
||||
$trackedMinorplanets = $stmtTrackedMinorplanets->fetchAll();
|
||||
|
||||
if (isHtmxRequest()) {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET' && array_key_exists('sat_q', $_GET)) {
|
||||
echo renderSatelliteSearchResults($satelliteSearchQuery, $satelliteSearchResults);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET' && array_key_exists('mp_q', $_GET)) {
|
||||
echo renderMinorplanetSearchResults($minorplanetSearchQuery, $minorplanetSearchResults);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($htmxTriggers !== []) {
|
||||
header('HX-Trigger: ' . (string) json_encode($htmxTriggers));
|
||||
}
|
||||
|
||||
echo renderMessages($successMessage, $errors);
|
||||
echo renderLocationsSection($locations, true);
|
||||
echo renderSatelliteSearchResults($satelliteSearchQuery, $satelliteSearchResults, true);
|
||||
echo renderMinorplanetSearchResults($minorplanetSearchQuery, $minorplanetSearchResults, true);
|
||||
echo renderTrackedSatellitesSection($trackedSatellites, true);
|
||||
echo renderTrackedMinorplanetsSection($trackedMinorplanets, true);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$loggedIn = true;
|
||||
?>
|
||||
<?php require __DIR__ . '/header.php'; ?>
|
||||
@@ -960,20 +1345,10 @@ $loggedIn = true;
|
||||
crossorigin=""
|
||||
>
|
||||
|
||||
<?php if ($successMessage !== ''): ?>
|
||||
<p class="msg-success"><?= h($successMessage) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<ul class="msg-error">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?= h($error) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<?= renderMessages($successMessage, $errors) ?>
|
||||
|
||||
<div class="grid-2">
|
||||
<div class="card">
|
||||
<div class="card" id="locations-section">
|
||||
<h2>Standorte</h2>
|
||||
<?php if (empty($locations)): ?>
|
||||
<p class="hint">Es sind noch keine Standorte gespeichert.</p>
|
||||
@@ -1012,14 +1387,14 @@ $loggedIn = true;
|
||||
data-location-default="<?= (int) $location['is_default'] === 1 ? '1' : '0' ?>"
|
||||
>Bearbeiten</button>
|
||||
<?php if ((int) $location['is_default'] !== 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Standard-Standort wird gesetzt...">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standard-Standort wird gesetzt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="set_default_location">
|
||||
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">Als Standard</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php if (count($locations) > 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Standort wird entfernt..." onsubmit="return confirm('Standort wirklich löschen?');">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standort wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Standort wirklich löschen?');">
|
||||
<input type="hidden" name="action" value="delete_location">
|
||||
<input type="hidden" name="location_id" value="<?= (int) $location['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Löschen</button>
|
||||
@@ -1048,7 +1423,7 @@ $loggedIn = true;
|
||||
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
<form method="post" action="" id="add-location-form" class="form-stack mt-xl favorites-loading-form" data-loading-message="Standort wird gespeichert...">
|
||||
<form method="post" action="" id="add-location-form" class="form-stack mt-xl favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standort wird gespeichert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="add_location">
|
||||
<div class="grid-2 gap-sm">
|
||||
<div class="form-group">
|
||||
@@ -1096,7 +1471,7 @@ $loggedIn = true;
|
||||
</div>
|
||||
|
||||
<dialog class="admin-dialog" id="editLocationDialog">
|
||||
<form method="post" action="" class="admin-dialog-card form-stack favorites-loading-form" data-loading-message="Standort wird aktualisiert...">
|
||||
<form method="post" action="" class="admin-dialog-card form-stack favorites-loading-form favorites-loading-form-htmx" data-loading-message="Standort wird aktualisiert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="update_location">
|
||||
<input type="hidden" name="location_id" id="edit-location-id" value="">
|
||||
<h3>Standort bearbeiten</h3>
|
||||
@@ -1137,7 +1512,7 @@ $loggedIn = true;
|
||||
<div class="grid-2">
|
||||
<div class="card">
|
||||
<h2>Satelliten suchen</h2>
|
||||
<form method="get" action="" class="favorites-loading-form" data-loading-message="Satelliten werden gesucht. Das kann kurz dauern...">
|
||||
<form method="get" action="" class="favorites-loading-form favorites-loading-form-htmx favorites-search-form" data-loading-message="Satelliten werden gesucht. Das kann kurz dauern..." hx-get="my_favorites.php" hx-target="#satellite-search-results" hx-swap="outerHTML" hx-push-url="true">
|
||||
<div class="input-row">
|
||||
<input
|
||||
type="text"
|
||||
@@ -1151,6 +1526,7 @@ $loggedIn = true;
|
||||
<p class="favorites-loading-hint" data-loading-hint hidden>Satelliten werden gesucht. Das kann kurz dauern...</p>
|
||||
</form>
|
||||
|
||||
<div id="satellite-search-results" class="favorites-search-results<?= $satelliteSearchQuery !== '' ? ' has-results' : '' ?>" aria-live="polite">
|
||||
<?php if ($satelliteSearchQuery !== ''): ?>
|
||||
<div class="mt-xl">
|
||||
<h2>Suchergebnisse</h2>
|
||||
@@ -1174,7 +1550,7 @@ $loggedIn = true;
|
||||
<?php if ((int) $satellite['already_added'] === 1): ?>
|
||||
<span class="hint">Bereits hinzugefuegt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satellit wird hinzugefuegt...">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satellit wird hinzugefuegt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="add_satellite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-primary">Hinzufuegen</button>
|
||||
@@ -1187,12 +1563,28 @@ $loggedIn = true;
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Noch keine Suche gestartet.</p>
|
||||
<p class="hint">Suche nach Namen oder NORAD-ID, um passende Satelliten direkt hier einzublenden.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Kleinplaneten suchen</h2>
|
||||
<form method="get" action="" class="favorites-loading-form" data-loading-message="Kleinplaneten werden gesucht. Das kann etwas dauern...">
|
||||
<p class="hint">Die Treffer werden direkt in der Karte aktualisiert, ohne die ganze Seite neu zu laden.</p>
|
||||
<form
|
||||
method="get"
|
||||
action=""
|
||||
class="favorites-loading-form favorites-loading-form-htmx favorites-search-form"
|
||||
data-loading-message="Kleinplaneten werden gesucht. Das kann etwas dauern..."
|
||||
hx-get="my_favorites.php"
|
||||
hx-target="#minorplanet-search-results"
|
||||
hx-swap="outerHTML"
|
||||
hx-push-url="true"
|
||||
>
|
||||
<div class="input-row">
|
||||
<input
|
||||
type="text"
|
||||
@@ -1206,6 +1598,7 @@ $loggedIn = true;
|
||||
<p class="favorites-loading-hint" data-loading-hint hidden>Kleinplaneten werden gesucht. Das kann etwas dauern...</p>
|
||||
</form>
|
||||
|
||||
<div id="minorplanet-search-results" class="favorites-search-results<?= $minorplanetSearchQuery !== '' ? ' has-results' : '' ?>" aria-live="polite">
|
||||
<?php if ($minorplanetSearchQuery !== ''): ?>
|
||||
<div class="mt-xl">
|
||||
<h2>Suchergebnisse</h2>
|
||||
@@ -1229,7 +1622,7 @@ $loggedIn = true;
|
||||
<?php if ((int) $minorplanet['already_added'] === 1): ?>
|
||||
<span class="hint">Bereits hinzugefuegt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Kleinplanet wird hinzugefuegt...">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplanet wird hinzugefuegt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="add_minorplanet">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-primary">Hinzufuegen</button>
|
||||
@@ -1242,12 +1635,18 @@ $loggedIn = true;
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="favorites-search-empty">
|
||||
<p>Noch keine Suche gestartet.</p>
|
||||
<p class="hint">Suche nach Nummer oder Bezeichnung, um passende Kleinplaneten direkt hier einzublenden.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-2">
|
||||
<div class="card">
|
||||
<div class="card" id="tracked-satellites-section">
|
||||
<h2>Meine Satelliten</h2>
|
||||
<?php if (empty($trackedSatellites)): ?>
|
||||
<p class="hint">Du hast noch keine Satelliten ausgewählt.</p>
|
||||
@@ -1273,7 +1672,7 @@ $loggedIn = true;
|
||||
<?php if (count($trackedSatellites) <= 1 && (int) $satellite['is_favorite'] === 1): ?>
|
||||
<span class="hint">Favorit bleibt gesetzt</span>
|
||||
<?php else: ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satelliten-Favorit wird aktualisiert...">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satelliten-Favorit wird aktualisiert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="toggle_satellite_favorite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">
|
||||
@@ -1282,7 +1681,7 @@ $loggedIn = true;
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php if (count($trackedSatellites) > 1): ?>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Satellit wird entfernt..." onsubmit="return confirm('Satellit wirklich entfernen?');">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Satellit wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Satellit wirklich entfernen?');">
|
||||
<input type="hidden" name="action" value="remove_satellite">
|
||||
<input type="hidden" name="satellite_id" value="<?= (int) $satellite['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
|
||||
@@ -1298,7 +1697,7 @@ $loggedIn = true;
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card" id="tracked-minorplanets-section">
|
||||
<h2>Meine Kleinplaneten</h2>
|
||||
<?php if (empty($trackedMinorplanets)): ?>
|
||||
<p class="hint">Du hast noch keine Kleinplaneten ausgewählt.</p>
|
||||
@@ -1321,14 +1720,14 @@ $loggedIn = true;
|
||||
<td><?= (int) $minorplanet['is_favorite'] === 1 ? '*' : '-' ?></td>
|
||||
<td><?= h($minorplanet['created_at']) ?></td>
|
||||
<td class="action-cell">
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Kleinplaneten-Favorit wird aktualisiert...">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplaneten-Favorit wird aktualisiert..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML">
|
||||
<input type="hidden" name="action" value="toggle_minorplanet_favorite">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-secondary">
|
||||
<?= (int) $minorplanet['is_favorite'] === 1 ? 'Favorit entfernen' : 'Als Favorit' ?>
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" action="" class="favorites-loading-form" data-loading-message="Kleinplanet wird entfernt..." onsubmit="return confirm('Kleinplanet wirklich entfernen?');">
|
||||
<form method="post" action="" class="favorites-loading-form favorites-loading-form-htmx" data-loading-message="Kleinplanet wird entfernt..." hx-post="my_favorites.php" hx-target="#favorites-messages" hx-swap="outerHTML" onsubmit="return confirm('Kleinplanet wirklich entfernen?');">
|
||||
<input type="hidden" name="action" value="remove_minorplanet">
|
||||
<input type="hidden" name="minorplanet_id" value="<?= (int) $minorplanet['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Entfernen</button>
|
||||
@@ -1342,6 +1741,7 @@ $loggedIn = true;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/htmx.min.js"></script>
|
||||
<script
|
||||
src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||||
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
|
||||
@@ -1526,6 +1926,10 @@ $loggedIn = true;
|
||||
|
||||
document.querySelectorAll('.favorites-loading-form').forEach((form) => {
|
||||
form.addEventListener('submit', (event) => {
|
||||
if (form.classList.contains('favorites-loading-form-htmx')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (form.id === 'add-location-form') {
|
||||
const nameField = form.querySelector('#name');
|
||||
const nameError = document.getElementById('add-location-name-error');
|
||||
@@ -1578,6 +1982,60 @@ document.querySelectorAll('.favorites-loading-form').forEach((form) => {
|
||||
});
|
||||
});
|
||||
|
||||
(function () {
|
||||
function setLoadingState(form) {
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = form.dataset.loadingMessage || 'Bitte warten...';
|
||||
let hint = form.querySelector('[data-loading-hint]');
|
||||
|
||||
if (!hint) {
|
||||
hint = document.createElement('p');
|
||||
hint.className = 'favorites-loading-hint';
|
||||
hint.dataset.loadingHint = 'true';
|
||||
form.appendChild(hint);
|
||||
}
|
||||
|
||||
hint.textContent = message;
|
||||
hint.hidden = false;
|
||||
form.classList.add('is-loading');
|
||||
|
||||
form.querySelectorAll('button').forEach((button) => {
|
||||
button.disabled = true;
|
||||
button.setAttribute('aria-busy', 'true');
|
||||
});
|
||||
}
|
||||
|
||||
function clearLoadingState(form) {
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
form.classList.remove('is-loading');
|
||||
form.querySelectorAll('button').forEach((button) => {
|
||||
button.disabled = false;
|
||||
button.removeAttribute('aria-busy');
|
||||
});
|
||||
}
|
||||
|
||||
document.body.addEventListener('htmx:beforeRequest', (event) => {
|
||||
const form = event.target.closest('.favorites-loading-form-htmx');
|
||||
setLoadingState(form);
|
||||
});
|
||||
|
||||
document.body.addEventListener('htmx:afterRequest', (event) => {
|
||||
const form = event.target.closest('.favorites-loading-form-htmx');
|
||||
clearLoadingState(form);
|
||||
});
|
||||
|
||||
document.body.addEventListener('htmx:responseError', (event) => {
|
||||
const form = event.target.closest('.favorites-loading-form-htmx');
|
||||
clearLoadingState(form);
|
||||
});
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const dialog = document.getElementById('editLocationDialog');
|
||||
const cancelButton = document.getElementById('editLocationCancel');
|
||||
@@ -1594,22 +2052,29 @@ document.querySelectorAll('.favorites-loading-form').forEach((form) => {
|
||||
const timezoneInput = document.getElementById('edit-location-timezone');
|
||||
const defaultInput = document.getElementById('edit-location-default');
|
||||
|
||||
document.querySelectorAll('.js-edit-location').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
idInput.value = button.dataset.locationId || '';
|
||||
nameInput.value = button.dataset.locationName || '';
|
||||
latitudeInput.value = button.dataset.locationLatitude || '';
|
||||
longitudeInput.value = button.dataset.locationLongitude || '';
|
||||
elevationInput.value = button.dataset.locationElevation || '';
|
||||
timezoneInput.value = button.dataset.locationTimezone || 'Europe/Berlin';
|
||||
defaultInput.checked = button.dataset.locationDefault === '1';
|
||||
dialog.showModal();
|
||||
});
|
||||
document.addEventListener('click', (event) => {
|
||||
const button = event.target.closest('.js-edit-location');
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
idInput.value = button.dataset.locationId || '';
|
||||
nameInput.value = button.dataset.locationName || '';
|
||||
latitudeInput.value = button.dataset.locationLatitude || '';
|
||||
longitudeInput.value = button.dataset.locationLongitude || '';
|
||||
elevationInput.value = button.dataset.locationElevation || '';
|
||||
timezoneInput.value = button.dataset.locationTimezone || 'Europe/Berlin';
|
||||
defaultInput.checked = button.dataset.locationDefault === '1';
|
||||
dialog.showModal();
|
||||
});
|
||||
|
||||
cancelButton?.addEventListener('click', () => {
|
||||
dialog.close();
|
||||
});
|
||||
|
||||
document.body.addEventListener('favorites:location-updated', () => {
|
||||
dialog.close();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user