290 lines
21 KiB
HTML
290 lines
21 KiB
HTML
{{define "content"}}
|
|
<h1 class="text-3xl font-bold mb-4 text-gray-800">Quotes Expiring</h1>
|
|
<div class="px-8">
|
|
<!-- Expiring Soon Section -->
|
|
<h2 class="text-xl font-semibold mt-6 mb-2">Expiring Soon</h2>
|
|
<table class="w-full border text-center align-middle mt-1">
|
|
<thead>
|
|
<tr>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Quote</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Enquiry</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Issued By</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Issued At</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Expires</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Reminder</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Reminder Sent</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .ExpiringSoonQuotes}}
|
|
<tr class="hover:bg-slate-50 transition">
|
|
<td class="px-4 py-2 border align-middle"><a href="/documents/view/{{.ID}}" class="text-blue-600 underline">{{.ID}}</a></td>
|
|
<td class="px-4 py-2 border align-middle"><a href="/enquiries/view/{{.EnquiryID}}" class="text-blue-600 underline">{{.EnquiryRef}}</a></td>
|
|
<td class="px-4 py-2 border align-middle">{{.Username}}</td>
|
|
<td class="px-4 py-2 border align-middle"><span class="localdate">{{.DateIssued}}</span></td>
|
|
<td class="px-4 py-2 border align-middle"><span class="localdate">{{.ValidUntil}}</span> <span class="text-gray-500">({{.ValidUntilRelative}})</span></td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
{{if .LatestReminderType}}
|
|
{{if or (eq .LatestReminderType "First Reminder") (eq .LatestReminderType "First Reminder Sent")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200">{{.LatestReminderType}}</span>
|
|
{{else if or (eq .LatestReminderType "Second Reminder") (eq .LatestReminderType "Second Reminder Sent")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-700 border border-yellow-200">{{.LatestReminderType}}</span>
|
|
{{else if or (eq .LatestReminderType "Final Reminder") (eq .LatestReminderType "Final Reminder Sent")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-red-100 text-red-700 border border-red-200">{{.LatestReminderType}}</span>
|
|
{{else}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-gray-200 text-gray-700 border border-gray-300">{{.LatestReminderType}}</span>
|
|
{{end}}
|
|
{{else}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-gray-200 text-gray-700 border border-gray-300">No Reminder Sent</span>
|
|
{{end}}
|
|
</td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
{{if .LatestReminderSent}}<span class="localdatetime">{{.LatestReminderSent}}</span>{{else}}-{{end}}
|
|
</td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
<form method="POST" action="/go/quotes/send-reminder" style="display:inline;">
|
|
<input type="hidden" name="quote_id" value="{{.ID}}">
|
|
<input type="hidden" name="customer_email" value="{{.CustomerEmail}}">
|
|
<input type="hidden" name="user_email" value="{{.UserEmail}}">
|
|
<input type="hidden" name="enquiry_ref" value="{{.EnquiryRef}}">
|
|
<input type="hidden" name="customer_name" value="{{.CustomerName}}">
|
|
<input type="hidden" name="date_issued" value="{{.DateIssued}}">
|
|
<input type="hidden" name="valid_until" value="{{.ValidUntil}}">
|
|
<div class="inline-flex rounded-md shadow-sm" role="group">
|
|
{{if eq .LatestReminderType "No Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 1, '{{.EnquiryRef}}', '{{.CustomerName}}', 'First Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send First Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else if eq .LatestReminderType "First Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 2, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Second Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Second Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else if eq .LatestReminderType "Second Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Final Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else}}
|
|
<button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Final Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{end}}
|
|
</div>
|
|
<div class="hidden absolute z-10 mt-1 bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5" style="min-width: 150px;">
|
|
<ul class="py-1 text-xs text-gray-700">
|
|
<li><button type="button" onclick="showConfirmModal(this, 1, '{{.EnquiryRef}}', '{{.CustomerName}}', 'First Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send First Reminder</button></li>
|
|
<li><button type="button" onclick="showConfirmModal(this, 2, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Second Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send Second Reminder</button></li>
|
|
<li><button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send Final Reminder</button></li>
|
|
</ul>
|
|
</div>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr><td colspan="8" class="px-4 py-2 border text-center align-middle">No quotes expiring soon.</td></tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
<!-- Recently Expired Quotes Section -->
|
|
<h2 class="text-xl font-semibold mt-6 mb-2">Recently Expired</h2>
|
|
<table class="w-full border mb-6 text-center align-middle mt-1">
|
|
<thead>
|
|
<tr>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Quote</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Enquiry</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Issued By</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Issued At</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Expires</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Reminder</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Reminder Sent</th>
|
|
<th class="px-4 py-3 border font-semibold text-gray-700 align-middle">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .RecentlyExpiredQuotes}}
|
|
<tr class="hover:bg-slate-50 transition">
|
|
<td class="px-4 py-2 border align-middle"><a href="/documents/view/{{.ID}}" class="text-blue-600 underline">{{.ID}}</a></td>
|
|
<td class="px-4 py-2 border align-middle"><a href="/enquiries/view/{{.EnquiryID}}" class="text-blue-600 underline">{{.EnquiryRef}}</a></td>
|
|
<td class="px-4 py-2 border align-middle">{{.Username}}</td>
|
|
<td class="px-4 py-2 border align-middle"><span class="localdate">{{.DateIssued}}</span></td>
|
|
<td class="px-4 py-2 border align-middle"><span class="localdate">{{.ValidUntil}}</span> <span class="text-gray-500">({{.ValidUntilRelative}})</span></td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
{{if .LatestReminderType}}
|
|
{{if or (eq .LatestReminderType "First Reminder Sent") (eq .LatestReminderType "First Reminder")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200">{{.LatestReminderType}}</span>
|
|
{{else if or (eq .LatestReminderType "Second Reminder Sent") (eq .LatestReminderType "Second Reminder")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-700 border border-yellow-200">{{.LatestReminderType}}</span>
|
|
{{else if or (eq .LatestReminderType "Final Reminder Sent") (eq .LatestReminderType "Final Reminder")}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-red-100 text-red-700 border border-red-200">{{.LatestReminderType}}</span>
|
|
{{else}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-gray-200 text-gray-700 border border-gray-300">{{.LatestReminderType}}</span>
|
|
{{end}}
|
|
{{else}}
|
|
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-gray-200 text-gray-700 border border-gray-300">No Reminder Sent</span>
|
|
{{end}}
|
|
</td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
{{if .LatestReminderSent}}<span class="localdatetime">{{.LatestReminderSent}}</span>{{else}}-{{end}}
|
|
</td>
|
|
<td class="px-4 py-2 border align-middle">
|
|
<form method="POST" action="/go/quotes/send-reminder" style="display:inline;">
|
|
<input type="hidden" name="quote_id" value="{{.ID}}">
|
|
<input type="hidden" name="customer_email" value="{{.CustomerEmail}}">
|
|
<input type="hidden" name="user_email" value="{{.UserEmail}}">
|
|
<input type="hidden" name="enquiry_ref" value="{{.EnquiryRef}}">
|
|
<input type="hidden" name="customer_name" value="{{.CustomerName}}">
|
|
<input type="hidden" name="date_issued" value="{{.DateIssued}}">
|
|
<input type="hidden" name="valid_until" value="{{.ValidUntil}}">
|
|
<div class="inline-flex rounded-md shadow-sm" role="group">
|
|
{{if eq .LatestReminderType "No Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 1, '{{.EnquiryRef}}', '{{.CustomerName}}', 'First Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send First Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else if eq .LatestReminderType "First Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 2, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Second Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Second Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else if eq .LatestReminderType "Second Reminder"}}
|
|
<button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Final Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{else}}
|
|
<button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="w-44 px-3 py-1.5 text-xs font-medium text-white bg-cmcblue rounded-l-md hover:bg-cmcblue/90 focus:z-10">Send Final Reminder</button>
|
|
<button type="button" onclick="toggleDropdown(this)" class="px-2 py-1.5 text-xs font-medium text-white bg-cmcblue border-l border-cmcblue/80 rounded-r-md hover:bg-cmcblue/90 focus:z-10">▼</button>
|
|
{{end}}
|
|
</div>
|
|
<div class="hidden absolute z-10 mt-1 bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5" style="min-width: 150px;">
|
|
<ul class="py-1 text-xs text-gray-700">
|
|
<li><button type="button" onclick="showConfirmModal(this, 1, '{{.EnquiryRef}}', '{{.CustomerName}}', 'First Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send First Reminder</button></li>
|
|
<li><button type="button" onclick="showConfirmModal(this, 2, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Second Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send Second Reminder</button></li>
|
|
<li><button type="button" onclick="showConfirmModal(this, 3, '{{.EnquiryRef}}', '{{.CustomerName}}', 'Final Reminder')" class="block w-full text-left px-4 py-2 hover:bg-gray-100">Send Final Reminder</button></li>
|
|
</ul>
|
|
</div>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr><td colspan="8" class="px-4 py-2 border text-center align-middle">No recently expired quotes.</td></tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Confirmation Modal -->
|
|
<div id="confirmModal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
|
|
<div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
|
|
<div class="mt-3">
|
|
<div class="flex items-center justify-center w-12 h-12 mx-auto bg-cmcblue rounded-full">
|
|
<i class="fas fa-envelope text-white text-xl"></i>
|
|
</div>
|
|
<h3 class="text-lg leading-6 font-medium text-gray-900 text-center mt-4">Send Email Reminder</h3>
|
|
<div class="mt-2 px-7 py-3">
|
|
<p class="text-sm text-gray-600 text-center">
|
|
Send <strong id="modalReminderType"></strong> for enquiry <strong id="modalEnquiryRef"></strong> to <strong id="modalCustomerName"></strong>?
|
|
</p>
|
|
</div>
|
|
<div class="flex gap-3 px-4 py-3">
|
|
<button id="modalCancelBtn" class="flex-1 px-4 py-2 bg-gray-200 text-gray-800 text-sm font-medium rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-300">
|
|
Cancel
|
|
</button>
|
|
<button id="modalConfirmBtn" class="flex-1 px-4 py-2 bg-cmcblue text-white text-sm font-medium rounded-md hover:bg-cmcblue/90 focus:outline-none focus:ring-2 focus:ring-cmcblue focus:ring-offset-2">
|
|
Send Reminder
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentForm = null;
|
|
let currentReminderType = null;
|
|
|
|
function showConfirmModal(button, reminderType, enquiryRef, customerName, reminderTypeName) {
|
|
currentForm = button.closest('form');
|
|
currentReminderType = reminderType;
|
|
|
|
document.getElementById('modalReminderType').textContent = reminderTypeName;
|
|
document.getElementById('modalEnquiryRef').textContent = enquiryRef;
|
|
document.getElementById('modalCustomerName').textContent = customerName;
|
|
document.getElementById('confirmModal').classList.remove('hidden');
|
|
}
|
|
|
|
function hideConfirmModal() {
|
|
document.getElementById('confirmModal').classList.add('hidden');
|
|
currentForm = null;
|
|
currentReminderType = null;
|
|
}
|
|
|
|
document.getElementById('modalCancelBtn').addEventListener('click', hideConfirmModal);
|
|
|
|
document.getElementById('modalConfirmBtn').addEventListener('click', function() {
|
|
if (currentForm && currentReminderType) {
|
|
// Create a hidden input for reminder_type and submit the form
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'reminder_type';
|
|
input.value = currentReminderType;
|
|
currentForm.appendChild(input);
|
|
currentForm.submit();
|
|
}
|
|
hideConfirmModal();
|
|
});
|
|
|
|
// Close modal when clicking outside
|
|
document.getElementById('confirmModal').addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
hideConfirmModal();
|
|
}
|
|
});
|
|
|
|
function toggleDropdown(button) {
|
|
const dropdown = button.parentElement.nextElementSibling;
|
|
const allDropdowns = document.querySelectorAll('form > div.absolute');
|
|
|
|
// Close all other dropdowns
|
|
allDropdowns.forEach(d => {
|
|
if (d !== dropdown) {
|
|
d.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
// Toggle current dropdown
|
|
dropdown.classList.toggle('hidden');
|
|
|
|
// Close dropdown when clicking outside
|
|
if (!dropdown.classList.contains('hidden')) {
|
|
setTimeout(() => {
|
|
document.addEventListener('click', function closeDropdown(e) {
|
|
if (!dropdown.contains(e.target) && !button.contains(e.target)) {
|
|
dropdown.classList.add('hidden');
|
|
document.removeEventListener('click', closeDropdown);
|
|
}
|
|
});
|
|
}, 0);
|
|
}
|
|
}
|
|
|
|
// Convert .localdate to browser local date, .localdatetime to browser local date+time (no offset)
|
|
function formatLocalDate(isoString) {
|
|
if (!isoString) return '';
|
|
var d = new Date(isoString);
|
|
if (isNaN(d.getTime())) return isoString;
|
|
return d.toLocaleDateString();
|
|
}
|
|
function formatLocalDateTime(isoString) {
|
|
if (!isoString) return '';
|
|
var d = new Date(isoString);
|
|
if (isNaN(d.getTime())) return isoString;
|
|
// Show date and time in local time, no offset
|
|
return d.toLocaleString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', year: 'numeric', month: '2-digit', day: '2-digit' });
|
|
}
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.querySelectorAll('.localdate').forEach(function(el) {
|
|
var iso = el.textContent.trim();
|
|
if (iso) {
|
|
el.textContent = formatLocalDate(iso);
|
|
}
|
|
});
|
|
document.querySelectorAll('.localdatetime').forEach(function(el) {
|
|
var iso = el.textContent.trim();
|
|
if (iso) {
|
|
el.textContent = formatLocalDateTime(iso);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{{end}}
|