Reorganize frontend into public/ with pages/ and js/ subdirectories

- public/index.html — landing page at root
- public/pages/ — all feature pages (regulations, loadboard, etc.)
- public/js/ — api.js, nav.js, mock data files
- All links updated to absolute paths (/pages/, /js/)
- Express static path updated to serve from public/
- Seed script path updated for new mock data location
- README updated with new project structure and setup guide
- Added .env.example template

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Daniel Kovalevich
2026-03-30 15:52:56 -04:00
parent f917fb8014
commit 93efb907ff
20 changed files with 281 additions and 109 deletions

227
README.md
View File

@@ -5,46 +5,211 @@ A proof-of-concept web application for truck drivers, carriers, and escort/pilot
> ⚠️ **All regulation data shown is SIMULATED for demonstration purposes and must be verified with actual state DOT regulations before any real-world use.**
## How to View
1. Open `index.html` in any modern web browser (Chrome, Edge, Firefox)
2. An internet connection is required (for map tiles and the CSS library)
3. Navigate between pages using the top navigation bar
## Prerequisites
- [Node.js](https://nodejs.org/) v18+ (LTS recommended)
- [PostgreSQL](https://www.postgresql.org/) 14+
- npm (comes with Node.js)
## Getting Started
### 1. Clone the repo
```bash
git clone <repo-url>
cd pilot-poc
```
### 2. Set up PostgreSQL
Create a database called `pilotedge`:
```bash
psql -U postgres -c "CREATE DATABASE pilotedge;"
```
### 3. Configure environment
Copy the example env file and update if needed:
```bash
cd server
cp .env.example .env
```
The default `.env` expects:
```
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/pilotedge?schema=public"
JWT_SECRET="change-this-to-a-long-random-string"
PORT=3000
```
Update the `DATABASE_URL` if your PostgreSQL password or port is different.
### 4. Install dependencies
```bash
cd server
npm install
```
### 5. Run database migrations
```bash
npm run db:migrate
```
This creates all 15 tables in your PostgreSQL database via Prisma.
### 6. Seed the database
```bash
npm run db:seed
```
Populates the database with demonstration data (51 states with regulations, contacts, equipment requirements, truck stops, bridges, weigh stations, alerts, and seasonal restrictions).
### 7. Start the server
```bash
npm run dev
```
Open [http://localhost:3000](http://localhost:3000) in your browser.
## Available Scripts
Run these from the `server/` directory:
| Command | Description |
|---------|-------------|
| `npm run dev` | Start server with auto-reload on file changes |
| `npm start` | Start server (production) |
| `npm run db:migrate` | Apply database migrations |
| `npm run db:seed` | Seed database with demo data |
| `npm run db:reset` | Drop all data and re-run migrations |
| `npm run db:studio` | Open Prisma Studio (visual database browser) |
## Pages
### Core
| Page | File | Description |
|------|------|-------------|
| **Home** | `index.html` | Platform overview and all feature modules |
| **Regulations Map** | `regulations.html` | Interactive US map + equipment requirements by state |
| **Request Service** | `order.html` | Escort vehicle service request form |
| Page | URL | Description |
|------|-----|-------------|
| **Home** | `/` | Platform overview and all feature modules |
| **Regulations Map** | `/pages/regulations.html` | Interactive US map + equipment requirements by state |
| **Request Service** | `/pages/order.html` | Escort vehicle service request form |
### Road Intelligence
| Page | File | Description |
|------|------|-------------|
| **Truck Stops** | `truckstops.html` | Oversize-friendly parking with user comments |
| **Bridge Clearances** | `bridges.html` | Height/width/weight restrictions for bridges |
| **Weigh Stations** | `weighstations.html` | Crowd-sourced open/closed status |
| **Route & Weather** | `alerts.html` | Construction, closures, and wind/weather alerts |
| Page | URL | Description |
|------|-----|-------------|
| **Truck Stops** | `/pages/truckstops.html` | Oversize-friendly parking with user comments |
| **Bridge Clearances** | `/pages/bridges.html` | Height/width/weight restrictions for bridges |
| **Weigh Stations** | `/pages/weighstations.html` | Crowd-sourced open/closed status |
| **Route & Weather** | `/pages/alerts.html` | Construction, closures, and wind/weather alerts |
### Services & Resources
| Page | File | Description |
|------|------|-------------|
| **Load Board** | `loadboard.html` | Oversize load listings needing escort services |
| **Find Escorts** | `locator.html` | Map of available escort vehicle operators |
| **DOT Contacts** | `contacts.html` | State permit office phone/email directory |
| **Seasonal Calendar** | `calendar.html` | Seasonal restrictions and closure calendar |
| **Document Vault** | `documents.html` | Store permits, insurance, certifications |
| Page | URL | Description |
|------|-----|-------------|
| **Load Board** | `/pages/loadboard.html` | Oversize load listings needing escort services |
| **Find Escorts** | `/pages/locator.html` | Map of available escort vehicle operators |
| **DOT Contacts** | `/pages/contacts.html` | State permit office phone/email directory |
| **Seasonal Calendar** | `/pages/calendar.html` | Seasonal restrictions and closure calendar |
| **Document Vault** | `/pages/documents.html` | Store permits, insurance, certifications |
## Tech Stack (POC)
- HTML / CSS / JavaScript (no build step required)
- [Tailwind CSS](https://tailwindcss.com/) via Play CDN
- [Leaflet.js](https://leafletjs.com/) for interactive maps via CDN
- Mock data (hardcoded — not yet connected to APIs or databases)
## API Endpoints
All endpoints are prefixed with `/api`. Public endpoints require no authentication; protected endpoints require a `Bearer` token in the `Authorization` header.
### Public
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/health` | Health check |
| GET | `/api/regulations` | All states with regulations |
| GET | `/api/regulations/:stateAbbr` | Single state with equipment requirements |
| GET | `/api/contacts` | All state DOT contacts |
| GET | `/api/calendar` | All seasonal restrictions |
| GET | `/api/truckstops?lat=&lng=&radius=` | Truck stops with optional geospatial filter |
| GET | `/api/bridges?maxHeight=&maxWidth=` | Bridges with optional conflict detection |
| GET | `/api/weighstations` | Weigh stations with status |
| GET | `/api/alerts?state=&type=` | Active route and weather alerts |
| GET | `/api/loads` | Load board listings |
| GET | `/api/escorts` | Escort operator profiles |
### Auth
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/auth/register` | Create account (email, password, name, role) |
| POST | `/api/auth/login` | Login and receive JWT token |
| GET | `/api/auth/me` | Get current user profile (protected) |
### Protected (requires auth)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/loads` | Post a new load |
| PUT | `/api/loads/:id` | Update own load |
| DELETE | `/api/loads/:id` | Delete own load |
| POST | `/api/escorts/profile` | Create/update escort profile |
| POST | `/api/orders` | Submit escort service request |
| GET | `/api/orders` | List own orders |
| POST/GET/DELETE | `/api/documents` | Upload, list, download, delete documents |
| POST | `/api/contributions` | Submit user contributions |
## Tech Stack
- **Frontend:** HTML, CSS, JavaScript (no build step)
- **CSS:** [Tailwind CSS](https://tailwindcss.com/) via Play CDN
- **Maps:** [Leaflet.js](https://leafletjs.com/) via CDN
- **Server:** [Express.js](https://expressjs.com/) (Node.js)
- **Database:** [PostgreSQL](https://www.postgresql.org/) 16
- **ORM:** [Prisma](https://www.prisma.io/) with auto-migrations
- **Auth:** JWT + bcrypt
## Project Structure
```
pilot-poc/
├── public/ # Frontend (served by Express)
│ ├── index.html # Landing page
│ ├── pages/
│ │ ├── regulations.html # State regulations map
│ │ ├── order.html # Escort service request form
│ │ ├── loadboard.html # Oversize load board
│ │ ├── locator.html # Escort operator locator
│ │ ├── truckstops.html # Oversize-friendly truck stops
│ │ ├── bridges.html # Bridge clearance database
│ │ ├── weighstations.html # Weigh station status
│ │ ├── alerts.html # Route & weather alerts
│ │ ├── contacts.html # State DOT contact directory
│ │ ├── calendar.html # Seasonal restriction calendar
│ │ └── documents.html # Document vault
│ └── js/
│ ├── api.js # Frontend API client
│ ├── nav.js # Shared navigation component
│ ├── mock-data.js # Original mock data (preserved)
│ └── mock-data-extended.js
├── server/
│ ├── package.json
│ ├── .env # Environment config (not in git)
│ ├── .env.example # Template for .env
│ ├── prisma/
│ │ └── schema.prisma # Database schema (15 models)
│ └── src/
│ ├── index.js # Express app entry point
│ ├── config/db.js # Prisma client
│ ├── middleware/
│ │ ├── auth.js # JWT verification
│ │ └── errorHandler.js
│ ├── routes/ # 13 API route files
│ └── seeds/seed.js # Database seeder
├── PLAN.md # Product plan and module breakdown
└── README.md
## Next Steps
- Replace mock data with real, verified state regulation data
- Connect to backend APIs and a database
- Add user accounts, authentication, and profiles
- Replace demo data with real, verified state regulation data
- Integrate payment processing for subscriptions
- Deploy to a web hosting service (Vercel, Netlify, or similar)
- Add real-time weigh station status updates (WebSockets)
- File storage service (S3) for document vault
- Email notifications for regulatory change alerts
- Deploy to a Cloud VPS (DigitalOcean, Linode, etc.)

View File

@@ -42,10 +42,10 @@
everything truck drivers and carriers need, all in one place.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="regulations.html" class="bg-amber-500 hover:bg-amber-600 text-slate-900 font-bold px-8 py-4 rounded-xl text-lg transition-colors shadow-lg hover:shadow-xl">
<a href="/pages/regulations.html" class="bg-amber-500 hover:bg-amber-600 text-slate-900 font-bold px-8 py-4 rounded-xl text-lg transition-colors shadow-lg hover:shadow-xl">
Explore Regulations Map
</a>
<a href="order.html" class="bg-white/10 hover:bg-white/20 text-white font-bold px-8 py-4 rounded-xl text-lg transition-colors border border-white/20">
<a href="/pages/order.html" class="bg-white/10 hover:bg-white/20 text-white font-bold px-8 py-4 rounded-xl text-lg transition-colors border border-white/20">
Request Escort Service
</a>
</div>
@@ -84,19 +84,19 @@
<!-- Row 1: Core Features -->
<h3 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Core Tools</h3>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-10">
<a href="regulations.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/regulations.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-amber-100 rounded-xl flex items-center justify-center text-xl mb-4">🗺️</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">State Regulations Map</h3>
<p class="text-slate-600 text-sm mb-3">Permit thresholds, escort requirements, and equipment rules for all 50 states.</p>
<span class="text-amber-600 font-semibold text-sm">Explore Map →</span>
</a>
<a href="order.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/order.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-amber-100 rounded-xl flex items-center justify-center text-xl mb-4">📋</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Request Escort Service</h3>
<p class="text-slate-600 text-sm mb-3">Submit your load details and route — we'll match you with available escort vehicles.</p>
<span class="text-amber-600 font-semibold text-sm">Request Service →</span>
</a>
<a href="loadboard.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/loadboard.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-amber-100 rounded-xl flex items-center justify-center text-xl mb-4">📦</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Oversize Load Board</h3>
<p class="text-slate-600 text-sm mb-3">Browse and post loads that need escorts. Connect carriers with pilot vehicles.</p>
@@ -107,25 +107,25 @@
<!-- Row 2: Road Intelligence -->
<h3 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Road Intelligence</h3>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6 mb-10">
<a href="truckstops.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/truckstops.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center text-xl mb-4"></div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Truck Stops & Parking</h3>
<p class="text-slate-600 text-sm mb-3">Oversize-friendly locations with entrance dimensions and user reviews.</p>
<span class="text-amber-600 font-semibold text-sm">Find Stops →</span>
</a>
<a href="bridges.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/bridges.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center text-xl mb-4">🌉</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Bridge Clearances</h3>
<p class="text-slate-600 text-sm mb-3">Height, width, and weight restrictions for bridges and overpasses.</p>
<span class="text-amber-600 font-semibold text-sm">Check Clearances →</span>
</a>
<a href="weighstations.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/weighstations.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center text-xl mb-4">⚖️</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Weigh Stations</h3>
<p class="text-slate-600 text-sm mb-3">Live crowd-sourced open/closed status and inspection info.</p>
<span class="text-amber-600 font-semibold text-sm">View Stations →</span>
</a>
<a href="alerts.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/alerts.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-orange-100 rounded-xl flex items-center justify-center text-xl mb-4">⚠️</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Route & Weather Alerts</h3>
<p class="text-slate-600 text-sm mb-3">Construction, closures, and wind conditions on your route.</p>
@@ -136,25 +136,25 @@
<!-- Row 3: Resources & Services -->
<h3 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Resources & Services</h3>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6 mb-10">
<a href="locator.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/locator.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-amber-100 rounded-xl flex items-center justify-center text-xl mb-4">📍</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Find Escorts</h3>
<p class="text-slate-600 text-sm mb-3">Locate pilot/escort vehicles near your load departure point.</p>
<span class="text-amber-600 font-semibold text-sm">Find Escorts →</span>
</a>
<a href="contacts.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/contacts.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center text-xl mb-4">📞</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">DOT Contacts</h3>
<p class="text-slate-600 text-sm mb-3">Permit office phone numbers and emails for every state.</p>
<span class="text-amber-600 font-semibold text-sm">View Directory →</span>
</a>
<a href="calendar.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/calendar.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-indigo-100 rounded-xl flex items-center justify-center text-xl mb-4">📅</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Seasonal Calendar</h3>
<p class="text-slate-600 text-sm mb-3">Weight restrictions, closures, and blackout periods by state and season.</p>
<span class="text-amber-600 font-semibold text-sm">View Calendar →</span>
</a>
<a href="documents.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<a href="/pages/documents.html" class="bg-white rounded-2xl p-7 shadow-md card-hover block">
<div class="w-12 h-12 bg-sky-100 rounded-xl flex items-center justify-center text-xl mb-4">🗂️</div>
<h3 class="text-lg font-bold text-slate-900 mb-2">Document Vault</h3>
<p class="text-slate-600 text-sm mb-3">Store permits, insurance, and certifications — accessible from the road.</p>
@@ -215,7 +215,7 @@
Whether it's a single pilot car or a full escort team, we've got you covered.
Tell us about your load and we'll handle the rest.
</p>
<a href="order.html" class="inline-block bg-slate-900 hover:bg-slate-800 text-white font-bold px-8 py-4 rounded-xl text-lg transition-colors shadow-lg">
<a href="/pages/order.html" class="inline-block bg-slate-900 hover:bg-slate-800 text-white font-bold px-8 py-4 rounded-xl text-lg transition-colors shadow-lg">
Request Escort Service →
</a>
</div>
@@ -223,7 +223,7 @@
<div id="main-footer"></div>
<script src="nav.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('home');
renderBanner();

View File

@@ -1,6 +1,6 @@
// =============================================
// Shared Navigation, Banner, and Footer
// Include on every page via <script src="nav.js">
// Include on every page via <script src="/js/nav.js">
// =============================================
function renderNav(activePage) {
@@ -18,14 +18,14 @@ function renderNav(activePage) {
<nav class="bg-slate-900 text-white fixed top-0 w-full z-50 shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<a href="index.html" class="flex items-center space-x-2 flex-shrink-0">
<a href="/" class="flex items-center space-x-2 flex-shrink-0">
<span class="text-2xl">🚛</span>
<span class="text-xl font-bold text-amber-400 tracking-tight">PilotEdge</span>
</a>
<!-- Desktop Nav -->
<div class="hidden lg:flex items-center space-x-1">
<a href="index.html" class="${linkClass('home')} px-3 py-2 rounded-md text-sm transition-colors">Home</a>
<a href="/" class="${linkClass('home')} px-3 py-2 rounded-md text-sm transition-colors">Home</a>
<!-- Regulations Dropdown -->
<div class="relative group">
@@ -35,19 +35,19 @@ function renderNav(activePage) {
</button>
<div class="absolute left-0 top-full pt-1 hidden group-hover:block" style="min-width:220px;">
<div class="bg-white rounded-xl shadow-xl border border-slate-200 py-2">
<a href="regulations.html" class="${dropLinkClass('regulations')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/regulations.html" class="${dropLinkClass('regulations')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">State Regulations Map</div>
<div class="text-xs text-slate-400 mt-0.5">Permits & escort thresholds</div>
</a>
<a href="regulations.html#equipment" class="${dropLinkClass('equipment')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/regulations.html#equipment" class="${dropLinkClass('equipment')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Equipment Requirements</div>
<div class="text-xs text-slate-400 mt-0.5">Escort & carrier gear by state</div>
</a>
<a href="contacts.html" class="${dropLinkClass('contacts')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/contacts.html" class="${dropLinkClass('contacts')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">DOT Contact Directory</div>
<div class="text-xs text-slate-400 mt-0.5">Permit office phone & email</div>
</a>
<a href="calendar.html" class="${dropLinkClass('calendar')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/calendar.html" class="${dropLinkClass('calendar')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Seasonal Calendar</div>
<div class="text-xs text-slate-400 mt-0.5">Restrictions & closures</div>
</a>
@@ -63,19 +63,19 @@ function renderNav(activePage) {
</button>
<div class="absolute left-0 top-full pt-1 hidden group-hover:block" style="min-width:220px;">
<div class="bg-white rounded-xl shadow-xl border border-slate-200 py-2">
<a href="truckstops.html" class="${dropLinkClass('truckstops')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/truckstops.html" class="${dropLinkClass('truckstops')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Truck Stops & Parking</div>
<div class="text-xs text-slate-400 mt-0.5">Oversize-friendly locations</div>
</a>
<a href="bridges.html" class="${dropLinkClass('bridges')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/bridges.html" class="${dropLinkClass('bridges')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Bridge Clearances</div>
<div class="text-xs text-slate-400 mt-0.5">Height & width restrictions</div>
</a>
<a href="weighstations.html" class="${dropLinkClass('weighstations')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/weighstations.html" class="${dropLinkClass('weighstations')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Weigh Stations</div>
<div class="text-xs text-slate-400 mt-0.5">Live open/closed status</div>
</a>
<a href="alerts.html" class="${dropLinkClass('alerts')} block px-4 py-2.5 text-sm transition-colors">
<a href="/pages/alerts.html" class="${dropLinkClass('alerts')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Route & Weather Alerts</div>
<div class="text-xs text-slate-400 mt-0.5">Closures, construction, wind</div>
</a>
@@ -83,11 +83,11 @@ function renderNav(activePage) {
</div>
</div>
<a href="loadboard.html" class="${linkClass('loadboard')} px-3 py-2 rounded-md text-sm transition-colors">Load Board</a>
<a href="locator.html" class="${linkClass('locator')} px-3 py-2 rounded-md text-sm transition-colors">Find Escorts</a>
<a href="documents.html" class="${linkClass('documents')} px-3 py-2 rounded-md text-sm transition-colors">Documents</a>
<a href="/pages/loadboard.html" class="${linkClass('loadboard')} px-3 py-2 rounded-md text-sm transition-colors">Load Board</a>
<a href="/pages/locator.html" class="${linkClass('locator')} px-3 py-2 rounded-md text-sm transition-colors">Find Escorts</a>
<a href="/pages/documents.html" class="${linkClass('documents')} px-3 py-2 rounded-md text-sm transition-colors">Documents</a>
<a href="order.html" class="ml-2 bg-amber-500 hover:bg-amber-600 text-slate-900 font-bold px-4 py-2 rounded-lg transition-colors shadow-md hover:shadow-lg text-sm">
<a href="/pages/order.html" class="ml-2 bg-amber-500 hover:bg-amber-600 text-slate-900 font-bold px-4 py-2 rounded-lg transition-colors shadow-md hover:shadow-lg text-sm">
Request Service
</a>
</div>
@@ -103,26 +103,26 @@ function renderNav(activePage) {
<!-- Mobile Menu -->
<div id="mobile-menu" class="lg:hidden hidden border-t border-slate-700 px-4 pb-4 max-h-[80vh] overflow-y-auto">
<a href="index.html" class="block py-2 px-3 mt-2 rounded ${isActive('home') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Home</a>
<a href="/" class="block py-2 px-3 mt-2 rounded ${isActive('home') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Home</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Regulations</div>
<a href="regulations.html" class="block py-2 px-3 rounded ${isActive('regulations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">State Regulations Map</a>
<a href="regulations.html#equipment" class="block py-2 px-3 rounded ${isActive('equipment') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Equipment Requirements</a>
<a href="contacts.html" class="block py-2 px-3 rounded ${isActive('contacts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">DOT Contacts</a>
<a href="calendar.html" class="block py-2 px-3 rounded ${isActive('calendar') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Seasonal Calendar</a>
<a href="/pages/regulations.html" class="block py-2 px-3 rounded ${isActive('regulations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">State Regulations Map</a>
<a href="/pages/regulations.html#equipment" class="block py-2 px-3 rounded ${isActive('equipment') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Equipment Requirements</a>
<a href="/pages/contacts.html" class="block py-2 px-3 rounded ${isActive('contacts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">DOT Contacts</a>
<a href="/pages/calendar.html" class="block py-2 px-3 rounded ${isActive('calendar') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Seasonal Calendar</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Road Intel</div>
<a href="truckstops.html" class="block py-2 px-3 rounded ${isActive('truckstops') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Truck Stops & Parking</a>
<a href="bridges.html" class="block py-2 px-3 rounded ${isActive('bridges') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Bridge Clearances</a>
<a href="weighstations.html" class="block py-2 px-3 rounded ${isActive('weighstations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Weigh Stations</a>
<a href="alerts.html" class="block py-2 px-3 rounded ${isActive('alerts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Route & Weather Alerts</a>
<a href="/pages/truckstops.html" class="block py-2 px-3 rounded ${isActive('truckstops') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Truck Stops & Parking</a>
<a href="/pages/bridges.html" class="block py-2 px-3 rounded ${isActive('bridges') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Bridge Clearances</a>
<a href="/pages/weighstations.html" class="block py-2 px-3 rounded ${isActive('weighstations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Weigh Stations</a>
<a href="/pages/alerts.html" class="block py-2 px-3 rounded ${isActive('alerts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Route & Weather Alerts</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Services</div>
<a href="loadboard.html" class="block py-2 px-3 rounded ${isActive('loadboard') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Load Board</a>
<a href="locator.html" class="block py-2 px-3 rounded ${isActive('locator') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Find Escorts</a>
<a href="documents.html" class="block py-2 px-3 rounded ${isActive('documents') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Document Vault</a>
<a href="/pages/loadboard.html" class="block py-2 px-3 rounded ${isActive('loadboard') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Load Board</a>
<a href="/pages/locator.html" class="block py-2 px-3 rounded ${isActive('locator') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Find Escorts</a>
<a href="/pages/documents.html" class="block py-2 px-3 rounded ${isActive('documents') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Document Vault</a>
<a href="order.html" class="block py-2 px-3 mt-3 bg-amber-500 text-slate-900 font-bold rounded-lg text-center">Request Service</a>
<a href="/pages/order.html" class="block py-2 px-3 mt-3 bg-amber-500 text-slate-900 font-bold rounded-lg text-center">Request Service</a>
</div>
</nav>
`;
@@ -160,27 +160,27 @@ function renderFooter() {
<div>
<h4 class="text-white font-semibold mb-3">Regulations</h4>
<ul class="space-y-2 text-sm">
<li><a href="regulations.html" class="hover:text-white transition-colors">State Regulations Map</a></li>
<li><a href="contacts.html" class="hover:text-white transition-colors">DOT Contact Directory</a></li>
<li><a href="calendar.html" class="hover:text-white transition-colors">Seasonal Calendar</a></li>
<li><a href="/pages/regulations.html" class="hover:text-white transition-colors">State Regulations Map</a></li>
<li><a href="/pages/contacts.html" class="hover:text-white transition-colors">DOT Contact Directory</a></li>
<li><a href="/pages/calendar.html" class="hover:text-white transition-colors">Seasonal Calendar</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold mb-3">Road Intel</h4>
<ul class="space-y-2 text-sm">
<li><a href="truckstops.html" class="hover:text-white transition-colors">Truck Stops & Parking</a></li>
<li><a href="bridges.html" class="hover:text-white transition-colors">Bridge Clearances</a></li>
<li><a href="weighstations.html" class="hover:text-white transition-colors">Weigh Stations</a></li>
<li><a href="alerts.html" class="hover:text-white transition-colors">Route & Weather Alerts</a></li>
<li><a href="/pages/truckstops.html" class="hover:text-white transition-colors">Truck Stops & Parking</a></li>
<li><a href="/pages/bridges.html" class="hover:text-white transition-colors">Bridge Clearances</a></li>
<li><a href="/pages/weighstations.html" class="hover:text-white transition-colors">Weigh Stations</a></li>
<li><a href="/pages/alerts.html" class="hover:text-white transition-colors">Route & Weather Alerts</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold mb-3">Services</h4>
<ul class="space-y-2 text-sm">
<li><a href="loadboard.html" class="hover:text-white transition-colors">Load Board</a></li>
<li><a href="locator.html" class="hover:text-white transition-colors">Find Escort Vehicles</a></li>
<li><a href="documents.html" class="hover:text-white transition-colors">Document Vault</a></li>
<li><a href="order.html" class="hover:text-white transition-colors">Request Escort Service</a></li>
<li><a href="/pages/loadboard.html" class="hover:text-white transition-colors">Load Board</a></li>
<li><a href="/pages/locator.html" class="hover:text-white transition-colors">Find Escort Vehicles</a></li>
<li><a href="/pages/documents.html" class="hover:text-white transition-colors">Document Vault</a></li>
<li><a href="/pages/order.html" class="hover:text-white transition-colors">Request Escort Service</a></li>
</ul>
</div>
</div>

View File

@@ -119,8 +119,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('alerts');
renderBanner();

View File

@@ -112,8 +112,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('bridges');
renderBanner();

View File

@@ -85,8 +85,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('calendar');
renderBanner();

View File

@@ -42,8 +42,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('contacts');
renderBanner();

View File

@@ -105,8 +105,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('documents');
renderBanner();

View File

@@ -141,8 +141,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('loadboard');
renderBanner();

View File

@@ -115,8 +115,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('locator');
renderBanner();

View File

@@ -221,7 +221,7 @@
<div id="main-footer"></div>
<script src="nav.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('order');
renderBanner();

View File

@@ -139,8 +139,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('regulations');
renderBanner();

View File

@@ -65,8 +65,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('truckstops');
renderBanner();

View File

@@ -90,8 +90,8 @@
<div id="main-footer"></div>
<script src="api.js"></script>
<script src="nav.js"></script>
<script src="/js/api.js"></script>
<script src="/js/nav.js"></script>
<script>
renderNav('weighstations');
renderBanner();

7
server/.env.example Normal file
View File

@@ -0,0 +1,7 @@
# Environment variables for PilotEdge backend
# Copy this to .env and fill in your values
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/pilotedge?schema=public"
JWT_SECRET="change-this-to-a-long-random-string"
PORT=3000
NODE_ENV=development

View File

@@ -12,8 +12,8 @@ app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Serve the frontend (static HTML/JS/CSS from project root)
app.use(express.static(path.join(__dirname, '..', '..')));
// Serve the frontend (static files from public/)
app.use(express.static(path.join(__dirname, '..', '..', 'public')));
// --------------- API Routes ---------------
app.use('/api/auth', require('./routes/auth'));

View File

@@ -11,7 +11,7 @@ const prisma = require('../config/db');
// Load the mock data files by evaluating them in a controlled context
function loadMockData(filename) {
const filepath = path.join(__dirname, '..', '..', '..', filename);
const filepath = path.join(__dirname, '..', '..', '..', 'public', 'js', filename);
const code = fs.readFileSync(filepath, 'utf-8');
const context = {};
// Execute the JS to populate the const variables