Created
June 27, 2025 03:32
-
-
Save rahulvramesh/1dfa840db2a6ffdb4284219a901e9301 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Tipaload Per-Load Payment Test</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
max-width: 1200px; | |
margin: 0 auto; | |
padding: 20px; | |
background-color: #f5f5f5; | |
} | |
.container { | |
background: white; | |
padding: 20px; | |
margin: 10px 0; | |
border-radius: 8px; | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
} | |
.section { | |
margin-bottom: 30px; | |
border-left: 4px solid #007bff; | |
padding-left: 15px; | |
} | |
button { | |
background: #007bff; | |
color: white; | |
border: none; | |
padding: 10px 20px; | |
border-radius: 4px; | |
cursor: pointer; | |
margin: 5px; | |
} | |
button:hover { | |
background: #0056b3; | |
} | |
button:disabled { | |
background: #ccc; | |
cursor: not-allowed; | |
} | |
.success { | |
background: #d4edda; | |
color: #155724; | |
padding: 10px; | |
border-radius: 4px; | |
margin: 10px 0; | |
} | |
.error { | |
background: #f8d7da; | |
color: #721c24; | |
padding: 10px; | |
border-radius: 4px; | |
margin: 10px 0; | |
} | |
.info { | |
background: #d1ecf1; | |
color: #0c5460; | |
padding: 10px; | |
border-radius: 4px; | |
margin: 10px 0; | |
} | |
pre { | |
background: #f8f9fa; | |
padding: 10px; | |
border-radius: 4px; | |
overflow-x: auto; | |
max-height: 300px; | |
} | |
input, select, textarea { | |
width: 100%; | |
padding: 8px; | |
margin: 5px 0; | |
border: 1px solid #ddd; | |
border-radius: 4px; | |
box-sizing: border-box; | |
} | |
.form-row { | |
display: flex; | |
gap: 10px; | |
margin: 10px 0; | |
} | |
.form-row > div { | |
flex: 1; | |
} | |
.bid-item { | |
border: 1px solid #ddd; | |
padding: 15px; | |
margin: 10px 0; | |
border-radius: 4px; | |
background: #f9f9f9; | |
} | |
.bid-item.selected { | |
border-color: #007bff; | |
background: #e7f3ff; | |
} | |
.allocation-item { | |
border: 1px solid #ccc; | |
padding: 10px; | |
margin: 5px 0; | |
border-radius: 4px; | |
background: #f0f0f0; | |
} | |
.status-badge { | |
display: inline-block; | |
padding: 3px 8px; | |
border-radius: 12px; | |
font-size: 12px; | |
font-weight: bold; | |
} | |
.status-pending { background: #ffeaa7; color: #2d3436; } | |
.status-approved { background: #55a3ff; color: white; } | |
.status-processing { background: #fdcb6e; color: #2d3436; } | |
.status-paid { background: #00b894; color: white; } | |
.status-failed { background: #e17055; color: white; } | |
.status-completed { background: #6c5ce7; color: white; } | |
.workflow-step { | |
border: 2px solid #ddd; | |
padding: 15px; | |
margin: 10px 0; | |
border-radius: 8px; | |
} | |
.workflow-step.active { | |
border-color: #007bff; | |
background: #e7f3ff; | |
} | |
.workflow-step.completed { | |
border-color: #28a745; | |
background: #d4edda; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>🚛 Tipaload Per-Load Payment System Test</h1> | |
<!-- Authentication Section --> | |
<div class="container section"> | |
<h2>1. Authentication</h2> | |
<div class="form-row"> | |
<div> | |
<label>Username:</label> | |
<input type="text" id="username" value="+618129220033"> | |
</div> | |
<div> | |
<label>Password:</label> | |
<input type="password" id="password" value="tipaload"> | |
</div> | |
</div> | |
<button onclick="login()">Login</button> | |
<div id="authStatus"></div> | |
</div> | |
<!-- Job Management Section --> | |
<div class="container section"> | |
<h2>2. Job Management</h2> | |
<button onclick="createJob()">Create New Job</button> | |
<button onclick="updateJobToBidding()">Update Job to Bidding</button> | |
<button onclick="getJobs()">Refresh Jobs</button> | |
<div id="jobStatus"></div> | |
<div id="jobsList"></div> | |
</div> | |
<!-- Bid Management Section --> | |
<div class="container section"> | |
<h2>3. Bid Management</h2> | |
<div class="form-row"> | |
<div> | |
<label>Job ID for Bidding:</label> | |
<input type="text" id="bidJobId" placeholder="Select a job first"> | |
</div> | |
</div> | |
<button onclick="createBid()">Create Bid</button> | |
<button onclick="getBidsForJob()">Get Bids for Job</button> | |
<div id="bidStatus"></div> | |
<div id="bidsList"></div> | |
</div> | |
<!-- NEW: Bid Approval Section --> | |
<div class="container section"> | |
<h2>4. Bid Approval (New API)</h2> | |
<div class="info"> | |
<strong>Per-Load Payment System:</strong> No payment required during bid approval. Payment will be collected after each load completion. | |
</div> | |
<button onclick="approveBids()">Approve Selected Bids</button> | |
<div id="bidApprovalStatus"></div> | |
</div> | |
<!-- Load Workflow Section --> | |
<div class="container section"> | |
<h2>5. Load Workflow (Per-Load Payment)</h2> | |
<div class="form-row"> | |
<div> | |
<label>Allocation ID:</label> | |
<input type="text" id="workflowAllocationId" placeholder="Select allocation"> | |
</div> | |
</div> | |
<div class="workflow-step" id="step1"> | |
<h4>Step 1: Start Trip</h4> | |
<button onclick="startTrip()">Start Trip</button> | |
</div> | |
<div class="workflow-step" id="step2"> | |
<h4>Step 2: Complete Load & Create Docket</h4> | |
<div class="form-row"> | |
<div> | |
<label>Quantity:</label> | |
<input type="number" id="loadQuantity" value="1" step="0.1"> | |
</div> | |
<div> | |
<label>Signature (Base64):</label> | |
<input type="text" id="signatureBase64" value="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="> | |
</div> | |
</div> | |
<button onclick="createDocket()">Complete Load & Create Docket</button> | |
</div> | |
<div class="workflow-step" id="step3"> | |
<h4>Step 3: Payment (If Required)</h4> | |
<div class="info">Payment will be automatically required if this is not the first load or if payment failed previously.</div> | |
<button onclick="checkCanStartNextLoad()">Check Payment Status</button> | |
<button onclick="retryPayment()" disabled id="retryPaymentBtn">Retry Failed Payment</button> | |
</div> | |
<div class="workflow-step" id="step4"> | |
<h4>Step 4: Next Load</h4> | |
<button onclick="startNextLoad()">Start Next Load</button> | |
</div> | |
<div id="workflowStatus"></div> | |
</div> | |
<!-- System State Section --> | |
<div class="container section"> | |
<h2>6. System State</h2> | |
<button onclick="getAllocations()">Refresh Allocations</button> | |
<button onclick="getPaymentStatus()">Check Payment Status</button> | |
<div id="allocationsStatus"></div> | |
<div id="allocationsList"></div> | |
</div> | |
<!-- Debug Section --> | |
<div class="container section"> | |
<h2>7. Debug & Logs</h2> | |
<button onclick="clearLogs()">Clear Logs</button> | |
<pre id="debugLogs"></pre> | |
</div> | |
<script> | |
// Global state | |
let authToken = ''; | |
let currentJobId = ''; | |
let currentBids = []; | |
let selectedBidIds = []; | |
let currentAllocations = []; | |
let currentAllocationId = ''; | |
const API_BASE = 'http://100.84.162.116:8080'; | |
// Utility functions | |
function log(message) { | |
const timestamp = new Date().toLocaleTimeString(); | |
const logElement = document.getElementById('debugLogs'); | |
logElement.textContent += `[${timestamp}] ${message}\n`; | |
logElement.scrollTop = logElement.scrollHeight; | |
console.log(message); | |
} | |
function clearLogs() { | |
document.getElementById('debugLogs').textContent = ''; | |
} | |
function showStatus(elementId, message, type = 'info') { | |
const element = document.getElementById(elementId); | |
element.innerHTML = `<div class="${type}">${message}</div>`; | |
} | |
function showError(elementId, error) { | |
showStatus(elementId, `Error: ${error.message || error}`, 'error'); | |
log(`ERROR: ${error.message || error}`); | |
} | |
function showSuccess(elementId, message) { | |
showStatus(elementId, message, 'success'); | |
log(`SUCCESS: ${message}`); | |
} | |
// API helper | |
async function apiCall(endpoint, method = 'GET', data = null) { | |
const options = { | |
method, | |
headers: { | |
'Content-Type': 'application/json', | |
} | |
}; | |
if (authToken) { | |
options.headers['Authorization'] = `Bearer ${authToken}`; | |
} | |
if (data) { | |
options.body = JSON.stringify(data); | |
} | |
log(`API Call: ${method} ${endpoint}`); | |
if (data) log(`Request data: ${JSON.stringify(data, null, 2)}`); | |
const response = await fetch(`${API_BASE}${endpoint}`, options); | |
const result = await response.text(); | |
log(`Response status: ${response.status}`); | |
log(`Response: ${result}`); | |
if (!response.ok) { | |
throw new Error(`HTTP ${response.status}: ${result}`); | |
} | |
try { | |
return JSON.parse(result); | |
} catch { | |
return result; | |
} | |
} | |
// Authentication | |
async function login() { | |
try { | |
const username = document.getElementById('username').value; | |
const password = document.getElementById('password').value; | |
const result = await apiCall('/auth/signin', 'POST', { username, password }); | |
// Handle different possible response formats | |
authToken = result.access_token || result.accessToken || result.token || result; | |
if (!authToken) { | |
throw new Error('No access token received from server'); | |
} | |
// Safely handle token display | |
const tokenDisplay = typeof authToken === 'string' && authToken.length > 20 | |
? `${authToken.substring(0, 20)}...` | |
: 'Token received'; | |
showSuccess('authStatus', `Logged in successfully! Token: ${tokenDisplay}`); | |
log(`Auth token set: ${authToken}`); | |
log(`Full login response: ${JSON.stringify(result, null, 2)}`); | |
} catch (error) { | |
showError('authStatus', error); | |
} | |
} | |
// Job Management | |
async function createJob() { | |
try { | |
const jobData = { | |
companyID: "682411097457a8bd66c0cc8f", | |
type: "cart_and_dispose" | |
}; | |
const result = await apiCall('/jobs', 'POST', jobData); | |
currentJobId = result.id; | |
document.getElementById('bidJobId').value = currentJobId; | |
showSuccess('jobStatus', `Job created! ID: ${result.id}`); | |
log(`Job created with ID: ${result.id}`); | |
await getJobs(); | |
} catch (error) { | |
showError('jobStatus', error); | |
} | |
} | |
async function updateJobToBidding() { | |
try { | |
if (!currentJobId) { | |
throw new Error('No job selected. Create a job first.'); | |
} | |
const updateData = { | |
status: "bidding", | |
type: "cart_and_dispose", | |
unitRate: "load", | |
loadNum: 3, | |
vehicleNum: 1, | |
tonneNum: 0, | |
vehicleTypeIDs: ["rigid_truck_3_bogie"], | |
wasteTypeID: "venm", | |
materialTypeIDs: ["clay", "sand"], | |
jobDate: "2025-01-15T09:00:00.000Z", | |
additionalInfo: "Construction waste removal - 3 loads required", | |
mobileNumber: "0412345678", | |
uhfNumber: "CH40", | |
betweenTrucksDuration: 1800, | |
minimumHireDuration: 7200, | |
loadTruckDuration: 2700, | |
minimumTravelDuration: 1800, | |
entrySiteDirection: "front", | |
exitSiteDirection: "front", | |
jobLocations: [{ | |
type: "Point", | |
locationType: "pickup", | |
address: "123 Construction St, Sydney NSW 2000", | |
coordinates: [-33.8688,151.2093] | |
}], | |
startLocation: { | |
type: "Point", | |
locationType: "pickup", | |
address: "123 Construction St, Sydney NSW 2000", | |
coordinates: [-33.8688,151.2093] | |
}, | |
vehicleNums: { | |
rigid_truck_3_bogie: 1 | |
}, | |
suggestedCosts: { | |
rigid_truck_3_bogie: 50000 | |
} | |
}; | |
const result = await apiCall(`/jobs/${currentJobId}`, 'PATCH', updateData); | |
showSuccess('jobStatus', `Job updated to bidding status!`); | |
await getJobs(); | |
} catch (error) { | |
showError('jobStatus', error); | |
} | |
} | |
async function getJobs() { | |
try { | |
const result = await apiCall('/jobs'); | |
const jobsHtml = result.data.map(job => ` | |
<div class="bid-item" onclick="selectJob('${job.id}')" style="cursor: pointer;"> | |
<strong>Job ${job.id}</strong><br> | |
Status: <span class="status-badge status-${job.status}">${job.status}</span><br> | |
Type: ${job.type}<br> | |
${job.loadNum ? `Loads: ${job.loadNum}` : ''}<br> | |
${job.additionalInfo ? `Info: ${job.additionalInfo}` : ''} | |
</div> | |
`).join(''); | |
document.getElementById('jobsList').innerHTML = jobsHtml; | |
showSuccess('jobStatus', `Found ${result.data.length} jobs`); | |
} catch (error) { | |
showError('jobStatus', error); | |
} | |
} | |
function selectJob(jobId) { | |
currentJobId = jobId; | |
document.getElementById('bidJobId').value = jobId; | |
showSuccess('jobStatus', `Selected job: ${jobId}`); | |
// Auto-load bids for this job | |
getBidsForJob(); | |
} | |
// Bid Management | |
async function createBid() { | |
try { | |
const jobId = document.getElementById('bidJobId').value; | |
if (!jobId) { | |
throw new Error('Please enter a job ID'); | |
} | |
const bidData = { | |
companyID: "682411097457a8bd66c0cc8f", | |
jobID: jobId, | |
cost: 150000, | |
costs: { | |
load_service: 50000 | |
}, | |
amountBidded: 3, | |
allocations: [{ | |
jobType: "cart_and_dispose", | |
unitRate: "load", | |
amount: 3, | |
vehicleID: "682775308a74a0be5fcc1597", | |
jobID: jobId, | |
companyID: "682411097457a8bd66c0cc8f", | |
bidID: "" | |
}], | |
comments: "Ready to handle 3 loads of construction waste disposal with rigid truck" | |
}; | |
const result = await apiCall('/bids', 'POST', bidData); | |
showSuccess('bidStatus', `Bid created! ID: ${result.id}`); | |
await getBidsForJob(); | |
} catch (error) { | |
showError('bidStatus', error); | |
} | |
} | |
async function getBidsForJob() { | |
try { | |
const jobId = document.getElementById('bidJobId').value; | |
if (!jobId) { | |
throw new Error('Please enter a job ID'); | |
} | |
const result = await apiCall(`/bids/find_bids_by_job?jobID=${jobId}`); | |
currentBids = result.data; | |
const bidsHtml = currentBids.map(bid => ` | |
<div class="bid-item ${selectedBidIds.includes(bid.id) ? 'selected' : ''}" | |
onclick="toggleBidSelection('${bid.id}')"> | |
<input type="checkbox" ${selectedBidIds.includes(bid.id) ? 'checked' : ''} | |
onchange="toggleBidSelection('${bid.id}')"> | |
<strong>Bid ${bid.id}</strong><br> | |
Status: <span class="status-badge status-${bid.status}">${bid.status}</span><br> | |
Company: ${bid.company.businessName}<br> | |
Amount Bidded: ${bid.amountBidded}<br> | |
Amount Approved: ${bid.amountApproved || 0}<br> | |
Comments: ${bid.comments}<br> | |
<div style="margin-top: 10px;"> | |
<strong>Allocations:</strong> | |
${bid.allocations.map(alloc => ` | |
<div class="allocation-item" onclick="selectAllocation('${alloc.id}', event)"> | |
ID: ${alloc.id}<br> | |
Status: <span class="status-badge status-${alloc.status}">${alloc.status}</span><br> | |
Amount: ${alloc.amount}, Approved: ${alloc.amountApproved || 0}<br> | |
Vehicle: ${alloc.vehicle.rego} | |
${alloc.loadNumber ? `<br>Load #: ${alloc.loadNumber}` : ''} | |
${alloc.loadPaymentStatus ? `<br>Payment: <span class="status-badge status-${alloc.loadPaymentStatus}">${alloc.loadPaymentStatus}</span>` : ''} | |
</div> | |
`).join('')} | |
</div> | |
</div> | |
`).join(''); | |
document.getElementById('bidsList').innerHTML = bidsHtml; | |
showSuccess('bidStatus', `Found ${currentBids.length} bids for job ${jobId}`); | |
} catch (error) { | |
showError('bidStatus', error); | |
} | |
} | |
function toggleBidSelection(bidId) { | |
if (selectedBidIds.includes(bidId)) { | |
selectedBidIds = selectedBidIds.filter(id => id !== bidId); | |
} else { | |
selectedBidIds.push(bidId); | |
} | |
getBidsForJob(); // Refresh to show selection | |
} | |
function selectAllocation(allocationId, event) { | |
event.stopPropagation(); | |
currentAllocationId = allocationId; | |
document.getElementById('workflowAllocationId').value = allocationId; | |
showSuccess('workflowStatus', `Selected allocation: ${allocationId}`); | |
} | |
// NEW: Bid Approval with New API | |
async function approveBids() { | |
try { | |
if (selectedBidIds.length === 0) { | |
throw new Error('Please select at least one bid to approve'); | |
} | |
const approvalData = { | |
bidIds: selectedBidIds | |
}; | |
const result = await apiCall('/bids/approve_by_bid_ids', 'POST', approvalData); | |
showSuccess('bidApprovalStatus', `${result} - Selected ${selectedBidIds.length} bids`); | |
// Refresh bids to show updated status | |
await getBidsForJob(); | |
await getAllocations(); | |
// Clear selection | |
selectedBidIds = []; | |
} catch (error) { | |
showError('bidApprovalStatus', error); | |
} | |
} | |
// Load Workflow | |
async function startTrip() { | |
try { | |
const allocationId = document.getElementById('workflowAllocationId').value; | |
if (!allocationId) { | |
throw new Error('Please select an allocation'); | |
} | |
const result = await apiCall(`/allocations/${allocationId}/start_trip`, 'POST'); | |
showSuccess('workflowStatus', 'Trip started successfully!'); | |
document.getElementById('step1').classList.add('completed'); | |
document.getElementById('step2').classList.add('active'); | |
await getAllocations(); | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
async function createDocket() { | |
try { | |
const allocationId = document.getElementById('workflowAllocationId').value; | |
const quantity = document.getElementById('loadQuantity').value; | |
const signature = document.getElementById('signatureBase64').value; | |
if (!allocationId) { | |
throw new Error('Please select an allocation'); | |
} | |
const docketData = { | |
signedBase64: signature, | |
quantity: quantity, | |
cancelByShipper: false | |
}; | |
const result = await apiCall(`/allocations/${allocationId}/create_docket`, 'POST', docketData); | |
let message = 'Docket created successfully!'; | |
if (result.loadPaymentStatus === 'processing') { | |
message += ` Payment required for Load #${result.loadNumber}. Payment Intent: ${result.loadPaymentIntentId}`; | |
document.getElementById('step3').classList.add('active'); | |
document.getElementById('retryPaymentBtn').disabled = false; | |
} | |
showSuccess('workflowStatus', message); | |
document.getElementById('step2').classList.add('completed'); | |
await getAllocations(); | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
async function checkCanStartNextLoad() { | |
try { | |
const allocationId = document.getElementById('workflowAllocationId').value; | |
if (!allocationId) { | |
throw new Error('Please select an allocation'); | |
} | |
const result = await apiCall(`/allocations/${allocationId}/can-start-next-load`); | |
if (result.canProceed) { | |
showSuccess('workflowStatus', 'Payment complete! Can start next load.'); | |
document.getElementById('step3').classList.add('completed'); | |
document.getElementById('step4').classList.add('active'); | |
} else { | |
showStatus('workflowStatus', `${result.message}. Payment Intent: ${result.paymentIntentId}`, 'info'); | |
document.getElementById('retryPaymentBtn').disabled = false; | |
} | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
async function retryPayment() { | |
try { | |
const allocationId = document.getElementById('workflowAllocationId').value; | |
if (!allocationId) { | |
throw new Error('Please select an allocation'); | |
} | |
const result = await apiCall(`/allocations/${allocationId}/retry-load-payment`, 'POST'); | |
showSuccess('workflowStatus', `Payment retry initiated. New Payment Intent: ${result.intentID}`); | |
// Simulate payment success after a delay (for testing) | |
setTimeout(async () => { | |
await simulatePaymentSuccess(allocationId); | |
}, 3000); | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
async function simulatePaymentSuccess(allocationId) { | |
try { | |
// In a real scenario, this would be handled by Stripe webhooks | |
showSuccess('workflowStatus', '💳 Payment simulation: Payment completed successfully!'); | |
document.getElementById('step3').classList.add('completed'); | |
document.getElementById('step4').classList.add('active'); | |
await getAllocations(); | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
async function startNextLoad() { | |
try { | |
const allocationId = document.getElementById('workflowAllocationId').value; | |
if (!allocationId) { | |
throw new Error('Please select an allocation'); | |
} | |
// Check if we can start next load | |
const canStart = await apiCall(`/allocations/${allocationId}/can-start-next-load`); | |
if (!canStart.canProceed) { | |
throw new Error(canStart.message); | |
} | |
showSuccess('workflowStatus', 'Next load can be started! Reset workflow for next load.'); | |
// Reset workflow steps | |
document.querySelectorAll('.workflow-step').forEach(step => { | |
step.classList.remove('active', 'completed'); | |
}); | |
document.getElementById('step1').classList.add('active'); | |
await getAllocations(); | |
} catch (error) { | |
showError('workflowStatus', error); | |
} | |
} | |
// System State | |
async function getAllocations() { | |
try { | |
const result = await apiCall('/allocations'); | |
currentAllocations = result.data; | |
const allocationsHtml = currentAllocations.map(alloc => ` | |
<div class="allocation-item" onclick="selectAllocation('${alloc.id}', event)"> | |
<strong>Allocation ${alloc.id}</strong><br> | |
Status: <span class="status-badge status-${alloc.status}">${alloc.status}</span><br> | |
Vehicle: ${alloc.vehicle.rego}<br> | |
Amount: ${alloc.amount}, Approved: ${alloc.amountApproved || 0}, Completed: ${alloc.amountCompleted || 0}<br> | |
${alloc.loadNumber ? `Load #: ${alloc.loadNumber}<br>` : ''} | |
${alloc.loadPaymentStatus ? `Payment Status: <span class="status-badge status-${alloc.loadPaymentStatus}">${alloc.loadPaymentStatus}</span><br>` : ''} | |
${alloc.loadPaymentIntentId ? `Payment Intent: ${alloc.loadPaymentIntentId}<br>` : ''} | |
${alloc.tripStartDate ? `Trip Started: ${new Date(alloc.tripStartDate).toLocaleString()}<br>` : ''} | |
${alloc.tripCompleteDate ? `Trip Completed: ${new Date(alloc.tripCompleteDate).toLocaleString()}<br>` : ''} | |
</div> | |
`).join(''); | |
document.getElementById('allocationsList').innerHTML = allocationsHtml; | |
showSuccess('allocationsStatus', `Found ${currentAllocations.length} allocations`); | |
} catch (error) { | |
showError('allocationsStatus', error); | |
} | |
} | |
async function getPaymentStatus() { | |
try { | |
if (!currentAllocationId) { | |
throw new Error('Please select an allocation first'); | |
} | |
const result = await apiCall(`/allocations/${currentAllocationId}`); | |
const paymentInfo = { | |
loadNumber: result.loadNumber, | |
loadPaymentStatus: result.loadPaymentStatus, | |
loadPaymentIntentId: result.loadPaymentIntentId, | |
loadInvoiceId: result.loadInvoiceId | |
}; | |
showSuccess('allocationsStatus', `Payment Status: ${JSON.stringify(paymentInfo, null, 2)}`); | |
} catch (error) { | |
showError('allocationsStatus', error); | |
} | |
} | |
// Initialize | |
document.addEventListener('DOMContentLoaded', function() { | |
log('Frontend test page loaded'); | |
showStatus('authStatus', 'Please login to start testing', 'info'); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment