[OWL] Critical fixes: registration routes, duplicate payments mount, missing views
Critical Fixes: - Registration routes: changed /shipper → /register/shipper, /driver → /register/driver (was causing 404s — landing page linked to /register/* but routes were /shipper and /driver) - Registration form actions: fixed to match /register/shipper and /register/driver - Removed duplicate /payments route mount in server.js (payments.js is escrow, mounted at /escrow) - Supabase client: now uses service key (falls back to anon key) - Created missing pages/errors/403.ejs view Documentation: - README.md: full project documentation - .env.example: environment variable template - .dockerignore: exclude dev files from Docker image
This commit is contained in:
parent
9b5e568e72
commit
ec6ec234ac
7 changed files with 215 additions and 11 deletions
161
README.md
Normal file
161
README.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# 🚛 FreightDesk
|
||||
|
||||
**India's Freight Marketplace Platform** — Connect shippers with truck drivers, manage loads, track payments through escrow, and grow your freight business.
|
||||
|
||||

|
||||

|
||||
|
||||
## Features
|
||||
|
||||
### For Everyone
|
||||
- 🌐 Public landing page with registration
|
||||
- 🔐 Secure authentication (admin + portal users)
|
||||
- 📱 Mobile-responsive design
|
||||
- 🌙 Dark mode
|
||||
|
||||
### Admin Panel
|
||||
- 📊 Dashboard with Recharts visualizations
|
||||
- 🚛 Load management (CRUD + WhatsApp parser)
|
||||
- 🏢 Shipper & vehicle management
|
||||
- 💳 Payment tracking & commission calculator
|
||||
- 📋 Reports & audit logs
|
||||
- 🧾 Invoice PDF generation
|
||||
- 🛡️ User moderation (verify, dispute resolution)
|
||||
- 📈 Prometheus metrics + Pino logging
|
||||
|
||||
### Shipper Portal
|
||||
- 📦 Post loads to marketplace
|
||||
- 💰 Deposit funds to escrow
|
||||
- 📊 View bids, accept/counter-offer
|
||||
- 💸 Release payment after delivery
|
||||
- 📝 Rate drivers
|
||||
- 🔔 Real-time notifications
|
||||
|
||||
### Driver Portal
|
||||
- 🔍 Browse & filter available loads
|
||||
- 💵 Place bids on loads
|
||||
- 📍 GPS location tracking
|
||||
- 📊 Earnings dashboard
|
||||
- 💸 Request payouts (UPI/Bank)
|
||||
- ⭐ View ratings & reviews
|
||||
|
||||
### Marketplace
|
||||
- 🏪 Browse loads with filters (city, type, budget)
|
||||
- 💲 Bidding system with negotiation
|
||||
- 🔔 Real-time notifications
|
||||
- 📊 Bid comparison with driver profiles
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|-----------|
|
||||
| Backend | Node.js + Express |
|
||||
| Frontend | EJS server-rendered + React (Recharts via CDN) |
|
||||
| Database | Supabase PostgreSQL |
|
||||
| Auth | bcrypt + express-session |
|
||||
| Security | Helmet + CSRF + rate limiting |
|
||||
| Logging | Pino structured logging |
|
||||
| Metrics | Prometheus |
|
||||
| Testing | Jest + Supertest |
|
||||
| Deployment | Docker + Coolify + Forgejo CI/CD |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Node.js 20+
|
||||
- Supabase project (self-hosted or cloud)
|
||||
|
||||
### 1. Clone & Install
|
||||
```bash
|
||||
git clone http://forgejo-vil3xyowqk0qsh4hiqy77e3h.187.127.178.110.sslip.io/iamcoolvivek007/freightdesk.git
|
||||
cd freightdesk/webapp
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Configure
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your Supabase credentials
|
||||
```
|
||||
|
||||
### 3. Run Migrations
|
||||
Run `supabase/migrations/001_initial_schema.sql` through `007_location_tracking.sql` in your Supabase SQL editor.
|
||||
|
||||
### 4. Create Admin Account
|
||||
Visit `http://localhost:3000/setup`
|
||||
|
||||
### 5. Seed Demo Data (optional)
|
||||
```bash
|
||||
node scripts/seed-demo.js
|
||||
```
|
||||
|
||||
### 6. Start
|
||||
```bash
|
||||
npm run dev # Development with nodemon
|
||||
npm start # Production
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
cd webapp
|
||||
docker build -t freightdesk .
|
||||
docker run -p 3000:3000 --env-file .env freightdesk
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
freightdesk/
|
||||
├── .github/workflows/deploy.yml # CI/CD pipeline
|
||||
├── DEPLOYMENT.md # Full deployment guide
|
||||
├── supabase/migrations/ # 7 migrations (001-007)
|
||||
└── webapp/
|
||||
├── Dockerfile
|
||||
├── package.json
|
||||
├── scripts/seed-demo.js # Demo data seeder
|
||||
└── src/
|
||||
├── server.js # Express app entry
|
||||
├── config/env.js # Environment config
|
||||
├── middleware/ # CSRF, auth, security
|
||||
├── routes/ # 14 route files
|
||||
│ ├── dashboard.js
|
||||
│ ├── loads.js
|
||||
│ ├── payments.js # Escrow payments
|
||||
│ ├── marketplace.js # Bidding system
|
||||
│ ├── admin-moderation.js
|
||||
│ └── ...
|
||||
├── services/ # Business logic
|
||||
│ ├── supabase.js
|
||||
│ ├── parser.js # WhatsApp parser
|
||||
│ ├── invoice-pdf.js
|
||||
│ ├── logger.js
|
||||
│ └── metrics.js
|
||||
├── views/pages/ # EJS templates
|
||||
│ ├── public/ # Landing, register
|
||||
│ ├── marketplace/ # Browse, post, bid
|
||||
│ ├── portal/ # Shipper/driver portal
|
||||
│ ├── payments/ # Deposit, payout
|
||||
│ └── admin/ # Moderation
|
||||
├── public/ # Static assets
|
||||
│ └── css/style.css # Govt-app aesthetic
|
||||
└── lib/ # India locale helpers
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
7 migrations totaling ~20 tables:
|
||||
|
||||
| Migration | Tables Added |
|
||||
|-----------|-------------|
|
||||
| 001 | loads, shippers, vehicles, payments, portal_users |
|
||||
| 002 | parser config, city list |
|
||||
| 003 | soft-delete columns |
|
||||
| 004 | audit_logs |
|
||||
| 005 | bids, negotiations, ratings, notifications, load_views |
|
||||
| 006 | escrow_accounts, escrow_transactions, payout_requests, disputes, platform_config |
|
||||
| 007 | vehicle_locations, GPS columns on vehicles |
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
11
webapp/.dockerignore
Normal file
11
webapp/.dockerignore
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.env
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
DEPLOYMENT.md
|
||||
.DS_Store
|
||||
*.md
|
||||
docker-compose*.yml
|
||||
.github
|
||||
|
|
@ -1,9 +1,25 @@
|
|||
# FreightDesk — Environment Variables
|
||||
# Copy to .env and fill in values
|
||||
|
||||
# Server
|
||||
NODE_ENV=development
|
||||
PORT=3000
|
||||
APP_URL=http://localhost:3000
|
||||
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_KEY=your-anon-key
|
||||
SUPABASE_SERVICE_KEY=your-service-role-key
|
||||
|
||||
# Session secret (generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
|
||||
SESSION_SECRET=change-this-to-a-random-string-in-production
|
||||
|
||||
# Supabase
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_SERVICE_KEY=your-service-role-key
|
||||
SUPABASE_KEY=your-anon-key
|
||||
|
||||
# Payment Gateway (production — Razorpay)
|
||||
RAZORPAY_KEY_ID=
|
||||
RAZORPAY_KEY_SECRET=
|
||||
|
||||
# Email (optional)
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=
|
||||
SMTP_PASS=
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const { asyncHandler } = require('../middleware/security');
|
|||
// ============================================================
|
||||
|
||||
// GET /register/shipper
|
||||
router.get('/shipper', (req, res) => {
|
||||
router.get('/register/shipper', (req, res) => {
|
||||
if (req.session.portalUser) {
|
||||
return res.redirect('/portal/dashboard');
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ router.get('/shipper', (req, res) => {
|
|||
});
|
||||
|
||||
// POST /register/shipper
|
||||
router.post('/shipper', asyncHandler(async (req, res) => {
|
||||
router.post('/register/shipper', asyncHandler(async (req, res) => {
|
||||
const { name, email, phone, password, confirm_password, company_name, gst_number, city, state, pincode } = req.body;
|
||||
|
||||
// Validation
|
||||
|
|
@ -104,7 +104,7 @@ router.post('/shipper', asyncHandler(async (req, res) => {
|
|||
-- ============================================================
|
||||
|
||||
// GET /register/driver
|
||||
router.get('/driver', (req, res) => {
|
||||
router.get('/register/driver', (req, res) => {
|
||||
if (req.session.portalUser) {
|
||||
return res.redirect('/portal/dashboard');
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ router.get('/driver', (req, res) => {
|
|||
});
|
||||
|
||||
// POST /register/driver
|
||||
router.post('/driver', asyncHandler(async (req, res) => {
|
||||
router.post('/register/driver', asyncHandler(async (req, res) => {
|
||||
const { name, email, phone, password, confirm_password, vehicle_number, vehicle_type, capacity_tons, driver_license, current_city } = req.body;
|
||||
|
||||
// Validation
|
||||
|
|
|
|||
|
|
@ -203,7 +203,6 @@ app.use('/setup', require('./routes/setup'));
|
|||
app.use('/loads', require('./routes/loads'));
|
||||
app.use('/shippers', require('./routes/shippers'));
|
||||
app.use('/vehicles', require('./routes/vehicles'));
|
||||
app.use('/payments', require('./routes/payments'));
|
||||
app.use('/reports', require('./routes/reports'));
|
||||
app.use('/audit-logs', require('./routes/audit'));
|
||||
app.use('/portal', require('./routes/portal'));
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ const { createClient } = require('@supabase/supabase-js');
|
|||
const config = require('../config/env');
|
||||
|
||||
const supabaseUrl = config.supabase.url;
|
||||
const supabaseKey = config.supabase.key;
|
||||
const supabaseKey = config.supabase.serviceKey || config.supabase.key;
|
||||
|
||||
if (!supabaseUrl || !supabaseKey) {
|
||||
console.error('Missing SUPABASE_URL or SUPABASE_KEY. Check .env file.');
|
||||
console.error('Missing SUPABASE_URL or SUPABASE_SERVICE_KEY. Check .env file.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
|
|
|||
17
webapp/src/views/pages/errors/403.ejs
Normal file
17
webapp/src/views/pages/errors/403.ejs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Access Denied — FreightDesk</title>
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
</head>
|
||||
<body style="display:flex;align-items:center;justify-content:center;min-height:100vh;background:#f8f9fa;">
|
||||
<div style="text-align:center;padding:48px;">
|
||||
<div style="font-size:72px;margin-bottom:16px;">🔒</div>
|
||||
<h1 style="font-size:28px;color:#000080;margin-bottom:8px;">Access Denied</h1>
|
||||
<p style="color:#666;margin-bottom:24px;"><%= typeof message !== 'undefined' ? message : 'You do not have permission to access this page.' %></p>
|
||||
<a href="/" class="btn btn-primary">Go to Dashboard</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue