Files
carmanagement/docs/project-design/INTEGRATION.md
T
2026-05-06 22:58:23 -04:00

183 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Staff Management — Integration Guide
## 1. Register the routes in your Express app
```ts
// apps/api/src/index.ts (or server.ts)
import express from 'express'
import teamRouter from './routes/team'
import webhookRouter from './routes/webhooks'
const app = express()
// Webhook MUST use raw body — register BEFORE express.json()
app.use(
'/webhooks',
express.raw({ type: 'application/json' }),
webhookRouter
)
// All other routes use JSON
app.use(express.json())
// Team routes — mounted under /api/v1/team (matches api-routes.md)
app.use('/api/v1/team', teamRouter)
```
---
## 2. Install the Clerk webhook (Clerk Dashboard → Webhooks)
1. Go to **clerk.com** → your app → **Webhooks****Add endpoint**
2. URL: `https://api.RentalDriveGo.com/webhooks/clerk`
3. Events to subscribe: `user.created`
4. Copy the **Signing Secret** and add to `.env`:
```env
CLERK_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx
```
5. Install `svix` for signature verification:
```bash
npm install svix
```
---
## 3. Environment variables needed
```env
# Clerk
CLERK_SECRET_KEY=sk_live_...
CLERK_WEBHOOK_SECRET=whsec_...
# Frontend
NEXT_PUBLIC_API_URL=https://api.RentalDriveGo.com/api/v1
# Dashboard URL (used in invite redirect)
DASHBOARD_URL=https://app.RentalDriveGo.com
```
---
## 4. Add the page to the Next.js dashboard app
```
apps/dashboard/
├── app/
│ └── dashboard/
│ └── team/
│ └── page.tsx ← copy frontend/pages/team.tsx here
├── components/
│ └── team/
│ ├── InviteModal.tsx ← copy from frontend/components/team/
│ ├── EditMemberModal.tsx
│ └── PermissionsMatrix.tsx
└── hooks/
└── useTeam.ts ← copy from frontend/hooks/
```
Add the route to your dashboard sidebar navigation:
```tsx
// components/Sidebar.tsx — add to nav items
{ href: '/dashboard/team', label: 'Team', icon: UsersIcon }
```
---
## 5. requireRole middleware placement
The `requireRole` middleware is already applied inside the team router.
Only expose it if you need it elsewhere (e.g., `PATCH /pricing-rules``requireRole('MANAGER')`):
```ts
import { requireRole } from './middleware/requireRole'
// Example: license approval endpoint (OWNER or MANAGER only)
router.post(
'/customers/:id/approve-license',
requireRole('MANAGER'),
approveLicenseHandler
)
```
---
## 6. Invite acceptance flow (frontend)
When a user clicks the magic link in their invitation email, Clerk redirects them to:
```
https://app.RentalDriveGo.com/onboarding/accept-invite?__clerk_ticket=...
```
Create this page in your Next.js app:
```tsx
// app/onboarding/accept-invite/page.tsx
'use client'
import { useEffect } from 'react'
import { useClerk } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
export default function AcceptInvite() {
const { handleRedirectCallback } = useClerk()
const router = useRouter()
useEffect(() => {
handleRedirectCallback({}).then(() => {
// Clerk webhook fires user.created → activates Employee record in DB
// Redirect to dashboard after a short delay
setTimeout(() => router.replace('/dashboard'), 1000)
})
}, [])
return (
<div className="flex items-center justify-center min-h-screen">
<p className="text-sm text-zinc-500">Setting up your account</p>
</div>
)
}
```
---
## 7. Prisma type extensions (optional, for `req.employee`)
To get TypeScript to recognize `req.companyId` and `req.employee` on Express requests,
add a type declaration file:
```ts
// types/express.d.ts
import { Employee, Company } from '@prisma/client'
declare global {
namespace Express {
interface Request {
companyId: string
company: Company
employee: Employee
}
}
}
```
---
## 8. Summary of files delivered
| File | Purpose |
|------|---------|
| `backend/services/teamService.ts` | All business logic — invite, update role, deactivate, remove, Clerk webhook handler |
| `backend/routes/team.ts` | Express router — all `/team` endpoints |
| `backend/routes/webhooks.ts` | Clerk webhook listener — activates employee on invite acceptance |
| `backend/middleware/requireRole.ts` | Role-rank guard middleware — reusable across all routers |
| `frontend/hooks/useTeam.ts` | React data hook — fetch, invite, updateRole, deactivate, reactivate, remove |
| `frontend/pages/team.tsx` | Full `/dashboard/team` Next.js page |
| `frontend/components/team/InviteModal.tsx` | Invite new member modal with role picker |
| `frontend/components/team/EditMemberModal.tsx` | Edit role, deactivate, reactivate, remove modal with confirmation step |
| `frontend/components/team/PermissionsMatrix.tsx` | Static role × feature permissions table |