Files
domili/index.php
2025-10-10 21:56:48 +02:00

921 lines
51 KiB
PHP
Executable File

<?php
include('inc/check_login.php');
include('inc/db.php');
include('inc/helpers.php');
// Die Benutzer-ID wird jetzt sicher aus der Session gelesen.
if (!isset($_SESSION['user_id'])) {
$logged_in_user_id = 1; // Fallback für Tests
} else {
$logged_in_user_id = intval($_SESSION['user_id']);
}
// Funktion, um den aktuellen, noch nicht abgeschlossenen Termin zu holen
function get_current_meeting($conn)
{
$sql = "SELECT id, meeting_date, color_id, reason
FROM meetings
WHERE is_completed = 0
ORDER BY meeting_date ASC
LIMIT 1";
$result = mysqli_query($conn, $sql);
if ($result && mysqli_num_rows($result) > 0) {
return mysqli_fetch_assoc($result);
}
return null;
}
// Den aktuellen Termin holen
$row = get_current_meeting($conn);
// Logik: Wenn ein Termin existiert und dessen Datum/Uhrzeit in der Vergangenheit liegt,
// wird er als "abgeschlossen" markiert und der nächste Termin wird geladen.
if ($row && strtotime($row['meeting_date']) < time()) {
$id_to_complete = $row['id'];
$sql_update = "UPDATE meetings SET is_completed = 1 WHERE id = ?";
$stmt_update = mysqli_prepare($conn, $sql_update);
if ($stmt_update) {
mysqli_stmt_bind_param($stmt_update, "i", $id_to_complete);
mysqli_stmt_execute($stmt_update);
mysqli_stmt_close($stmt_update);
}
// Den nächsten (jetzt aktuellen) Termin neu laden
$row = get_current_meeting($conn);
}
// --- NEUE LOGIK FÜR TEILNAHMEBESTÄTIGUNG ---
if ($row) {
$meeting_id = $row['id'];
$user_attendance_status = null;
// Aktionen aus der URL verarbeiten
if (isset($_GET['action']) && isset($_GET['meeting_id']) && $_GET['meeting_id'] == $meeting_id) {
$action = $_GET['action'];
$rsvp_status_value = null;
$attended_value = 0;
if ($action == 'accept') {
$rsvp_status_value = 'accepted';
$attended_value = 1;
} elseif ($action == 'decline') {
$rsvp_status_value = 'declined';
$attended_value = 0;
} elseif ($action == 'maybe') {
$rsvp_status_value = 'maybe';
$attended_value = 0;
}
if ($rsvp_status_value !== null) {
// Vorhandenen Eintrag prüfen
$check_sql = "SELECT rsvp_status FROM meeting_teilnehmer WHERE meeting_id = ? AND user_id = ?";
$check_stmt = mysqli_prepare($conn, $check_sql);
if ($check_stmt) {
mysqli_stmt_bind_param($check_stmt, "ii", $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($check_stmt);
$check_result = mysqli_stmt_get_result($check_stmt);
$existing_attendance = mysqli_fetch_assoc($check_result);
mysqli_stmt_close($check_stmt);
if ($existing_attendance) {
// Eintrag aktualisieren
$update_sql = "UPDATE meeting_teilnehmer SET rsvp_status = ?, attended = ? WHERE meeting_id = ? AND user_id = ?";
$update_stmt = mysqli_prepare($conn, $update_sql);
if ($update_stmt) {
mysqli_stmt_bind_param($update_stmt, "siii", $rsvp_status_value, $attended_value, $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($update_stmt);
mysqli_stmt_close($update_stmt);
}
} else {
// Neuen Eintrag hinzufügen
$insert_sql = "INSERT INTO meeting_teilnehmer (meeting_id, user_id, attended, rsvp_status) VALUES (?, ?, ?, ?)";
$insert_stmt = mysqli_prepare($conn, $insert_sql);
if ($insert_stmt) {
mysqli_stmt_bind_param($insert_stmt, "iiis", $meeting_id, $logged_in_user_id, $attended_value, $rsvp_status_value);
mysqli_stmt_execute($insert_stmt);
mysqli_stmt_close($insert_stmt);
}
}
}
header("Location: index.php");
exit;
}
}
// Status des eingeloggten Nutzers abrufen
$user_status_sql = "SELECT rsvp_status FROM meeting_teilnehmer WHERE meeting_id = ? AND user_id = ?";
$user_status_stmt = mysqli_prepare($conn, $user_status_sql);
if ($user_status_stmt) {
mysqli_stmt_bind_param($user_status_stmt, "ii", $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($user_status_stmt);
$user_status_result = mysqli_stmt_get_result($user_status_stmt);
$user_status_row = mysqli_fetch_assoc($user_status_result);
if ($user_status_row) {
$user_attendance_status = $user_status_row['rsvp_status'];
}
mysqli_stmt_close($user_status_stmt);
}
// Daten für die Benutzerübersicht abrufen
$attendees_sql = "SELECT t.rsvp_status, u.username
FROM meeting_teilnehmer AS t
LEFT JOIN users AS u ON t.user_id = u.id
WHERE t.meeting_id = ?";
$attendees_stmt = mysqli_prepare($conn, $attendees_sql);
$accepted_users = [];
$declined_users = [];
$maybe_users = [];
$total_accepted = 0;
$total_declined = 0;
$total_maybe = 0;
if ($attendees_stmt) {
mysqli_stmt_bind_param($attendees_stmt, "i", $meeting_id);
mysqli_stmt_execute($attendees_stmt);
$attendees_result = mysqli_stmt_get_result($attendees_stmt);
while ($row_user = mysqli_fetch_assoc($attendees_result)) {
switch ($row_user['rsvp_status']) {
case 'accepted':
$accepted_users[] = htmlspecialchars($row_user['username']);
$total_accepted++;
break;
case 'declined':
$declined_users[] = htmlspecialchars($row_user['username']);
$total_declined++;
break;
case 'maybe':
$maybe_users[] = htmlspecialchars($row_user['username']);
$total_maybe++;
break;
}
}
mysqli_stmt_close($attendees_stmt);
}
// --- NEUE LOGIK FÜR DIE BESTIMMUNG DES NÄCHSTEN ZAHLERS ---
$next_payer_username = null;
if ($total_accepted > 0) {
$sql_next_payer = "
SELECT
u.username,
(SELECT COUNT(*) FROM meeting_teilnehmer WHERE user_id = u.id AND paid = 1) AS paid_count
FROM meeting_teilnehmer mt
JOIN users u ON mt.user_id = u.id
WHERE mt.meeting_id = ? AND mt.rsvp_status = 'accepted'
ORDER BY paid_count ASC
";
$stmt_next_payer = mysqli_prepare($conn, $sql_next_payer);
mysqli_stmt_bind_param($stmt_next_payer, "i", $meeting_id);
mysqli_stmt_execute($stmt_next_payer);
$result_next_payer = mysqli_stmt_get_result($stmt_next_payer);
$payer_candidates = [];
$min_paid_count = -1;
while ($row_payer = mysqli_fetch_assoc($result_next_payer)) {
if ($min_paid_count == -1 || $row_payer['paid_count'] < $min_paid_count) {
$min_paid_count = $row_payer['paid_count'];
$payer_candidates = [$row_payer['username']];
} elseif ($row_payer['paid_count'] == $min_paid_count) {
$payer_candidates[] = $row_payer['username'];
}
}
mysqli_stmt_close($stmt_next_payer);
if (!empty($payer_candidates)) {
sort($payer_candidates);
$next_payer_username = $payer_candidates[0];
}
}
// --- NEUE LOGIK FÜR TERMINVERSCHIEBUNG ---
if ($row) {
// Aktive Verschiebungsvorschläge abrufen
$proposals_sql = "SELECT p.*, u.username as proposer_name,
COUNT(CASE WHEN v.vote = 'yes' THEN 1 END) as yes_votes,
COUNT(CASE WHEN v.vote = 'no' THEN 1 END) as no_votes,
COUNT(CASE WHEN v.vote = 'maybe' THEN 1 END) as maybe_votes
FROM meeting_reschedule_proposals p
LEFT JOIN users u ON p.proposed_by_user_id = u.id
LEFT JOIN meeting_reschedule_votes v ON p.id = v.proposal_id
WHERE p.meeting_id = ? AND p.status = 'pending'
GROUP BY p.id
ORDER BY p.created_at DESC";
$proposals_stmt = mysqli_prepare($conn, $proposals_sql);
$active_proposals = [];
if ($proposals_stmt) {
mysqli_stmt_bind_param($proposals_stmt, "i", $meeting_id);
mysqli_stmt_execute($proposals_stmt);
$proposals_result = mysqli_stmt_get_result($proposals_stmt);
while ($proposal = mysqli_fetch_assoc($proposals_result)) {
$active_proposals[] = $proposal;
}
mysqli_stmt_close($proposals_stmt);
}
// User-Stimme für aktive Vorschläge abrufen
$user_votes = [];
if (!empty($active_proposals)) {
$vote_sql = "SELECT proposal_id, vote FROM meeting_reschedule_votes
WHERE user_id = ? AND proposal_id IN (" .
implode(',', array_column($active_proposals, 'id')) . ")";
$vote_stmt = mysqli_prepare($conn, $vote_sql);
if ($vote_stmt) {
mysqli_stmt_bind_param($vote_stmt, "i", $logged_in_user_id);
mysqli_stmt_execute($vote_stmt);
$vote_result = mysqli_stmt_get_result($vote_stmt);
while ($vote = mysqli_fetch_assoc($vote_result)) {
$user_votes[$vote['proposal_id']] = $vote['vote'];
}
mysqli_stmt_close($vote_stmt);
}
}
// Neue Verschiebung vorschlagen - MIT EINSCHRÄNKUNG (nur eine pro User)
if (isset($_POST['propose_reschedule']) && isset($_POST['new_date']) && isset($_POST['reason'])) {
$new_date = $_POST['new_date'];
$reason = $_POST['reason'];
// Prüfen, ob User bereits einen Vorschlag eingereicht hat
$check_existing_sql = "SELECT id FROM meeting_reschedule_proposals
WHERE meeting_id = ? AND proposed_by_user_id = ? AND status = 'pending'";
$check_existing_stmt = mysqli_prepare($conn, $check_existing_sql);
$existing_proposal = null;
if ($check_existing_stmt) {
mysqli_stmt_bind_param($check_existing_stmt, "ii", $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($check_existing_stmt);
$check_result = mysqli_stmt_get_result($check_existing_stmt);
$existing_proposal = mysqli_fetch_assoc($check_result);
mysqli_stmt_close($check_existing_stmt);
}
// Nur einreichen, wenn noch kein aktiver Vorschlag existiert
if (!$existing_proposal) {
$insert_proposal_sql = "INSERT INTO meeting_reschedule_proposals
(meeting_id, proposed_by_user_id, proposed_date, reason)
VALUES (?, ?, ?, ?)";
$insert_stmt = mysqli_prepare($conn, $insert_proposal_sql);
if ($insert_stmt) {
mysqli_stmt_bind_param($insert_stmt, "iiss", $meeting_id, $logged_in_user_id, $new_date, $reason);
mysqli_stmt_execute($insert_stmt);
mysqli_stmt_close($insert_stmt);
// >>> E-MAIL-BENACHRICHTIGUNG SENDEN <<<
require_once __DIR__ . '/vendor/autoload.php';
$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
try {
// SMTP-Konfiguration aus secure.php
$mail->isSMTP();
$mail->Host = SMTP_HOST;
$mail->SMTPAuth = true;
$mail->Username = SMTP_USERNAME;
$mail->Password = SMTP_PASSWORD;
$mail->SMTPSecure = SMTP_ENCRYPTION;
$mail->Port = SMTP_PORT;
$mail->setFrom(MAIL_FROM_ADDRESS, MAIL_FROM_NAME);
$proposer_name = $_SESSION['username'] ?? 'Ein Benutzer';
$new_date_formatted = date('d.m.Y H:i', strtotime($new_date));
$subject = "DoMiLi: Neuer Terminvorschlag für " . date('d.m.Y H:i', strtotime($row['meeting_date']));
$message_template = "Hallo %s,\n\n%s hat einen neuen Vorschlag zur Verschiebung des Termins eingereicht.\n\nNeuer vorgeschlagener Termin: %s\nGrund: %s\n\nBitte logge dich ein, um abzustimmen oder den Vorschlag einzusehen.\n\nDein DoMiLi-Team";
$participant_sql = "SELECT DISTINCT u.email, u.username
FROM meeting_teilnehmer mt
JOIN users u ON mt.user_id = u.id
WHERE mt.meeting_id = ? AND mt.user_id != ? AND u.email IS NOT NULL AND u.email != ''";
$participant_stmt = mysqli_prepare($conn, $participant_sql);
mysqli_stmt_bind_param($participant_stmt, "ii", $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($participant_stmt);
$participants = mysqli_stmt_get_result($participant_stmt);
while ($participant = mysqli_fetch_assoc($participants)) {
$mail->addAddress($participant['email']);
$mail->Subject = $subject;
$mail->Body = sprintf($message_template, $participant['username'], $proposer_name, $new_date_formatted, $reason);
$mail->send();
$mail->clearAddresses();
}
$_SESSION['success_message'] = "Vorschlag eingereicht! Alle Teilnehmer wurden per E-Mail benachrichtigt.";
} catch (Exception $e) {
$_SESSION['error_message'] = "Fehler beim Senden der E-Mails.";
error_log("PHPMailer Error: " . $mail->ErrorInfo);
}
}
} else {
$_SESSION['error_message'] = "Du hast bereits einen Verschiebungsvorschlag eingereicht. Bitte lösche zuerst deinen bestehenden Vorschlag.";
}
header("Location: index.php");
exit;
}
// Für Vorschlag abstimmen
if (isset($_POST['vote_proposal']) && isset($_POST['proposal_id'])) {
$proposal_id = intval($_POST['proposal_id']);
$vote = $_POST['vote_proposal'];
if (!in_array($vote, ['yes', 'no', 'maybe'])) {
error_log("Ungültige Abstimmung: " . $vote);
header("Location: index.php");
exit;
}
error_log("Abstimmung empfangen: proposal_id=$proposal_id, vote=$vote, user_id=$logged_in_user_id");
// Vorhandene Stimme prüfen
$check_vote_sql = "SELECT id FROM meeting_reschedule_votes
WHERE proposal_id = ? AND user_id = ?";
$check_stmt = mysqli_prepare($conn, $check_vote_sql);
$existing_vote = null;
if ($check_stmt) {
mysqli_stmt_bind_param($check_stmt, "ii", $proposal_id, $logged_in_user_id);
mysqli_stmt_execute($check_stmt);
$check_result = mysqli_stmt_get_result($check_stmt);
$existing_vote = mysqli_fetch_assoc($check_result);
mysqli_stmt_close($check_stmt);
error_log("Vorhandene Stimme gefunden: " . ($existing_vote ? "Ja (ID: " . $existing_vote['id'] . ")" : "Nein"));
if ($existing_vote) {
// Stimme aktualisieren
$update_vote_sql = "UPDATE meeting_reschedule_votes
SET vote = ? WHERE id = ?";
$update_stmt = mysqli_prepare($conn, $update_vote_sql);
if ($update_stmt) {
mysqli_stmt_bind_param($update_stmt, "si", $vote, $existing_vote['id']);
$result = mysqli_stmt_execute($update_stmt);
error_log("Stimme aktualisiert: " . ($result ? "Erfolg" : "Fehler"));
mysqli_stmt_close($update_stmt);
}
} else {
// Neue Stimme abgeben
$insert_vote_sql = "INSERT INTO meeting_reschedule_votes
(proposal_id, user_id, vote) VALUES (?, ?, ?)";
$insert_stmt = mysqli_prepare($conn, $insert_vote_sql);
if ($insert_stmt) {
mysqli_stmt_bind_param($insert_stmt, "iis", $proposal_id, $logged_in_user_id, $vote);
$result = mysqli_stmt_execute($insert_stmt);
error_log("Neue Stimme eingefügt: " . ($result ? "Erfolg" : "Fehler"));
error_log("Affected rows: " . mysqli_stmt_affected_rows($insert_stmt));
mysqli_stmt_close($insert_stmt);
}
}
}
header("Location: index.php");
exit;
}
// Vorschlag löschen (nur vom Ersteller)
if (isset($_POST['delete_proposal']) && isset($_POST['proposal_id'])) {
$proposal_id = $_POST['proposal_id'];
$check_owner_sql = "SELECT proposed_by_user_id FROM meeting_reschedule_proposals
WHERE id = ? AND meeting_id = ?";
$check_owner_stmt = mysqli_prepare($conn, $check_owner_sql);
if ($check_owner_stmt) {
mysqli_stmt_bind_param($check_owner_stmt, "ii", $proposal_id, $meeting_id);
mysqli_stmt_execute($check_owner_stmt);
$check_owner_result = mysqli_stmt_get_result($check_owner_stmt);
$proposal_owner = mysqli_fetch_assoc($check_owner_result);
mysqli_stmt_close($check_owner_stmt);
if ($proposal_owner && $proposal_owner['proposed_by_user_id'] == $logged_in_user_id) {
$delete_votes_sql = "DELETE FROM meeting_reschedule_votes WHERE proposal_id = ?";
$delete_votes_stmt = mysqli_prepare($conn, $delete_votes_sql);
if ($delete_votes_stmt) {
mysqli_stmt_bind_param($delete_votes_stmt, "i", $proposal_id);
mysqli_stmt_execute($delete_votes_stmt);
mysqli_stmt_close($delete_votes_stmt);
}
$delete_proposal_sql = "DELETE FROM meeting_reschedule_proposals WHERE id = ?";
$delete_proposal_stmt = mysqli_prepare($conn, $delete_proposal_sql);
if ($delete_proposal_stmt) {
mysqli_stmt_bind_param($delete_proposal_stmt, "i", $proposal_id);
mysqli_stmt_execute($delete_proposal_stmt);
mysqli_stmt_close($delete_proposal_stmt);
}
}
}
header("Location: index.php");
exit;
}
// Vorschlag bearbeiten (nur vom Ersteller)
if (isset($_POST['edit_proposal']) && isset($_POST['proposal_id']) && isset($_POST['new_date']) && isset($_POST['reason'])) {
$proposal_id = $_POST['proposal_id'];
$new_date = $_POST['new_date'];
$reason = $_POST['reason'];
$check_owner_sql = "SELECT proposed_by_user_id FROM meeting_reschedule_proposals
WHERE id = ? AND meeting_id = ?";
$check_owner_stmt = mysqli_prepare($conn, $check_owner_sql);
if ($check_owner_stmt) {
mysqli_stmt_bind_param($check_owner_stmt, "ii", $proposal_id, $meeting_id);
mysqli_stmt_execute($check_owner_stmt);
$check_owner_result = mysqli_stmt_get_result($check_owner_stmt);
$proposal_owner = mysqli_fetch_assoc($check_owner_result);
mysqli_stmt_close($check_owner_stmt);
if ($proposal_owner && $proposal_owner['proposed_by_user_id'] == $logged_in_user_id) {
$delete_votes_sql = "DELETE FROM meeting_reschedule_votes WHERE proposal_id = ?";
$delete_votes_stmt = mysqli_prepare($conn, $delete_votes_sql);
if ($delete_votes_stmt) {
mysqli_stmt_bind_param($delete_votes_stmt, "i", $proposal_id);
mysqli_stmt_execute($delete_votes_stmt);
mysqli_stmt_close($delete_votes_stmt);
}
$update_proposal_sql = "UPDATE meeting_reschedule_proposals
SET proposed_date = ?, reason = ?
WHERE id = ?";
$update_proposal_stmt = mysqli_prepare($conn, $update_proposal_sql);
if ($update_proposal_stmt) {
mysqli_stmt_bind_param($update_proposal_stmt, "ssi", $new_date, $reason, $proposal_id);
mysqli_stmt_execute($update_proposal_stmt);
mysqli_stmt_close($update_proposal_stmt);
}
}
}
header("Location: index.php");
exit;
}
// Vorschlag annehmen (nur Admin)
if (isset($_POST['accept_proposal']) && isset($_POST['proposal_id'])) {
if (isset($_SESSION['role']) && $_SESSION['role'] == 'admin') {
$proposal_id = $_POST['proposal_id'];
$accept_sql = "UPDATE meeting_reschedule_proposals
SET status = 'accepted'
WHERE id = ?";
$accept_stmt = mysqli_prepare($conn, $accept_sql);
if ($accept_stmt) {
mysqli_stmt_bind_param($accept_stmt, "i", $proposal_id);
mysqli_stmt_execute($accept_stmt);
mysqli_stmt_close($accept_stmt);
}
header("Location: index.php");
exit;
}
}
// Vorschlag ablehnen (nur Admin)
if (isset($_POST['reject_proposal']) && isset($_POST['proposal_id'])) {
if (isset($_SESSION['role']) && $_SESSION['role'] == 'admin') {
$proposal_id = $_POST['proposal_id'];
$reject_sql = "UPDATE meeting_reschedule_proposals
SET status = 'rejected'
WHERE id = ?";
$reject_stmt = mysqli_prepare($conn, $reject_sql);
if ($reject_stmt) {
mysqli_stmt_bind_param($reject_stmt, "i", $proposal_id);
mysqli_stmt_execute($reject_stmt);
mysqli_stmt_close($reject_stmt);
}
header("Location: index.php");
exit;
}
}
}
}
include('inc/header.php');
$german_weekdays = [
'Mon' => 'Mo.',
'Tue' => 'Di.',
'Wed' => 'Mi.',
'Thu' => 'Do.',
'Fri' => 'Fr.',
'Sat' => 'Sa.',
'Sun' => 'So.',
];
?>
<div class="container py-0">
<!-- Erfolgsmeldung anzeigen -->
<?php if (isset($_SESSION['success_message'])): ?>
<div class="alert alert-info alert-dismissible fade show" role="alert">
<?= htmlspecialchars($_SESSION['success_message']) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php unset($_SESSION['success_message']); ?>
<?php endif; ?>
<!-- Fehlermeldung anzeigen -->
<?php if (isset($_SESSION['error_message'])): ?>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<?= htmlspecialchars($_SESSION['error_message']) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php unset($_SESSION['error_message']); ?>
<?php endif; ?>
<div class="text-center mb-4">
<h2 class="fw-bold">Farbe des nächsten Treffens</h2>
</div>
<?php if ($row): ?>
<?php
$english_weekday = date('D', strtotime($row['meeting_date']));
$german_weekday = $german_weekdays[$english_weekday] ?? '';
$color_sql = "SELECT * FROM colors WHERE id = ?";
$color_stmt = mysqli_prepare($conn, $color_sql);
mysqli_stmt_bind_param($color_stmt, "i", $row['color_id']);
mysqli_stmt_execute($color_stmt);
$color_result = mysqli_stmt_get_result($color_stmt);
$color_row = mysqli_fetch_assoc($color_result);
?>
<div class="card mx-auto bg-light shadow" style="max-width: 500px;">
<div class="card-body text-center">
<div class="rounded-4 mb-3 mx-auto d-flex flex-column justify-content-center align-items-center color-box" style="background-image: linear-gradient(135deg, <?= htmlspecialchars($color_row['hex_code']) ?>, <?= darken_color($color_row['hex_code']) ?>);">
<p class="fs-5 fw-semibold m-0" style="color: <?= get_readable_text_color($color_row['hex_code']) ?>;"><?= htmlspecialchars($color_row['name']) ?></p>
<p class="fs-6 fw-normal m-0" style="color: <?= get_readable_text_color($color_row['hex_code']) ?>;"><?= htmlspecialchars($row['reason']) ?></p>
</div>
<p class="text-muted">nächster Termin:</p>
<p class="text-muted h3 fw-bold mb-2"><?= $german_weekday . ' ' . date('d.m.Y H:i', strtotime($row['meeting_date'])) ?></p>
<div class="mt-3 mb-2">
<button class="btn btn-sm btn-outline-primary" type="button" data-bs-toggle="collapse" data-bs-target="#rescheduleForm" aria-expanded="false" aria-controls="rescheduleForm">
Terminverschiebung vorschlagen
</button>
</div>
</div>
<div class="d-flex justify-content-center pt-2 pb-3" style="max-width: 500px; margin-left: auto; margin-right: auto; flex-direction: column; align-items: center;">
<?php if ($user_attendance_status === 'accepted'): ?>
<p class="text-success fw-bold mb-4">Du hast zugesagt!</p>
<div class="d-flex justify-content-center">
<a href="index.php?action=decline&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-danger me-2">Absagen</a>
<a href="index.php?action=maybe&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-info">noch unklar</a>
</div>
<?php elseif ($user_attendance_status === 'declined'): ?>
<p class="text-danger fw-bold mb-4">Du hast abgesagt!</p>
<div class="d-flex justify-content-center">
<a href="index.php?action=accept&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-success me-2">Zusagen</a>
<a href="index.php?action=maybe&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-info">noch unklar</a>
</div>
<?php elseif ($user_attendance_status === 'maybe'): ?>
<p class="text-muted fw-bold mb-4">Vielleicht dabei!</p>
<div class="d-flex justify-content-center">
<a href="index.php?action=accept&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-success me-2">Zusagen</a>
<a href="index.php?action=decline&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-danger">Absagen</a>
</div>
<?php else: ?>
<p class="text-muted fw-bold mb-4">Bist du dabei?</p>
<div class="d-flex justify-content-center">
<a href="index.php?action=accept&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-success me-2">Zusagen</a>
<a href="index.php?action=decline&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-danger me-2">Absagen</a>
<a href="index.php?action=maybe&meeting_id=<?= htmlspecialchars($meeting_id); ?>" class="btn btn-sm btn-outline-info">Vielleicht</a>
</div>
<?php endif; ?>
</div>
<?php if ($next_payer_username): ?>
<div class="text-center my-2 mx-auto" style="max-width: 500px; border-radius: 0.5rem;">
<p class="fw-bold mb-1">Rechnung wird bezahlt von:</p>
<h4 class="text-muted fw-bold mb-0"><?= htmlspecialchars($next_payer_username); ?></h4>
</div>
<?php endif; ?>
<div class="d-flex justify-content-center my-3" style="max-width: 500px; margin-left: auto; margin-right: auto;">
<a href="admin/participant.php?id=<?= htmlspecialchars($row['id']) ?>" class="btn btn-sm btn-outline-secondary">Teilnahme eintragen</a>
</div>
<div class="card-footer text-center mt-3">
<p class="text-muted mb-1">Teilnehmerübersicht:</p>
<div class="d-flex justify-content-around">
<div class="text-center">
<p class="text-success mb-1 small">
<a class="text-success text-decoration-none participant-toggle-collapse" href="#acceptedCollapse" role="button" aria-expanded="false" aria-controls="acceptedCollapse">
Zusagen: <?= $total_accepted; ?>
</a>
</p>
<div class="collapse mt-2" id="acceptedCollapse">
<?php if (!empty($accepted_users)): ?>
<ul class="list-unstyled mb-0">
<?php foreach ($accepted_users as $user): ?>
<li class="small">
<?= $user; ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="mb-0 text-muted small">Keine</p>
<?php endif; ?>
</div>
</div>
<div class="text-center">
<p class="text-danger mb-1 small">
<a class="text-danger text-decoration-none participant-toggle-collapse" href="#declinedCollapse" role="button" aria-expanded="false" aria-controls="declinedCollapse">
Absagen: <?= $total_declined; ?>
</a>
</p>
<div class="collapse mt-2" id="declinedCollapse">
<?php if (!empty($declined_users)): ?>
<ul class="list-unstyled mb-0">
<?php foreach ($declined_users as $user): ?>
<li class="small">
<?= $user; ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="mb-0 text-muted small">Keine</p>
<?php endif; ?>
</div>
</div>
<div class="text-center">
<p class="text-warning mb-1 small">
<a class="text-info text-decoration-none participant-toggle-collapse" href="#maybeCollapse" role="button" aria-expanded="false" aria-controls="maybeCollapse">
Vielleicht: <?= $total_maybe; ?>
</a>
</p>
<div class="collapse mt-2" id="maybeCollapse">
<?php if (!empty($maybe_users)): ?>
<ul class="list-unstyled mb-0">
<?php foreach ($maybe_users as $user): ?>
<li class="small">
<?= $user; ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="mb-0 text-muted small">Keine</p>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php if ($row): ?>
<!-- Aktive Verschiebungsvorschläge -->
<?php if (!empty($active_proposals)): ?>
<div class="mt-4">
<h5 class="text-center">Aktive Verschiebungsvorschläge</h5>
<?php foreach ($active_proposals as $proposal): ?>
<div class="card mt-3 mx-auto" style="max-width: 500px;">
<div class="card-body">
<h6 class="card-title">
Vorschlag von <?= htmlspecialchars($proposal['proposer_name']) ?>
<?php if ($proposal['proposed_by_user_id'] == $logged_in_user_id): ?>
<span class="float-end">
<button class="btn btn-sm btn-outline-primary d-inline-flex align-items-center justify-content-center" type="button" data-bs-toggle="collapse" data-bs-target="#editProposal<?= $proposal['id'] ?>" aria-expanded="false" aria-controls="editProposal<?= $proposal['id'] ?>">
<span class="material-icons" style="font-size: 16px; vertical-align: middle;">edit_calendar</span>
</button>
<form method="POST" class="d-inline" onsubmit="return confirm('Vorschlag wirklich löschen? Alle Abstimmungen werden gelöscht.')">
<input type="hidden" name="proposal_id" value="<?= $proposal['id'] ?>">
<button type="submit" name="delete_proposal" class="btn btn-sm btn-outline-danger d-inline-flex align-items-center justify-content-center ms-1">
<span class="material-icons" style="font-size: 16px; vertical-align: middle;">delete_outline</span>
</button>
</form>
</span>
<?php endif; ?>
</h6>
<!-- Edit-Formular (nur für Ersteller sichtbar) -->
<?php if ($proposal['proposed_by_user_id'] == $logged_in_user_id): ?>
<div class="collapse mt-3" id="editProposal<?= $proposal['id'] ?>">
<div class="card card-body bg-light">
<h6>Bearbeiten</h6>
<form method="POST">
<input type="hidden" name="proposal_id" value="<?= $proposal['id'] ?>">
<div class="mb-2">
<label for="edit_date_<?= $proposal['id'] ?>" class="form-label">Neuer Termin:</label>
<input type="datetime-local" class="form-control" id="edit_date_<?= $proposal['id'] ?>" name="new_date" value="<?= date('Y-m-d\TH:i', strtotime($proposal['proposed_date'])) ?>" required>
</div>
<div class="mb-2">
<label for="edit_reason_<?= $proposal['id'] ?>" class="form-label">Grund/Bemerkung:</label>
<textarea class="form-control" id="edit_reason_<?= $proposal['id'] ?>" name="reason" rows="2" required><?= htmlspecialchars($proposal['reason']) ?></textarea>
</div>
<button type="submit" name="edit_proposal" class="btn btn-primary btn-sm">
Speichern
</button>
</form>
</div>
</div>
<?php endif; ?>
<p class="card-text mb-2">
<strong>Neuer Termin:</strong> <?= date('d.m.Y H:i', strtotime($proposal['proposed_date'])) ?><br>
<strong>Grund:</strong> <?= htmlspecialchars($proposal['reason']) ?><br>
<strong>Erstellt:</strong> <?= date('d.m.Y H:i', strtotime($proposal['created_at'])) ?>
</p>
<!-- Für mich OK - Abstimmung -->
<div class="d-flex justify-content-between align-items-center mb-2">
<div class="flex-grow-1">
<strong>Für mich OK:</strong>
</div>
<div class="flex-shrink-0">
<form method="POST" class="d-inline">
<input type="hidden" name="proposal_id" value="<?= $proposal['id'] ?>">
<?php if (!isset($user_votes[$proposal['id']])): ?>
<button type="submit" name="vote_proposal" value="yes" class="btn btn-xs btn-outline-success btn-sm py-1 px-2 me-1">
Ja
</button>
<button type="submit" name="vote_proposal" value="no" class="btn btn-xs btn-outline-danger btn-sm py-1 px-2">
Nein
</button>
<?php else: ?>
<?php if ($user_votes[$proposal['id']] == 'yes'): ?>
<button type="submit" name="vote_proposal" value="yes" class="btn btn-xs btn-success btn-sm py-1 px-2 me-1" disabled>
Ja
</button>
<button type="submit" name="vote_proposal" value="no" class="btn btn-xs btn-outline-danger btn-sm py-1 px-2">
Nein
</button>
<?php else: ?>
<button type="submit" name="vote_proposal" value="yes" class="btn btn-xs btn-outline-success btn-sm py-1 px-2 me-1">
Ja
</button>
<button type="submit" name="vote_proposal" value="no" class="btn btn-xs btn-danger btn-sm py-1 px-2" disabled>
Nein
</button>
<?php endif; ?>
<?php endif; ?>
</form>
</div>
</div>
<!-- Verschiebung zustimmen - nur für Admins -->
<?php if (isset($_SESSION['role']) && $_SESSION['role'] == 'admin'): ?>
<div class="d-flex justify-content-between align-items-center">
<div class="flex-grow-1">
<strong>Verschiebung zustimmen:</strong>
</div>
<div class="flex-shrink-0">
<form method="POST" class="d-inline">
<input type="hidden" name="proposal_id" value="<?= $proposal['id'] ?>">
<button type="submit" name="accept_proposal" class="btn btn-xs btn-outline-success btn-sm py-1 px-2 me-1" title="Vorschlag annehmen">
<span class="material-icons" style="font-size: 14px; vertical-align: middle;">check</span>
</button>
<button type="submit" name="reject_proposal" class="btn btn-xs btn-outline-danger btn-sm py-1 px-2" title="Vorschlag ablehnen">
<span class="material-icons" style="font-size: 14px; vertical-align: middle;">close</span>
</button>
</form>
</div>
</div>
<?php endif; ?>
</div>
<div class="card-footer text-center mt-3">
<p class="text-muted mb-1">Rückmeldung zur Verschiebung:</p>
<div class="d-flex justify-content-around">
<div class="text-center">
<p class="text-success mb-1 small">
<a class="text-success text-decoration-none participant-toggle-collapse" href="#yesCollapse<?= $proposal['id'] ?>" role="button" aria-expanded="false" aria-controls="yesCollapse<?= $proposal['id'] ?>">
Ja: <?= $proposal['yes_votes'] ?>
</a>
</p>
<div class="collapse mt-2" id="yesCollapse<?= $proposal['id'] ?>">
<?php
$yes_voters_sql = "SELECT u.username FROM meeting_reschedule_votes v
LEFT JOIN users u ON v.user_id = u.id
WHERE v.proposal_id = ? AND v.vote = 'yes'";
$yes_voters_stmt = mysqli_prepare($conn, $yes_voters_sql);
$yes_voters = [];
if ($yes_voters_stmt) {
mysqli_stmt_bind_param($yes_voters_stmt, "i", $proposal['id']);
mysqli_stmt_execute($yes_voters_stmt);
$yes_voters_result = mysqli_stmt_get_result($yes_voters_stmt);
while ($voter = mysqli_fetch_assoc($yes_voters_result)) {
$yes_voters[] = htmlspecialchars($voter['username']);
}
mysqli_stmt_close($yes_voters_stmt);
}
?>
<?php if (!empty($yes_voters)): ?>
<ul class="list-unstyled mb-0">
<?php foreach ($yes_voters as $voter): ?>
<li class="small">
<?= $voter ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="mb-0 text-muted small">Keine</p>
<?php endif; ?>
</div>
</div>
<div class="text-center">
<p class="text-danger mb-1 small">
<a class="text-danger text-decoration-none participant-toggle-collapse" href="#noCollapse<?= $proposal['id'] ?>" role="button" aria-expanded="false" aria-controls="noCollapse<?= $proposal['id'] ?>">
Nein: <?= $proposal['no_votes'] ?>
</a>
</p>
<div class="collapse mt-2" id="noCollapse<?= $proposal['id'] ?>">
<?php
$no_voters_sql = "SELECT u.username FROM meeting_reschedule_votes v
LEFT JOIN users u ON v.user_id = u.id
WHERE v.proposal_id = ? AND v.vote = 'no'";
$no_voters_stmt = mysqli_prepare($conn, $no_voters_sql);
$no_voters = [];
if ($no_voters_stmt) {
mysqli_stmt_bind_param($no_voters_stmt, "i", $proposal['id']);
mysqli_stmt_execute($no_voters_stmt);
$no_voters_result = mysqli_stmt_get_result($no_voters_stmt);
while ($voter = mysqli_fetch_assoc($no_voters_result)) {
$no_voters[] = htmlspecialchars($voter['username']);
}
mysqli_stmt_close($no_voters_stmt);
}
?>
<?php if (!empty($no_voters)): ?>
<ul class="list-unstyled mb-0">
<?php foreach ($no_voters as $voter): ?>
<li class="small">
<?= $voter ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p class="mb-0 text-muted small">Keine</p>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<!-- Zusätzlicher Freiraum unter der letzten Karte -->
<div class="mb-5"></div>
</div>
<?php endif; ?>
<?php endif; ?>
<?php else: ?>
<div class="alert alert-warning text-center">
Keine anstehenden Termine gefunden.
</div>
<?php endif; ?>
</div>
<!-- Formular für Verschiebungsvorschlag -->
<div class="collapse" id="rescheduleForm">
<div class="card card-body bg-light mt-3 mx-auto" style="max-width: 500px;">
<h5>Anderen Termin vorschlagen</h5>
<form method="POST">
<div class="mb-3">
<label for="new_date" class="form-label">Neuer Termin:</label>
<input type="datetime-local" class="form-control" id="new_date" name="new_date" value="<?= date('Y-m-d\TH:i', strtotime($row['meeting_date'])) ?>" required>
</div>
<div class="mb-3">
<label for="reason" class="form-label">Grund/Bemerkung:</label>
<textarea class="form-control" id="reason" name="reason" rows="2" placeholder="Warum soll der Termin verschoben werden?"></textarea>
</div>
<div class="d-flex gap-2">
<button type="submit" name="propose_reschedule" class="btn btn-sm btn-outline-primary">
Vorschlag einreichen
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="collapse" data-bs-target="#rescheduleForm">
Abbrechen
</button>
</div>
</form>
</div>
</div>
<script>
// Dies ist ein einfaches JavaScript, um alle drei Listen gleichzeitig ein- und auszuklappen.
document.addEventListener('DOMContentLoaded', function() {
// Wählt nur die Links mit der spezifischen Klasse aus
const links = document.querySelectorAll('.participant-toggle-collapse');
// Wählt nur die Collapse-Elemente innerhalb des .card-footer aus
const collapseElements = document.querySelectorAll('.card-footer .collapse');
links.forEach(link => {
link.addEventListener('click', function(e) {
// Verhindert das Standardverhalten des Links (Springen zur ID)
e.preventDefault();
// Überprüft, ob das erste Element sichtbar ist
const isExpanded = collapseElements[0].classList.contains('show');
// Fügt die "show"-Klasse zu allen Elementen hinzu oder entfernt sie
collapseElements.forEach(el => {
if (isExpanded) {
el.classList.remove('show');
} else {
el.classList.add('show');
}
});
// Aktualisiert den aria-expanded-Status für Barrierefreiheit
links.forEach(l => {
l.setAttribute('aria-expanded', !isExpanded);
});
});
});
});
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
console.log('DoMiLi Service Worker registriert');
})
.catch(function(err) {
console.log('Service Worker Registrierung fehlgeschlagen:', err);
});
});
}
</script>
<?php include('inc/footer.php'); ?>