- Fixed 30 EJS views: changed ../partials/ to ../../partials/ for views in subdirectories
(pages/loads/, pages/shippers/, pages/portal/, pages/marketplace/, pages/payments/, etc.)
- Fixed layouts/main.ejs: corrected malformed EJS tags on lines 11 and 66
(<% ... { <% → <% ... { %>)
118 lines
5.7 KiB
Text
118 lines
5.7 KiB
Text
<%- include('../../partials/portal-header', { activeMenu: 'marketplace' }) %>
|
|
|
|
<div class="page-header">
|
|
<div>
|
|
<h1 class="page-title">🚚 Load Marketplace</h1>
|
|
<p class="page-subtitle">Browse available loads and place your bids</p>
|
|
</div>
|
|
<% if (userRole === 'shipper') { %>
|
|
<a href="/marketplace/post" class="btn btn-primary">+ Post a Load</a>
|
|
<% } %>
|
|
</div>
|
|
|
|
<% if (error) { %>
|
|
<div class="alert alert-error"><%= error %></div>
|
|
<% } %>
|
|
|
|
<!-- Filters -->
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<form method="GET" action="/marketplace" style="display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;">
|
|
<div class="form-group" style="margin:0;min-width:140px;">
|
|
<label class="form-label">From</label>
|
|
<input type="text" name="from_city" class="form-input" value="<%= filters.from_city || '' %>" placeholder="Any city">
|
|
</div>
|
|
<div class="form-group" style="margin:0;min-width:140px;">
|
|
<label class="form-label">To</label>
|
|
<input type="text" name="to_city" class="form-input" value="<%= filters.to_city || '' %>" placeholder="Any city">
|
|
</div>
|
|
<div class="form-group" style="margin:0;min-width:120px;">
|
|
<label class="form-label">Type</label>
|
|
<select name="load_type" class="form-input">
|
|
<option value="">All</option>
|
|
<option value="ftl" <%= filters.load_type === 'ftl' ? 'selected' : '' %>>FTL</option>
|
|
<option value="ptl" <%= filters.load_type === 'ptl' ? 'selected' : '' %>>PTL</option>
|
|
<option value="parcel" <%= filters.load_type === 'parcel' ? 'selected' : '' %>>Parcel</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" style="margin:0;min-width:120px;">
|
|
<label class="form-label">Sort</label>
|
|
<select name="sort" class="form-input">
|
|
<option value="recent" <%= filters.sort === 'recent' ? 'selected' : '' %>>Recent</option>
|
|
<option value="budget" <%= filters.sort === 'budget' ? 'selected' : '' %>>Budget</option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-secondary">Filter</button>
|
|
<a href="/marketplace" class="btn btn-outline">Clear</a>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Load Cards -->
|
|
<% if (!loads || loads.length === 0) { %>
|
|
<div class="empty-state">
|
|
<div class="empty-icon">🚚</div>
|
|
<h3>No loads available</h3>
|
|
<p>Check back soon for new freight opportunities</p>
|
|
<% if (userRole === 'shipper') { %>
|
|
<a href="/marketplace/post" class="btn btn-primary mt-2">Post the First Load</a>
|
|
<% } %>
|
|
</div>
|
|
<% } else { %>
|
|
<div class="loads-grid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px;">
|
|
<% for (const load of loads) { %>
|
|
<div class="load-card" style="background:#fff;border:1px solid #e0ddd5;border-radius:12px;padding:20px;transition:box-shadow 0.2s;">
|
|
<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;">
|
|
<div>
|
|
<div style="font-size:18px;font-weight:700;color:#000080;">
|
|
<%= load.from_city %> → <%= load.to_city %>
|
|
</div>
|
|
<% if (load.via) { %>
|
|
<div style="font-size:12px;color:#666;margin-top:2px;">via <%= load.via %></div>
|
|
<% } %>
|
|
</div>
|
|
<span class="badge" style="background:<%= load.load_type === 'ftl' ? '#e8f5e9' : load.load_type === 'ptl' ? '#fff3e0' : '#e3f2fd' %>;color:<%= load.load_type === 'ftl' ? '#2e7d32' : load.load_type === 'ptl' ? '#e65100' : '#1565c0' %>;">
|
|
<%= load.load_type ? load.load_type.toUpperCase() : 'FTL' %>
|
|
</span>
|
|
</div>
|
|
|
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px;font-size:13px;">
|
|
<div><span style="color:#666;">📅 Pickup:</span> <%= load.pickup_date || 'Flexible' %></div>
|
|
<div><span style="color:#666;">📍 Weight:</span> <%= load.weight_kg ? load.weight_kg + ' kg' : 'N/A' %></div>
|
|
<div><span style="color:#666;">💰 Budget:</span>
|
|
<% if (load.budget_max) { %>
|
|
₹ <%= load.budget_max.toLocaleString('en-IN') %>
|
|
<% if (load.budget_min) { %> - ₹ <%= load.budget_min.toLocaleString('en-IN') %><% } %>
|
|
<% } else { %> Open <% } %>
|
|
</div>
|
|
<div><span style="color:#666;">👤 Shipper:</span> <%= load.shippers?.name || 'N/A' %></div>
|
|
</div>
|
|
|
|
<% if (load.material_type) { %>
|
|
<div style="font-size:12px;color:#666;margin-bottom:8px;">📦 <%= load.material_type %></div>
|
|
<% } %>
|
|
|
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:12px;padding-top:12px;border-top:1px solid #f0ede5;">
|
|
<div style="font-size:11px;color:#999;">
|
|
👁 <%= load.views || 0 %> views · Expires <%= new Date(load.expires_at).toLocaleDateString('en-IN') %>
|
|
</div>
|
|
<a href="/marketplace/load/<%= load.id %>" class="btn btn-sm btn-primary">View & Bid</a>
|
|
</div>
|
|
|
|
<% if (userRole === 'driver') { %>
|
|
<% const myBid = myBids.find(b => b.load_id === load.id); %>
|
|
<% if (myBid) { %>
|
|
<div style="margin-top:8px;padding:8px;background:#f0f4ff;border-radius:6px;font-size:12px;">
|
|
Your bid: <strong>₹ <%= myBid.amount.toLocaleString('en-IN') %></strong>
|
|
<span class="badge badge-<%= myBid.status === 'accepted' ? 'success' : myBid.status === 'rejected' ? 'danger' : 'warning' %>" style="margin-left:4px;">
|
|
<%= myBid.status %>
|
|
</span>
|
|
</div>
|
|
<% } %>
|
|
<% } %>
|
|
</div>
|
|
<% } %>
|
|
</div>
|
|
<% } %>
|
|
|
|
<%- include('../../partials/portal-footer') %>
|