Files
JasonandClaude Sonnet 4.6 bd8a322fc0 Initial Release: Lütte Planer mit Google-Login-Vorbereitung
- Login-System (Mock für Tests, Google OAuth vorbereitet)
- Reisen erstellen mit Emoji, Ziel und Datum
- Ablauf (Timeline), Packliste, Ideen, Notizen, Dokumente
- Team-System: Personen einladen per E-Mail + Einladungslinks
- Berechtigungen: Nur lesen / Bearbeiten / Admin
- E-Mail-Benachrichtigungen beim Einladen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 20:56:30 +02:00

201 lines
11 KiB
PHP

<?php
require_once __DIR__ . '/config.php';
$tripId = $_GET['trip'] ?? '';
[$trip, $user] = requireTripAccess($tripId);
$isAdmin = userIsAdmin($tripId, $user['id']);
// Person einladen
if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['einladen'])) {
$email = strtolower(trim($_POST['email'] ?? ''));
$access = in_array($_POST['access'] ?? '', ['see','edit']) ? $_POST['access'] : 'see';
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Prüfen ob schon Mitglied
$existing = dbOne('SELECT u.id FROM users u JOIN reise_zugriff rz ON rz.user_id = u.id WHERE u.email = ? AND rz.trip_id = ?', [$email, $tripId]);
if (!$existing) {
// Prüfen ob User schon existiert
$invitedUser = dbOne('SELECT * FROM users WHERE email = ?', [$email]);
if ($invitedUser) {
// Direkt hinzufügen
$alreadyZugriff = dbOne('SELECT 1 FROM reise_zugriff WHERE trip_id = ? AND user_id = ?', [$tripId, $invitedUser['id']]);
if (!$alreadyZugriff) {
dbInsert('reise_zugriff', ['trip_id' => $tripId, 'user_id' => $invitedUser['id'], 'access' => $access, 'invited_by' => $user['id']]);
$tripUrl = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/Develop/PlanerGoogel/ablauf.php?trip=' . $tripId;
sendAddedToTripMail($invitedUser['email'], $invitedUser['name'], $trip['name'], $tripUrl, $user['name']);
}
$msg = h($invitedUser['name']) . ' wurde zur Reise hinzugefügt und per E-Mail informiert.';
} else {
// Einladungslink erstellen
$token = bin2hex(random_bytes(16));
// Alte offene Einladung für diese E-Mail löschen
dbExec('DELETE FROM reise_einladungen WHERE trip_id = ? AND email = ? AND used_at IS NULL', [$tripId, $email]);
dbInsert('reise_einladungen', ['trip_id' => $tripId, 'email' => $email, 'token' => $token, 'access' => $access, 'invited_by' => $user['id']]);
$inviteLink = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/Develop/PlanerGoogel/login.php?invite=' . $token;
$mailSent = sendInviteMail($email, $trip['name'], $inviteLink, $user['name']);
$msg = $mailSent
? 'Einladungsmail an <strong>' . h($email) . '</strong> wurde verschickt!'
: 'Einladungslink erstellt (E-Mail konnte nicht gesendet werden).<br><code style="font-size:.75rem;word-break:break-all;">' . h($inviteLink) . '</code>';
}
} else {
$msg = 'Diese Person ist bereits Mitglied.';
}
}
}
// Zugriff ändern
if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_access'])) {
$memberId = (int)$_POST['member_id'];
$newAccess = $_POST['new_access'] ?? '';
if ($memberId !== $user['id'] && in_array($newAccess, ['see','edit','admin'])) {
dbExec('UPDATE reise_zugriff SET access = ? WHERE trip_id = ? AND user_id = ?', [$newAccess, $tripId, $memberId]);
}
header('Location: /Develop/PlanerGoogel/team.php?trip=' . $tripId); exit;
}
// Person entfernen
if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['remove'])) {
$memberId = (int)$_POST['remove'];
if ($memberId !== $user['id']) {
dbExec('DELETE FROM reise_zugriff WHERE trip_id = ? AND user_id = ?', [$tripId, $memberId]);
}
header('Location: /Develop/PlanerGoogel/team.php?trip=' . $tripId); exit;
}
// Reise-Einstellungen speichern
if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_trip'])) {
dbExec('UPDATE reisen SET name = ?, ziel = ?, start_datum = ?, end_datum = ?, cover_emoji = ?, beschreibung = ? WHERE id = ?', [
trim($_POST['name'] ?? $trip['name']),
trim($_POST['ziel'] ?? ''),
$_POST['start_datum'] ?? '',
$_POST['end_datum'] ?? '',
trim($_POST['cover_emoji'] ?? '✈️') ?: '✈️',
trim($_POST['beschreibung'] ?? ''),
$tripId,
]);
header('Location: /Develop/PlanerGoogel/team.php?trip=' . $tripId); exit;
}
// Reise löschen
if ($isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_trip'])) {
dbExec('DELETE FROM reisen WHERE id = ?', [$tripId]);
header('Location: /Develop/PlanerGoogel/'); exit;
}
$members = getTripMembers($tripId);
$invites = dbAll('SELECT * FROM reise_einladungen WHERE trip_id = ? AND used_at IS NULL ORDER BY created_at DESC', [$tripId]);
$baseUrl = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
$pageTitle = 'Team & Einstellungen';
$activeTab = 'team';
include __DIR__ . '/includes/header.php';
?>
<main class="main">
<h1 class="section-head">Team & Einstellungen</h1>
<?php if (!empty($msg)): ?>
<div class="alert-success"><?= $msg ?></div>
<?php endif; ?>
<!-- Mitglieder -->
<div class="settings-section">
<h2 class="col-title">Mitglieder</h2>
<div class="member-list">
<?php foreach ($members as $m): ?>
<div class="member-item">
<?= avatarHtml($m, '38px') ?>
<div class="member-info">
<div class="member-name"><?= h($m['name']) ?></div>
<div class="member-email"><?= h($m['email']) ?></div>
</div>
<span class="access-badge access-<?= $m['access'] ?>"><?= ucfirst($m['access']) ?></span>
<?php if ($isAdmin && $m['id'] != $user['id']): ?>
<form method="POST" style="display:flex;gap:6px;align-items:center;">
<input type="hidden" name="member_id" value="<?= $m['id'] ?>">
<select name="new_access" style="font-size:.78rem;padding:4px 8px;border:1.5px solid var(--border);border-radius:6px;">
<option value="see" <?= $m['access'] === 'see' ? 'selected' : '' ?>>Nur lesen</option>
<option value="edit" <?= $m['access'] === 'edit' ? 'selected' : '' ?>>Bearbeiten</option>
<option value="admin" <?= $m['access'] === 'admin' ? 'selected' : '' ?>>Admin</option>
</select>
<button type="submit" name="change_access" class="btn-edit">Ändern</button>
</form>
<form method="POST" onsubmit="return confirm('Person entfernen?')">
<button type="submit" name="remove" value="<?= $m['id'] ?>" class="btn-delete">✕</button>
</form>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php if ($isAdmin): ?>
<div class="invite-form">
<h3 style="font-size:.88rem;font-weight:600;margin-bottom:10px;color:var(--ink);">Person einladen</h3>
<form method="POST" style="display:flex;gap:8px;flex-wrap:wrap;">
<input type="email" name="email" placeholder="E-Mail-Adresse" required style="flex:1;min-width:200px;padding:8px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.85rem;">
<select name="access" style="padding:8px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.85rem;">
<option value="see">Nur lesen</option>
<option value="edit">Bearbeiten</option>
</select>
<button type="submit" name="einladen" class="btn btn-primary">Einladen</button>
</form>
</div>
<?php if (!empty($invites)): ?>
<div style="margin-top:16px;">
<h3 style="font-size:.82rem;font-weight:600;color:var(--muted);margin-bottom:8px;">Offene Einladungen</h3>
<?php foreach ($invites as $inv): ?>
<div style="display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--sky);border-radius:8px;margin-bottom:6px;font-size:.8rem;">
<span>✉️ <?= h($inv['email']) ?></span>
<span class="access-badge access-<?= $inv['access'] ?>"><?= ucfirst($inv['access']) ?></span>
<code style="flex:1;font-size:.68rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"><?= $baseUrl ?>/Develop/PlanerGoogel/login.php?invite=<?= $inv['token'] ?></code>
<button onclick="navigator.clipboard.writeText('<?= $baseUrl ?>/Develop/PlanerGoogel/login.php?invite=<?= $inv['token'] ?>').then(()=>alert('Link kopiert!'))" class="btn-edit" type="button">📋 Kopieren</button>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<!-- Reise-Einstellungen -->
<?php if ($isAdmin): ?>
<div class="settings-section">
<h2 class="col-title">Reise bearbeiten</h2>
<form method="POST" style="display:flex;flex-direction:column;gap:12px;max-width:500px;">
<div>
<label style="font-size:.78rem;font-weight:500;color:var(--muted);display:block;margin-bottom:4px;">Name</label>
<input type="text" name="name" value="<?= h($trip['name']) ?>" required style="width:100%;padding:9px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.88rem;">
</div>
<div style="display:flex;gap:8px;">
<div style="flex:1;">
<label style="font-size:.78rem;font-weight:500;color:var(--muted);display:block;margin-bottom:4px;">Ziel</label>
<input type="text" name="ziel" value="<?= h($trip['ziel'] ?? '') ?>" style="width:100%;padding:9px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.88rem;">
</div>
<div style="max-width:80px;">
<label style="font-size:.78rem;font-weight:500;color:var(--muted);display:block;margin-bottom:4px;">Emoji</label>
<input type="text" name="cover_emoji" value="<?= h($trip['cover_emoji']) ?>" style="width:100%;padding:9px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.88rem;text-align:center;">
</div>
</div>
<div style="display:flex;gap:8px;">
<div style="flex:1;">
<label style="font-size:.78rem;font-weight:500;color:var(--muted);display:block;margin-bottom:4px;">Start</label>
<input type="date" name="start_datum" value="<?= h($trip['start_datum'] ?? '') ?>" style="width:100%;padding:9px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.88rem;">
</div>
<div style="flex:1;">
<label style="font-size:.78rem;font-weight:500;color:var(--muted);display:block;margin-bottom:4px;">Ende</label>
<input type="date" name="end_datum" value="<?= h($trip['end_datum'] ?? '') ?>" style="width:100%;padding:9px 12px;border:1.5px solid var(--border);border-radius:8px;font-size:.88rem;">
</div>
</div>
<button type="submit" name="save_trip" class="btn btn-primary">Speichern</button>
</form>
<div style="margin-top:32px;padding-top:20px;border-top:1.5px solid #fca5a5;">
<h3 style="font-size:.88rem;font-weight:600;color:#dc2626;margin-bottom:8px;">Gefahrenzone</h3>
<form method="POST" onsubmit="return confirm('Reise wirklich löschen? Alle Daten gehen verloren!')">
<button type="submit" name="delete_trip" class="btn" style="background:#dc2626;color:#fff;padding:8px 20px;">Reise löschen</button>
</form>
</div>
</div>
<?php endif; ?>
</main>
<?php include __DIR__ . '/includes/footer.php'; ?>