497 lines
27 KiB
PHP
497 lines
27 KiB
PHP
<?= $this->extend('layout/main_layout') ?>
|
|
<?= $this->section('content') ?>
|
|
|
|
<div class="container-fluid py-5">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<h2>Print/Copy Requests</h2>
|
|
|
|
<!-- Print/Copy Request Tabs -->
|
|
<div class="card my-4">
|
|
<div class="card-header pb-0">
|
|
<div class="btn-group" role="tablist" aria-label="Print request tabs">
|
|
<button
|
|
class="btn btn-outline-primary active"
|
|
id="tab-print-tab"
|
|
data-bs-toggle="tab"
|
|
data-bs-target="#tab-print"
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="tab-print"
|
|
aria-selected="true"
|
|
>
|
|
Print Request
|
|
</button>
|
|
<button
|
|
class="btn btn-outline-primary"
|
|
id="tab-copy-tab"
|
|
data-bs-toggle="tab"
|
|
data-bs-target="#tab-copy"
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="tab-copy"
|
|
aria-selected="false"
|
|
>
|
|
Copy Request
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body tab-content" id="printRequestTabContent">
|
|
<div class="tab-pane fade show active" id="tab-print" role="tabpanel" aria-labelledby="tab-print-tab">
|
|
<form action="<?= site_url('print-requests/create') ?>" method="post" enctype="multipart/form-data">
|
|
<?= csrf_field() ?>
|
|
<?php if (session()->has('errors')): ?>
|
|
<div class="alert alert-danger">
|
|
<ul>
|
|
<?php foreach (session('errors') as $error): ?>
|
|
<li><?= esc($error) ?></li>
|
|
<?php endforeach ?>
|
|
</ul>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="row g-3 align-items-end">
|
|
<div class="col-md-3">
|
|
<label for="file" class="form-label">File (PDF, JPG, PNG, DOC, TXT)</label>
|
|
<input type="file" class="form-control" id="file" name="file" required>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="page_selection" class="form-label">Page Selection (Optional)</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="page_selection"
|
|
name="page_selection"
|
|
placeholder="Examples: 1-4, 8, 12-15 or 1-5 or 1-9, 12."
|
|
pattern="\s*\d+(\s*-\s*\d+)?(\s*,\s*\d+(\s*-\s*\d+)?)*\s*"
|
|
>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="num_copies" class="form-label">Number of Copies</label>
|
|
<input type="number" class="form-control" id="num_copies" name="num_copies" min="1" required>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="pickup_method" class="form-label">Pickup Method</label>
|
|
<select class="form-select" id="pickup_method" name="pickup_method" required>
|
|
<option value="">Please select</option>
|
|
<option value="Self Pickup">Self Pickup</option>
|
|
<option value="Delivered to class">Delivered to class</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3 mt-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Job Needed By</label>
|
|
<div class="row g-2">
|
|
<div class="col">
|
|
<select class="form-select" id="required_by_date" required>
|
|
<option value="">Select a Sunday</option>
|
|
<?php foreach ($sundays as $sunday): ?>
|
|
<option value="<?= $sunday ?>"><?= date('m-d-Y', strtotime($sunday)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col">
|
|
<select class="form-select" id="required_by_time" required>
|
|
<option value="">Select a time</option>
|
|
<?php foreach ($times as $time): ?>
|
|
<option value="<?= $time ?>"><?= date('h:i A', strtotime($time)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="required_by" name="required_by">
|
|
</div>
|
|
<div class="col-md-6 text-end">
|
|
<?php if (isset($class_id) && $class_id): ?>
|
|
<input type="hidden" name="class_id" value="<?= $class_id ?>">
|
|
<?php else: ?>
|
|
<div class="alert alert-warning mb-0" role="alert">
|
|
You are not assigned to any class. Please contact the administrator to be able to submit print requests.
|
|
</div>
|
|
<?php endif; ?>
|
|
<button type="submit" class="btn btn-primary mt-3" <?= (!isset($class_id) || !$class_id) ? 'disabled' : '' ?>>Submit Request</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane fade" id="tab-copy" role="tabpanel" aria-labelledby="tab-copy-tab">
|
|
<div class="mb-3">
|
|
<p class="text-muted">
|
|
Submit a copy request for a physical document. Bring the originals to the copy center instead of uploading a file.
|
|
</p>
|
|
</div>
|
|
<form id="copyRequestForm" method="post" action="<?= site_url('print-requests/create-copy') ?>">
|
|
<?= csrf_field() ?>
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<label for="copy_num_copies" class="form-label">Number of Copies</label>
|
|
<input type="number" class="form-control" id="copy_num_copies" name="num_copies" min="1" required>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label">Job Needed By</label>
|
|
<div class="row g-2">
|
|
<div class="col">
|
|
<select class="form-select" id="copy_required_by_date" required>
|
|
<option value="">Select a Sunday</option>
|
|
<?php foreach ($sundays as $sunday): ?>
|
|
<option value="<?= $sunday ?>"><?= date('m-d-Y', strtotime($sunday)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col">
|
|
<select class="form-select" id="copy_required_by_time" required>
|
|
<option value="">Select a time</option>
|
|
<?php foreach ($times as $time): ?>
|
|
<option value="<?= $time ?>"><?= date('h:i A', strtotime($time)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="copy_required_by" name="required_by">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label for="copy_pickup_method" class="form-label">Pickup Method</label>
|
|
<select class="form-select" id="copy_pickup_method" name="pickup_method" required>
|
|
<option value="">Please select</option>
|
|
<option value="Self Pickup">Self Pickup</option>
|
|
<option value="Delivered to class">Delivered to class</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<?php if (isset($class_id) && $class_id): ?>
|
|
<input type="hidden" name="class_id" value="<?= $class_id ?>">
|
|
<?php endif; ?>
|
|
<div class="form-text mt-2">
|
|
No file upload is required; please hand the original document to the copy staff after submitting.
|
|
</div>
|
|
<button type="submit" class="btn btn-outline-primary mt-3">Submit Copy Request</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Print Request History -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
Print Request History
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-bordered table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>File</th>
|
|
<th>Pages</th>
|
|
<th>Copies</th>
|
|
<th>Job Needed By</th>
|
|
<th>Pickup Method</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (!empty($print_requests)): ?>
|
|
<?php foreach ($print_requests as $request): ?>
|
|
<tr>
|
|
<td><?= $request['id'] ?></td>
|
|
<td>
|
|
<?php if (!empty($request['file_path'])): ?>
|
|
<a href="<?= site_url('print-requests/file/' . rawurlencode($request['file_path'])) ?>" target="_blank"><?= esc($request['file_path']) ?></a>
|
|
<?php else: ?>
|
|
<span class="text-muted">Physical copy request</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if (!empty($request['page_selection'])): ?>
|
|
<?= esc($request['page_selection']) ?>
|
|
<?php else: ?>
|
|
<span class="text-muted">ALL</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= $request['num_copies'] ?></td>
|
|
<td><?= $request['required_by'] ?></td>
|
|
<td><?= $request['pickup_method'] ?></td>
|
|
<td>
|
|
<?php
|
|
$status = $request['status'];
|
|
$badge_class = 'bg-light text-dark';
|
|
$status_text = ucfirst(str_replace('_', ' ', $status));
|
|
$assignedAdmin = trim(($request['admin_firstname'] ?? '') . ' ' . ($request['admin_lastname'] ?? ''));
|
|
switch ($status) {
|
|
case 'not_assigned':
|
|
$badge_class = 'bg-secondary';
|
|
$status_text = 'Pending assignment';
|
|
break;
|
|
case 'assigned':
|
|
$badge_class = 'bg-warning text-dark';
|
|
$status_text = $assignedAdmin !== '' ? 'Assigned to ' . $assignedAdmin : 'Assigned';
|
|
break;
|
|
case 'done':
|
|
$badge_class = 'bg-primary';
|
|
$status_text = 'Printed. Pending delivery/pick-up';
|
|
break;
|
|
case 'delivered':
|
|
$badge_class = 'bg-success';
|
|
$status_text = 'Done';
|
|
break;
|
|
}
|
|
?>
|
|
<span class="badge <?= $badge_class ?>">
|
|
<?= $status_text ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<div class="d-flex flex-wrap gap-1">
|
|
<?php if (in_array($request['status'], ['not_assigned', 'assigned'])): ?>
|
|
<button type="button" class="btn btn-sm btn-warning mb-1" onclick='editRequest(<?= json_encode($request, JSON_HEX_APOS | JSON_HEX_QUOT) ?>)'>Edit</button>
|
|
<?php endif; ?>
|
|
<?php if ($request['status'] === 'not_assigned'): ?>
|
|
<button type="button" class="btn btn-sm btn-danger mb-1" onclick="deleteRequest(<?= $request['id'] ?>)">Delete</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="8" class="text-center">No print requests found.</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit Modal -->
|
|
<div class="modal fade" id="editRequestModal" tabindex="-1" aria-labelledby="editRequestModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<form id="editRequestForm" method="post" enctype="multipart/form-data">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editRequestModalLabel">Edit Print Request</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" id="edit_request_id" name="request_id">
|
|
<div class="mb-3">
|
|
<label for="edit_num_copies" class="form-label">Number of Copies</label>
|
|
<input type="number" class="form-control" id="edit_num_copies" name="num_copies" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="edit_page_selection" class="form-label">Page Selection</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="edit_page_selection"
|
|
name="page_selection"
|
|
placeholder="Examples: 1-4, 8, 12-15 or 1-5 or 1-9, 12."
|
|
pattern="\s*\d+(\s*-\s*\d+)?(\s*,\s*\d+(\s*-\s*\d+)?)*\s*"
|
|
>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="edit_pickup_method" class="form-label">Pickup Method</label>
|
|
<select class="form-select" id="edit_pickup_method" name="pickup_method" required>
|
|
<option value="">Please select</option>
|
|
<option value="Self Pickup">Self Pickup</option>
|
|
<option value="Delivered to class">Delivered to class</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="edit_required_by_date" class="form-label">Job Needed By</label>
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<select class="form-select" id="edit_required_by_date" required>
|
|
<option value="">Select a Sunday</option>
|
|
<?php foreach ($sundays as $sunday): ?>
|
|
<option value="<?= $sunday ?>"><?= date('m-d-Y', strtotime($sunday)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<select class="form-select" id="edit_required_by_time" required>
|
|
<option value="">Select a time</option>
|
|
<?php foreach ($times as $time): ?>
|
|
<option value="<?= $time ?>"><?= date('h:i A', strtotime($time)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="edit_required_by" name="required_by">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="edit_file" class="form-label">Replace File (PDF, JPG, PNG, DOC, TXT) (optional)</label>
|
|
<input type="file" class="form-control" id="edit_file" name="file">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary">Save changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?= $this->endSection() ?>
|
|
|
|
<?= $this->section('scripts') ?>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Main form submission logic
|
|
const createForm = document.querySelector('form[action="<?= site_url('print-requests/create') ?>"]');
|
|
if (createForm) {
|
|
createForm.addEventListener('submit', function(e) {
|
|
const dateSelect = document.getElementById('required_by_date');
|
|
const timeSelect = document.getElementById('required_by_time');
|
|
const hiddenInput = document.getElementById('required_by');
|
|
if (dateSelect.value && timeSelect.value) {
|
|
hiddenInput.value = dateSelect.value + 'T' + timeSelect.value;
|
|
} else {
|
|
if (!dateSelect.value) {
|
|
alert('Please select a date.');
|
|
e.preventDefault();
|
|
} else if (!timeSelect.value) {
|
|
alert('Please select a time.');
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Edit form submission logic
|
|
const editForm = document.getElementById('editRequestForm');
|
|
if (editForm) {
|
|
editForm.addEventListener('submit', function(e) {
|
|
const dateValue = document.getElementById('edit_required_by_date').value;
|
|
const timeValue = document.getElementById('edit_required_by_time').value;
|
|
if (dateValue && timeValue) {
|
|
document.getElementById('edit_required_by').value = dateValue + 'T' + timeValue;
|
|
} else {
|
|
alert('Please select a date and time for the edit form.');
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Client-side file validation for new request form
|
|
const fileInput = document.getElementById('file');
|
|
if (fileInput) {
|
|
fileInput.addEventListener('change', function(event) {
|
|
const file = event.target.files[0];
|
|
if (!file) {
|
|
return;
|
|
}
|
|
const allowedExtensions = ['pdf', 'jpg', 'png', 'jpeg', 'doc', 'docx', 'txt'];
|
|
const fileExtension = file.name.split('.').pop().toLowerCase();
|
|
if (!allowedExtensions.includes(fileExtension)) {
|
|
alert('Invalid file type. Please upload a PDF, JPG, PNG, or JPEG file.');
|
|
this.value = '';
|
|
return;
|
|
}
|
|
const maxSizeInBytes = 5 * 1024 * 1024; // 5MB
|
|
if (file.size > maxSizeInBytes) {
|
|
alert('File is too large. The maximum size is 5MB.');
|
|
this.value = '';
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
function editRequest(requestData) {
|
|
console.log("Editing request:", requestData);
|
|
|
|
const form = document.getElementById('editRequestForm');
|
|
form.action = `<?= site_url('print-requests/update/') ?>${requestData.id}`;
|
|
|
|
document.getElementById('edit_request_id').value = requestData.id;
|
|
document.getElementById('edit_num_copies').value = requestData.num_copies;
|
|
document.getElementById('edit_page_selection').value = requestData.page_selection || '';
|
|
document.getElementById('edit_pickup_method').value = requestData.pickup_method;
|
|
|
|
if (requestData.required_by) {
|
|
try {
|
|
// Manually parse 'YYYY-MM-DD HH:MM:SS'
|
|
const parts = requestData.required_by.split(/[- :]/);
|
|
// new Date(year, monthIndex, day, hours, minutes, seconds)
|
|
const requiredByDate = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
|
|
|
|
if (!isNaN(requiredByDate)) {
|
|
const dateString = requiredByDate.getFullYear() + '-' + ('0' + (requiredByDate.getMonth() + 1)).slice(-2) + '-' + ('0' + requiredByDate.getDate()).slice(-2);
|
|
const timeString = ('0' + requiredByDate.getHours()).slice(-2) + ':' + ('0' + requiredByDate.getMinutes()).slice(-2);
|
|
|
|
console.log("Setting date to:", dateString);
|
|
console.log("Setting time to:", timeString);
|
|
|
|
document.getElementById('edit_required_by_date').value = dateString;
|
|
document.getElementById('edit_required_by_time').value = timeString;
|
|
} else {
|
|
console.error("Could not parse date, result is NaN for:", requestData.required_by);
|
|
}
|
|
} catch (e) {
|
|
console.error('Error parsing required_by date:', requestData.required_by, e);
|
|
}
|
|
}
|
|
|
|
var editModal = new bootstrap.Modal(document.getElementById('editRequestModal'));
|
|
editModal.show();
|
|
}
|
|
|
|
function deleteRequest(id) {
|
|
if (confirm('Are you sure you want to delete this request?')) {
|
|
const formData = new FormData();
|
|
const csrfInput = document.querySelector('form[action="<?= site_url('print-requests/create') ?>"] input[name^="csrf_"]');
|
|
if (csrfInput) {
|
|
formData.append(csrfInput.name, csrfInput.value);
|
|
} else {
|
|
console.error('CSRF token not found!');
|
|
alert('Could not delete request. Security token not found.');
|
|
return;
|
|
}
|
|
|
|
fetch(`<?= site_url('print-requests/delete/') ?>${id}`, {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => {
|
|
if (response.ok) {
|
|
window.location.reload();
|
|
} else {
|
|
response.text().then(text => {
|
|
alert('Failed to delete request. Server responded with: ' + text);
|
|
});
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while trying to delete the request.');
|
|
});
|
|
}
|
|
}
|
|
const copyForm = document.getElementById('copyRequestForm');
|
|
if (copyForm) {
|
|
copyForm.addEventListener('submit', function(e) {
|
|
const dateSelect = document.getElementById('copy_required_by_date');
|
|
const timeSelect = document.getElementById('copy_required_by_time');
|
|
const hiddenInput = document.getElementById('copy_required_by');
|
|
if (!dateSelect || !dateSelect.value) {
|
|
alert('Please select a date for the copy request.');
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
if (!timeSelect || !timeSelect.value) {
|
|
alert('Please select a time for the copy request.');
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
if (hiddenInput) {
|
|
hiddenInput.value = dateSelect.value + 'T' + timeSelect.value;
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
<?= $this->endSection() ?>
|