File size: 8,307 Bytes
8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 b44aa74 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 b44aa74 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 8271f95 46505d1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
/**
* Client-Side JavaScript for the International Umbrella Endowment
*
* Handles all user interactions:
* - Opening the submission modal via a floating button.
* - Submitting a new deal and auto-populating the lookup field.
* - Looking up a deal's status and displaying it in a modal.
* - Admin actions for approving/declining deals.
*
* Final Version: Monday, June 16, 2025
*/
document.addEventListener('DOMContentLoaded', () => {
// --- CONFIGURATION ---
const workerUrl = 'https://form-handler-worker.aiagents.workers.dev/'; // Ensure this is your correct worker URL
// --- ELEMENT SELECTIONS ---
// Forms
const submissionForm = document.getElementById('vessel-exchange-form');
const lookupForm = document.getElementById('deal-lookup-form');
const adminForm = document.getElementById('admin-action-form');
// Buttons
const showSubmissionButton = document.getElementById('show-submission-button');
const submitButton = document.getElementById('submit-button');
const adminApproveButton = document.getElementById('admin-approve-button');
const adminDeclineButton = document.getElementById('admin-decline-button');
const submissionModalCloseButton = document.getElementById('submission-modal-close-button');
const dealModalCloseButton = document.getElementById('modal-close-button');
// Modals & Containers
const submissionModal = document.getElementById('submission-modal');
const dealModal = document.getElementById('deal-modal');
const lookupContainer = document.getElementById('lookup-container');
const lookupInput = document.getElementById('lookup-deal-id');
// Status Message Areas
const submissionStatus = document.getElementById('status-message');
const adminStatus = document.getElementById('admin-status-message');
// --- EVENT LISTENERS ---
// Floating button to show the submission form modal
if (showSubmissionButton) {
showSubmissionButton.addEventListener('click', () => {
submissionModal.classList.remove('hidden');
});
}
// Close the submission form modal
if (submissionModal) {
submissionModalCloseButton.addEventListener('click', () => closeModal(submissionModal));
submissionModal.addEventListener('click', (event) => {
if (event.target === submissionModal) closeModal(submissionModal);
});
}
// Close the deal info modal
if (dealModal) {
dealModalCloseButton.addEventListener('click', () => closeModal(dealModal));
dealModal.addEventListener('click', (event) => {
if (event.target === dealModal) closeModal(dealModal);
});
}
// Handle New Deal Submissions
if (submissionForm) {
submissionForm.addEventListener('submit', handleFormSubmit);
}
// Handle Deal Status Lookups
if (lookupForm) {
lookupForm.addEventListener('submit', handleLookupSubmit);
}
// Handle Admin Actions
if (adminForm) {
adminApproveButton.addEventListener('click', () => handleAdminClick('approve'));
adminDeclineButton.addEventListener('click', () => handleAdminClick('decline'));
}
// --- HANDLER FUNCTIONS ---
/**
* Handles the main form submission to create a new deal.
*/
async function handleFormSubmit(event) {
event.preventDefault(); // Stop page reload
showStatus(submissionStatus, 'Submitting...');
submitButton.disabled = true;
try {
const formData = new FormData(submissionForm);
const response = await fetch(workerUrl, { method: 'POST', body: formData });
const resultText = await response.text();
if (!response.ok) {
throw new Error(resultText); // Use the error text from the worker
}
const result = JSON.parse(resultText);
const dealId = result.deal_id;
// --- Auto-populate and Highlight Logic ---
showSuccess(submissionStatus, `Success! Deal ID copied below.`);
lookupInput.value = dealId; // Auto-populate the lookup field
lookupContainer.classList.add('highlight');
setTimeout(() => {
lookupContainer.classList.remove('highlight');
}, 2000);
submissionForm.reset();
// Close the modal after a delay
setTimeout(() => closeModal(submissionModal), 2500);
} catch (error) {
showError(submissionStatus, error.message);
} finally {
submitButton.disabled = false;
}
}
/**
* Handles the lookup form submission to check a deal's status.
*/
async function handleLookupSubmit(event) {
event.preventDefault();
if (!lookupInput.value) return;
try {
const response = await fetch(`${workerUrl}?deal_id=${lookupInput.value}`, { method: 'GET' });
const result = await response.json();
if (!response.ok) throw new Error(result.error || 'Failed to fetch deal.');
openDealInfoModal(result);
} catch (error) {
alert(`Error: ${error.message}`);
}
}
/**
* Handles clicks on the admin approve/decline buttons.
*/
async function handleAdminClick(action) {
const dealId = document.getElementById('admin-deal-id').value;
if (!dealId) {
showError(adminStatus, 'Please enter a Deal ID.');
return;
}
showStatus(adminStatus, 'Processing action...');
const formData = new FormData();
formData.append('action', action);
formData.append('deal_id', dealId);
try {
const response = await fetch(workerUrl, { method: 'POST', body: formData });
const result = await response.json();
if (!response.ok) throw new Error(result.error || `Server responded with status ${response.status}`);
showSuccess(adminStatus, result.message);
} catch (error) {
showError(adminStatus, error.message);
}
}
// --- UI HELPER FUNCTIONS ---
/**
* Populates and opens the deal information modal.
*/
function openDealInfoModal(dealData) {
document.getElementById('modal-deal-id').textContent = dealData.deal_id;
document.getElementById('modal-owner-name').textContent = dealData.owner_name;
document.getElementById('modal-contact-email').textContent = dealData.contact_email;
document.getElementById('modal-contact-phone').textContent = dealData.contact_phone || 'N/A';
document.getElementById('modal-year-built').textContent = dealData.year_built || 'N/A';
document.getElementById('modal-gross-tonnage').textContent = dealData.gross_tonnage || 'N/A';
document.getElementById('modal-token-amount').textContent = dealData.token_amount;
document.getElementById('modal-vessel-description').textContent = dealData.vessel_description || 'No description provided.';
const statusBadge = document.getElementById('modal-status-badge');
statusBadge.textContent = dealData.status;
statusBadge.className = `badge ${dealData.status}`;
dealModal.classList.remove('hidden');
}
/**
* Hides a modal element.
*/
function closeModal(modalElement) {
modalElement.classList.add('hidden');
}
/**
* Displays a generic status message.
*/
function showStatus(element, message) {
element.className = 'status';
element.innerHTML = message;
element.style.display = 'block';
}
/**
* Displays a success message.
*/
function showSuccess(element, message) {
element.className = 'status success';
element.innerHTML = `<strong>${message}</strong>`;
element.style.display = 'block';
}
/**
* Displays an error message.
*/
function showError(element, message) {
element.className = 'status error';
element.innerHTML = `<strong>Error:</strong> ${message}`;
element.style.display = 'block';
}
}); |