# FleetOps -- UAE Fleet Management

This document covers the installation, features, daily usage, and technical architecture of FleetOps, a fleet management mobile app for Curve Genaral Transport LLC.

**Estimated reading time:** 20 minutes

> **Note:** The company name "Curve Genaral Transport" uses an intentional spelling. Do not correct "Genaral" to "General" in any context.

---

## Overview

FleetOps is a native mobile shell that connects to the FleetOps web portal at `app.cgt.llc`. It provides vehicle and equipment tracking, invoicing with aging analysis, maintenance scheduling, timesheet management, and role-based access control for fleet operations in the UAE.

| Field              | Value                                      |
|--------------------|--------------------------------------------|
| App ID             | `com.cgt.fleetops`                         |
| Current version    | 1.0.0                                      |
| Android APK size   | 4.0 MB                                     |
| iOS IPA size       | 642 KB                                     |
| Application type   | Capacitor native shell (loads online portal) |
| Backend            | Next.js 16, React 19, Prisma, PostgreSQL (Neon) |
| Authentication     | NextAuth v5 (credentials provider, JWT sessions) |
| Company            | Curve Genaral Transport LLC, Abu Dhabi, UAE |
| Contact email      | interact.solutions@yahoo.com               |
| Portal URL         | [app.cgt.llc](https://app.cgt.llc)        |
| Demo login         | Credentials provided by administrator               |

---

## Properties

### Architecture

FleetOps uses a thin native shell built with Capacitor. The shell displays a loading screen with connection status, then redirects to the full web application at `app.cgt.llc`. All business logic, data storage, and authentication run on the server.

| Component          | Technology                                 |
|--------------------|--------------------------------------------|
| Native shell       | Capacitor 8.x (Android + iOS)             |
| Shell UI           | Static HTML/CSS/JS (`www/index.html`)      |
| Web application    | Next.js 16, React 19, TypeScript           |
| Database           | PostgreSQL on Neon (production)            |
| ORM                | Prisma (26 models)                         |
| Authentication     | NextAuth v5 with credentials provider      |
| Authorization      | RBAC: 5 roles, 36 permissions              |
| CSS framework      | Tailwind CSS v4 with custom theme tokens   |
| UI components      | Radix UI primitives                        |
| Charts             | Recharts                                   |
| Data fetching      | SWR with manual mutation                   |
| PDF export         | html2canvas + jspdf                        |
| Service worker     | Shell-only caching (offline fallback page)  |
| Theme colors       | Navy `#1B3A5C` (primary), Orange `#F47920` (accent) |

### Connectivity model

FleetOps requires an active internet connection for all operations. The native shell handles connectivity as follows:

1. **On launch:** The app displays a loading spinner and the message "Connecting to FleetOps..." for 1.5 seconds.
2. **If online:** The app sends a request to `https://app.cgt.llc`. On success, the browser redirects to the full web portal.
3. **If offline:** The app displays an offline panel with a "Retry Connection" button and a grid showing the four main feature areas (Vehicles, Operators, Invoices, Maintenance).
4. **On reconnection:** The app listens for the browser's `online` event and automatically retries the connection.

### Language support

Five languages with right-to-left (RTL) support:

| Code | Language   | Direction | Font override         |
|------|------------|-----------|----------------------|
| EN   | English    | LTR       | System default        |
| AR   | Arabic     | RTL       | Noto Sans Arabic      |
| TR   | Turkish    | LTR       | System default        |
| RU   | Russian    | LTR       | System default        |
| UR   | Urdu       | RTL       | Noto Sans Arabic      |

The language preference is stored in `localStorage` under the key `fleetops-locale`. Selecting Arabic or Urdu automatically switches the document direction to RTL and loads the Noto Sans Arabic font.

### Role-based access control (RBAC)

FleetOps enforces permissions at both the API and UI levels. Every API route calls `requireAuth("module:action")` before processing. The sidebar navigation filters items based on the logged-in user's role.

**Roles and their access:**

| Role       | Scope                                                        |
|------------|--------------------------------------------------------------|
| Admin      | Full access to all 36 permissions across every module        |
| Accounts   | View/create/edit estimates and invoices, view all other modules, manage timesheets |
| Operations | View/edit equipment, manage maintenance and timesheets, view estimates and invoices |
| Sales      | View/edit clients and marketing, create/edit estimates, view invoices and equipment |
| Viewer     | Read-only access to clients, equipment, estimates, invoices, reports |

**Permission types per module:**

| Module       | Available permissions                    |
|--------------|------------------------------------------|
| Clients      | `view`, `edit`                           |
| Equipment    | `view`, `edit`                           |
| Rate Cards   | `view`, `edit`                           |
| Estimates    | `view`, `create`, `edit`, `dispatch`     |
| Invoices     | `view`, `create`, `edit`, `dispatch`     |
| Timesheets   | `view`, `edit`                           |
| Maintenance  | `view`, `edit`                           |
| Comms        | `view`                                   |
| Marketing    | `view`, `edit`                           |
| Receivables  | `view`                                   |
| Reports      | `view`                                   |
| Review Log   | `view`                                   |
| Settings     | `view`, `users`                          |
| Vehicles     | `view`, `edit`, `approve`                |
| HR           | `view`, `edit`                           |
| Marketplace  | `view`, `edit`                           |

---

## Features

### Dashboard

The dashboard displays KPI cards, invoice aging bucket summaries, and recent activity. Aging buckets use color-coded indicators:

| Bucket     | Days outstanding | Color  |
|------------|-----------------|--------|
| Current    | 0               | Green  |
| 1--30      | 1 to 30         | Yellow |
| 31--60     | 31 to 60        | Orange |
| 61--90     | 61 to 90        | Red    |
| 90+        | Over 90         | Purple |

Aging is recalculated on every read. It is not stored in the database.

### Vehicle and equipment tracking

Manage the fleet inventory including:

- Vehicle profiles with registration, make, model, and status
- Equipment assignments to operators
- Mileage and utilization tracking
- Availability status (available, assigned, maintenance, retired)
- Public vehicle registration endpoint for external submissions

### Operator management

Track driver and operator information:

- Personal profiles with contact details
- License type, number, and expiry date tracking
- Assignment history
- Scheduling and availability

### Client management

Maintain client records with:

- Company name, address, contact details
- Client portal access credentials
- Associated estimates, invoices, and timesheets
- Client notes for internal reference

### Estimate creation and management

Create detailed estimates for fleet services:

1. Select a client.
2. Add line items with equipment, rate type, quantity, and unit price.
3. Apply discounts if applicable.
4. VAT (5% AED) calculates automatically on the subtotal after discount.
5. Save, dispatch, or convert the estimate to an invoice.

### Invoice generation

Create invoices directly or convert from approved estimates:

- Line items with equipment snapshots (client name and address are stored at creation time to preserve historical accuracy)
- VAT calculation: `(subtotal - discount) * 0.05`
- Payment tracking with partial payment support
- Balance due and status derivation (draft, sent, partially paid, paid, overdue)
- Aging bucket classification based on invoice date

### Estimate-to-invoice conversion

Convert an approved estimate into an invoice in a single step:

1. Open the estimate.
2. Select "Convert to Invoice."
3. The system creates a new invoice with all line items, quantities, and pricing copied from the estimate.
4. The invoice links back to the source estimate via `sourceEstimateId`.

### Maintenance scheduling

Schedule and track vehicle maintenance:

- Service type, date, cost, and notes
- Link maintenance records to specific vehicles/equipment
- Cost tracking and history

### Timesheet management

Record daily work entries:

- Daily entries with hours, equipment used, and work description
- Link timesheets to clients and equipment
- Approval workflows

### Marketing leads

Track prospective clients and sales opportunities:

- Lead source, status, and contact details
- Follow-up scheduling
- Conversion tracking

### Document management

Upload, store, and manage documents associated with vehicles, clients, and operations.

### Reports and analytics

View performance reports and analytics across fleet operations, including utilization rates, revenue summaries, and maintenance costs.

### PDF export

Export invoices, estimates, and reports as PDF files. The export process uses `html2canvas` to capture the document view and `jspdf` to generate the PDF.

### Keyboard shortcuts

| Shortcut | Action                        |
|----------|-------------------------------|
| `?`      | Open keyboard shortcuts help  |
| `Alt+N`  | Open quick create menu        |

---

## User guide

### Open the app

1. Tap the FleetOps icon on your home screen.
2. The app displays a loading screen with the FleetOps branding and a spinning indicator.
3. If you have an internet connection, the app redirects to the FleetOps portal at `app.cgt.llc` within a few seconds.
4. If you are offline, the app shows the offline panel. Tap "Retry Connection" after restoring connectivity.

### Sign in

1. Enter your email address and password on the login screen.
2. Tap "Sign In."
3. The dashboard loads with navigation items filtered to your role's permissions.

**Demo credentials for testing:**

| Email              | Password  | Role  |
|--------------------|-----------|-------|
| Contact administrator for credentials |     |       |

### Navigate the interface

The sidebar on the left side lists all accessible modules. On mobile, the sidebar collapses into a hamburger menu. The top bar shows the current page title, language selector, and user menu.

### Create an estimate

1. Open "Estimates" from the sidebar.
2. Tap "New Estimate."
3. Select the client from the dropdown.
4. Tap "Add Line Item."
5. Select the equipment from the picker.
6. Enter the rate type, quantity, and unit price.
7. Repeat steps 4-6 for additional line items.
8. Review the subtotal, discount (if any), VAT (5%), and total.
9. Tap "Save" to store the estimate as a draft.

### Convert an estimate to an invoice

1. Open the estimate you want to convert.
2. Verify the estimate status is approved or ready for conversion.
3. Tap "Convert to Invoice."
4. The system creates a new invoice with all line items copied from the estimate.
5. Review the invoice and make any final adjustments.
6. Save or dispatch the invoice.

### Create an invoice directly

1. Open "Invoices" from the sidebar.
2. Tap "New Invoice."
3. Select the client. The client's name and address are captured as snapshot fields on the invoice.
4. Add line items with equipment, quantities, and rates.
5. The system calculates VAT at 5% on `(subtotal - discount)`.
6. Save the invoice.

### Export a document as PDF

1. Open the invoice, estimate, or report you want to export.
2. Tap the PDF download button (or use the export action in the document toolbar).
3. The app captures the document using `html2canvas` and generates a PDF via `jspdf`.
4. The PDF downloads to your device.

### Record a timesheet entry

1. Open "Timesheets" from the sidebar.
2. Select the date and client.
3. Add daily entries with hours worked, equipment used, and work description.
4. Save the timesheet.

### Schedule maintenance

1. Open "Maintenance" from the sidebar.
2. Tap "New Record."
3. Select the vehicle or equipment.
4. Enter the service type, scheduled date, and estimated cost.
5. Add notes about the required service.
6. Save the maintenance record.

### Change the language

1. Tap the language selector in the top bar.
2. Select your preferred language (EN, AR, TR, RU, UR).
3. The interface updates immediately. Arabic and Urdu switch the layout to right-to-left.

---

## Technical specifications

### Capacitor configuration

```json
{
  "appId": "com.cgt.fleetops",
  "appName": "CGT FleetOps",
  "webDir": "www",
  "server": {
    "androidScheme": "https",
    "iosScheme": "https",
    "allowNavigation": [
      "app.cgt.llc",
      "cgt.llc",
      "*.cgt.llc"
    ]
  },
  "plugins": {
    "SplashScreen": {
      "launchShowDuration": 2000,
      "backgroundColor": "#1B3A5C"
    },
    "StatusBar": {
      "style": "DARK",
      "backgroundColor": "#1B3A5C"
    }
  }
}
```

### Native shell behavior

The `www/index.html` file is a self-contained loading page that:

1. Registers a service worker (`sw.js`) to cache the shell assets.
2. Waits 1.5 seconds, then checks `navigator.onLine`.
3. If online, sends a `no-cors` fetch to `https://app.cgt.llc` and redirects on success.
4. If offline, displays the offline panel with a retry button.
5. Listens for the browser `online` event and retries automatically.

### Service worker

The shell service worker (`sw.js`) caches three assets: `./`, `./index.html`, and `./manifest.json`. It uses a cache-first strategy for local shell files and a network-first strategy for requests to `app.cgt.llc`, falling back to the cached `index.html` if the network is unavailable.

### Backend API routes

The web application at `app.cgt.llc` exposes 26 API route directories:

| Route                      | Auth required | Purpose                                |
|----------------------------|---------------|----------------------------------------|
| `/api/auth`                | No            | NextAuth authentication endpoints      |
| `/api/dashboard`           | Yes           | Dashboard KPI and summary data         |
| `/api/clients`             | Yes           | Client CRUD                            |
| `/api/equipment`           | Yes           | Equipment/vehicle CRUD                 |
| `/api/rate-cards`          | Yes           | Rate card management                   |
| `/api/estimates`           | Yes           | Estimate CRUD + dispatch               |
| `/api/estimates/[id]/convert` | Yes        | Estimate-to-invoice conversion         |
| `/api/invoices`            | Yes           | Invoice CRUD + dispatch                |
| `/api/timesheets`          | Yes           | Timesheet CRUD with daily entries       |
| `/api/maintenance`         | Yes           | Maintenance record CRUD                |
| `/api/comms`               | Yes           | Communications log                     |
| `/api/marketing`           | Yes           | Marketing leads CRUD                   |
| `/api/receivables`         | Yes           | Accounts receivable tracking           |
| `/api/hr`                  | Yes           | HR records management                  |
| `/api/marketplace`         | Yes           | Marketplace listings                   |
| `/api/users`               | Yes           | User management (Admin only)           |
| `/api/settings`            | Yes           | Company settings management            |
| `/api/signatures`          | Yes           | Digital signature management           |
| `/api/export`              | Yes           | Data export                            |
| `/api/feedback`            | Yes           | User feedback collection               |
| `/api/activity-log`        | Yes           | Activity audit trail                   |
| `/api/audit`               | Yes           | Audit records                          |
| `/api/backup`              | Yes           | Database backup operations             |
| `/api/notifications`       | Yes           | Notification management                |
| `/api/next-number`         | Yes           | Sequential number generation           |
| `/api/registered-vehicles` | Yes           | Registered vehicle records             |
| `/api/public/register-vehicle` | No        | Public vehicle registration form       |
| `/api/public/apply`        | No            | Public job application form            |

### Database schema

The Prisma schema defines 26 models. Key relationships:

```
Client --> Estimates, Invoices, Timesheets, MarketingLeads, Notes
Equipment --> RateCards, EstimateLines, InvoiceLines, Timesheets, Maintenance
Estimate --> Invoice (one-to-one via sourceEstimateId)
```

**Snapshot fields:** Invoices store `clientNameSnapshot` and `clientAddressSnapshot` at creation time. These fields preserve the client's details as they were when the invoice was issued, even if the client's current information changes later.

### VAT calculation

VAT is calculated at 5% on the net amount after discounts:

```
vat = (subtotal - discount) * vatRate / 100
total = subtotal - discount + vat
```

The VAT rate is stored per document for historical integrity. If the rate changes in the future, previously issued documents retain their original rate.

### External connections

| Domain     | Purpose                    | Required |
|------------|----------------------------|----------|
| cgt.llc    | Web application portal     | Yes      |

The app connects exclusively to the `cgt.llc` domain. No external CDNs, analytics services, or third-party APIs are loaded at runtime.

### Build commands

```bash
cd mobile-apps/fleetops-mobile

# First-time setup
npm install
mkdir -p www
npx cap add android
npx cap add ios

# Android builds
npm run build:android:debug     # Debug APK for testing
npm run build:android:release   # Release AAB for Google Play

# iOS builds
npm run build:ios               # Opens Xcode for archive/distribution
```

### File structure

```
fleetops-mobile/
  www/
    index.html       -- Native shell loading page
    manifest.json    -- PWA manifest
    sw.js            -- Service worker for shell caching
  android/           -- Capacitor Android project
  ios/               -- Capacitor iOS project
  package.json       -- Build scripts and Capacitor dependencies
  capacitor.config.json -- App ID, server config, plugin settings
```

---

## Known limitations

| Limitation                              | Impact                                                   | Workaround                                                |
|-----------------------------------------|----------------------------------------------------------|-----------------------------------------------------------|
| Internet required for all operations    | The app cannot display fleet data, create documents, or perform any business operation without connectivity. The offline shell shows a static landing page only. | Ensure reliable internet before starting work sessions. Use the retry button when connectivity is restored. |
| No offline data caching                 | Unlike the LeathX app, FleetOps does not cache business data for offline browsing. Losing connection mid-session shows a connection error. | Save or submit work frequently. The web portal auto-saves form drafts in the browser session. |
| No push notifications                   | Users do not receive alerts for overdue invoices, maintenance due dates, license expirations, or new assignments. | Check the dashboard regularly. Aging bucket colors on the dashboard highlight overdue items. |
| PDF quality varies by device            | The `html2canvas` + `jspdf` pipeline renders the current screen view as a PDF. Quality depends on the device's screen resolution and pixel density. | Use a tablet or desktop browser for higher-resolution PDF exports. |
| Neon PostgreSQL connection pool limit   | The Neon free/starter tier limits concurrent database connections. High simultaneous usage from many users may result in connection errors. | Coordinate peak usage times. Upgrade the Neon plan for higher connection limits if needed. |
| Locked to cgt.llc domain               | The Capacitor config allows navigation only to `cgt.llc` and its subdomains. The app cannot be pointed at a different server without rebuilding. | Modify `capacitor.config.json` and rebuild the native shell to use a different domain. |
| iOS app is unsigned                     | The iOS build produces an unsigned IPA. Distribution through the Apple App Store requires an Apple Developer account ($99/year) and signing the app through Xcode. | Distribute via TestFlight with a Developer account, or install directly on provisioned devices during development. |
| Single-domain navigation only           | The `allowNavigation` config restricts the WebView to `cgt.llc`. External links (for example, a link to a supplier's website) will not open inside the app. | External links open in the device's default browser via the OS. |

---

## Support and contact

| Channel    | Details                                         |
|------------|--------------------------------------------------|
| Email      | interact.solutions@yahoo.com                     |
| Portal     | [app.cgt.llc](https://app.cgt.llc)              |
| Company    | Curve Genaral Transport LLC, Abu Dhabi, UAE      |
| Demo login | Credentials provided by administrator                     |
| Developer  | INTERACT Solutions, Karachi, Pakistan            |

For bug reports, include the following: app version (1.0.0), device model, operating system version, a description of the steps to reproduce the issue, and a screenshot if applicable.

---

*Curve Genaral Transport LLC -- Abu Dhabi, UAE*
*Developed by INTERACT Solutions -- Karachi, Pakistan*
*Version 1.0.0 -- Last updated: 2026-03-27*
