Add leads handlers, WhatsApp integration, and test files

This commit is contained in:
2026-05-02 17:40:38 +00:00
parent 8833e38b80
commit 57e6e5a6fd
24 changed files with 2305 additions and 115 deletions

143
AGENTS.md
View File

@@ -1,6 +1,6 @@
# AGENTS.md - Agent Coding Guidelines
This workspace is a monorepo containing data engineering projects and WhatsApp CRM applications.
Monorepo: data engineering projects + WhatsApp CRM apps.
---
@@ -9,11 +9,15 @@ This workspace is a monorepo containing data engineering projects and WhatsApp C
```
workspace/
├── apps/
│ ├── whatsapp-crm/ # Next.js CRM with Kanban board (primary app)
│ ├── whatsapp-sync/ # WhatsApp message sync service
│ ├── whatsapp-reader/ # WhatsApp message reader
── timesfm-forecast/ # Time series forecasting app
├── data-engineering/ # Udacity DE portfolio projects
│ ├── go-crm/ # Go CRM, Chi router (primary)
│ ├── whatsapp-crm/ # Next.js CRM, Kanban board
│ ├── whatsapp-sync/ # WhatsApp message sync
── whatsapp-reader/ # WhatsApp message reader
│ └── timesfm-forecast/ # Time series forecast (Python/uv)
├── data/ # SQLite files
│ ├── go-crm.db
│ └── whatsapp.db
├── data-engineering/ # Udacity DE portfolio
└── skills/ # dbt reference templates
```
@@ -21,24 +25,34 @@ workspace/
## Build / Lint / Test Commands
### whatsapp-crm (primary app)
### go-crm (primary)
```bash
cd apps/go-crm
go run main.go # dev
go build -o go-crm main.go # build binary
./go-crm # run binary
go mod download # deps
go mod tidy # clean go.mod/go.sum
# DB: /workspace/data/go-crm.db
```
### whatsapp-crm (Next.js)
```bash
cd apps/whatsapp-crm
# Development
npm run dev # Start Next.js dev server on 0.0.0.0:3000
npm run build # Production build
npm run start # Production server
npm run dev # dev server 0.0.0.0:3000
npm run build # production build
npm run start # production server
# Linting
npm run lint # ESLint with Next.js config
npm run lint # ESLint
# Testing
npm run test # Run all Jest tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage
npm run test # all Jest tests
npm run test:watch # watch mode
npm run test:coverage # coverage
# Single test file
npm run test -- tests/kanban.test.ts
npm run test -- --testPathPattern=kanban
```
@@ -51,24 +65,26 @@ npm run start # node src/index.js
npm run dev # node --watch src/index.js
npm run sync # node src/sync.js
npm run test # Jest
npm run test:watch # Jest watch mode
npm run test:coverage # Jest with coverage
npm run test:watch
npm run test:coverage
```
### whatsapp-reader
```bash
cd apps/whatsapp-reader
# No test script defined
node index.js # Run main script
node sync.js # Run sync script
node index.js # main script
node sync.js # sync script
# no test script
```
### timesfm-forecast (Python/uv)
### timesfm-forecast
```bash
cd apps/timesfm-forecast
uv venv && source .venv/bin/activate # Create & activate venv
uv pip install -e . # Install package
timesfm-app # Run Streamlit app
uv venv && source .venv/bin/activate # create + activate venv
uv pip install -e . # install package
timesfm-app # run Streamlit app
```
---
@@ -76,12 +92,11 @@ timesfm-app # Run Streamlit app
## Code Style Guidelines
### TypeScript
- `strict: true` enabled in tsconfig.json
- Always use explicit types for function parameters and return values
- Use `interface` for objects, `type` for unions/aliases
- `strict: true` in tsconfig.json
- Explicit types for params + return values
- `interface` for objects, `type` for unions/aliases
```typescript
// Good
interface Contact {
id: number
name: string
@@ -89,15 +104,12 @@ interface Contact {
}
function getContactById(id: number): Contact | null
// Avoid
const contact = { id: 1, name: 'Test' } // implicit any
```
### Imports
- Use path alias `@/*` for internal imports (configured in tsconfig.json)
- Path alias `@/*` (tsconfig.json)
- Order: external → internal → relative
- Group by: React imports → other imports → types → components
- Group: React imports → other imports → types → components
```typescript
import { useState, useMemo } from 'react'
@@ -105,21 +117,20 @@ import { Stage, STAGES, Contact } from '@/lib/types'
import { ContactCard } from '@/components/ContactCard'
```
### Naming Conventions
- **Components**: PascalCase (e.g., `KanbanBoard`, `ContactCard`)
- **Files**: PascalCase for components (`.tsx`), camelCase for utilities (`.ts`)
- **Interfaces/Types**: PascalCase (e.g., `Contact`, `Task`, `CreateContactInput`)
- **Constants**: UPPER_SNAKE_CASE (e.g., `STAGES`, `STAGE_LIST`)
- **React hooks**: camelCase with `use` prefix (e.g., `useContacts`, `useTask`)
- **Boolean variables**: prefix with `is`, `has`, `should` (e.g., `isLoading`, `hasError`)
### Naming
- **Components**: PascalCase (`KanbanBoard`, `ContactCard`)
- **Files**: PascalCase (`.tsx`), camelCase (`.ts`)
- **Interfaces/Types**: PascalCase
- **Constants**: UPPER_SNAKE_CASE
- **Hooks**: camelCase + `use` prefix
- **Booleans**: `is`/`has`/`should` prefix
### Error Handling
- Use Zod for input validation with react-hook-form
- Always wrap async operations in try/catch
- Return proper HTTP status codes in API routes
- Zod for input validation + react-hook-form
- Wrap async in try/catch
- Return proper HTTP status codes
```typescript
// API route error handling
export async function POST(request: Request) {
try {
const body = await request.json()
@@ -134,9 +145,9 @@ export async function POST(request: Request) {
```
### Component Structure
- Use `'use client'` directive for client-side components
- Destructure props with explicit typing
- Keep components focused and small
- `'use client'` directive for client-side
- Destructure props, explicit typing
- Keep components focused, small
- Extract reusable logic to custom hooks
```typescript
@@ -155,15 +166,15 @@ export default function ComponentName({ contacts, onContactClick }: Props) {
```
### Database (sql.js)
- Use Zod schemas for table definitions
- Always validate data before insert/update
- Use transactions for multi-step operations
- Zod schemas for table definitions
- Validate data before insert/update
- Use transactions for multi-step ops
### Testing
- Test files: `tests/*.test.ts` or `*.test.tsx`
- Use `@testing-library/react` for component tests
- Use `@testing-library/user-event` for user interactions
- Follow AAA pattern: Arrange, Act, Assert
- `@testing-library/react` for component tests
- `@testing-library/user-event` for interactions
- AAA pattern: Arrange, Act, Assert
```typescript
test('should update contact stage', async () => {
@@ -176,20 +187,20 @@ test('should update contact stage', async () => {
```
### CSS / Styling
- This project uses CSS modules or global CSS
- Follow BEM-like naming: `block-element--modifier`
- Keep styles co-located when possible
- CSS modules or global CSS
- BEM-like: `block-element--modifier`
- Co-locate styles when possible
### Git Conventions
- Use meaningful commit messages
### Git
- Meaningful commit messages
- Branch naming: `feature/description` or `fix/description`
- Run `npm run lint` and `npm run test` before committing
- Run `npm run lint` + `npm run test` before commit
---
## Important Notes
- whatsapp-crm uses Next.js 14 App Router
- Database is sql.js (WebAssembly SQLite) - runs in browser
- Authentication uses WhatsApp Web.js QR code scanning
- STAGES constant defines the Kanban pipeline (defined in `src/lib/types.ts`)
- whatsapp-crm: Next.js 14 App Router
- Database: sql.js (WebAssembly SQLite), runs in browser
- Auth: WhatsApp Web.js QR code scanning
- STAGES constant: Kanban pipeline (defined in `src/lib/types.ts`)