37338-vm/calendar.php
2026-03-01 17:31:49 +00:00

352 lines
19 KiB
PHP

<?php
require_once 'db/config.php';
include '_header.php';
// Get current month and year
$month = isset($_GET['month']) ? (int)$_GET['month'] : date('m');
$year = isset($_GET['year']) ? (int)$_GET['year'] : date('Y');
// Create a DateTime object for the first day of the month
$firstDayOfMonth = new DateTime("$year-$month-01");
$daysInMonth = $firstDayOfMonth->format('t');
$dayOfWeek = $firstDayOfMonth->format('N'); // 1 (for Monday) through 7 (for Sunday)
// Get events for the current month
$pdo = db();
$stmt = $pdo->prepare("SELECT c.*, t.name as type_name, t.color as type_color, GROUP_CONCAT(g.name SEPARATOR ', ') as group_names FROM calendar_events c LEFT JOIN event_types t ON c.event_type_id = t.id LEFT JOIN calendar_event_groups ceg ON c.id = ceg.calendar_event_id LEFT JOIN bni_groups g ON ceg.bni_group_id = g.id WHERE MONTH(c.start_datetime) = ? AND YEAR(c.start_datetime) = ? GROUP BY c.id ORDER BY c.start_datetime ASC");
$stmt->execute([$month, $year]);
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
$eventsByDay = [];
foreach ($events as $event) {
$day = (new DateTime($event['start_datetime']))->format('j');
if (!isset($eventsByDay[$day])) {
$eventsByDay[$day] = [];
}
$eventsByDay[$day][] = $event;
}
// Get event types for the modal
$stmt_types = $pdo->query("SELECT * FROM event_types ORDER BY display_order");
$event_types = $stmt_types->fetchAll(PDO::FETCH_ASSOC);
// Get BNI groups for the modal
$stmt_groups = $pdo->query("SELECT * FROM bni_groups ORDER BY display_order");
$bni_groups = $stmt_groups->fetchAll(PDO::FETCH_ASSOC);
$prevMonth = $month == 1 ? 12 : $month - 1;
$prevYear = $month == 1 ? $year - 1 : $year;
$nextMonth = $month == 12 ? 1 : $month + 1;
$nextYear = $month == 12 ? $year + 1 : $year;
?>
<?php include '_navbar.php'; ?>
<div class="container-fluid">
<div class="row">
<?php include '_sidebar.php'; ?>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<h2 class="text-center"><?php echo t('calendar.' . strtolower($firstDayOfMonth->format('F')), $firstDayOfMonth->format('F')) . ' ' . $firstDayOfMonth->format('Y'); ?></h2>
<div class="d-flex justify-content-between mb-3">
<a href="?month=<?php echo $prevMonth; ?>&year=<?php echo $prevYear; ?>" class="btn btn-primary">&lt; <?php echo t('calendar.previous', 'Previous'); ?></a>
<a href="?month=<?php echo $nextMonth; ?>&year=<?php echo $nextYear; ?>" class="btn btn-primary"><?php echo t('calendar.next', 'Next'); ?> &gt;</a>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addEventModal">
<?php echo t('calendar.add_event', 'Add Event'); ?>
</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th><?php echo t('calendar.monday', 'Monday'); ?></th>
<th><?php echo t('calendar.tuesday', 'Tuesday'); ?></th>
<th><?php echo t('calendar.wednesday', 'Wednesday'); ?></th>
<th><?php echo t('calendar.thursday', 'Thursday'); ?></th>
<th><?php echo t('calendar.friday', 'Friday'); ?></th>
<th><?php echo t('calendar.saturday', 'Saturday'); ?></th>
<th><?php echo t('calendar.sunday', 'Sunday'); ?></th>
</tr>
</thead>
<tbody>
<tr>
<?php
// Print empty cells
for ($i = 1; $i < $dayOfWeek; $i++) {
echo "<td></td>";
}
$currentDay = 1;
while ($currentDay <= $daysInMonth) {
if ($dayOfWeek > 7) {
$dayOfWeek = 1;
echo "</tr><tr>";
}
echo "<td class=\"calendar-day\" data-date=\"$year-$month-$currentDay\">";
echo "<strong>$currentDay</strong>";
if (isset($eventsByDay[$currentDay])) {
echo "<ul class=\"list-unstyled\">";
foreach ($eventsByDay[$currentDay] as $event) {
echo '<li class="badge" style="background-color: '.($event['type_color'] ?? '#007bff').'" data-event-id="'.$event['id'].'">' . htmlspecialchars($event['title']);
if (!empty($event['group_names'])) {
echo '<br><small class="fst-italic">(' . htmlspecialchars($event['group_names']) . ')</small>';
}
echo "</li>";
}
echo "</ul>";
}
echo "</td>";
$currentDay++;
$dayOfWeek++;
}
// Print remaining empty cells
while ($dayOfWeek <= 7) {
echo "<td></td>";
$dayOfWeek++;
}
?>
</tr>
</tbody>
</table>
</main>
</div>
</div>
<!-- Event Details Modal -->
<div class="modal fade" id="eventDetailsModal" tabindex="-1" aria-labelledby="eventDetailsModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="eventDetailsModalLabel"><?php echo t('calendar.event_details', 'Event Details'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<h5 id="event-title"></h5>
<p id="event-description"></p>
<p><strong><?php echo t('calendar.starts', 'Starts:'); ?></strong> <span id="event-start"></span></p>
<p><strong><?php echo t('calendar.ends', 'Ends:'); ?></strong> <span id="event-end"></span></p>
<p><strong><?php echo t('calendar.type', 'Type:'); ?></strong> <span id="event-type"></span></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo t('modal.close', 'Close'); ?></button>
<button type="button" class="btn btn-primary" id="edit-event-btn"><?php echo t('calendar.edit', 'Edit'); ?></button>
<a href="#" id="delete-event-btn" class="btn btn-danger"><?php echo t('calendar.delete', 'Delete'); ?></a>
</div>
</div>
</div>
</div>
<div class="modal fade" id="addEventModal" tabindex="-1" aria-labelledby="addEventModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addEventModalLabel"><?php echo t('calendar.add_event_title', 'Add Calendar Event'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="_add_calendar_event.php" method="post">
<div class="mb-3">
<label for="title" class="form-label"><?php echo t('calendar.title', 'Title'); ?></label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label"><?php echo t('form.description', 'Description'); ?></label>
<textarea class="form-control" id="description" name="description"></textarea>
</div>
<div class="mb-3">
<label for="start_datetime" class="form-label"><?php echo t('calendar.start_time', 'Start Time'); ?></label>
<input type="datetime-local" class="form-control" id="start_datetime" name="start_datetime" required>
</div>
<div class="mb-3">
<label for="end_datetime" class="form-label"><?php echo t('calendar.end_time', 'End Time'); ?></label>
<input type="datetime-local" class="form-control" id="end_datetime" name="end_datetime" required>
</div>
<div class="mb-3">
<label for="event_type_id" class="form-label"><?php echo t('form.type', 'Type'); ?></label>
<select class="form-select" id="event_type_id" name="event_type_id">
<?php foreach ($event_types as $type): ?>
<option value="<?= $type['id'] ?>"><?= htmlspecialchars($type['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="group_ids" class="form-label"><?php echo t('calendar.groups', 'Group(s)'); ?></label>
<select class="form-select" id="group_ids" name="group_ids[]" multiple required>
<?php foreach ($bni_groups as $group): ?>
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="recurrence" class="form-label"><?php echo t('calendar.recurrence', 'Recurrence'); ?></label>
<select class="form-select" id="recurrence" name="recurrence">
<option value=""><?php echo t('calendar.no_repeat', 'Does not repeat'); ?></option>
<option value="daily"><?php echo t('calendar.daily', 'Daily'); ?></option>
<option value="weekly"><?php echo t('calendar.weekly', 'Weekly'); ?></option>
<option value="monthly"><?php echo t('calendar.monthly', 'Monthly'); ?></option>
</select>
</div>
<div class="mb-3" id="recurrence_end_date_container" style="display: none;">
<label for="recurrence_end_date" class="form-label"><?php echo t('calendar.recurrence_end_date', 'Recurrence End Date'); ?></label>
<input type="date" class="form-control" id="recurrence_end_date" name="recurrence_end_date">
</div>
<button type="submit" class="btn btn-primary"><?php echo t('calendar.save_event', 'Save Event'); ?></button>
</form>
</div>
</div>
</div>
</div>
<div class="modal fade" id="editEventModal" tabindex="-1" aria-labelledby="editEventModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editEventModalLabel"><?php echo t('calendar.edit_event_title', 'Edit Calendar Event'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="_update_calendar_event.php" method="post">
<input type="hidden" id="edit_event_id" name="event_id">
<div class="mb-3">
<label for="edit_title" class="form-label"><?php echo t('calendar.title', 'Title'); ?></label>
<input type="text" class="form-control" id="edit_title" name="title" required>
</div>
<div class="mb-3">
<label for="edit_description" class="form-label"><?php echo t('form.description', 'Description'); ?></label>
<textarea class="form-control" id="edit_description" name="description"></textarea>
</div>
<div class="mb-3">
<label for="edit_start_datetime" class="form-label"><?php echo t('calendar.start_time', 'Start Time'); ?></label>
<input type="datetime-local" class="form-control" id="edit_start_datetime" name="start_datetime" required>
</div>
<div class="mb-3">
<label for="edit_end_datetime" class="form-label"><?php echo t('calendar.end_time', 'End Time'); ?></label>
<input type="datetime-local" class="form-control" id="edit_end_datetime" name="end_datetime" required>
</div>
<div class="mb-3">
<label for="edit_event_type_id" class="form-label"><?php echo t('form.type', 'Type'); ?></label>
<select class="form-select" id="edit_event_type_id" name="event_type_id">
<?php foreach ($event_types as $type): ?>
<option value="<?= $type['id'] ?>"><?= htmlspecialchars($type['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="edit_group_ids" class="form-label"><?php echo t('calendar.groups', 'Group(s)'); ?></label>
<select class="form-select" id="edit_group_ids" name="group_ids[]" multiple required>
<?php foreach ($bni_groups as $group): ?>
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div id="edit-recurrence-options" class="mb-3" style="display: none;">
<strong><?php echo t('calendar.recurring_notice', 'This is a recurring event.'); ?></strong><br>
<div class="form-check">
<input class="form-check-input" type="radio" name="update_scope" id="update_scope_one" value="one" checked>
<label class="form-check-label" for="update_scope_one">
<?php echo t('calendar.update_scope_one', 'Update this event only'); ?>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="update_scope" id="update_scope_all" value="all">
<label class="form-check-label" for="update_scope_all">
<?php echo t('calendar.update_scope_all', 'Update all events in the series'); ?>
</label>
</div>
</div>
<button type="submit" class="btn btn-primary"><?php echo t('modal.save_changes', 'Save Changes'); ?></button>
</form>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const addEventModal = new bootstrap.Modal(document.getElementById('addEventModal'));
const eventDetailsModal = new bootstrap.Modal(document.getElementById('eventDetailsModal'));
const editEventModal = new bootstrap.Modal(document.getElementById('editEventModal'));
let currentEventData = null;
document.querySelectorAll('.calendar-day').forEach(day => {
day.addEventListener('click', function(e) {
if (e.target.classList.contains('badge')) {
const eventId = e.target.dataset.eventId;
fetch(`_get_event_details.php?id=${eventId}`)
.then(response => response.json())
.then(data => {
currentEventData = data;
document.getElementById('event-title').textContent = data.title;
document.getElementById('event-description').textContent = data.description;
document.getElementById('event-start').textContent = new Date(data.start_datetime).toLocaleString();
document.getElementById('event-end').textContent = new Date(data.end_datetime).toLocaleString();
document.getElementById('event-type').textContent = data.type_name;
document.getElementById('delete-event-btn').href = `_delete_calendar_event.php?id=${eventId}`;
eventDetailsModal.show();
});
} else {
const date = this.dataset.date;
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const currentTime = `${hours}:${minutes}`;
const startInput = document.getElementById('start_datetime');
const month = String(new Date(date).getMonth() + 1).padStart(2, '0');
const dayOfMonth = String(new Date(date).getDate()).padStart(2, '0');
const year = new Date(date).getFullYear();
startInput.value = `${year}-${month}-${dayOfMonth}T${currentTime}`;
addEventModal.show();
}
});
});
document.getElementById('edit-event-btn').addEventListener('click', function() {
if (currentEventData) {
const recurrenceOptions = document.getElementById('edit-recurrence-options');
if (currentEventData.parent_event_id !== null || currentEventData.recurrence !== null) {
recurrenceOptions.style.display = 'block';
document.getElementById('update_scope_all').checked = true;
} else {
recurrenceOptions.style.display = 'none';
}
document.getElementById('edit_event_id').value = currentEventData.id;
document.getElementById('edit_title').value = currentEventData.title;
document.getElementById('edit_description').value = currentEventData.description;
document.getElementById('edit_start_datetime').value = currentEventData.start_datetime.slice(0, 16);
document.getElementById('edit_end_datetime').value = currentEventData.end_datetime.slice(0, 16);
document.getElementById('edit_event_type_id').value = currentEventData.event_type_id;
const groupSelect = document.getElementById('edit_group_ids');
const groupIds = currentEventData.group_ids || [];
for (const option of groupSelect.options) {
option.selected = groupIds.includes(option.value);
}
eventDetailsModal.hide();
editEventModal.show();
}
});
const recurrenceSelect = document.getElementById('recurrence');
const recurrenceEndDateContainer = document.getElementById('recurrence_end_date_container');
recurrenceSelect.addEventListener('change', function() {
if (this.value) {
recurrenceEndDateContainer.style.display = 'block';
} else {
recurrenceEndDateContainer.style.display = 'none';
}
});
});
</script>
<?php
include '_footer.php';
?>