34318-vm/calendar.php
Flatlogic Bot 64b701287d v1
2025-09-23 20:48:22 +00:00

269 lines
11 KiB
PHP

<?php
require_once __DIR__ . '/auth.php';
require_once __DIR__ . '/db/config.php';
$pdo = db();
$stmt = $pdo->prepare("SELECT id, name FROM leads WHERE status != 'Closed'");
$stmt->execute();
$leads = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/js-calendar-pro/dist/js-calendar.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="main-container">
<aside class="sidebar">
<div class="logo">SaaSApp</div>
<nav class="nav flex-column">
<a class="nav-link" href="index.php">Dashboard</a>
<a class="nav-link" href="leads.php">Leads</a>
<a class="nav-link active" href="calendar.php">Calendar</a>
<?php if (is_admin()): ?>
<a class="nav-link" href="users.php">Users</a>
<a class="nav-link" href="settings.php">Settings</a>
<?php endif; ?>
<a class="nav-link" href="logout.php">Logout</a>
</nav>
</aside>
<main class="main-content">
<header class="header">
<h1>Calendar</h1>
</header>
<div class="card">
<div class="card-body">
<div id="calendar"></div>
</div>
</div>
<div class="card mt-4" id="eventsCard" style="display: none;">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title" id="eventsDate">Events for...</h5>
<button class="btn btn-primary btn-sm" id="addEventBtn">Add Event</button>
</div>
<ul class="list-group mt-3" id="eventsList"></ul>
</div>
</div>
</main>
</div>
<!-- Event Modal -->
<div class="modal fade" id="eventModal" tabindex="-1" aria-labelledby="eventModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="eventModalLabel">New Event</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="eventForm">
<input type="hidden" id="eventDate" name="eventDate">
<input type="hidden" id="eventId" name="eventId">
<div class="mb-3">
<label for="eventTitle" class="form-label">Title</label>
<input type="text" class="form-control" id="eventTitle" name="eventTitle" required>
</div>
<div class="mb-3">
<label for="leadId" class="form-label">Lead (optional)</label>
<select class="form-select" id="leadId" name="leadId">
<option value="">Select a lead</option>
<?php foreach ($leads as $lead): ?>
<option value="<?php echo $lead['id']; ?>"><?php echo htmlspecialchars($lead['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="startTime" class="form-label">Start Time</label>
<input type="time" class="form-control" id="startTime" name="startTime" required>
</div>
<div class="col-md-6 mb-3">
<label for="endTime" class="form-label">End Time</label>
<input type="time" class="form-control" id="endTime" name="endTime" required>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="saveEvent">Save Event</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/js-calendar-pro/dist/js-calendar.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const calendarEl = document.getElementById('calendar');
const calendar = new JsCalendar(calendarEl);
const eventModal = new bootstrap.Modal(document.getElementById('eventModal'));
const eventDateInput = document.getElementById('eventDate');
const addEventBtn = document.getElementById('addEventBtn');
let selectedDate = null;
function fetchAndRenderEvents() {
fetch('api/get_events.php')
.then(response => response.json())
.then(events => {
// Clear existing markers
calendarEl.querySelectorAll('.event-marker').forEach(marker => marker.remove());
events.forEach(event => {
const eventDate = new Date(event.start_time);
const dateString = eventDate.toISOString().slice(0, 10);
const dateCell = calendarEl.querySelector(`.jsCalendar-cell[data-date='${dateString}']`);
if (dateCell && !dateCell.querySelector('.event-marker')) {
const marker = document.createElement('div');
marker.classList.add('event-marker');
dateCell.appendChild(marker);
}
});
});
}
calendar.onDateClick((event, date) => {
selectedDate = date;
const dateString = date.toISOString().slice(0, 10);
const eventsCard = document.getElementById('eventsCard');
const eventsDate = document.getElementById('eventsDate');
const eventsList = document.getElementById('eventsList');
eventsDate.textContent = `Events for ${date.toLocaleDateString()}`;
eventsList.innerHTML = ''; // Clear previous events
fetch(`api/get_events_for_day.php?date=${dateString}`)
.then(response => response.json())
.then(events => {
if (events.length > 0) {
events.forEach(event => {
const li = document.createElement('li');
li.classList.add('list-group-item');
const startTime = new Date(event.start_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const endTime = new Date(event.end_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
li.innerHTML = `
<div>
<strong>${event.title}</strong><br>
${startTime} - ${endTime}
${event.lead_name ? `<br><small>Lead: ${event.lead_name}</small>` : ''}
</div>
<div>
<button class="btn btn-sm btn-outline-primary edit-event" data-id="${event.id}">Edit</button>
<button class="btn btn-sm btn-outline-danger delete-event" data-id="${event.id}">Delete</button>
</div>
`;
li.classList.add('d-flex', 'justify-content-between', 'align-items-center');
eventsList.appendChild(li);
});
} else {
const li = document.createElement('li');
li.classList.add('list-group-item');
li.textContent = 'No events for this day.';
eventsList.appendChild(li);
}
eventsCard.style.display = 'block';
});
});
addEventBtn.addEventListener('click', () => {
if (selectedDate) {
eventDateInput.value = selectedDate.toISOString().slice(0, 10);
eventModal.show();
}
});
calendar.onMonthChange(() => {
fetchAndRenderEvents();
document.getElementById('eventsCard').style.display = 'none';
});
document.getElementById('saveEvent').addEventListener('click', () => {
const form = document.getElementById('eventForm');
const formData = new FormData(form);
const eventData = Object.fromEntries(formData.entries());
const eventId = document.getElementById('eventId').value;
const url = eventId ? 'api/update_event.php' : 'api/create_event.php';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(eventData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
eventModal.hide();
fetchAndRenderEvents();
if (selectedDate) {
calendar.emit('dateClick', null, selectedDate);
}
} else {
alert('Failed to save event: ' + data.message);
}
});
});
eventsList.addEventListener('click', (e) => {
if (e.target.classList.contains('edit-event')) {
const eventId = e.target.dataset.id;
fetch(`api/get_events_for_day.php?date=${selectedDate.toISOString().slice(0,10)}`)
.then(response => response.json())
.then(events => {
const event = events.find(ev => ev.id == eventId);
if (event) {
document.getElementById('eventId').value = event.id;
document.getElementById('eventTitle').value = event.title;
document.getElementById('leadId').value = event.lead_id;
document.getElementById('startTime').value = new Date(event.start_time).toTimeString().slice(0,5);
document.getElementById('endTime').value = new Date(event.end_time).toTimeString().slice(0,5);
document.getElementById('eventModalLabel').textContent = 'Edit Event';
eventModal.show();
}
});
} else if (e.target.classList.contains('delete-event')) {
const eventId = e.target.dataset.id;
if (confirm('Are you sure you want to delete this event?')) {
fetch('api/delete_event.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ id: eventId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
fetchAndRenderEvents();
if (selectedDate) {
calendar.emit('dateClick', null, selectedDate);
}
} else {
alert('Failed to delete event: ' + data.message);
}
});
}
}
});
fetchAndRenderEvents();
});
</script>
</body>
</html>