# Beck Cabinet Company — Client Portal
## Complete IT Setup & Deployment Guide  ·  v2.0

---

### What's in this package

```
beck-cabinet-portal/
├── server.js              ← Main server — start here
├── monday.js              ← Monday.com API client
├── monday-config.js       ← Column mapping — YOU EDIT THIS
├── auth.js                ← Login & user management
├── tokens.js              ← Unique link generation
├── package.json           ← Node.js dependencies
├── .env.example           ← Copy to .env and fill in values
├── scripts/
│   ├── create-user.js     ← Run once to create first admin account
│   └── list-columns.js    ← Run to find Monday column IDs
└── public/
    ├── portal.html        ← Customer-facing portal (live Monday data)
    ├── admin.html         ← Internal admin dashboard
    ├── login.html         ← Admin login screen
    └── logo.png           ← Company logo (transparent background)
```

---

### Prerequisites

- Node.js 18 or higher
- Monday.com account with API access
- Domain pointed at your server (e.g. `beckportal.com`)
- SSL certificate (HTTPS required)

---

### Step 1 — Install dependencies

```bash
cd beck-cabinet-portal
npm install
```

---

### Step 2 — Configure .env

```bash
cp .env.example .env
```

Edit `.env`:

| Variable         | Where to find it |
|---|---|
| `MONDAY_API_TOKEN` | Monday.com → Avatar → Admin → API |
| `MONDAY_BOARD_ID`  | Board URL: `monday.com/boards/XXXXXXXXXX` |
| `PORT`             | Leave as `3000` |
| `BASE_URL`         | `https://beckportal.com` |
| `TOKEN_SECRET`     | `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` |
| `SESSION_SECRET`   | Same command, run again for a different value |
| `ADMIN_KEY`        | Another random string — protects admin API routes |
| `SESSION_DURATION` | `8h` or `24h` |

---

### Step 3 — Find your Monday column IDs

```bash
node scripts/list-columns.js
```

This prints every column on your board with its ID and type. Use the output to fill in `monday-config.js`.

---

### Step 4 — Edit monday-config.js

This is the only file you need to edit to match your Monday board.

**Area setup** — each area (Kitchen, Master Bath, etc.) needs two Monday columns:
- A **Status** column for the production step
- A **Date** column for the scheduled delivery date

```javascript
areas: [
  { label: 'Kitchen',      statusColumn: 'status',  deliveryColumn: 'date5' },
  { label: 'Master Bath',  statusColumn: 'status2', deliveryColumn: 'date6' },
  // add more areas as needed
],
```

**Status mapping** — map your Monday status labels to portal steps:

```javascript
statusMap: {
  'Drafting':           'drafting',
  'Submitted for Review': 'review',
  'Awaiting Approval':  'approval_waiting',  // shows amber "Action needed" tag
  'Approved':           'approval',
  'Materials Ordered':  'materials',
  'In Production':      'production',
  'Ready for Delivery': 'delivery',
  'Delivered':          'delivered',
},
```

---

### Step 5 — Create the first admin user

```bash
npm run create-user
```

Follow the prompts. After this, all user management happens through the admin dashboard.

---

### Step 6 — Test locally

```bash
npm start
```

- Health check: `http://localhost:3000/health`
- Admin login: `http://localhost:3000/admin`
- List all projects + portal links:
  ```bash
  curl -H "x-admin-key: YOUR_ADMIN_KEY" http://localhost:3000/api/admin/projects
  ```

---

### Step 7 — Deploy to server

**Keep running with PM2:**
```bash
npm install -g pm2
pm2 start server.js --name "beck-portal"
pm2 save && pm2 startup
```

**Nginx reverse proxy:**
```nginx
server {
    listen 443 ssl;
    server_name beckportal.com;
    ssl_certificate     /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    # Protect admin from public internet (office network only)
    location /admin {
        allow 192.168.1.0/24;  # your office subnet
        deny all;
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
    }
}
```

---

### Step 8 — Monday.com webhook (recommended)

Makes portal update instantly when you change a status in Monday.

1. Monday board → Automations → Custom Automation
2. Trigger: "When status changes"
3. Action: Send webhook to `https://beckportal.com/webhooks/monday`

Without this, the portal cache refreshes every 5 minutes automatically.

---

### Portal features summary

**Customer portal** (`/project/:token`)
- Live production status per area, 7-step tracker
- Approval step with amber "Action needed" indicator when awaiting customer sign-off
- Per-area scheduled delivery dates with live countdown
- Combined view (all areas at a glance) + By Area view (detailed steps per area)
- Delivery info: project address + installer name, company, phone
- Your team: each member's name, role, phone, and email
- Architectural floorplan watermark background

**Admin dashboard** (`/admin`)
- Requires username + password login
- Projects tab: all Monday projects with one-click portal link copying
- Users tab: add/remove team members, reset passwords
- My Account tab: change your own password

**Login & security**
- Session-based login, expires per `SESSION_DURATION`
- Passwords hashed with bcrypt (never stored in plain text)
- 10 login attempts max per 15 minutes (brute-force protection)
- Rate limiting on all routes (100 req/IP/15min)
- Admin API routes require `x-admin-key` header

---

### Monday board setup checklist

Create these columns on your project board:

| Column type | Name (suggestion)          | Maps to config key        |
|---|---|---|
| Text        | Job Number                 | `jobNumber`               |
| Text        | Customer / GC              | `customer`                |
| Date        | Project Start              | `startDate`               |
| Text        | Project Address            | `projectAddress`          |
| Text        | City / State / Zip         | `projectAddressCity`      |
| Text        | Installer Name             | `installerName`           |
| Text        | Installer Company          | `installerCompany`        |
| Phone       | Installer Phone            | `installerPhone`          |
| People      | Project Manager            | `projectManager`          |
| People      | Design Coordinator         | `designCoordinator`       |
| Status      | Kitchen Status             | area statusColumn         |
| Date        | Kitchen Delivery Date      | area deliveryColumn       |
| Status      | Master Bath Status         | area statusColumn         |
| Date        | Master Bath Delivery Date  | area deliveryColumn       |
| *(repeat per area)*                                            |

---

### How client links work

Each Monday item gets a unique, stable URL:
```
https://beckportal.com/project/a3f7k9m2q8x1b4n6
```

The 16-character token is derived from the Monday item ID + `TOKEN_SECRET`. Same project always gets the same link. Cannot be guessed. No database needed to store links.

**To share a link:** log into the admin dashboard → Projects → Copy Link button.

---

### Troubleshooting

| Problem | Fix |
|---|---|
| "Project not found" | Check Monday item exists; verify TOKEN_SECRET hasn't changed |
| Team phone/email missing | Ensure Monday user profiles have phone numbers filled in |
| Area not showing | Status column for that area may be blank in Monday |
| Approval step not amber | Check status label exactly matches `'Awaiting Approval'` in statusMap |
| Delivery date not showing | Verify date column ID is correct in monday-config.js areas array |
| 401 on admin API | Include `x-admin-key: YOUR_ADMIN_KEY` header |
| Can't log in to admin | Run `npm run create-user` to reset/create account |
