Files
domili/index.php
2025-10-13 17:44:43 +02:00

442 lines
21 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
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
include('inc/check_login.php');
include('inc/db.php');
include('inc/helpers.php');
$logged_in_user_id = isset($_SESSION['user_id']) ? intval($_SESSION['user_id']) : 1;
// 🔹 Funktion: Prüft, ob Benutzer im Abwesenheitsmodus ist
function is_user_on_vacation($conn, $user_id, $meeting_date)
{
$stmt = mysqli_prepare($conn, "
SELECT 1 FROM vacations
WHERE user_id = ?
AND ? BETWEEN start_date AND end_date
LIMIT 1
");
if (!$stmt) return false;
mysqli_stmt_bind_param($stmt, "is", $user_id, $meeting_date);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$found = mysqli_fetch_assoc($result);
mysqli_stmt_close($stmt);
return $found !== null;
}
// 🔹 Funktion: Automatisch ablehnen, wenn im Urlaub (außer bei expliziter Zusage)
function auto_decline_if_on_vacation($conn, $meeting_id, $user_id, $meeting_date)
{
if (!is_user_on_vacation($conn, $user_id, $meeting_date)) {
return null;
}
$check_sql = "SELECT rsvp_status FROM meeting_teilnehmer WHERE meeting_id = ? AND user_id = ?";
$check_stmt = mysqli_prepare($conn, $check_sql);
mysqli_stmt_bind_param($check_stmt, "ii", $meeting_id, $user_id);
mysqli_stmt_execute($check_stmt);
$existing = mysqli_fetch_assoc(mysqli_stmt_get_result($check_stmt));
mysqli_stmt_close($check_stmt);
// Wenn bereits "accepted", nichts tun
if ($existing && $existing['rsvp_status'] === 'accepted') {
return 'accepted';
}
// Sonst: ablehnen
if ($existing) {
$upd = mysqli_prepare($conn, "UPDATE meeting_teilnehmer SET rsvp_status = 'declined', attended = 0 WHERE meeting_id = ? AND user_id = ?");
mysqli_stmt_bind_param($upd, "ii", $meeting_id, $user_id);
mysqli_stmt_execute($upd);
mysqli_stmt_close($upd);
} else {
$ins = mysqli_prepare($conn, "INSERT INTO meeting_teilnehmer (meeting_id, user_id, rsvp_status, attended) VALUES (?, ?, 'declined', 0)");
mysqli_stmt_bind_param($ins, "ii", $meeting_id, $user_id);
mysqli_stmt_execute($ins);
mysqli_stmt_close($ins);
}
return 'declined';
}
// Funktion: aktueller, nicht abgeschlossener Termin
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);
return ($result && mysqli_num_rows($result) > 0) ? mysqli_fetch_assoc($result) : null;
}
$row = get_current_meeting($conn);
// 🔴 Automatisches Abschließen bei vergangenem Termin wurde ENTFERNT
// → Termin bleibt sichtbar, bis Admin in participant.php abschließt
// --- TEILNAHME-LOGIK ---
if ($row) {
$meeting_id = $row['id'];
// Aktionen verarbeiten (Zusagen / Absagen / Vielleicht)
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) {
$check_sql = "SELECT rsvp_status FROM meeting_teilnehmer WHERE meeting_id = ? AND user_id = ?";
$check_stmt = mysqli_prepare($conn, $check_sql);
$existing = null;
if ($check_stmt) {
mysqli_stmt_bind_param($check_stmt, "ii", $meeting_id, $logged_in_user_id);
mysqli_stmt_execute($check_stmt);
$existing = mysqli_fetch_assoc(mysqli_stmt_get_result($check_stmt));
mysqli_stmt_close($check_stmt);
}
if ($existing) {
$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 {
$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;
}
}
// 🔥 Automatisch ablehnen, wenn im Abwesenheitsmodus
$auto_declined = auto_decline_if_on_vacation($conn, $meeting_id, $logged_in_user_id, $row['meeting_date']);
// Status abrufen (kann jetzt "declined" sein)
$user_attendance_status = null;
$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);
}
// Teilnehmerlisten laden
$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);
}
// --- ZAHLENDE PERSON BESTIMMEN ---
$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];
}
}
// --- TERMINVERSCHIEBUNG (ohne Änderung) ---
include('verschiebung.php'); // oder den gesamten Block hier lassen optional
// ... (hier kommt dein bestehender Verschiebungscode unverändert)
// Da du ihn bereits modularisiert hast, kannst du auch `include('verschiebung.php');` nutzen
// Für diese Version lasse ich ihn aus Platzgründen weg du kannst ihn wie gewohnt einfügen.
}
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">
<!-- Optional: Hinweis bei automatischer Ablehnung -->
<?php if (isset($auto_declined) && $auto_declined === 'declined'): ?>
<div class="alert alert-info alert-dismissible fade show" role="alert">
Du befindest dich im Abwesenheitsmodus → Teilnahme wurde automatisch abgelehnt.
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<?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; ?>
<?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_stmt = mysqli_prepare($conn, "SELECT * FROM colors WHERE id = ?");
mysqli_stmt_bind_param($color_stmt, "i", $row['color_id']);
mysqli_stmt_execute($color_stmt);
$color_row = mysqli_fetch_assoc(mysqli_stmt_get_result($color_stmt));
?>
<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>
<!-- Teilnehmerübersicht (unverändert) -->
<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>
<!-- Hier kommt dein bestehender Verschiebungs-HTML-Block unverändert -->
<!-- (Du kannst ihn aus deinem Originalcode kopieren) -->
<?php else: ?>
<div class="alert alert-warning text-center">Keine anstehenden Termine gefunden.</div>
<?php endif; ?>
</div>
<!-- Verschiebungsformular (unverändert) -->
<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="<?= $row ? 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>
document.addEventListener('DOMContentLoaded', function() {
const links = document.querySelectorAll('.participant-toggle-collapse');
const collapseElements = document.querySelectorAll('.card-footer .collapse');
links.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const isExpanded = collapseElements[0].classList.contains('show');
collapseElements.forEach(el => isExpanded ? el.classList.remove('show') : el.classList.add('show'));
links.forEach(l => l.setAttribute('aria-expanded', !isExpanded));
});
});
});
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').catch(console.error);
});
}
</script>
<?php include('inc/footer.php'); ?>