freightdesk/webapp/src/routes/location.js
FreightDesk 59d93d5281
Some checks are pending
FreightDesk CI/CD / Lint & Test (push) Waiting to run
FreightDesk CI/CD / Build Docker Image (push) Blocked by required conditions
FreightDesk CI/CD / Deploy to Coolify (push) Blocked by required conditions
[OWL] Driver location tracking + bulk WhatsApp parser + deployment docs
Location Tracking:
- POST /api/location/update — driver GPS update
- GET /api/location/:load_id — get driver location for load
- Migration 007: vehicle_locations table with spatial indexes

Bulk WhatsApp Parser:
- UI for pasting multiple messages at once
- Batch parse via /api/parse-whatsapp
- Review parsed results with confidence scores
- Select and save all valid loads to database
- One-click import from WhatsApp to loads

Deployment:
- DEPLOYMENT.md: full deployment guide
- Environment configuration
- Docker + Docker Compose setup
- Coolify deployment steps
- Post-deployment checklist
- Troubleshooting guide
- Architecture diagram
2026-06-08 01:59:05 +00:00

68 lines
2 KiB
JavaScript

// POST /api/location/update — driver updates their GPS location
// GET /api/location/:load_id — get driver location for a load (shipper views this)
const express = require('express');
const router = express.Router();
const supabase = require('../services/supabase');
const { asyncHandler } = require('../middleware/security');
function requirePortalAuth(req, res, next) {
if (!req.session.portalUser) {
return res.status(401).json({ error: 'Authentication required' });
}
next();
}
// POST /api/location/update
router.post('/update', requirePortalAuth, asyncHandler(async (req, res) => {
const { lat, lng, accuracy, heading, speed } = req.body;
const driverId = req.session.portalUser?.driver_id;
if (!lat || !lng) {
return res.status(400).json({ error: 'lat and lng are required' });
}
if (!driverId) {
return res.status(400).json({ error: 'Driver profile not found' });
}
await supabase.from('vehicles').update({
current_lat: parseFloat(lat),
current_lng: parseFloat(lng),
updated_at: new Date().toISOString(),
}).eq('id', driverId);
// Also store in location history
await supabase.from('vehicle_locations').insert({
vehicle_id: driverId,
lat: parseFloat(lat),
lng: parseFloat(lng),
accuracy: accuracy || null,
heading: heading || null,
speed: speed || null,
});
res.json({ success: true });
}));
// GET /api/location/:load_id — get assigned driver's location
router.get('/:load_id', requirePortalAuth, asyncHandler(async (req, res) => {
const { data: load } = await supabase
.from('loads')
.select('accepted_bid_id, vehicles(current_lat, current_lng, driver_name, updated_at)')
.eq('id', req.params.load_id)
.single();
if (!load?.vehicles) {
return res.json({ error: 'No driver assigned or location not available' });
}
res.json({
driver_name: load.vehicles.driver_name,
lat: load.vehicles.current_lat,
lng: load.vehicles.current_lng,
last_updated: load.vehicles.updated_at,
});
}));
module.exports = router;